From cb51e03587f0079665dca9048f522bb264a41a10 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 13 Oct 2018 01:36:26 +0100 Subject: [PATCH 001/395] Add Sprout support to TransactionBuilder --- src/gtest/test_transaction_builder.cpp | 158 ++++++++++ src/transaction_builder.cpp | 396 ++++++++++++++++++++++++- src/transaction_builder.h | 43 ++- 3 files changed, 589 insertions(+), 8 deletions(-) diff --git a/src/gtest/test_transaction_builder.cpp b/src/gtest/test_transaction_builder.cpp index 72aab05f717..f6aecb88f0b 100644 --- a/src/gtest/test_transaction_builder.cpp +++ b/src/gtest/test_transaction_builder.cpp @@ -12,6 +12,67 @@ #include #include +extern ZCJoinSplit* params; + +// Fake an empty view +class TransactionBuilderCoinsViewDB : public CCoinsView { +public: + std::map sproutTrees; + + TransactionBuilderCoinsViewDB() {} + + bool GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const { + auto it = sproutTrees.find(rt); + if (it != sproutTrees.end()) { + tree = it->second; + return true; + } else { + return false; + } + } + + bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const { + return false; + } + + bool GetNullifier(const uint256 &nf, ShieldedType type) const { + return false; + } + + bool GetCoins(const uint256 &txid, CCoins &coins) const { + return false; + } + + bool HaveCoins(const uint256 &txid) const { + return false; + } + + uint256 GetBestBlock() const { + uint256 a; + return a; + } + + uint256 GetBestAnchor(ShieldedType type) const { + uint256 a; + return a; + } + + bool BatchWrite(CCoinsMap &mapCoins, + const uint256 &hashBlock, + const uint256 &hashSproutAnchor, + const uint256 &hashSaplingAnchor, + CAnchorsSproutMap &mapSproutAnchors, + CAnchorsSaplingMap &mapSaplingAnchors, + CNullifiersMap &mapSproutNullifiers, + CNullifiersMap saplingNullifiersMap) { + return false; + } + + bool GetStats(CCoinsStats &stats) const { + return false; + } +}; + TEST(TransactionBuilder, Invoke) { auto consensusParams = RegtestActivateSapling(); @@ -30,6 +91,10 @@ TEST(TransactionBuilder, Invoke) libzcash::diversifier_t d = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; auto pk = *ivk.address(d); + auto sproutSk = libzcash::SproutSpendingKey::random(); + ZCNoteDecryption sproutDecryptor(sproutSk.receiving_key()); + auto sproutAddr = sproutSk.address(); + // Create a shielding transaction from transparent to Sapling // 0.0005 t-ZEC in, 0.0004 z-ZEC out, 0.0001 t-ZEC fee auto builder1 = TransactionBuilder(consensusParams, 1, &keystore); @@ -81,10 +146,103 @@ TEST(TransactionBuilder, Invoke) EXPECT_TRUE(ContextualCheckTransaction(tx2, state, 3, 0)); EXPECT_EQ(state.GetRejectReason(), ""); + // Create a Sapling-to-Sprout transaction (reusing the note from above) + // - 0.0004 Sapling-ZEC in - 0.00025 Sprout-ZEC out + // - 0.00005 Sapling-ZEC change + // - 0.0001 t-ZEC fee + auto builder3 = TransactionBuilder(consensusParams, 2, nullptr, params); + builder3.AddSaplingSpend(expsk, note, anchor, witness); + builder3.AddSproutOutput(sproutAddr, 25000); + auto tx3 = builder3.Build().GetTxOrThrow(); + + EXPECT_EQ(tx3.vin.size(), 0); + EXPECT_EQ(tx3.vout.size(), 0); + EXPECT_EQ(tx3.vjoinsplit.size(), 1); + EXPECT_EQ(tx3.vjoinsplit[0].vpub_old, 25000); + EXPECT_EQ(tx3.vjoinsplit[0].vpub_new, 0); + EXPECT_EQ(tx3.vShieldedSpend.size(), 1); + EXPECT_EQ(tx3.vShieldedOutput.size(), 1); + EXPECT_EQ(tx3.valueBalance, 35000); + + EXPECT_TRUE(ContextualCheckTransaction(tx3, state, 3, 0)); + EXPECT_EQ(state.GetRejectReason(), ""); + + // Prepare to spend the Sprout note that was just created + SproutMerkleTree sproutTree; + libzcash::SproutNote sproutNote; + SproutWitness sproutWitness; + for (int i = 0; i < ZC_NUM_JS_OUTPUTS; i++) { + sproutTree.append(tx3.vjoinsplit[0].commitments[i]); + + auto hSig = tx3.vjoinsplit[0].h_sig(*params, tx3.joinSplitPubKey); + try { + auto pt = libzcash::SproutNotePlaintext::decrypt( + sproutDecryptor, + tx3.vjoinsplit[0].ciphertexts[i], + tx3.vjoinsplit[0].ephemeralKey, + hSig, + (unsigned char)i); + sproutNote = pt.note(sproutAddr); + sproutWitness = sproutTree.witness(); + break; + } catch (const std::exception& e) { + // One of the outputs must be ours + assert(i + 1 < ZC_NUM_JS_OUTPUTS); + } + } + + // Fake a view with the Sprout note in it + auto rt = sproutTree.root(); + TransactionBuilderCoinsViewDB fakeDB; + fakeDB.sproutTrees.insert(std::pair(rt, sproutTree)); + CCoinsViewCache view(&fakeDB); + + // Create a Sprout-to-[Sprout-and-Sapling] transaction + // - 0.00025 Sprout-ZEC in - 0.00006 Sprout-ZEC out + // - 0.00004 Sprout-ZEC out + // - 0.00005 Sprout-ZEC change + // - 0.00005 Sapling-ZEC out + // - 0.00005 t-ZEC fee + auto builder4 = TransactionBuilder(consensusParams, 2, nullptr, params, &view); + builder4.SetFee(5000); + builder4.AddSproutInput(sproutSk, sproutNote, sproutWitness); + builder4.AddSproutOutput(sproutAddr, 6000); + builder4.AddSproutOutput(sproutAddr, 4000); + builder4.AddSaplingOutput(fvk.ovk, pk, 5000); + auto tx4 = builder4.Build().GetTxOrThrow(); + + EXPECT_EQ(tx4.vin.size(), 0); + EXPECT_EQ(tx4.vout.size(), 0); + // TODO: This should be doable in two JoinSplits. + // There's an inefficiency in the implementation. + EXPECT_EQ(tx4.vjoinsplit.size(), 3); + EXPECT_EQ(tx4.vjoinsplit[0].vpub_old, 0); + EXPECT_EQ(tx4.vjoinsplit[0].vpub_new, 0); + EXPECT_EQ(tx4.vjoinsplit[1].vpub_old, 0); + EXPECT_EQ(tx4.vjoinsplit[1].vpub_new, 0); + EXPECT_EQ(tx4.vjoinsplit[2].vpub_old, 0); + EXPECT_EQ(tx4.vjoinsplit[2].vpub_new, 10000); + EXPECT_EQ(tx4.vShieldedSpend.size(), 0); + EXPECT_EQ(tx4.vShieldedOutput.size(), 1); + EXPECT_EQ(tx4.valueBalance, -5000); + + EXPECT_TRUE(ContextualCheckTransaction(tx4, state, 4, 0)); + EXPECT_EQ(state.GetRejectReason(), ""); + // Revert to default RegtestDeactivateSapling(); } +TEST(TransactionBuilder, ThrowsOnSproutOutputWithoutParams) +{ + auto consensusParams = Params().GetConsensus(); + auto sk = libzcash::SproutSpendingKey::random(); + auto addr = sk.address(); + + auto builder = TransactionBuilder(consensusParams, 1); + ASSERT_THROW(builder.AddSproutOutput(addr, 10), std::runtime_error); +} + TEST(TransactionBuilder, ThrowsOnTransparentInputWithoutKeyStore) { SelectParams(CBaseChainParams::REGTEST); diff --git a/src/transaction_builder.cpp b/src/transaction_builder.cpp index c90ac968076..d8743cee4e0 100644 --- a/src/transaction_builder.cpp +++ b/src/transaction_builder.cpp @@ -8,6 +8,7 @@ #include "pubkey.h" #include "rpc/protocol.h" #include "script/sign.h" +#include "utilmoneystr.h" #include #include @@ -49,7 +50,16 @@ std::string TransactionBuilderResult::GetError() { TransactionBuilder::TransactionBuilder( const Consensus::Params& consensusParams, int nHeight, - CKeyStore* keystore) : consensusParams(consensusParams), nHeight(nHeight), keystore(keystore) + CKeyStore* keystore, + ZCJoinSplit* sproutParams, + CCoinsViewCache* coinsView, + CCriticalSection* cs_coinsView) : + consensusParams(consensusParams), + nHeight(nHeight), + keystore(keystore), + sproutParams(sproutParams), + coinsView(coinsView), + cs_coinsView(cs_coinsView) { mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight); } @@ -90,6 +100,39 @@ void TransactionBuilder::AddSaplingOutput( mtx.valueBalance -= value; } +void TransactionBuilder::AddSproutInput( + libzcash::SproutSpendingKey sk, + libzcash::SproutNote note, + SproutWitness witness) +{ + if (sproutParams == nullptr) { + throw std::runtime_error("Cannot add Sprout inputs to a TransactionBuilder without Sprout params"); + } + + // Consistency check: all anchors must equal the first one + if (!jsInputs.empty()) { + if (jsInputs[0].witness.root() != witness.root()) { + throw JSONRPCError(RPC_WALLET_ERROR, "Anchor does not match previously-added Sprout spends."); + } + } + + jsInputs.emplace_back(witness, note, sk); +} + +void TransactionBuilder::AddSproutOutput( + libzcash::SproutPaymentAddress to, + CAmount value, + std::array memo) +{ + if (sproutParams == nullptr) { + throw std::runtime_error("Cannot add Sprout outputs to a TransactionBuilder without Sprout params"); + } + + libzcash::JSOutput jsOutput(to, value); + jsOutput.memo = memo; + jsOutputs.push_back(jsOutput); +} + void TransactionBuilder::AddTransparentInput(COutPoint utxo, CScript scriptPubKey, CAmount value) { if (keystore == nullptr) { @@ -118,7 +161,15 @@ void TransactionBuilder::SetFee(CAmount fee) void TransactionBuilder::SendChangeTo(libzcash::SaplingPaymentAddress changeAddr, uint256 ovk) { - zChangeAddr = std::make_pair(ovk, changeAddr); + saplingChangeAddr = std::make_pair(ovk, changeAddr); + sproutChangeAddr = boost::none; + tChangeAddr = boost::none; +} + +void TransactionBuilder::SendChangeTo(libzcash::SproutPaymentAddress changeAddr) +{ + sproutChangeAddr = changeAddr; + saplingChangeAddr = boost::none; tChangeAddr = boost::none; } @@ -129,7 +180,8 @@ void TransactionBuilder::SendChangeTo(CTxDestination& changeAddr) } tChangeAddr = changeAddr; - zChangeAddr = boost::none; + saplingChangeAddr = boost::none; + sproutChangeAddr = boost::none; } TransactionBuilderResult TransactionBuilder::Build() @@ -140,6 +192,12 @@ TransactionBuilderResult TransactionBuilder::Build() // Valid change CAmount change = mtx.valueBalance - fee; + for (auto jsInput : jsInputs) { + change += jsInput.note.value(); + } + for (auto jsOutput : jsOutputs) { + change -= jsOutput.value; + } for (auto tIn : tIns) { change += tIn.value; } @@ -156,9 +214,12 @@ TransactionBuilderResult TransactionBuilder::Build() if (change > 0) { // Send change to the specified change address. If no change address - // was set, send change to the first Sapling address given as input. - if (zChangeAddr) { - AddSaplingOutput(zChangeAddr->first, zChangeAddr->second, change); + // was set, send change to the first Sapling address given as input, + // or the first Sprout address given as input. + if (saplingChangeAddr) { + AddSaplingOutput(saplingChangeAddr->first, saplingChangeAddr->second, change); + } else if (sproutChangeAddr) { + AddSproutOutput(sproutChangeAddr.get(), change); } else if (tChangeAddr) { // tChangeAddr has already been validated. AddTransparentOutput(tChangeAddr.value(), change); @@ -167,6 +228,9 @@ TransactionBuilderResult TransactionBuilder::Build() auto note = spends[0].note; libzcash::SaplingPaymentAddress changeAddr(note.d, note.pk_d); AddSaplingOutput(fvk.ovk, changeAddr, change); + } else if (!jsInputs.empty()) { + auto changeAddr = jsInputs[0].key.address(); + AddSproutOutput(changeAddr, change); } else { return TransactionBuilderResult("Could not determine change address"); } @@ -260,6 +324,22 @@ TransactionBuilderResult TransactionBuilder::Build() mtx.vShieldedOutput.push_back(odesc); } + // + // Sprout JoinSplits + // + + unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES]; + crypto_sign_keypair(mtx.joinSplitPubKey.begin(), joinSplitPrivKey); + + // Create Sprout JSDescriptions + if (!jsInputs.empty() || !jsOutputs.empty()) { + auto result = CreateJSDescriptions(); + if (result) { + librustzcash_sapling_proving_ctx_free(ctx); + return result.get(); + } + } + // // Signatures // @@ -292,6 +372,24 @@ TransactionBuilderResult TransactionBuilder::Build() librustzcash_sapling_proving_ctx_free(ctx); + // Create Sprout joinSplitSig + if (crypto_sign_detached( + mtx.joinSplitSig.data(), NULL, + dataToBeSigned.begin(), 32, + joinSplitPrivKey) != 0) + { + return TransactionBuilderResult("Failed to create Sprout joinSplitSig"); + } + + // Sanity check Sprout joinSplitSig + if (crypto_sign_verify_detached( + mtx.joinSplitSig.data(), + dataToBeSigned.begin(), 32, + mtx.joinSplitPubKey.begin()) != 0) + { + return TransactionBuilderResult("Sprout joinSplitSig sanity check failed"); + } + // Transparent signatures CTransaction txNewConst(mtx); for (int nIn = 0; nIn < mtx.vin.size(); nIn++) { @@ -311,3 +409,289 @@ TransactionBuilderResult TransactionBuilder::Build() return TransactionBuilderResult(CTransaction(mtx)); } + +boost::optional TransactionBuilder::CreateJSDescriptions() +{ + // Copy jsInputs and jsOutputs to more flexible containers + std::deque jsInputsDeque; + for (auto jsInput : jsInputs) { + jsInputsDeque.push_back(jsInput); + } + std::deque jsOutputsDeque; + for (auto jsOutput : jsOutputs) { + jsOutputsDeque.push_back(jsOutput); + } + + // If we have no Sprout shielded inputs, then we do the simpler more-leaky + // process where we just create outputs directly. We save the chaining logic, + // at the expense of leaking the sums of pairs of output values in vpub_old. + if (jsInputs.empty()) { + // Create joinsplits, where each output represents a zaddr recipient. + while (jsOutputsDeque.size() > 0) { + // Default array entries are dummy inputs and outputs + std::array vjsin; + std::array vjsout; + uint64_t vpub_old = 0; + + for (int n = 0; n < ZC_NUM_JS_OUTPUTS && jsOutputsDeque.size() > 0; n++) { + vjsout[n] = jsOutputsDeque.front(); + jsOutputsDeque.pop_front(); + + // Funds are removed from the value pool and enter the private pool + vpub_old += vjsout[n].value; + } + + std::array inputMap; + std::array outputMap; + CreateJSDescription(vpub_old, 0, vjsin, vjsout, inputMap, outputMap); + } + return boost::none; + } + + // At this point, we are guaranteed to have at least one input note. + // Use address of first input note as the temporary change address. + auto changeKey = jsInputsDeque.front().key; + auto changeAddress = changeKey.address(); + + CAmount jsChange = 0; // this is updated after each joinsplit + int changeOutputIndex = -1; // this is updated after each joinsplit if jsChange > 0 + bool vpubOldProcessed = false; // updated when vpub_old for taddr inputs is set in first joinsplit + bool vpubNewProcessed = false; // updated when vpub_new for miner fee and taddr outputs is set in last joinsplit + + CAmount valueOut = 0; + for (auto jsInput : jsInputs) { + valueOut += jsInput.note.value(); + } + for (auto jsOutput : jsOutputs) { + valueOut -= jsOutput.value; + } + CAmount vpubOldTarget = valueOut < 0 ? -valueOut : 0; + CAmount vpubNewTarget = valueOut > 0 ? valueOut : 0; + + // Keep track of treestate within this transaction + boost::unordered_map intermediates; + std::vector previousCommitments; + + while (!vpubNewProcessed) { + // Default array entries are dummy inputs and outputs + std::array vjsin; + std::array vjsout; + uint64_t vpub_old = 0; + uint64_t vpub_new = 0; + + // Set vpub_old in the first joinsplit + if (!vpubOldProcessed) { + vpub_old += vpubOldTarget; // funds flowing from public pool + vpubOldProcessed = true; + } + + CAmount jsInputValue = 0; + uint256 jsAnchor; + + JSDescription prevJoinSplit; + + // Keep track of previous JoinSplit and its commitments + if (mtx.vjoinsplit.size() > 0) { + prevJoinSplit = mtx.vjoinsplit.back(); + } + + // If there is no change, the chain has terminated so we can reset the tracked treestate. + if (jsChange == 0 && mtx.vjoinsplit.size() > 0) { + intermediates.clear(); + previousCommitments.clear(); + } + + // + // Consume change as the first input of the JoinSplit. + // + if (jsChange > 0) { + // Update tree state with previous joinsplit + SproutMerkleTree tree; + { + LOCK(cs_coinsView); + auto it = intermediates.find(prevJoinSplit.anchor); + if (it != intermediates.end()) { + tree = it->second; + } else if (!coinsView->GetSproutAnchorAt(prevJoinSplit.anchor, tree)) { + return TransactionBuilderResult("Could not find previous JoinSplit anchor"); + } + } + + assert(changeOutputIndex != -1); + assert(changeOutputIndex < prevJoinSplit.commitments.size()); + boost::optional changeWitness; + int n = 0; + for (const uint256& commitment : prevJoinSplit.commitments) { + tree.append(commitment); + previousCommitments.push_back(commitment); + if (!changeWitness && changeOutputIndex == n++) { + changeWitness = tree.witness(); + } else if (changeWitness) { + changeWitness.get().append(commitment); + } + } + assert(changeWitness.has_value()); + jsAnchor = tree.root(); + intermediates.insert(std::make_pair(tree.root(), tree)); // chained js are interstitial (found in between block boundaries) + + // Decrypt the change note's ciphertext to retrieve some data we need + ZCNoteDecryption decryptor(changeKey.receiving_key()); + auto hSig = prevJoinSplit.h_sig(*sproutParams, mtx.joinSplitPubKey); + try { + auto plaintext = libzcash::SproutNotePlaintext::decrypt( + decryptor, + prevJoinSplit.ciphertexts[changeOutputIndex], + prevJoinSplit.ephemeralKey, + hSig, + (unsigned char)changeOutputIndex); + + auto note = plaintext.note(changeAddress); + vjsin[0] = libzcash::JSInput(changeWitness.get(), note, changeKey); + + jsInputValue += plaintext.value(); + + LogPrint("zrpcunsafe", "spending change (amount=%s)\n", FormatMoney(plaintext.value())); + + } catch (const std::exception& e) { + return TransactionBuilderResult("Error decrypting output note of previous JoinSplit"); + } + } + + // + // Consume spendable non-change notes + // + for (int n = (jsChange > 0) ? 1 : 0; n < ZC_NUM_JS_INPUTS && jsInputsDeque.size() > 0; n++) { + auto jsInput = jsInputsDeque.front(); + jsInputsDeque.pop_front(); + + // Add history of previous commitments to witness + if (jsChange > 0) { + for (const uint256& commitment : previousCommitments) { + jsInput.witness.append(commitment); + } + if (jsAnchor != jsInput.witness.root()) { + return TransactionBuilderResult("Witness for spendable note does not have same anchor as change input"); + } + } + + // The jsAnchor is null if this JoinSplit is at the start of a new chain + if (jsAnchor.IsNull()) { + jsAnchor = jsInput.witness.root(); + } + + jsInputValue += jsInput.note.value(); + vjsin[n] = jsInput; + } + + // Find recipient to transfer funds to + libzcash::JSOutput recipient; + if (jsOutputsDeque.size() > 0) { + recipient = jsOutputsDeque.front(); + jsOutputsDeque.pop_front(); + } + // `recipient` is now either a valid recipient, or a dummy output with value = 0 + + // Reset change + jsChange = 0; + CAmount outAmount = recipient.value; + + // Set vpub_new in the last joinsplit (when there are no more notes to spend or zaddr outputs to satisfy) + if (jsOutputsDeque.empty() && jsInputsDeque.empty()) { + assert(!vpubNewProcessed); + if (jsInputValue < vpubNewTarget) { + return TransactionBuilderResult( + strprintf("Insufficient funds for vpub_new %s", FormatMoney(vpubNewTarget)) + ); + } + outAmount += vpubNewTarget; + vpub_new += vpubNewTarget; // funds flowing back to public pool + vpubNewProcessed = true; + jsChange = jsInputValue - outAmount; + assert(jsChange >= 0); + } else { + // This is not the last joinsplit, so compute change and any amount still due to the recipient + if (jsInputValue > outAmount) { + jsChange = jsInputValue - outAmount; + } else if (outAmount > jsInputValue) { + // Any amount due is owed to the recipient. Let the miners fee get paid first. + CAmount due = outAmount - jsInputValue; + libzcash::JSOutput recipientDue(recipient.addr, due); + recipientDue.memo = recipient.memo; + jsOutputsDeque.push_front(recipientDue); + + // reduce the amount being sent right now to the value of all inputs + recipient.value = jsInputValue; + } + } + + // create output for recipient + assert(ZC_NUM_JS_OUTPUTS == 2); // If this changes, the logic here will need to be adjusted + vjsout[0] = recipient; + + // create output for any change + if (jsChange > 0) { + vjsout[1] = libzcash::JSOutput(changeAddress, jsChange); + + LogPrint("zrpcunsafe", "generating note for change (amount=%s)\n", FormatMoney(jsChange)); + } + + std::array inputMap; + std::array outputMap; + CreateJSDescription(vpub_old, vpub_new, vjsin, vjsout, inputMap, outputMap); + + if (jsChange > 0) { + changeOutputIndex = -1; + for (size_t i = 0; i < outputMap.size(); i++) { + if (outputMap[i] == 1) { + changeOutputIndex = i; + } + } + assert(changeOutputIndex != -1); + } + } + + return boost::none; +} + +void TransactionBuilder::CreateJSDescription( + uint64_t vpub_old, + uint64_t vpub_new, + std::array vjsin, + std::array vjsout, + std::array& inputMap, + std::array& outputMap) +{ + LogPrint("zrpcunsafe", "%s: creating joinsplit at index %d (vpub_old=%s, vpub_new=%s, in[0]=%s, in[1]=%s, out[0]=%s, out[1]=%s)\n", + mtx.vjoinsplit.size(), + FormatMoney(vpub_old), FormatMoney(vpub_new), + FormatMoney(vjsin[0].note.value()), FormatMoney(vjsin[1].note.value()), + FormatMoney(vjsout[0].value), FormatMoney(vjsout[1].value)); + + uint256 esk; // payment disclosure - secret + + // Generate the proof, this can take over a minute. + JSDescription jsdesc = JSDescription::Randomized( + mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION), + *sproutParams, + mtx.joinSplitPubKey, + vjsin[0].witness.root(), + vjsin, + vjsout, + inputMap, + outputMap, + vpub_old, + vpub_new, + true, //!this->testmode, + &esk); // parameter expects pointer to esk, so pass in address + + { + auto verifier = libzcash::ProofVerifier::Strict(); + if (!jsdesc.Verify(*sproutParams, verifier, mtx.joinSplitPubKey)) { + throw std::runtime_error("error verifying joinsplit"); + } + } + + mtx.vjoinsplit.push_back(jsdesc); + + // TODO: Sprout payment disclosure +} diff --git a/src/transaction_builder.h b/src/transaction_builder.h index 592f4f64db2..43946f498ed 100644 --- a/src/transaction_builder.h +++ b/src/transaction_builder.h @@ -5,6 +5,7 @@ #ifndef TRANSACTION_BUILDER_H #define TRANSACTION_BUILDER_H +#include "coins.h" #include "consensus/params.h" #include "keystore.h" #include "primitives/transaction.h" @@ -13,6 +14,7 @@ #include "uint256.h" #include "zcash/Address.hpp" #include "zcash/IncrementalMerkleTree.hpp" +#include "zcash/JoinSplit.hpp" #include "zcash/Note.hpp" #include "zcash/NoteEncryption.hpp" @@ -72,19 +74,31 @@ class TransactionBuilder Consensus::Params consensusParams; int nHeight; const CKeyStore* keystore; + ZCJoinSplit* sproutParams; + const CCoinsViewCache* coinsView; + CCriticalSection* cs_coinsView; CMutableTransaction mtx; CAmount fee = 10000; std::vector spends; std::vector outputs; + std::vector jsInputs; + std::vector jsOutputs; std::vector tIns; - boost::optional> zChangeAddr; + boost::optional> saplingChangeAddr; + boost::optional sproutChangeAddr; boost::optional tChangeAddr; public: TransactionBuilder() {} - TransactionBuilder(const Consensus::Params& consensusParams, int nHeight, CKeyStore* keyStore = nullptr); + TransactionBuilder( + const Consensus::Params& consensusParams, + int nHeight, + CKeyStore* keyStore = nullptr, + ZCJoinSplit* sproutParams = nullptr, + CCoinsViewCache* coinsView = nullptr, + CCriticalSection* cs_coinsView = nullptr); void SetFee(CAmount fee); @@ -102,6 +116,18 @@ class TransactionBuilder CAmount value, std::array memo = {{0xF6}}); + // Throws if the anchor does not match the anchor used by + // previously-added Sprout inputs. + void AddSproutInput( + libzcash::SproutSpendingKey sk, + libzcash::SproutNote note, + SproutWitness witness); + + void AddSproutOutput( + libzcash::SproutPaymentAddress to, + CAmount value, + std::array memo = {{0xF6}}); + // Assumes that the value correctly corresponds to the provided UTXO. void AddTransparentInput(COutPoint utxo, CScript scriptPubKey, CAmount value); @@ -109,9 +135,22 @@ class TransactionBuilder void SendChangeTo(libzcash::SaplingPaymentAddress changeAddr, uint256 ovk); + void SendChangeTo(libzcash::SproutPaymentAddress); + void SendChangeTo(CTxDestination& changeAddr); TransactionBuilderResult Build(); + +private: + boost::optional CreateJSDescriptions(); + + void CreateJSDescription( + uint64_t vpub_old, + uint64_t vpub_new, + std::array vjsin, + std::array vjsout, + std::array& inputMap, + std::array& outputMap); }; #endif /* TRANSACTION_BUILDER_H */ From 9e8729113cc94a3f4cb6ad8472c329aa29c5becd Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Tue, 26 Feb 2019 15:09:55 -0700 Subject: [PATCH 002/395] Split test in to multiple parts --- src/gtest/test_transaction_builder.cpp | 212 +++++++++++++------------ 1 file changed, 114 insertions(+), 98 deletions(-) diff --git a/src/gtest/test_transaction_builder.cpp b/src/gtest/test_transaction_builder.cpp index f6aecb88f0b..6676ef21eec 100644 --- a/src/gtest/test_transaction_builder.cpp +++ b/src/gtest/test_transaction_builder.cpp @@ -73,7 +73,7 @@ class TransactionBuilderCoinsViewDB : public CCoinsView { } }; -TEST(TransactionBuilder, Invoke) +TEST(TransactionBuilder, TransparentToSapling) { auto consensusParams = RegtestActivateSapling(); @@ -91,106 +91,121 @@ TEST(TransactionBuilder, Invoke) libzcash::diversifier_t d = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; auto pk = *ivk.address(d); - auto sproutSk = libzcash::SproutSpendingKey::random(); - ZCNoteDecryption sproutDecryptor(sproutSk.receiving_key()); - auto sproutAddr = sproutSk.address(); - // Create a shielding transaction from transparent to Sapling // 0.0005 t-ZEC in, 0.0004 z-ZEC out, 0.0001 t-ZEC fee - auto builder1 = TransactionBuilder(consensusParams, 1, &keystore); - builder1.AddTransparentInput(COutPoint(), scriptPubKey, 50000); - builder1.AddSaplingOutput(fvk_from.ovk, pk, 40000, {}); - auto tx1 = builder1.Build().GetTxOrThrow(); - - EXPECT_EQ(tx1.vin.size(), 1); - EXPECT_EQ(tx1.vout.size(), 0); - EXPECT_EQ(tx1.vjoinsplit.size(), 0); - EXPECT_EQ(tx1.vShieldedSpend.size(), 0); - EXPECT_EQ(tx1.vShieldedOutput.size(), 1); - EXPECT_EQ(tx1.valueBalance, -40000); + auto builder = TransactionBuilder(consensusParams, 1, &keystore); + builder.AddTransparentInput(COutPoint(), scriptPubKey, 50000); + builder.AddSaplingOutput(fvk_from.ovk, pk, 40000, {}); + auto tx = builder.Build().GetTxOrThrow(); + + EXPECT_EQ(tx.vin.size(), 1); + EXPECT_EQ(tx.vout.size(), 0); + EXPECT_EQ(tx.vjoinsplit.size(), 0); + EXPECT_EQ(tx.vShieldedSpend.size(), 0); + EXPECT_EQ(tx.vShieldedOutput.size(), 1); + EXPECT_EQ(tx.valueBalance, -40000); CValidationState state; - EXPECT_TRUE(ContextualCheckTransaction(tx1, state, 2, 0)); + EXPECT_TRUE(ContextualCheckTransaction(tx, state, 2, 0)); EXPECT_EQ(state.GetRejectReason(), ""); - // Prepare to spend the note that was just created - auto maybe_pt = libzcash::SaplingNotePlaintext::decrypt( - tx1.vShieldedOutput[0].encCiphertext, ivk, tx1.vShieldedOutput[0].ephemeralKey, tx1.vShieldedOutput[0].cm); - ASSERT_EQ(static_cast(maybe_pt), true); - auto maybe_note = maybe_pt.get().note(ivk); - ASSERT_EQ(static_cast(maybe_note), true); - auto note = maybe_note.get(); - SaplingMerkleTree tree; - tree.append(tx1.vShieldedOutput[0].cm); - auto anchor = tree.root(); - auto witness = tree.witness(); + // Revert to default + RegtestDeactivateSapling(); +} + +TEST(TransactionBuilder, SaplingToSapling) { + auto consensusParams = RegtestActivateSapling(); + + auto sk = libzcash::SaplingSpendingKey::random(); + auto expsk = sk.expanded_spending_key(); + auto fvk = sk.full_viewing_key(); + auto pa = sk.default_address(); + auto testNote = GetTestSaplingNote(pa, 40000); + // Create a Sapling-only transaction // 0.0004 z-ZEC in, 0.00025 z-ZEC out, 0.0001 t-ZEC fee, 0.00005 z-ZEC change - auto builder2 = TransactionBuilder(consensusParams, 2); - builder2.AddSaplingSpend(expsk, note, anchor, witness); + auto builder = TransactionBuilder(consensusParams, 2); + builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); + // Check that trying to add a different anchor fails // TODO: the following check can be split out in to another test - ASSERT_THROW(builder2.AddSaplingSpend(expsk, note, uint256(), witness), UniValue); + ASSERT_THROW(builder.AddSaplingSpend(expsk, testNote.note, uint256(), testNote.tree.witness()), UniValue); - builder2.AddSaplingOutput(fvk.ovk, pk, 25000, {}); - auto tx2 = builder2.Build().GetTxOrThrow(); + builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); + auto tx = builder.Build().GetTxOrThrow(); - EXPECT_EQ(tx2.vin.size(), 0); - EXPECT_EQ(tx2.vout.size(), 0); - EXPECT_EQ(tx2.vjoinsplit.size(), 0); - EXPECT_EQ(tx2.vShieldedSpend.size(), 1); - EXPECT_EQ(tx2.vShieldedOutput.size(), 2); - EXPECT_EQ(tx2.valueBalance, 10000); + EXPECT_EQ(tx.vin.size(), 0); + EXPECT_EQ(tx.vout.size(), 0); + EXPECT_EQ(tx.vjoinsplit.size(), 0); + EXPECT_EQ(tx.vShieldedSpend.size(), 1); + EXPECT_EQ(tx.vShieldedOutput.size(), 2); + EXPECT_EQ(tx.valueBalance, 10000); - EXPECT_TRUE(ContextualCheckTransaction(tx2, state, 3, 0)); + CValidationState state; + EXPECT_TRUE(ContextualCheckTransaction(tx, state, 3, 0)); EXPECT_EQ(state.GetRejectReason(), ""); + // Revert to default + RegtestDeactivateSapling(); +} + +TEST(TransactionBuilder, SaplingToSprout) { + auto consensusParams = RegtestActivateSapling(); + + auto sk = libzcash::SaplingSpendingKey::random(); + auto expsk = sk.expanded_spending_key(); + auto pa = sk.default_address(); + + auto testNote = GetTestSaplingNote(pa, 40000); + + auto sproutSk = libzcash::SproutSpendingKey::random(); + auto sproutAddr = sproutSk.address(); + // Create a Sapling-to-Sprout transaction (reusing the note from above) // - 0.0004 Sapling-ZEC in - 0.00025 Sprout-ZEC out // - 0.00005 Sapling-ZEC change // - 0.0001 t-ZEC fee - auto builder3 = TransactionBuilder(consensusParams, 2, nullptr, params); - builder3.AddSaplingSpend(expsk, note, anchor, witness); - builder3.AddSproutOutput(sproutAddr, 25000); - auto tx3 = builder3.Build().GetTxOrThrow(); - - EXPECT_EQ(tx3.vin.size(), 0); - EXPECT_EQ(tx3.vout.size(), 0); - EXPECT_EQ(tx3.vjoinsplit.size(), 1); - EXPECT_EQ(tx3.vjoinsplit[0].vpub_old, 25000); - EXPECT_EQ(tx3.vjoinsplit[0].vpub_new, 0); - EXPECT_EQ(tx3.vShieldedSpend.size(), 1); - EXPECT_EQ(tx3.vShieldedOutput.size(), 1); - EXPECT_EQ(tx3.valueBalance, 35000); - - EXPECT_TRUE(ContextualCheckTransaction(tx3, state, 3, 0)); + auto builder = TransactionBuilder(consensusParams, 2, nullptr, params); + builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); + builder.AddSproutOutput(sproutAddr, 25000); + auto tx = builder.Build().GetTxOrThrow(); + + EXPECT_EQ(tx.vin.size(), 0); + EXPECT_EQ(tx.vout.size(), 0); + EXPECT_EQ(tx.vjoinsplit.size(), 1); + EXPECT_EQ(tx.vjoinsplit[0].vpub_old, 25000); + EXPECT_EQ(tx.vjoinsplit[0].vpub_new, 0); + EXPECT_EQ(tx.vShieldedSpend.size(), 1); + EXPECT_EQ(tx.vShieldedOutput.size(), 1); + EXPECT_EQ(tx.valueBalance, 35000); + + CValidationState state; + EXPECT_TRUE(ContextualCheckTransaction(tx, state, 3, 0)); EXPECT_EQ(state.GetRejectReason(), ""); - // Prepare to spend the Sprout note that was just created + // Revert to default + RegtestDeactivateSapling(); +} + +TEST(TransactionBuilder, SproutToSproutAndSapling) { + auto consensusParams = RegtestActivateSapling(); + + auto sk = libzcash::SaplingSpendingKey::random(); + auto fvk = sk.full_viewing_key(); + auto pa = sk.default_address(); + + auto sproutSk = libzcash::SproutSpendingKey::random(); + auto sproutAddr = sproutSk.address(); + + auto wtx = GetValidSproutReceive(*params, sproutSk, 25000, true); + auto sproutNote = GetSproutNote(*params, sproutSk, wtx, 0, 1); + SproutMerkleTree sproutTree; - libzcash::SproutNote sproutNote; - SproutWitness sproutWitness; for (int i = 0; i < ZC_NUM_JS_OUTPUTS; i++) { - sproutTree.append(tx3.vjoinsplit[0].commitments[i]); - - auto hSig = tx3.vjoinsplit[0].h_sig(*params, tx3.joinSplitPubKey); - try { - auto pt = libzcash::SproutNotePlaintext::decrypt( - sproutDecryptor, - tx3.vjoinsplit[0].ciphertexts[i], - tx3.vjoinsplit[0].ephemeralKey, - hSig, - (unsigned char)i); - sproutNote = pt.note(sproutAddr); - sproutWitness = sproutTree.witness(); - break; - } catch (const std::exception& e) { - // One of the outputs must be ours - assert(i + 1 < ZC_NUM_JS_OUTPUTS); - } + sproutTree.append(wtx.vjoinsplit[0].commitments[i]); } - + SproutWitness sproutWitness = sproutTree.witness(); // Fake a view with the Sprout note in it auto rt = sproutTree.root(); TransactionBuilderCoinsViewDB fakeDB; @@ -203,30 +218,31 @@ TEST(TransactionBuilder, Invoke) // - 0.00005 Sprout-ZEC change // - 0.00005 Sapling-ZEC out // - 0.00005 t-ZEC fee - auto builder4 = TransactionBuilder(consensusParams, 2, nullptr, params, &view); - builder4.SetFee(5000); - builder4.AddSproutInput(sproutSk, sproutNote, sproutWitness); - builder4.AddSproutOutput(sproutAddr, 6000); - builder4.AddSproutOutput(sproutAddr, 4000); - builder4.AddSaplingOutput(fvk.ovk, pk, 5000); - auto tx4 = builder4.Build().GetTxOrThrow(); - - EXPECT_EQ(tx4.vin.size(), 0); - EXPECT_EQ(tx4.vout.size(), 0); + auto builder = TransactionBuilder(consensusParams, 2, nullptr, params, &view); + builder.SetFee(5000); + builder.AddSproutInput(sproutSk, sproutNote, sproutWitness); + builder.AddSproutOutput(sproutAddr, 6000); + builder.AddSproutOutput(sproutAddr, 4000); + builder.AddSaplingOutput(fvk.ovk, pa, 5000); + auto tx = builder.Build().GetTxOrThrow(); + + EXPECT_EQ(tx.vin.size(), 0); + EXPECT_EQ(tx.vout.size(), 0); // TODO: This should be doable in two JoinSplits. // There's an inefficiency in the implementation. - EXPECT_EQ(tx4.vjoinsplit.size(), 3); - EXPECT_EQ(tx4.vjoinsplit[0].vpub_old, 0); - EXPECT_EQ(tx4.vjoinsplit[0].vpub_new, 0); - EXPECT_EQ(tx4.vjoinsplit[1].vpub_old, 0); - EXPECT_EQ(tx4.vjoinsplit[1].vpub_new, 0); - EXPECT_EQ(tx4.vjoinsplit[2].vpub_old, 0); - EXPECT_EQ(tx4.vjoinsplit[2].vpub_new, 10000); - EXPECT_EQ(tx4.vShieldedSpend.size(), 0); - EXPECT_EQ(tx4.vShieldedOutput.size(), 1); - EXPECT_EQ(tx4.valueBalance, -5000); - - EXPECT_TRUE(ContextualCheckTransaction(tx4, state, 4, 0)); + EXPECT_EQ(tx.vjoinsplit.size(), 3); + EXPECT_EQ(tx.vjoinsplit[0].vpub_old, 0); + EXPECT_EQ(tx.vjoinsplit[0].vpub_new, 0); + EXPECT_EQ(tx.vjoinsplit[1].vpub_old, 0); + EXPECT_EQ(tx.vjoinsplit[1].vpub_new, 0); + EXPECT_EQ(tx.vjoinsplit[2].vpub_old, 0); + EXPECT_EQ(tx.vjoinsplit[2].vpub_new, 10000); + EXPECT_EQ(tx.vShieldedSpend.size(), 0); + EXPECT_EQ(tx.vShieldedOutput.size(), 1); + EXPECT_EQ(tx.valueBalance, -5000); + + CValidationState state; + EXPECT_TRUE(ContextualCheckTransaction(tx, state, 4, 0)); EXPECT_EQ(state.GetRejectReason(), ""); // Revert to default From 6281cc32b7ed349ad2de9be4584406ef05171e8e Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Thu, 28 Feb 2019 11:19:36 -0700 Subject: [PATCH 003/395] Use a custom error type if creating joinsplit descriptions fails --- src/transaction_builder.cpp | 37 ++++++++++++++++++++++++------------- src/transaction_builder.h | 2 +- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/transaction_builder.cpp b/src/transaction_builder.cpp index d8743cee4e0..a2e515834d4 100644 --- a/src/transaction_builder.cpp +++ b/src/transaction_builder.cpp @@ -64,6 +64,17 @@ TransactionBuilder::TransactionBuilder( mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight); } +// This exception is thrown in certain scenarios when building JoinSplits fails. +struct JSDException : public std::exception +{ + JSDException (const std::string msg_) : msg(msg_) {} + + const char* what() { return msg.c_str(); } + +private: + std::string msg; +}; + void TransactionBuilder::AddSaplingSpend( libzcash::SaplingExpandedSpendingKey expsk, libzcash::SaplingNote note, @@ -333,10 +344,14 @@ TransactionBuilderResult TransactionBuilder::Build() // Create Sprout JSDescriptions if (!jsInputs.empty() || !jsOutputs.empty()) { - auto result = CreateJSDescriptions(); - if (result) { + try { + CreateJSDescriptions(); + } catch (JSDException e) { + librustzcash_sapling_proving_ctx_free(ctx); + return TransactionBuilderResult(e.what()); + } catch (std::runtime_error e) { librustzcash_sapling_proving_ctx_free(ctx); - return result.get(); + throw e; } } @@ -410,7 +425,7 @@ TransactionBuilderResult TransactionBuilder::Build() return TransactionBuilderResult(CTransaction(mtx)); } -boost::optional TransactionBuilder::CreateJSDescriptions() +void TransactionBuilder::CreateJSDescriptions() { // Copy jsInputs and jsOutputs to more flexible containers std::deque jsInputsDeque; @@ -445,7 +460,7 @@ boost::optional TransactionBuilder::CreateJSDescriptio std::array outputMap; CreateJSDescription(vpub_old, 0, vjsin, vjsout, inputMap, outputMap); } - return boost::none; + return; } // At this point, we are guaranteed to have at least one input note. @@ -513,7 +528,7 @@ boost::optional TransactionBuilder::CreateJSDescriptio if (it != intermediates.end()) { tree = it->second; } else if (!coinsView->GetSproutAnchorAt(prevJoinSplit.anchor, tree)) { - return TransactionBuilderResult("Could not find previous JoinSplit anchor"); + throw JSDException("Could not find previous JoinSplit anchor"); } } @@ -553,7 +568,7 @@ boost::optional TransactionBuilder::CreateJSDescriptio LogPrint("zrpcunsafe", "spending change (amount=%s)\n", FormatMoney(plaintext.value())); } catch (const std::exception& e) { - return TransactionBuilderResult("Error decrypting output note of previous JoinSplit"); + throw JSDException("Error decrypting output note of previous JoinSplit"); } } @@ -570,7 +585,7 @@ boost::optional TransactionBuilder::CreateJSDescriptio jsInput.witness.append(commitment); } if (jsAnchor != jsInput.witness.root()) { - return TransactionBuilderResult("Witness for spendable note does not have same anchor as change input"); + throw JSDException("Witness for spendable note does not have same anchor as change input"); } } @@ -599,9 +614,7 @@ boost::optional TransactionBuilder::CreateJSDescriptio if (jsOutputsDeque.empty() && jsInputsDeque.empty()) { assert(!vpubNewProcessed); if (jsInputValue < vpubNewTarget) { - return TransactionBuilderResult( - strprintf("Insufficient funds for vpub_new %s", FormatMoney(vpubNewTarget)) - ); + throw JSDException(strprintf("Insufficient funds for vpub_new %s", FormatMoney(vpubNewTarget))); } outAmount += vpubNewTarget; vpub_new += vpubNewTarget; // funds flowing back to public pool @@ -649,8 +662,6 @@ boost::optional TransactionBuilder::CreateJSDescriptio assert(changeOutputIndex != -1); } } - - return boost::none; } void TransactionBuilder::CreateJSDescription( diff --git a/src/transaction_builder.h b/src/transaction_builder.h index 43946f498ed..ee3c4e7ae45 100644 --- a/src/transaction_builder.h +++ b/src/transaction_builder.h @@ -142,7 +142,7 @@ class TransactionBuilder TransactionBuilderResult Build(); private: - boost::optional CreateJSDescriptions(); + void CreateJSDescriptions(); void CreateJSDescription( uint64_t vpub_old, From 74de4ddc465d76e58cef98a38168aa20d4312f8d Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sun, 24 Jun 2018 16:03:43 -0400 Subject: [PATCH 004/395] depends: Use full path to cargo binary The native binaries generated in the depends system are available on the path, but system binaries are still visible. This change ensures we use cargo from the depends system rather than whatever might be installed locally. --- depends/packages/librustzcash.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/depends/packages/librustzcash.mk b/depends/packages/librustzcash.mk index a47c757de80..0d2fc3dd24b 100644 --- a/depends/packages/librustzcash.mk +++ b/depends/packages/librustzcash.mk @@ -27,7 +27,7 @@ define $(package)_preprocess_cmds endef define $(package)_build_cmds - cargo build --package librustzcash $($(package)_build_opts) + $(host_prefix)/native/bin/cargo build --package librustzcash $($(package)_build_opts) endef define $(package)_stage_cmds From d7ab9545116f4cf20ba9c803d8a253f639d83546 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 25 Jun 2018 13:43:46 -0400 Subject: [PATCH 005/395] depends: Generalise the rust package cross-compilation functions --- depends/funcs.mk | 4 ++-- depends/packages/librustzcash.mk | 8 +++++++- depends/packages/rust.mk | 22 +++++++++++++++------- depends/patches/librustzcash/cargo.config | 3 --- 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/depends/funcs.mk b/depends/funcs.mk index 3d89de8a703..f17b246a4c8 100644 --- a/depends/funcs.mk +++ b/depends/funcs.mk @@ -59,8 +59,8 @@ $(eval $(1)_build_id:=$(shell echo -n "$($(1)_build_id_long)" | $(build_SHA256SU final_build_id_long+=$($(package)_build_id_long) #override platform specific files and hashes -$(eval $(1)_file_name=$(if $($(1)_file_name_$(host_os)),$($(1)_file_name_$(host_os)),$($(1)_file_name))) -$(eval $(1)_sha256_hash=$(if $($(1)_sha256_hash_$(host_os)),$($(1)_sha256_hash_$(host_os)),$($(1)_sha256_hash))) +$(eval $(1)_file_name=$(if $($(1)_exact_file_name),$($(1)_exact_file_name),$(if $($(1)_file_name_$(host_os)),$($(1)_file_name_$(host_os)),$($(1)_file_name)))) +$(eval $(1)_sha256_hash=$(if $($(1)_exact_sha256_hash),$($(1)_exact_sha256_hash),$(if $($(1)_sha256_hash_$(host_os)),$($(1)_sha256_hash_$(host_os)),$($(1)_sha256_hash)))) #compute package-specific paths $(1)_build_subdir?=. diff --git a/depends/packages/librustzcash.mk b/depends/packages/librustzcash.mk index 0d2fc3dd24b..9bc8ee543ec 100644 --- a/depends/packages/librustzcash.mk +++ b/depends/packages/librustzcash.mk @@ -8,15 +8,21 @@ $(package)_git_commit=06da3b9ac8f278e5d4ae13088cf0a4c03d2c13f5 $(package)_dependencies=rust $(rust_crates) $(package)_patches=cargo.config 0001-Start-using-cargo-clippy-for-CI.patch remove-dev-dependencies.diff +$(package)_rust_target=$(if $(rust_rust_target_$(canonical_host)),$(rust_rust_target_$(canonical_host)),$(canonical_host)) + ifeq ($(host_os),mingw32) $(package)_library_file=target/x86_64-pc-windows-gnu/release/rustzcash.lib +else ifneq ($(canonical_host),$(build)) +$(package)_library_file=target/$($(package)_rust_target)/release/librustzcash.a else $(package)_library_file=target/release/librustzcash.a endif define $(package)_set_vars $(package)_build_opts=--frozen --release -$(package)_build_opts_mingw32=--target=x86_64-pc-windows-gnu +ifneq ($(canonical_host),$(build)) +$(package)_build_opts+=--target=$($(package)_rust_target) +endif endef define $(package)_preprocess_cmds diff --git a/depends/packages/rust.mk b/depends/packages/rust.mk index 18d5b131647..b8227ff93aa 100644 --- a/depends/packages/rust.mk +++ b/depends/packages/rust.mk @@ -5,12 +5,20 @@ $(package)_file_name_linux=rust-$($(package)_version)-x86_64-unknown-linux-gnu.t $(package)_sha256_hash_linux=e024698320d76b74daf0e6e71be3681a1e7923122e3ebd03673fcac3ecc23810 $(package)_file_name_darwin=rust-$($(package)_version)-x86_64-apple-darwin.tar.gz $(package)_sha256_hash_darwin=f0dfba507192f9b5c330b5984ba71d57d434475f3d62bd44a39201e36fa76304 -$(package)_file_name_mingw32=rust-$($(package)_version)-x86_64-pc-windows-gnu.tar.gz -$(package)_sha256_hash_mingw32=358e1435347c67dbf33aa9cad6fe501a833d6633ed5d5aa1863d5dffa0349be9 -ifeq ($(host_os),mingw32) +# Mapping from GCC canonical hosts to Rust targets +# If a mapping is not present, we assume they are identical +$(package)_rust_target_x86_64-w64-mingw32=x86_64-pc-windows-gnu + +# Mapping from Rust targets to SHA-256 hashes +$(package)_rust_std_sha256_hash_x86_64-pc-windows-gnu=cad5f1454d591c13eeb3657f1c9dbfeb30e648f59680bd0765b94c63e7afc49e + +ifneq ($(canonical_host),$(build)) +$(package)_rust_target=$(if $($(package)_rust_target_$(canonical_host)),$($(package)_rust_target_$(canonical_host)),$(canonical_host)) +$(package)_exact_file_name=rust-std-$($(package)_version)-$($(package)_rust_target).tar.gz +$(package)_exact_sha256_hash=$($(package)_rust_std_sha256_hash_$($(package)_rust_target)) $(package)_build_subdir=buildos -$(package)_extra_sources = $($(package)_file_name_$(build_os)) +$(package)_extra_sources=$($(package)_file_name_$(build_os)) define $(package)_fetch_cmds $(call fetch_file,$(package),$($(package)_download_path),$($(package)_download_file),$($(package)_file_name),$($(package)_sha256_hash)) && \ @@ -22,15 +30,15 @@ define $(package)_extract_cmds echo "$($(package)_sha256_hash) $($(package)_source)" > $($(package)_extract_dir)/.$($(package)_file_name).hash && \ echo "$($(package)_sha256_hash_$(build_os)) $($(package)_source_dir)/$($(package)_file_name_$(build_os))" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \ $(build_SHA256SUM) -c $($(package)_extract_dir)/.$($(package)_file_name).hash && \ - mkdir mingw32 && \ - tar --strip-components=1 -xf $($(package)_source) -C mingw32 && \ + mkdir $(canonical_host) && \ + tar --strip-components=1 -xf $($(package)_source) -C $(canonical_host) && \ mkdir buildos && \ tar --strip-components=1 -xf $($(package)_source_dir)/$($(package)_file_name_$(build_os)) -C buildos endef define $(package)_stage_cmds ./install.sh --destdir=$($(package)_staging_dir) --prefix=$(host_prefix)/native --disable-ldconfig && \ - cp -r ../mingw32/rust-std-x86_64-pc-windows-gnu/lib/rustlib/x86_64-pc-windows-gnu $($(package)_staging_dir)$(host_prefix)/native/lib/rustlib + ../$(canonical_host)/install.sh --destdir=$($(package)_staging_dir) --prefix=$(host_prefix)/native --disable-ldconfig endef else diff --git a/depends/patches/librustzcash/cargo.config b/depends/patches/librustzcash/cargo.config index a0252d1c681..84d447afb62 100644 --- a/depends/patches/librustzcash/cargo.config +++ b/depends/patches/librustzcash/cargo.config @@ -18,6 +18,3 @@ replace-with = "vendored-sources" [source.vendored-sources] directory = "CRATE_REGISTRY" - -[target.x86_64-pc-windows-gnu] -linker = "x86_64-w64-mingw32-gcc" From d2cd57c0f27c68485be3d311b08992bf9158d1e2 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 25 Jun 2018 14:12:44 -0400 Subject: [PATCH 006/395] depends: Add rust-std hash for aarch64-unknown-linux-gnu Usage on Debian / Ubuntu: > $ sudo apt install g++-aarch64-linux-gnu > $ HOST=aarch64-linux-gnu ./zcutil/build.sh Currently fails to cross-compile due to later configuration issues in the depends system that need to be worked around. --- depends/packages/rust.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/depends/packages/rust.mk b/depends/packages/rust.mk index b8227ff93aa..b892d8b7265 100644 --- a/depends/packages/rust.mk +++ b/depends/packages/rust.mk @@ -11,6 +11,7 @@ $(package)_sha256_hash_darwin=f0dfba507192f9b5c330b5984ba71d57d434475f3d62bd44a3 $(package)_rust_target_x86_64-w64-mingw32=x86_64-pc-windows-gnu # Mapping from Rust targets to SHA-256 hashes +$(package)_rust_std_sha256_hash_aarch64-unknown-linux-gnu=346efe3aef2aff7b71a611bf7661bcec5f9bc4025a599c2866ec5fd330247cb9 $(package)_rust_std_sha256_hash_x86_64-pc-windows-gnu=cad5f1454d591c13eeb3657f1c9dbfeb30e648f59680bd0765b94c63e7afc49e ifneq ($(canonical_host),$(build)) From 56df83d710ad1aa6c90460cdf81a346adb0d19a7 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 13 Mar 2019 06:39:12 +0000 Subject: [PATCH 007/395] depends: Compile bdb with --disable-atomics on aarch64 This sidesteps the problem where the atomics check tries to run a test binary, which cannot be performed during cross compilation. We should replace this with a better solution in future. Part of #3710. --- depends/packages/bdb.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/depends/packages/bdb.mk b/depends/packages/bdb.mk index 6b385f2ab59..21019aeb71f 100644 --- a/depends/packages/bdb.mk +++ b/depends/packages/bdb.mk @@ -9,6 +9,7 @@ define $(package)_set_vars $(package)_config_opts=--disable-shared --enable-cxx --disable-replication $(package)_config_opts_mingw32=--enable-mingw $(package)_config_opts_linux=--with-pic +$(package)_config_opts_aarch64=--disable-atomicsupport $(package)_cxxflags=-std=c++11 endef From b1ef5eaef923b74e1055682ca97af5a4f1d3faef Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 13 Mar 2019 06:41:23 +0000 Subject: [PATCH 008/395] depends: Update .gitignore --- depends/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/depends/.gitignore b/depends/.gitignore index 1f163897b9e..3cb4b9ac155 100644 --- a/depends/.gitignore +++ b/depends/.gitignore @@ -7,3 +7,4 @@ x86_64* i686* mips* arm* +aarch64* From 98cfe4228c376b9224f8f72085a4fcb2cdca9cc4 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 13 Mar 2019 07:34:31 +0000 Subject: [PATCH 009/395] configure: Guess -march for libsnark OPTFLAGS instead of hard-coding When cross-compiling, this will remove the -march flag entirely unless the user specifies CONFIGURE_FLAGS="--with-gcc-arch=". --- build-aux/m4/ax_compiler_vendor.m4 | 117 +++++++++++++ build-aux/m4/ax_gcc_archflag.m4 | 267 +++++++++++++++++++++++++++++ build-aux/m4/ax_gcc_x86_cpuid.m4 | 89 ++++++++++ configure.ac | 4 + src/Makefile.am | 4 +- 5 files changed, 479 insertions(+), 2 deletions(-) create mode 100644 build-aux/m4/ax_compiler_vendor.m4 create mode 100644 build-aux/m4/ax_gcc_archflag.m4 create mode 100644 build-aux/m4/ax_gcc_x86_cpuid.m4 diff --git a/build-aux/m4/ax_compiler_vendor.m4 b/build-aux/m4/ax_compiler_vendor.m4 new file mode 100644 index 00000000000..f06e865405c --- /dev/null +++ b/build-aux/m4/ax_compiler_vendor.m4 @@ -0,0 +1,117 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_compiler_vendor.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_COMPILER_VENDOR +# +# DESCRIPTION +# +# Determine the vendor of the C, C++ or Fortran compiler. The vendor is +# returned in the cache variable $ax_cv_c_compiler_vendor for C, +# $ax_cv_cxx_compiler_vendor for C++ or $ax_cv_fc_compiler_vendor for +# (modern) Fortran. The value is one of "intel", "ibm", "pathscale", +# "clang" (LLVM), "cray", "fujitsu", "sdcc", "sx", "portland" (PGI), "gnu" +# (GCC), "sun" (Oracle Developer Studio), "hp", "dec", "borland", +# "comeau", "kai", "lcc", "sgi", "microsoft", "metrowerks", "watcom", +# "tcc" (Tiny CC) or "unknown" (if the compiler cannot be determined). +# +# To check for a Fortran compiler, you must first call AC_FC_PP_SRCEXT +# with an appropriate preprocessor-enabled extension. For example: +# +# AC_LANG_PUSH([Fortran]) +# AC_PROG_FC +# AC_FC_PP_SRCEXT([F]) +# AX_COMPILER_VENDOR +# AC_LANG_POP([Fortran]) +# +# LICENSE +# +# Copyright (c) 2008 Steven G. Johnson +# Copyright (c) 2008 Matteo Frigo +# Copyright (c) 2018-19 John Zaitseff +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 30 + +AC_DEFUN([AX_COMPILER_VENDOR], [dnl + AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, [dnl + dnl If you modify this list of vendors, please add similar support + dnl to ax_compiler_version.m4 if at all possible. + dnl + dnl Note: Do NOT check for GCC first since some other compilers + dnl define __GNUC__ to remain compatible with it. Compilers that + dnl are very slow to start (such as Intel) are listed first. + + vendors=" + intel: __ICC,__ECC,__INTEL_COMPILER + ibm: __xlc__,__xlC__,__IBMC__,__IBMCPP__,__ibmxl__ + pathscale: __PATHCC__,__PATHSCALE__ + clang: __clang__ + cray: _CRAYC + fujitsu: __FUJITSU + sdcc: SDCC,__SDCC + sx: _SX + portland: __PGI + gnu: __GNUC__ + sun: __SUNPRO_C,__SUNPRO_CC,__SUNPRO_F90,__SUNPRO_F95 + hp: __HP_cc,__HP_aCC + dec: __DECC,__DECCXX,__DECC_VER,__DECCXX_VER + borland: __BORLANDC__,__CODEGEARC__,__TURBOC__ + comeau: __COMO__ + kai: __KCC + lcc: __LCC__ + sgi: __sgi,sgi + microsoft: _MSC_VER + metrowerks: __MWERKS__ + watcom: __WATCOMC__ + tcc: __TINYC__ + unknown: UNKNOWN + " + for ventest in $vendors; do + case $ventest in + *:) + vendor=$ventest + continue + ;; + *) + vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")" + ;; + esac + + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [[ +#if !($vencpp) + thisisanerror; +#endif + ]])], [break]) + done + + ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=`echo $vendor | cut -d: -f1` + ]) +])dnl diff --git a/build-aux/m4/ax_gcc_archflag.m4 b/build-aux/m4/ax_gcc_archflag.m4 new file mode 100644 index 00000000000..c52b9b296e9 --- /dev/null +++ b/build-aux/m4/ax_gcc_archflag.m4 @@ -0,0 +1,267 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_gcc_archflag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_GCC_ARCHFLAG([PORTABLE?], [ACTION-SUCCESS], [ACTION-FAILURE]) +# +# DESCRIPTION +# +# This macro tries to guess the "native" arch corresponding to the target +# architecture for use with gcc's -march=arch or -mtune=arch flags. If +# found, the cache variable $ax_cv_gcc_archflag is set to this flag and +# ACTION-SUCCESS is executed; otherwise $ax_cv_gcc_archflag is set to +# "unknown" and ACTION-FAILURE is executed. The default ACTION-SUCCESS is +# to add $ax_cv_gcc_archflag to the end of $CFLAGS. +# +# PORTABLE? should be either [yes] (default) or [no]. In the former case, +# the flag is set to -mtune (or equivalent) so that the architecture is +# only used for tuning, but the instruction set used is still portable. In +# the latter case, the flag is set to -march (or equivalent) so that +# architecture-specific instructions are enabled. +# +# The user can specify --with-gcc-arch= in order to override the +# macro's choice of architecture, or --without-gcc-arch to disable this. +# +# When cross-compiling, or if $CC is not gcc, then ACTION-FAILURE is +# called unless the user specified --with-gcc-arch manually. +# +# Requires macros: AX_CHECK_COMPILE_FLAG, AX_GCC_X86_CPUID +# +# (The main emphasis here is on recent CPUs, on the principle that doing +# high-performance computing on old hardware is uncommon.) +# +# LICENSE +# +# Copyright (c) 2008 Steven G. Johnson +# Copyright (c) 2008 Matteo Frigo +# Copyright (c) 2014 Tsukasa Oi +# Copyright (c) 2017-2018 Alexey Kopytov +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 22 + +AC_DEFUN([AX_GCC_ARCHFLAG], +[AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_SED]) +AC_REQUIRE([AX_COMPILER_VENDOR]) + +AC_ARG_WITH(gcc-arch, [AS_HELP_STRING([--with-gcc-arch=], [use architecture for gcc -march/-mtune, instead of guessing])], + ax_gcc_arch=$withval, ax_gcc_arch=yes) + +AC_MSG_CHECKING([for gcc architecture flag]) +AC_MSG_RESULT([]) +AC_CACHE_VAL(ax_cv_gcc_archflag, +[ +ax_cv_gcc_archflag="unknown" + +if test "$GCC" = yes; then + +if test "x$ax_gcc_arch" = xyes; then +ax_gcc_arch="" +if test "$cross_compiling" = no; then +case $host_cpu in + i[[3456]]86*|x86_64*|amd64*) # use cpuid codes + AX_GCC_X86_CPUID(0) + AX_GCC_X86_CPUID(1) + case $ax_cv_gcc_x86_cpuid_0 in + *:756e6547:6c65746e:49656e69) # Intel + case $ax_cv_gcc_x86_cpuid_1 in + *5[[4578]]?:*:*:*) ax_gcc_arch="pentium-mmx pentium" ;; + *5[[123]]?:*:*:*) ax_gcc_arch=pentium ;; + *0?61?:*:*:*|?61?:*:*:*|61?:*:*:*) ax_gcc_arch=pentiumpro ;; + *0?6[[356]]?:*:*:*|?6[[356]]?:*:*:*|6[[356]]?:*:*:*) ax_gcc_arch="pentium2 pentiumpro" ;; + *0?6[[78ab]]?:*:*:*|?6[[78ab]]?:*:*:*|6[[78ab]]?:*:*:*) ax_gcc_arch="pentium3 pentiumpro" ;; + *0?6[[9d]]?:*:*:*|?6[[9d]]?:*:*:*|6[[9d]]?:*:*:*|*1?65?:*:*:*) ax_gcc_arch="pentium-m pentium3 pentiumpro" ;; + *0?6e?:*:*:*|?6e?:*:*:*|6e?:*:*:*) ax_gcc_arch="yonah pentium-m pentium3 pentiumpro" ;; + *0?6f?:*:*:*|?6f?:*:*:*|6f?:*:*:*|*1?66?:*:*:*) ax_gcc_arch="core2 pentium-m pentium3 pentiumpro" ;; + *1?6[[7d]]?:*:*:*) ax_gcc_arch="penryn core2 pentium-m pentium3 pentiumpro" ;; + *1?6[[aef]]?:*:*:*|*2?6e?:*:*:*) ax_gcc_arch="nehalem corei7 core2 pentium-m pentium3 pentiumpro" ;; + *2?6[[5cf]]?:*:*:*) ax_gcc_arch="westmere corei7 core2 pentium-m pentium3 pentiumpro" ;; + *2?6[[ad]]?:*:*:*) ax_gcc_arch="sandybridge corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;; + *3?6[[ae]]?:*:*:*) ax_gcc_arch="ivybridge core-avx-i corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;; + *3?6[[cf]]?:*:*:*|*4?6[[56]]?:*:*:*) ax_gcc_arch="haswell core-avx2 core-avx-i corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;; + *3?6d?:*:*:*|*4?6[[7f]]?:*:*:*|*5?66?:*:*:*) ax_gcc_arch="broadwell core-avx2 core-avx-i corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;; + *1?6c?:*:*:*|*2?6[[67]]?:*:*:*|*3?6[[56]]?:*:*:*) ax_gcc_arch="bonnell atom core2 pentium-m pentium3 pentiumpro" ;; + *3?67?:*:*:*|*[[45]]?6[[ad]]?:*:*:*) ax_gcc_arch="silvermont atom core2 pentium-m pentium3 pentiumpro" ;; + *000?f[[012]]?:*:*:*|?f[[012]]?:*:*:*|f[[012]]?:*:*:*) ax_gcc_arch="pentium4 pentiumpro" ;; + *000?f[[346]]?:*:*:*|?f[[346]]?:*:*:*|f[[346]]?:*:*:*) ax_gcc_arch="nocona prescott pentium4 pentiumpro" ;; + # fallback + *5??:*:*:*) ax_gcc_arch=pentium ;; + *??6??:*:*:*) ax_gcc_arch="core2 pentiumpro" ;; + *6??:*:*:*) ax_gcc_arch=pentiumpro ;; + *00??f??:*:*:*|??f??:*:*:*|?f??:*:*:*|f??:*:*:*) ax_gcc_arch="pentium4 pentiumpro" ;; + esac ;; + *:68747541:444d4163:69746e65) # AMD + case $ax_cv_gcc_x86_cpuid_1 in + *5[[67]]?:*:*:*) ax_gcc_arch=k6 ;; + *5[[8]]?:*:*:*) ax_gcc_arch="k6-2 k6" ;; + *5[[9d]]?:*:*:*) ax_gcc_arch="k6-3 k6" ;; + *6[[12]]?:*:*:*) ax_gcc_arch="athlon k7" ;; + *6[[34]]?:*:*:*) ax_gcc_arch="athlon-tbird k7" ;; + *6[[678a]]?:*:*:*) ax_gcc_arch="athlon-xp athlon-4 athlon k7" ;; + *000?f[[4578bcef]]?:*:*:*|?f[[4578bcef]]?:*:*:*|f[[4578bcef]]?:*:*:*|*001?f[[4578bcf]]?:*:*:*|1?f[[4578bcf]]?:*:*:*) ax_gcc_arch="athlon64 k8" ;; + *002?f[[13457bcf]]?:*:*:*|2?f[[13457bcf]]?:*:*:*|*004?f[[138bcf]]?:*:*:*|4?f[[138bcf]]?:*:*:*|*005?f[[df]]?:*:*:*|5?f[[df]]?:*:*:*|*006?f[[8bcf]]?:*:*:*|6?f[[8bcf]]?:*:*:*|*007?f[[cf]]?:*:*:*|7?f[[cf]]?:*:*:*|*00c?f1?:*:*:*|c?f1?:*:*:*|*020?f3?:*:*:*|20?f3?:*:*:*) ax_gcc_arch="athlon64-sse3 k8-sse3 athlon64 k8" ;; + *010?f[[245689a]]?:*:*:*|10?f[[245689a]]?:*:*:*|*030?f1?:*:*:*|30?f1?:*:*:*) ax_gcc_arch="barcelona amdfam10 k8" ;; + *050?f[[12]]?:*:*:*|50?f[[12]]?:*:*:*) ax_gcc_arch="btver1 amdfam10 k8" ;; + *060?f1?:*:*:*|60?f1?:*:*:*) ax_gcc_arch="bdver1 amdfam10 k8" ;; + *060?f2?:*:*:*|60?f2?:*:*:*|*061?f[[03]]?:*:*:*|61?f[[03]]?:*:*:*) ax_gcc_arch="bdver2 bdver1 amdfam10 k8" ;; + *063?f0?:*:*:*|63?f0?:*:*:*) ax_gcc_arch="bdver3 bdver2 bdver1 amdfam10 k8" ;; + *07[[03]]?f0?:*:*:*|7[[03]]?f0?:*:*:*) ax_gcc_arch="btver2 btver1 amdfam10 k8" ;; + # fallback + *0[[13]]??f??:*:*:*|[[13]]??f??:*:*:*) ax_gcc_arch="barcelona amdfam10 k8" ;; + *020?f??:*:*:*|20?f??:*:*:*) ax_gcc_arch="athlon64-sse3 k8-sse3 athlon64 k8" ;; + *05??f??:*:*:*|5??f??:*:*:*) ax_gcc_arch="btver1 amdfam10 k8" ;; + *060?f??:*:*:*|60?f??:*:*:*) ax_gcc_arch="bdver1 amdfam10 k8" ;; + *061?f??:*:*:*|61?f??:*:*:*) ax_gcc_arch="bdver2 bdver1 amdfam10 k8" ;; + *06??f??:*:*:*|6??f??:*:*:*) ax_gcc_arch="bdver3 bdver2 bdver1 amdfam10 k8" ;; + *070?f??:*:*:*|70?f??:*:*:*) ax_gcc_arch="btver2 btver1 amdfam10 k8" ;; + *???f??:*:*:*) ax_gcc_arch="amdfam10 k8" ;; + esac ;; + *:746e6543:736c7561:48727561) # IDT / VIA (Centaur) + case $ax_cv_gcc_x86_cpuid_1 in + *54?:*:*:*) ax_gcc_arch=winchip-c6 ;; + *5[[89]]?:*:*:*) ax_gcc_arch=winchip2 ;; + *66?:*:*:*) ax_gcc_arch=winchip2 ;; + *6[[78]]?:*:*:*) ax_gcc_arch=c3 ;; + *6[[9adf]]?:*:*:*) ax_gcc_arch="c3-2 c3" ;; + esac ;; + esac + if test x"$ax_gcc_arch" = x; then # fallback + case $host_cpu in + i586*) ax_gcc_arch=pentium ;; + i686*) ax_gcc_arch=pentiumpro ;; + esac + fi + ;; + + sparc*) + AC_PATH_PROG([PRTDIAG], [prtdiag], [prtdiag], [$PATH:/usr/platform/`uname -i`/sbin/:/usr/platform/`uname -m`/sbin/]) + cputype=`(((grep cpu /proc/cpuinfo | cut -d: -f2) ; ($PRTDIAG -v |grep -i sparc) ; grep -i cpu /var/run/dmesg.boot ) | head -n 1) 2> /dev/null` + cputype=`echo "$cputype" | tr -d ' -' | $SED 's/SPARCIIi/SPARCII/' |tr $as_cr_LETTERS $as_cr_letters` + case $cputype in + *ultrasparciv*) ax_gcc_arch="ultrasparc4 ultrasparc3 ultrasparc v9" ;; + *ultrasparciii*) ax_gcc_arch="ultrasparc3 ultrasparc v9" ;; + *ultrasparc*) ax_gcc_arch="ultrasparc v9" ;; + *supersparc*|*tms390z5[[05]]*) ax_gcc_arch="supersparc v8" ;; + *hypersparc*|*rt62[[056]]*) ax_gcc_arch="hypersparc v8" ;; + *cypress*) ax_gcc_arch=cypress ;; + esac ;; + + alphaev5) ax_gcc_arch=ev5 ;; + alphaev56) ax_gcc_arch=ev56 ;; + alphapca56) ax_gcc_arch="pca56 ev56" ;; + alphapca57) ax_gcc_arch="pca57 pca56 ev56" ;; + alphaev6) ax_gcc_arch=ev6 ;; + alphaev67) ax_gcc_arch=ev67 ;; + alphaev68) ax_gcc_arch="ev68 ev67" ;; + alphaev69) ax_gcc_arch="ev69 ev68 ev67" ;; + alphaev7) ax_gcc_arch="ev7 ev69 ev68 ev67" ;; + alphaev79) ax_gcc_arch="ev79 ev7 ev69 ev68 ev67" ;; + + powerpc*) + cputype=`((grep cpu /proc/cpuinfo | head -n 1 | cut -d: -f2 | cut -d, -f1 | $SED 's/ //g') ; /usr/bin/machine ; /bin/machine; grep CPU /var/run/dmesg.boot | head -n 1 | cut -d" " -f2) 2> /dev/null` + cputype=`echo $cputype | $SED -e 's/ppc//g;s/ *//g'` + case $cputype in + *750*) ax_gcc_arch="750 G3" ;; + *740[[0-9]]*) ax_gcc_arch="$cputype 7400 G4" ;; + *74[[4-5]][[0-9]]*) ax_gcc_arch="$cputype 7450 G4" ;; + *74[[0-9]][[0-9]]*) ax_gcc_arch="$cputype G4" ;; + *970*) ax_gcc_arch="970 G5 power4";; + *POWER4*|*power4*|*gq*) ax_gcc_arch="power4 970";; + *POWER5*|*power5*|*gr*|*gs*) ax_gcc_arch="power5 power4 970";; + 603ev|8240) ax_gcc_arch="$cputype 603e 603";; + *POWER7*) ax_gcc_arch="power7";; + *POWER8*) ax_gcc_arch="power8";; + *POWER9*) ax_gcc_arch="power9";; + *POWER10*) ax_gcc_arch="power10";; + *) ax_gcc_arch=$cputype ;; + esac + ax_gcc_arch="$ax_gcc_arch powerpc" + ;; + aarch64) + cpuimpl=`grep 'CPU implementer' /proc/cpuinfo 2> /dev/null | cut -d: -f2 | tr -d " " | head -n 1` + cpuarch=`grep 'CPU architecture' /proc/cpuinfo 2> /dev/null | cut -d: -f2 | tr -d " " | head -n 1` + cpuvar=`grep 'CPU variant' /proc/cpuinfo 2> /dev/null | cut -d: -f2 | tr -d " " | head -n 1` + case $cpuimpl in + 0x42) case $cpuarch in + 8) case $cpuvar in + 0x0) ax_gcc_arch="thunderx2t99 vulcan armv8.1-a armv8-a+lse armv8-a native" ;; + esac + ;; + esac + ;; + 0x43) case $cpuarch in + 8) case $cpuvar in + 0x0) ax_gcc_arch="thunderx armv8-a native" ;; + 0x1) ax_gcc_arch="thunderx+lse armv8.1-a armv8-a+lse armv8-a native" ;; + esac + ;; + esac + ;; + esac + ;; +esac +fi # not cross-compiling +fi # guess arch + +if test "x$ax_gcc_arch" != x -a "x$ax_gcc_arch" != xno; then +if test "x[]m4_default([$1],yes)" = xyes; then # if we require portable code + flag_prefixes="-mtune=" + if test "x$ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor" = xclang; then flag_prefixes="-march="; fi + # -mcpu=$arch and m$arch generate nonportable code on every arch except + # x86. And some other arches (e.g. Alpha) don't accept -mtune. Grrr. + case $host_cpu in i*86|x86_64*|amd64*) flag_prefixes="$flag_prefixes -mcpu= -m";; esac +else + flag_prefixes="-march= -mcpu= -m" +fi +for flag_prefix in $flag_prefixes; do + for arch in $ax_gcc_arch; do + flag="$flag_prefix$arch" + AX_CHECK_COMPILE_FLAG($flag, [if test "x$ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor" = xclang; then + if test "x[]m4_default([$1],yes)" = xyes; then + if test "x$flag" = "x-march=$arch"; then flag=-mtune=$arch; fi + fi + fi; ax_cv_gcc_archflag=$flag; break]) + done + test "x$ax_cv_gcc_archflag" = xunknown || break +done +fi + +fi # $GCC=yes +]) +AC_MSG_CHECKING([for gcc architecture flag]) +AC_MSG_RESULT($ax_cv_gcc_archflag) +if test "x$ax_cv_gcc_archflag" = xunknown; then + m4_default([$3],:) +else + m4_default([$2], [CFLAGS="$CFLAGS $ax_cv_gcc_archflag"]) +fi +]) diff --git a/build-aux/m4/ax_gcc_x86_cpuid.m4 b/build-aux/m4/ax_gcc_x86_cpuid.m4 new file mode 100644 index 00000000000..df954658ee1 --- /dev/null +++ b/build-aux/m4/ax_gcc_x86_cpuid.m4 @@ -0,0 +1,89 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_gcc_x86_cpuid.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_GCC_X86_CPUID(OP) +# AX_GCC_X86_CPUID_COUNT(OP, COUNT) +# +# DESCRIPTION +# +# On Pentium and later x86 processors, with gcc or a compiler that has a +# compatible syntax for inline assembly instructions, run a small program +# that executes the cpuid instruction with input OP. This can be used to +# detect the CPU type. AX_GCC_X86_CPUID_COUNT takes an additional COUNT +# parameter that gets passed into register ECX before calling cpuid. +# +# On output, the values of the eax, ebx, ecx, and edx registers are stored +# as hexadecimal strings as "eax:ebx:ecx:edx" in the cache variable +# ax_cv_gcc_x86_cpuid_OP. +# +# If the cpuid instruction fails (because you are running a +# cross-compiler, or because you are not using gcc, or because you are on +# a processor that doesn't have this instruction), ax_cv_gcc_x86_cpuid_OP +# is set to the string "unknown". +# +# This macro mainly exists to be used in AX_GCC_ARCHFLAG. +# +# LICENSE +# +# Copyright (c) 2008 Steven G. Johnson +# Copyright (c) 2008 Matteo Frigo +# Copyright (c) 2015 Michael Petch +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 10 + +AC_DEFUN([AX_GCC_X86_CPUID], +[AX_GCC_X86_CPUID_COUNT($1, 0) +]) + +AC_DEFUN([AX_GCC_X86_CPUID_COUNT], +[AC_REQUIRE([AC_PROG_CC]) +AC_LANG_PUSH([C]) +AC_CACHE_CHECK(for x86 cpuid $1 output, ax_cv_gcc_x86_cpuid_$1, + [AC_RUN_IFELSE([AC_LANG_PROGRAM([#include ], [ + int op = $1, level = $2, eax, ebx, ecx, edx; + FILE *f; + __asm__ __volatile__ ("xchg %%ebx, %1\n" + "cpuid\n" + "xchg %%ebx, %1\n" + : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx) + : "a" (op), "2" (level)); + + f = fopen("conftest_cpuid", "w"); if (!f) return 1; + fprintf(f, "%x:%x:%x:%x\n", eax, ebx, ecx, edx); + fclose(f); + return 0; +])], + [ax_cv_gcc_x86_cpuid_$1=`cat conftest_cpuid`; rm -f conftest_cpuid], + [ax_cv_gcc_x86_cpuid_$1=unknown; rm -f conftest_cpuid], + [ax_cv_gcc_x86_cpuid_$1=unknown])]) +AC_LANG_POP([C]) +]) diff --git a/configure.ac b/configure.ac index e6a9ea3f345..ac855644eed 100644 --- a/configure.ac +++ b/configure.ac @@ -760,6 +760,9 @@ else LIBSNARK_DEPINST="$prefix" fi +# Set optimization flags for libsnark +AX_GCC_ARCHFLAG([no], [LIBSNARK_OPTFLAGS="-O2 $ax_cv_gcc_archflag"], [LIBSNARK_OPTFLAGS="-O2"]) + # Additional Zcash flags AX_CHECK_COMPILE_FLAG([-fwrapv],[CXXFLAGS="$CXXFLAGS -fwrapv"]) AX_CHECK_COMPILE_FLAG([-fno-strict-aliasing],[CXXFLAGS="$CXXFLAGS -fno-strict-aliasing"]) @@ -898,6 +901,7 @@ AC_SUBST(ZMQ_LIBS) AC_SUBST(GMP_LIBS) AC_SUBST(GMPXX_LIBS) AC_SUBST(LIBSNARK_DEPINST) +AC_SUBST(LIBSNARK_OPTFLAGS) AC_SUBST(LIBZCASH_LIBS) AC_SUBST(PROTON_LIBS) AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile src/test/buildenv.py]) diff --git a/src/Makefile.am b/src/Makefile.am index 5733549ff91..2df328cc047 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -64,10 +64,10 @@ LIBSNARK_CONFIG_FLAGS += PLATFORM=darwin endif $(LIBSNARK): $(wildcard snark/src/*) - $(AM_V_at) CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="-O2 -march=x86-64" + $(AM_V_at) CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="$(LIBSNARK_OPTFLAGS)" libsnark-tests: $(wildcard snark/src/*) - $(AM_V_at) CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ check DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="-O2 -march=x86-64" + $(AM_V_at) CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ check DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="$(LIBSNARK_OPTFLAGS)" $(LIBUNIVALUE): $(wildcard univalue/lib/*) $(wildcard univalue/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) From ee9ff2ce74e4162b9b0c48f53560cdbba45136e7 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Tue, 19 Mar 2019 12:55:55 -0600 Subject: [PATCH 010/395] Rename and update comment --- src/transaction_builder.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/transaction_builder.cpp b/src/transaction_builder.cpp index a2e515834d4..fbe1043a5f6 100644 --- a/src/transaction_builder.cpp +++ b/src/transaction_builder.cpp @@ -65,9 +65,9 @@ TransactionBuilder::TransactionBuilder( } // This exception is thrown in certain scenarios when building JoinSplits fails. -struct JSDException : public std::exception +struct JSDescException : public std::exception { - JSDException (const std::string msg_) : msg(msg_) {} + JSDescException (const std::string msg_) : msg(msg_) {} const char* what() { return msg.c_str(); } @@ -225,8 +225,9 @@ TransactionBuilderResult TransactionBuilder::Build() if (change > 0) { // Send change to the specified change address. If no change address - // was set, send change to the first Sapling address given as input, - // or the first Sprout address given as input. + // was set, send change to the first Sapling address given as input + // if any; otherwise the first Sprout address given as input. + // (A t-address can only be used as the change address if explicitly set.) if (saplingChangeAddr) { AddSaplingOutput(saplingChangeAddr->first, saplingChangeAddr->second, change); } else if (sproutChangeAddr) { @@ -346,7 +347,7 @@ TransactionBuilderResult TransactionBuilder::Build() if (!jsInputs.empty() || !jsOutputs.empty()) { try { CreateJSDescriptions(); - } catch (JSDException e) { + } catch (JSDescException e) { librustzcash_sapling_proving_ctx_free(ctx); return TransactionBuilderResult(e.what()); } catch (std::runtime_error e) { @@ -528,7 +529,7 @@ void TransactionBuilder::CreateJSDescriptions() if (it != intermediates.end()) { tree = it->second; } else if (!coinsView->GetSproutAnchorAt(prevJoinSplit.anchor, tree)) { - throw JSDException("Could not find previous JoinSplit anchor"); + throw JSDescException("Could not find previous JoinSplit anchor"); } } @@ -568,7 +569,7 @@ void TransactionBuilder::CreateJSDescriptions() LogPrint("zrpcunsafe", "spending change (amount=%s)\n", FormatMoney(plaintext.value())); } catch (const std::exception& e) { - throw JSDException("Error decrypting output note of previous JoinSplit"); + throw JSDescException("Error decrypting output note of previous JoinSplit"); } } @@ -585,7 +586,7 @@ void TransactionBuilder::CreateJSDescriptions() jsInput.witness.append(commitment); } if (jsAnchor != jsInput.witness.root()) { - throw JSDException("Witness for spendable note does not have same anchor as change input"); + throw JSDescException("Witness for spendable note does not have same anchor as change input"); } } @@ -614,7 +615,7 @@ void TransactionBuilder::CreateJSDescriptions() if (jsOutputsDeque.empty() && jsInputsDeque.empty()) { assert(!vpubNewProcessed); if (jsInputValue < vpubNewTarget) { - throw JSDException(strprintf("Insufficient funds for vpub_new %s", FormatMoney(vpubNewTarget))); + throw JSDescException(strprintf("Insufficient funds for vpub_new %s", FormatMoney(vpubNewTarget))); } outAmount += vpubNewTarget; vpub_new += vpubNewTarget; // funds flowing back to public pool From 7420711d9e1d5de0b10985e186609165d21a1bfb Mon Sep 17 00:00:00 2001 From: Dimitris Apostolou Date: Wed, 20 Mar 2019 09:04:32 +0200 Subject: [PATCH 011/395] Electric Coin Company --- code_of_conduct.md | 2 +- contrib/debian/control | 2 +- contrib/debian/copyright | 2 +- zcutil/make-release.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code_of_conduct.md b/code_of_conduct.md index 82446d3831d..ceb5f506d62 100644 --- a/code_of_conduct.md +++ b/code_of_conduct.md @@ -25,7 +25,7 @@ reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. Note that contributors may be volunteers -who do not represent Zcash Company. They are free to express their own +who do not represent Electric Coin Company. They are free to express their own opinions so long as they adhere to these guidelines. By adopting this Code of Conduct, project maintainers commit themselves to diff --git a/contrib/debian/control b/contrib/debian/control index b0c220cf01c..c2c9d17d555 100644 --- a/contrib/debian/control +++ b/contrib/debian/control @@ -1,7 +1,7 @@ Source: zcash Section: utils Priority: optional -Maintainer: Zcash Company +Maintainer: Electric Coin Company Homepage: https://z.cash Build-Depends: autoconf, automake, bsdmainutils, build-essential, git, g++-multilib, libc6-dev, libtool, diff --git a/contrib/debian/copyright b/contrib/debian/copyright index 14cbe9e9aef..de1fdf97d19 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -1,6 +1,6 @@ Format: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?rev=174 Upstream-Name: Zcash -Upstream-Contact: Zcash Company +Upstream-Contact: Electric Coin Company Source: https://github.com/zcash/zcash Files: * diff --git a/zcutil/make-release.py b/zcutil/make-release.py index bc47d0b1909..303048ed00b 100755 --- a/zcutil/make-release.py +++ b/zcutil/make-release.py @@ -292,7 +292,7 @@ def gen_release_notes(release, releasefrom): @phase('Updating debian changelog.') def update_debian_changelog(release): os.environ['DEBEMAIL'] = 'team@z.cash' - os.environ['DEBFULLNAME'] = 'Zcash Company' + os.environ['DEBFULLNAME'] = 'Electric Coin Company' sh_log( 'debchange', '--newversion', release.debversion, From e0774bf8d320787be668773d492bb99bc69213a1 Mon Sep 17 00:00:00 2001 From: zebambam Date: Wed, 20 Mar 2019 08:55:58 -0700 Subject: [PATCH 012/395] Minor speling changes --- responsible_disclosure.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/responsible_disclosure.md b/responsible_disclosure.md index ddd6ca93b9c..1f3c9401bba 100644 --- a/responsible_disclosure.md +++ b/responsible_disclosure.md @@ -43,11 +43,11 @@ CDHCrwSovQRMHtoOWZijBNobO2y1d0FkUpzNlNw44Ssw0Vo= In the case where we become aware of security issues affecting other projects that has never affected Zcash, our intention is to inform those projects of security issues on a best effort basis. -In the case where we fix a security issue in Zcash that also affects the following neighboring projects, our intention is to engage in responsible disclosures with them as described in https://github.com/RD-Crypto-Spec/Responsible-Disclosure, subject to the deviations described in the that section. +In the case where we fix a security issue in Zcash that also affects the following neighboring projects, our intention is to engage in responsible disclosures with them as described in https://github.com/RD-Crypto-Spec/Responsible-Disclosure, subject to the deviations described in the section at the bottom of this document. ## Bilateral Responsible Disclosure Agreements -We have set up agreements with the following neighboring projects to share vulnerability information, subject to the deviaions described in the next section. +We have set up agreements with the following neighboring projects to share vulnerability information, subject to the deviations described in the next section. Specifically, we have agreed to engage in responsible disclosures for security issues affecting Zcash technology with the following contacts: From 361647d8dae304251da6fc39c22d626b45ace239 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20Kj=C3=A6rstad?= Date: Wed, 20 Mar 2019 21:09:51 +0100 Subject: [PATCH 013/395] Update _COPYRIGHT_YEAR in configure.ac to 2019 Update _COPYRIGHT_YEAR in configure.ac to 2019 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 93efbb117c4..46e79b1107c 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ define(_CLIENT_VERSION_BUILD, 25) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) -define(_COPYRIGHT_YEAR, 2018) +define(_COPYRIGHT_YEAR, 2019) AC_INIT([Zcash],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_SUFFIX(_ZC_BUILD_VAL)],[https://github.com/zcash/zcash/issues],[zcash]) AC_CONFIG_SRCDIR([src/main.cpp]) AC_CONFIG_HEADERS([src/config/bitcoin-config.h]) From e1df250a0df342733eb4f4a180663dd750e5dbd4 Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Wed, 20 Mar 2019 16:29:06 -0600 Subject: [PATCH 014/395] fix enable-debug build DB_COINS undefined --- src/zcbenchmarks.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/zcbenchmarks.cpp b/src/zcbenchmarks.cpp index 5283d50975e..d91e36d730a 100644 --- a/src/zcbenchmarks.cpp +++ b/src/zcbenchmarks.cpp @@ -453,9 +453,11 @@ double benchmark_increment_sapling_note_witnesses(size_t nTxs) // This class is based on the class CCoinsViewDB, but with limited functionality. // The construtor and the functions `GetCoins` and `HaveCoins` come directly from // CCoinsViewDB, but the rest are either mocks and/or don't really do anything. + +// The following constant is a duplicate of the one found in txdb.cpp +static const char DB_COINS = 'c'; + class FakeCoinsViewDB : public CCoinsView { - // The following constant is a duplicate of the one found in txdb.cpp - static const char DB_COINS = 'c'; CDBWrapper db; From 7e99b6c094073be68692f3b4b839850689e62ae6 Mon Sep 17 00:00:00 2001 From: William M Peaster Date: Wed, 27 Mar 2019 17:46:28 -0500 Subject: [PATCH 015/395] Handful of copyedits to README.md A few copyedits for improved grammatical polish and clarity --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d1c12009834..1c5910283c0 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,9 @@ What is Zcash? -------------- [Zcash](https://z.cash/) is an implementation of the "Zerocash" protocol. -Based on Bitcoin's code, it intends to offer a far higher standard of privacy +Based on Bitcoin's code, Zcash intends to offer a far higher standard of privacy through a sophisticated zero-knowledge proving scheme that preserves -confidentiality of transaction metadata. Technical details are available +confidentiality of transaction metadata. More technical details are available in our [Protocol Specification](https://github.com/zcash/zips/raw/master/protocol/protocol.pdf). This software is the Zcash client. It downloads and stores the entire history @@ -25,13 +25,13 @@ blockchain has reached a significant size. See important security warnings on the [Security Information page](https://z.cash/support/security/). -**Zcash is experimental and a work-in-progress.** Use at your own risk. +**Zcash is experimental and a work in progress.** Use it at your own risk. #### :ledger: Deprecation Policy This release is considered deprecated 16 weeks after the release day. There is an automatic deprecation shutdown feature which will halt the node some -time after this 16 week time period. The automatic feature is based on block +time after this 16-week period. The automatic feature is based on block height. ## Getting Started @@ -50,13 +50,13 @@ Participation in the Zcash project is subject to a ### Building -Build Zcash along with most dependencies from source by running: +Build Zcash along with most dependencies from source by running the following command: ``` ./zcutil/build.sh -j$(nproc) ``` -Currently only Linux is officially supported. +Currently, Zcash is only built for Linux. License ------- From 6cf0e50b56b39eda3cd2cf91e99a594f36e01618 Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Tue, 19 Mar 2019 13:28:02 -0600 Subject: [PATCH 016/395] add -addressindex changes for bitcore insight block explorer --- src/addressindex.h | 225 ++++++++++++++++++++++++++++++++++++++++++ src/init.cpp | 17 ++++ src/main.cpp | 144 ++++++++++++++++++++++++++- src/main.h | 20 ++-- src/script/script.cpp | 42 ++++++++ src/script/script.h | 6 ++ src/serialize.h | 11 +++ src/txdb.cpp | 83 ++++++++++++++++ src/txdb.h | 21 ++++ 9 files changed, 558 insertions(+), 11 deletions(-) create mode 100644 src/addressindex.h diff --git a/src/addressindex.h b/src/addressindex.h new file mode 100644 index 00000000000..e83c9fc2fdc --- /dev/null +++ b/src/addressindex.h @@ -0,0 +1,225 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_ADDRESSINDEX_H +#define BITCOIN_ADDRESSINDEX_H + +#include "uint256.h" +#include "amount.h" +#include "script/script.h" + +struct CAddressUnspentKey { + unsigned int type; + uint160 hashBytes; + uint256 txhash; + size_t index; + + size_t GetSerializeSize(int nType, int nVersion) const { + return 57; + } + template + void Serialize(Stream& s) const { + ser_writedata8(s, type); + hashBytes.Serialize(s); + txhash.Serialize(s); + ser_writedata32(s, index); + } + template + void Unserialize(Stream& s) { + type = ser_readdata8(s); + hashBytes.Unserialize(s); + txhash.Unserialize(s); + index = ser_readdata32(s); + } + + CAddressUnspentKey(unsigned int addressType, uint160 addressHash, uint256 txid, size_t indexValue) { + type = addressType; + hashBytes = addressHash; + txhash = txid; + index = indexValue; + } + + CAddressUnspentKey() { + SetNull(); + } + + void SetNull() { + type = 0; + hashBytes.SetNull(); + txhash.SetNull(); + index = 0; + } +}; + +struct CAddressUnspentValue { + CAmount satoshis; + CScript script; + int blockHeight; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(satoshis); + READWRITE(*(CScriptBase*)(&script)); + READWRITE(blockHeight); + } + + CAddressUnspentValue(CAmount sats, CScript scriptPubKey, int height) { + satoshis = sats; + script = scriptPubKey; + blockHeight = height; + } + + CAddressUnspentValue() { + SetNull(); + } + + void SetNull() { + satoshis = -1; + script.clear(); + blockHeight = 0; + } + + bool IsNull() const { + return (satoshis == -1); + } +}; + +struct CAddressIndexKey { + unsigned int type; + uint160 hashBytes; + int blockHeight; + unsigned int txindex; + uint256 txhash; + size_t index; + bool spending; + + size_t GetSerializeSize(int nType, int nVersion) const { + return 66; + } + template + void Serialize(Stream& s) const { + ser_writedata8(s, type); + hashBytes.Serialize(s); + // Heights are stored big-endian for key sorting in LevelDB + ser_writedata32be(s, blockHeight); + ser_writedata32be(s, txindex); + txhash.Serialize(s); + ser_writedata32(s, index); + char f = spending; + ser_writedata8(s, f); + } + template + void Unserialize(Stream& s) { + type = ser_readdata8(s); + hashBytes.Unserialize(s); + blockHeight = ser_readdata32be(s); + txindex = ser_readdata32be(s); + txhash.Unserialize(s); + index = ser_readdata32(s); + char f = ser_readdata8(s); + spending = f; + } + + CAddressIndexKey(unsigned int addressType, uint160 addressHash, int height, int blockindex, + uint256 txid, size_t indexValue, bool isSpending) { + type = addressType; + hashBytes = addressHash; + blockHeight = height; + txindex = blockindex; + txhash = txid; + index = indexValue; + spending = isSpending; + } + + CAddressIndexKey() { + SetNull(); + } + + void SetNull() { + type = 0; + hashBytes.SetNull(); + blockHeight = 0; + txindex = 0; + txhash.SetNull(); + index = 0; + spending = false; + } + +}; + +struct CAddressIndexIteratorKey { + unsigned int type; + uint160 hashBytes; + + size_t GetSerializeSize(int nType, int nVersion) const { + return 21; + } + template + void Serialize(Stream& s) const { + ser_writedata8(s, type); + hashBytes.Serialize(s); + } + template + void Unserialize(Stream& s) { + type = ser_readdata8(s); + hashBytes.Unserialize(s); + } + + CAddressIndexIteratorKey(unsigned int addressType, uint160 addressHash) { + type = addressType; + hashBytes = addressHash; + } + + CAddressIndexIteratorKey() { + SetNull(); + } + + void SetNull() { + type = 0; + hashBytes.SetNull(); + } +}; + +struct CAddressIndexIteratorHeightKey { + unsigned int type; + uint160 hashBytes; + int blockHeight; + + size_t GetSerializeSize(int nType, int nVersion) const { + return 25; + } + template + void Serialize(Stream& s) const { + ser_writedata8(s, type); + hashBytes.Serialize(s); + ser_writedata32be(s, blockHeight); + } + template + void Unserialize(Stream& s) { + type = ser_readdata8(s); + hashBytes.Unserialize(s); + blockHeight = ser_readdata32be(s); + } + + CAddressIndexIteratorHeightKey(unsigned int addressType, uint160 addressHash, int height) { + type = addressType; + hashBytes = addressHash; + blockHeight = height; + } + + CAddressIndexIteratorHeightKey() { + SetNull(); + } + + void SetNull() { + type = 0; + hashBytes.SetNull(); + blockHeight = 0; + } +}; + +#endif // BITCOIN_ADDRESSINDEX_H diff --git a/src/init.cpp b/src/init.cpp index f9da81e877d..ec459e36b21 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -841,6 +841,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) return InitError(_("RPC method z_mergetoaddress requires -experimentalfeatures.")); } else if (mapArgs.count("-savesproutr1cs")) { return InitError(_("Saving the Sprout R1CS requires -experimentalfeatures.")); + } else if (mapArgs.count("-insightexplorer")) { + return InitError(_("Insight explorer requires -experimentalfeatures.")); } } @@ -1442,6 +1444,15 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) int64_t nBlockTreeDBCache = nTotalCache / 8; if (nBlockTreeDBCache > (1 << 21) && !GetBoolArg("-txindex", false)) nBlockTreeDBCache = (1 << 21); // block tree db cache shouldn't be larger than 2 MiB + + // https://github.com/bitpay/bitcoin/commit/c91d78b578a8700a45be936cb5bb0931df8f4b87#diff-c865a8939105e6350a50af02766291b7R1233 + if (GetBoolArg("-insightexplorer", false)) { + if (!GetBoolArg("-txindex", false)) { + return InitError(_("-insightexplorer requires -txindex.")); + } + // increase cache if additional indices are needed + nBlockTreeDBCache = nTotalCache * 3 / 4; + } nTotalCache -= nBlockTreeDBCache; int64_t nCoinDBCache = std::min(nTotalCache / 2, (nTotalCache / 4) + (1 << 23)); // use 25%-50% of the remainder for disk cache nTotalCache -= nCoinDBCache; @@ -1503,6 +1514,12 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) break; } + // Check for changed -insightexplorer state + if (fInsightExplorer != GetBoolArg("-insightexplorer", false)) { + strLoadError = _("You need to rebuild the database using -reindex to change -insightexplorer"); + break; + } + // Check for changed -prune state. What we are concerned about is a user who has pruned blocks // in the past, but is now trying to run unpruned. if (fHavePruned && !fPruneMode) { diff --git a/src/main.cpp b/src/main.cpp index d0d8db976d1..4c47cfa0c80 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -67,6 +67,8 @@ bool fExperimentalMode = false; bool fImporting = false; bool fReindex = false; bool fTxIndex = false; +bool fInsightExplorer = false; // insightexplorer +bool fAddressIndex = false; // insightexplorer bool fHavePruned = false; bool fPruneMode = false; bool fIsBareMultisigStd = true; @@ -2226,8 +2228,11 @@ enum DisconnectResult }; /** Undo the effects of this block (with given index) on the UTXO set represented by coins. - * When UNCLEAN or FAILED is returned, view is left in an indeterminate state. */ -DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view) + * When UNCLEAN or FAILED is returned, view is left in an indeterminate state. + * The addressIndex will be updated if requested. + */ +static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& state, + const CBlockIndex* pindex, CCoinsViewCache& view, const bool fUpdateAddressIndex) { assert(pindex->GetBlockHash() == view.GetBestBlock()); @@ -2248,11 +2253,35 @@ DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, error("DisconnectBlock(): block and undo data inconsistent"); return DISCONNECT_FAILED; } + std::vector addressIndex; + std::vector addressUnspentIndex; // undo transactions in reverse order for (int i = block.vtx.size() - 1; i >= 0; i--) { const CTransaction &tx = block.vtx[i]; - uint256 hash = tx.GetHash(); + uint256 const hash = tx.GetHash(); + + // insightexplorer + // https://github.com/bitpay/bitcoin/commit/017f548ea6d89423ef568117447e61dd5707ec42#diff-7ec3c68a81efff79b6ca22ac1f1eabbaR2236 + if (fAddressIndex && fUpdateAddressIndex) { + for (unsigned int k = tx.vout.size(); k-- > 0;) { + const CTxOut &out = tx.vout[k]; + int const scriptType = out.scriptPubKey.Type(); + if (scriptType > 0) { + uint160 const addrHash = out.scriptPubKey.AddressHash(); + + // undo receiving activity + addressIndex.push_back(make_pair( + CAddressIndexKey(scriptType, addrHash, pindex->nHeight, i, hash, k, false), + out.nValue)); + + // undo unspent index + addressUnspentIndex.push_back(make_pair( + CAddressUnspentKey(scriptType, addrHash, hash, k), + CAddressUnspentValue())); + } + } + } // Check that all outputs are available and match the outputs in the block itself // exactly. @@ -2288,6 +2317,27 @@ DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, const CTxInUndo &undo = txundo.vprevout[j]; if (!ApplyTxInUndo(undo, view, out)) fClean = false; + + // insightexplorer + // https://github.com/bitpay/bitcoin/commit/017f548ea6d89423ef568117447e61dd5707ec42#diff-7ec3c68a81efff79b6ca22ac1f1eabbaR2304 + if (fAddressIndex && fUpdateAddressIndex) { + const CTxIn input = tx.vin[j]; + const CTxOut &prevout = view.GetOutputFor(input); + int const scriptType = prevout.scriptPubKey.Type(); + if (scriptType > 0) { + uint160 const addrHash = prevout.scriptPubKey.AddressHash(); + + // undo spending activity + addressIndex.push_back(make_pair( + CAddressIndexKey(scriptType, addrHash, pindex->nHeight, i, hash, j, true), + prevout.nValue * -1)); + + // restore unspent index + addressUnspentIndex.push_back(make_pair( + CAddressUnspentKey(scriptType, addrHash, input.prevout.hash, input.prevout.n), + CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight))); + } + } } } } @@ -2309,6 +2359,17 @@ DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, // move best block pointer to prevout block view.SetBestBlock(pindex->pprev->GetBlockHash()); + // insightexplorer + if (fAddressIndex && fUpdateAddressIndex) { + if (!pblocktree->EraseAddressIndex(addressIndex)) { + AbortNode(state, "Failed to delete address index"); + return DISCONNECT_FAILED; + } + if (!pblocktree->UpdateAddressUnspentIndex(addressUnspentIndex)) { + AbortNode(state, "Failed to write address unspent index"); + return DISCONNECT_FAILED; + } + } return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN; } @@ -2505,6 +2566,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin std::vector > vPos; vPos.reserve(block.vtx.size()); blockundo.vtxundo.reserve(block.vtx.size() - 1); + std::vector addressIndex; + std::vector addressUnspentIndex; // Construct the incremental merkle tree at the current // block position, @@ -2535,6 +2598,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin for (unsigned int i = 0; i < block.vtx.size(); i++) { const CTransaction &tx = block.vtx[i]; + const uint256 hash = tx.GetHash(); nInputs += tx.vin.size(); nSigOps += GetLegacySigOpCount(tx); @@ -2553,6 +2617,30 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return state.DoS(100, error("ConnectBlock(): JoinSplit requirements not met"), REJECT_INVALID, "bad-txns-joinsplit-requirements-not-met"); + // insightexplorer + // https://github.com/bitpay/bitcoin/commit/017f548ea6d89423ef568117447e61dd5707ec42#diff-7ec3c68a81efff79b6ca22ac1f1eabbaR2597 + if (fAddressIndex) { + for (size_t j = 0; j < tx.vin.size(); j++) { + + const CTxIn input = tx.vin[j]; + const CTxOut &prevout = view.GetOutputFor(tx.vin[j]); + int const scriptType = prevout.scriptPubKey.Type(); + if (scriptType > 0) { + uint160 const addrHash = prevout.scriptPubKey.AddressHash(); + + // record spending activity + addressIndex.push_back(make_pair( + CAddressIndexKey(scriptType, addrHash, pindex->nHeight, i, hash, j, true), + prevout.nValue * -1)); + + // remove address from unspent index + addressUnspentIndex.push_back(make_pair( + CAddressUnspentKey(scriptType, addrHash, input.prevout.hash, input.prevout.n), + CAddressUnspentValue())); + } + } + } + // Add in sigops done by pay-to-script-hash inputs; // this is to prevent a "rogue miner" from creating // an incredibly-expensive-to-validate block. @@ -2575,6 +2663,28 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin control.Add(vChecks); } + // insightexplorer + // https://github.com/bitpay/bitcoin/commit/017f548ea6d89423ef568117447e61dd5707ec42#diff-7ec3c68a81efff79b6ca22ac1f1eabbaR2656 + if (fAddressIndex) { + for (unsigned int k = 0; k < tx.vout.size(); k++) { + const CTxOut &out = tx.vout[k]; + int const scriptType = out.scriptPubKey.Type(); + if (scriptType > 0) { + uint160 const addrHash = out.scriptPubKey.AddressHash(); + + // record receiving activity + addressIndex.push_back(make_pair( + CAddressIndexKey(scriptType, addrHash, pindex->nHeight, i, hash, k, false), + out.nValue)); + + // record unspent output + addressUnspentIndex.push_back(make_pair( + CAddressUnspentKey(scriptType, addrHash, hash, k), + CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight))); + } + } + } + CTxUndo undoDummy; if (i > 0) { blockundo.vtxundo.push_back(CTxUndo()); @@ -2666,6 +2776,16 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (!pblocktree->WriteTxIndex(vPos)) return AbortNode(state, "Failed to write transaction index"); + // insightexplorer + if (fAddressIndex) { + if (!pblocktree->WriteAddressIndex(addressIndex)) { + return AbortNode(state, "Failed to write address index"); + } + if (!pblocktree->UpdateAddressUnspentIndex(addressUnspentIndex)) { + return AbortNode(state, "Failed to write address unspent index"); + } + } + // add this block to the view's block chain view.SetBestBlock(pindex->GetBlockHash()); @@ -2860,7 +2980,8 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) { int64_t nStart = GetTimeMicros(); { CCoinsViewCache view(pcoinsTip); - if (DisconnectBlock(block, pindexDelete, view) != DISCONNECT_OK) + // insightexplorer: update indices (true) + if (DisconnectBlock(block, state, pindexDelete, view, true) != DISCONNECT_OK) return error("DisconnectTip(): DisconnectBlock %s failed", pindexDelete->GetBlockHash().ToString()); assert(view.Flush()); } @@ -4195,6 +4316,12 @@ bool static LoadBlockIndexDB() pblocktree->ReadFlag("txindex", fTxIndex); LogPrintf("%s: transaction index %s\n", __func__, fTxIndex ? "enabled" : "disabled"); + // insightexplorer + // Check whether block explorer features are enabled + pblocktree->ReadFlag("insightexplorer", fInsightExplorer); + LogPrintf("%s: insight explorer %s\n", __func__, fAddressIndex ? "enabled" : "disabled"); + fAddressIndex = fInsightExplorer; + // Fill in-memory data BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex) { @@ -4283,7 +4410,8 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth } // check level 3: check for inconsistencies during memory-only disconnect of tip blocks if (nCheckLevel >= 3 && pindex == pindexState && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) { - DisconnectResult res = DisconnectBlock(block, pindex, coins); + // insightexplorer: do not update indices (false) + DisconnectResult res = DisconnectBlock(block, state, pindex, coins, false); if (res == DISCONNECT_FAILED) { return error("VerifyDB(): *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); } @@ -4530,6 +4658,12 @@ bool InitBlockIndex() { // Use the provided setting for -txindex in the new database fTxIndex = GetBoolArg("-txindex", false); pblocktree->WriteFlag("txindex", fTxIndex); + + // Use the provided setting for -insightexplorer in the new database + fInsightExplorer = GetBoolArg("-insightexplorer", false); + pblocktree->WriteFlag("insightexplorer", fInsightExplorer); + fAddressIndex = fInsightExplorer; + LogPrintf("Initializing databases...\n"); // Only add the genesis block if not reindexing (in which case we reuse the one already on disk) diff --git a/src/main.h b/src/main.h index ce489d9ae9c..3b8c6aff9db 100644 --- a/src/main.h +++ b/src/main.h @@ -26,6 +26,7 @@ #include "tinyformat.h" #include "txmempool.h" #include "uint256.h" +#include "addressindex.h" #include #include @@ -131,6 +132,19 @@ extern bool fImporting; extern bool fReindex; extern int nScriptCheckThreads; extern bool fTxIndex; + +// START insightexplorer +extern bool fInsightExplorer; + +// The following flags enable specific indices (DB tables), but are not exposed as +// separate command-line options; instead they are enabled by experimental feature "-insightexplorer" +// and are always equal to the overall controlling flag, fInsightExplorer. + +// Maintain a full address index, used to query for the balance, txids and unspent outputs for addresses +extern bool fAddressIndex; + +// END insightexplorer + extern bool fIsBareMultisigStd; extern bool fCheckBlockIndex; extern bool fCheckpointsEnabled; @@ -449,12 +463,6 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex); /** Functions for validating blocks and updating the block tree */ -/** Undo the effects of this block (with given index) on the UTXO set represented by coins. - * In case pfClean is provided, operation will try to be tolerant about errors, and *pfClean - * will be true if no problems were found. Otherwise, the return value will be false in case - * of problems. Note that in any case, coins may be modified. */ -bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool* pfClean = NULL); - /** Apply the effects of this block (with given index) on the UTXO set represented by coins */ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false); diff --git a/src/script/script.cpp b/src/script/script.cpp index d5234cae803..32fe34b5949 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -201,6 +201,19 @@ unsigned int CScript::GetSigOpCount(const CScript& scriptSig) const return subscript.GetSigOpCount(true); } +// insightexplorer +// https://github.com/bitpay/bitcoin/commit/017f548ea6d89423ef568117447e61dd5707ec42#diff-f7ca24fb80ddba0f291cb66344ca6fcbR204 +bool CScript::IsPayToPublicKeyHash() const +{ + // Extra-fast test for pay-to-pubkey-hash CScripts: + return (this->size() == 25 && + (*this)[0] == OP_DUP && + (*this)[1] == OP_HASH160 && + (*this)[2] == 0x14 && + (*this)[23] == OP_EQUALVERIFY && + (*this)[24] == OP_CHECKSIG); +} + bool CScript::IsPayToScriptHash() const { // Extra-fast test for pay-to-script-hash CScripts: @@ -227,3 +240,32 @@ bool CScript::IsPushOnly() const } return true; } + +// insightexplorer +int CScript::Type() const +{ + if (this->IsPayToPublicKeyHash()) + return 1; + if (this->IsPayToScriptHash()) + return 2; + // We don't know this script + return 0; +} + +// insightexplorer +uint160 CScript::AddressHash() const +{ + // where the address bytes begin depends on the script type + int start; + if (this->IsPayToPublicKeyHash()) + start = 3; + else if (this->IsPayToScriptHash()) + start = 2; + else { + // unknown script type; return an empty vector + vector hashBytes; + return uint160(hashBytes); + } + vector hashBytes(this->begin()+start, this->begin()+start+20); + return uint160(hashBytes); +} diff --git a/src/script/script.h b/src/script/script.h index 541ece1f519..6f88676118c 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -18,6 +18,8 @@ #include #include +#include "uint256.h" + static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes // Maximum script length in bytes @@ -565,8 +567,12 @@ class CScript : public CScriptBase */ unsigned int GetSigOpCount(const CScript& scriptSig) const; + bool IsPayToPublicKeyHash() const; bool IsPayToScriptHash() const; + int Type() const; + uint160 AddressHash() const; + /** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */ bool IsPushOnly() const; diff --git a/src/serialize.h b/src/serialize.h index a945650d6f5..ac2db6eddfb 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -110,6 +110,11 @@ template inline void ser_writedata32(Stream &s, uint32_t obj) obj = htole32(obj); s.write((char*)&obj, 4); } +template inline void ser_writedata32be(Stream &s, uint32_t obj) +{ + obj = htobe32(obj); + s.write((char*)&obj, 4); +} template inline void ser_writedata64(Stream &s, uint64_t obj) { obj = htole64(obj); @@ -133,6 +138,12 @@ template inline uint32_t ser_readdata32(Stream &s) s.read((char*)&obj, 4); return le32toh(obj); } +template inline uint32_t ser_readdata32be(Stream &s) +{ + uint32_t obj; + s.read((char*)&obj, 4); + return be32toh(obj); +} template inline uint64_t ser_readdata64(Stream &s) { uint64_t obj; diff --git a/src/txdb.cpp b/src/txdb.cpp index 8749ffcc6b1..162a790140b 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -35,6 +35,10 @@ static const char DB_FLAG = 'F'; static const char DB_REINDEX_FLAG = 'R'; static const char DB_LAST_BLOCK = 'l'; +// insightexplorer +static const char DB_ADDRESSINDEX = 'd'; +static const char DB_ADDRESSUNSPENTINDEX = 'u'; + CCoinsViewDB::CCoinsViewDB(std::string dbName, size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / dbName, nCacheSize, fMemory, fWipe) { } @@ -293,6 +297,85 @@ bool CBlockTreeDB::WriteTxIndex(const std::vector return WriteBatch(batch); } +// START insightexplorer +// https://github.com/bitpay/bitcoin/commit/017f548ea6d89423ef568117447e61dd5707ec42#diff-81e4f16a1b5d5b7ca25351a63d07cb80R183 +bool CBlockTreeDB::UpdateAddressUnspentIndex(const std::vector &vect) +{ + CDBBatch batch(*this); + for (std::vector::const_iterator it=vect.begin(); it!=vect.end(); it++) { + if (it->second.IsNull()) { + batch.Erase(make_pair(DB_ADDRESSUNSPENTINDEX, it->first)); + } else { + batch.Write(make_pair(DB_ADDRESSUNSPENTINDEX, it->first), it->second); + } + } + return WriteBatch(batch); +} + +bool CBlockTreeDB::ReadAddressUnspentIndex(uint160 addressHash, int type, std::vector &unspentOutputs) +{ + boost::scoped_ptr pcursor(NewIterator()); + + pcursor->Seek(make_pair(DB_ADDRESSUNSPENTINDEX, CAddressIndexIteratorKey(type, addressHash))); + + while (pcursor->Valid()) { + boost::this_thread::interruption_point(); + std::pair key; + if (!(pcursor->GetKey(key) && key.first == DB_ADDRESSUNSPENTINDEX && key.second.hashBytes == addressHash)) + break; + CAddressUnspentValue nValue; + if (pcursor->GetValue(nValue)) + return error("failed to get address unspent value"); + unspentOutputs.push_back(make_pair(key.second, nValue)); + pcursor->Next(); + } + return true; +} + +bool CBlockTreeDB::WriteAddressIndex(const std::vector &vect) { + CDBBatch batch(*this); + for (std::vector::const_iterator it=vect.begin(); it!=vect.end(); it++) + batch.Write(make_pair(DB_ADDRESSINDEX, it->first), it->second); + return WriteBatch(batch); +} + +bool CBlockTreeDB::EraseAddressIndex(const std::vector &vect) { + CDBBatch batch(*this); + for (std::vector::const_iterator it=vect.begin(); it!=vect.end(); it++) + batch.Erase(make_pair(DB_ADDRESSINDEX, it->first)); + return WriteBatch(batch); +} + +bool CBlockTreeDB::ReadAddressIndex( + uint160 addressHash, int type, + std::vector &addressIndex, + int start, int end) +{ + boost::scoped_ptr pcursor(NewIterator()); + + if (start > 0 && end > 0) { + pcursor->Seek(make_pair(DB_ADDRESSINDEX, CAddressIndexIteratorHeightKey(type, addressHash, start))); + } else { + pcursor->Seek(make_pair(DB_ADDRESSINDEX, CAddressIndexIteratorKey(type, addressHash))); + } + + while (pcursor->Valid()) { + boost::this_thread::interruption_point(); + std::pair key; + if (!(pcursor->GetKey(key) && key.first == DB_ADDRESSINDEX && key.second.hashBytes == addressHash)) + break; + if (end > 0 && key.second.blockHeight > end) + break; + CAmount nValue; + if (!pcursor->GetValue(nValue)) + return error("failed to get address index value"); + addressIndex.push_back(make_pair(key.second, nValue)); + pcursor->Next(); + } + return true; +} +// END insightexplorer + bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) { return Write(std::make_pair(DB_FLAG, name), fValue ? '1' : '0'); } diff --git a/src/txdb.h b/src/txdb.h index a415ad2bbfd..305e93e9c15 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -17,6 +17,18 @@ class CBlockFileInfo; class CBlockIndex; struct CDiskTxPos; + +// START insightexplorer +struct CAddressUnspentKey; +struct CAddressUnspentValue; +struct CAddressIndexKey; +struct CAddressIndexIteratorKey; +struct CAddressIndexIteratorHeightKey; + +typedef std::pair CAddressUnspentDbEntry; +typedef std::pair CAddressIndexDbEntry; +// END insightexplorer + class uint256; //! -dbcache default (MiB) @@ -70,6 +82,15 @@ class CBlockTreeDB : public CDBWrapper bool ReadReindexing(bool &fReindex); bool ReadTxIndex(const uint256 &txid, CDiskTxPos &pos); bool WriteTxIndex(const std::vector > &list); + + // START insightexplorer + bool UpdateAddressUnspentIndex(const std::vector &vect); + bool ReadAddressUnspentIndex(uint160 addressHash, int type, std::vector &vect); + bool WriteAddressIndex(const std::vector &vect); + bool EraseAddressIndex(const std::vector &vect); + bool ReadAddressIndex(uint160 addressHash, int type, std::vector &addressIndex, int start = 0, int end = 0); + // END insightexplorer + bool WriteFlag(const std::string &name, bool fValue); bool ReadFlag(const std::string &name, bool &fValue); bool LoadBlockIndexGuts(); From ec81c709644147a8924ae2a9e1d38d31d6c30c81 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Tue, 4 Oct 2016 15:03:13 -0400 Subject: [PATCH 017/395] tests: adds unit test for IsPayToPublicKeyHash method --- src/Makefile.test.include | 1 + src/test/script_P2PKH_tests.cpp | 59 +++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 src/test/script_P2PKH_tests.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 91526ceb681..1eb6b262e91 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -86,6 +86,7 @@ BITCOIN_TESTS =\ test/sanity_tests.cpp \ test/scheduler_tests.cpp \ test/script_P2SH_tests.cpp \ + test/script_P2PKH_tests.cpp \ test/script_tests.cpp \ test/scriptnum_tests.cpp \ test/serialize_tests.cpp \ diff --git a/src/test/script_P2PKH_tests.cpp b/src/test/script_P2PKH_tests.cpp new file mode 100644 index 00000000000..3a7dc16608a --- /dev/null +++ b/src/test/script_P2PKH_tests.cpp @@ -0,0 +1,59 @@ +// Copyright (c) 2012-2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "script/script.h" +#include "test/test_bitcoin.h" + +#include + +using namespace std; + +BOOST_FIXTURE_TEST_SUITE(script_P2PKH_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(IsPayToPublicKeyHash) +{ + // Test CScript::IsPayToPublicKeyHash() + uint160 dummy; + CScript p2pkh; + p2pkh << OP_DUP << OP_HASH160 << ToByteVector(dummy) << OP_EQUALVERIFY << OP_CHECKSIG; + BOOST_CHECK(p2pkh.IsPayToPublicKeyHash()); + + static const unsigned char direct[] = { + OP_DUP, OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUALVERIFY, OP_CHECKSIG + }; + BOOST_CHECK(CScript(direct, direct+sizeof(direct)).IsPayToPublicKeyHash()); + + static const unsigned char notp2pkh1[] = { + OP_DUP, OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUALVERIFY, OP_CHECKSIG, OP_CHECKSIG + }; + BOOST_CHECK(!CScript(notp2pkh1, notp2pkh1+sizeof(notp2pkh1)).IsPayToPublicKeyHash()); + + static const unsigned char p2sh[] = { + OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL + }; + BOOST_CHECK(!CScript(p2sh, p2sh+sizeof(p2sh)).IsPayToPublicKeyHash()); + + static const unsigned char extra[] = { + OP_DUP, OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUALVERIFY, OP_CHECKSIG, OP_CHECKSIG + }; + BOOST_CHECK(!CScript(extra, extra+sizeof(extra)).IsPayToPublicKeyHash()); + + static const unsigned char missing[] = { + OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUALVERIFY, OP_CHECKSIG, OP_RETURN + }; + BOOST_CHECK(!CScript(missing, missing+sizeof(missing)).IsPayToPublicKeyHash()); + + static const unsigned char missing2[] = { + OP_DUP, OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + }; + BOOST_CHECK(!CScript(missing2, missing2+sizeof(missing)).IsPayToPublicKeyHash()); + + static const unsigned char tooshort[] = { + OP_DUP, OP_HASH160, 2, 0,0, OP_EQUALVERIFY, OP_CHECKSIG + }; + BOOST_CHECK(!CScript(tooshort, tooshort+sizeof(direct)).IsPayToPublicKeyHash()); + +} + +BOOST_AUTO_TEST_SUITE_END() From 885fce070a6aaf1c98e635551667a0dfa691d2a7 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 2 Apr 2019 07:39:36 +0100 Subject: [PATCH 018/395] Add Blossom to upgrade list --- src/chainparams.cpp | 9 +++++++++ src/consensus/params.h | 1 + src/consensus/upgrades.cpp | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 511e6a40242..45b77a09ede 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -106,6 +106,9 @@ class CMainParams : public CChainParams { consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = 347500; consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nProtocolVersion = 170007; consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = 419200; + consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].nProtocolVersion = 170009; + consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight = + Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; // The best chain should have at least this much work. consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000000c12875ded911cf"); @@ -285,6 +288,9 @@ class CTestNetParams : public CChainParams { consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = 207500; consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nProtocolVersion = 170007; consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = 280000; + consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].nProtocolVersion = 170008; + consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight = + Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; // The best chain should have at least this much work. consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000000000001d0c4d9cd"); @@ -416,6 +422,9 @@ class CRegTestParams : public CChainParams { consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nProtocolVersion = 170006; consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; + consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].nProtocolVersion = 170008; + consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight = + Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; // The best chain should have at least this much work. consensus.nMinimumChainWork = uint256S("0x00"); diff --git a/src/consensus/params.h b/src/consensus/params.h index 26288f24339..77f30bf4e69 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -26,6 +26,7 @@ enum UpgradeIndex { UPGRADE_TESTDUMMY, UPGRADE_OVERWINTER, UPGRADE_SAPLING, + UPGRADE_BLOSSOM, // NOTE: Also add new upgrades to NetworkUpgradeInfo in upgrades.cpp MAX_NETWORK_UPGRADES }; diff --git a/src/consensus/upgrades.cpp b/src/consensus/upgrades.cpp index 04be05cdf99..e11aaa260e4 100644 --- a/src/consensus/upgrades.cpp +++ b/src/consensus/upgrades.cpp @@ -28,6 +28,11 @@ const struct NUInfo NetworkUpgradeInfo[Consensus::MAX_NETWORK_UPGRADES] = { /*.nBranchId =*/ 0x76b809bb, /*.strName =*/ "Sapling", /*.strInfo =*/ "See https://z.cash/upgrade/sapling.html for details.", + }, + { + /*.nBranchId =*/ 0x2bb40e60, + /*.strName =*/ "Blossom", + /*.strInfo =*/ "See https://z.cash/upgrade/blossom.html for details.", } }; From b59b0a519f8c4f662b503dc6284f77906210b96f Mon Sep 17 00:00:00 2001 From: str4d Date: Tue, 2 Apr 2019 10:08:12 -0500 Subject: [PATCH 019/395] Update README.md Committed str4d's suggestion for final line. Co-Authored-By: wmpea --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1c5910283c0..c66ac1ea24f 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ Build Zcash along with most dependencies from source by running the following co ./zcutil/build.sh -j$(nproc) ``` -Currently, Zcash is only built for Linux. +Currently, Zcash is only officially supported on Debian and Ubuntu. License ------- From 1f561f323f54191e1323a8cd2df101df4f054b62 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 4 Apr 2019 18:27:46 +0100 Subject: [PATCH 020/395] init: Fix new HD seed generation for previously-encrypted wallets Closes #3607. --- src/init.cpp | 8 ++++++-- src/wallet/wallet.cpp | 8 +++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index f9da81e877d..6910cf30888 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1645,8 +1645,12 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (!pwalletMain->HaveHDSeed()) { - // generate a new HD seed - pwalletMain->GenerateNewSeed(); + // We can't set the new HD seed until the wallet is decrypted. + // https://github.com/zcash/zcash/issues/3607 + if (!pwalletMain->IsCrypted()) { + // generate a new HD seed + pwalletMain->GenerateNewSeed(); + } } if (fFirstRun) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 6dfa150252c..97500911a66 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -499,8 +499,14 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase) return false; if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey)) continue; // try another master key - if (CCryptoKeyStore::Unlock(vMasterKey)) + if (CCryptoKeyStore::Unlock(vMasterKey)) { + // Now that the wallet is decrypted, ensure we have an HD seed. + // https://github.com/zcash/zcash/issues/3607 + if (!this->HaveHDSeed()) { + this->GenerateNewSeed(); + } return true; + } } } return false; From e4d40e4756135d2eafc29a558822f71990e13376 Mon Sep 17 00:00:00 2001 From: Mary Moore-Simmons Date: Tue, 9 Apr 2019 09:57:17 -0600 Subject: [PATCH 021/395] Creates checklist template for new PRs being opened and addresses Str4d's suggestion for using GitHub handles --- .github/pull_request_template.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000000..18694855b37 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,5 @@ +Please ensure this checklist is followed for any pull requests for this repo. This checklist must be checked by both the PR creator and by anyone who reviews the PR. +* [ ] Relevant documentation for this PR has to be completed and reviewed by the documentation team (@ioptio, @mdr0id, or @Eirik0) before the PR can be merged +* [ ] A test plan for the PR must be documented in the PR notes and included in the test plan for the next regular release + +As a note, all buildbot tests need to be passing and all appropriate code reviews need to be done before this PR can be merged From 82848efb0ea68e5653cf3e386bed02584d1e9404 Mon Sep 17 00:00:00 2001 From: Gareth Davies Date: Sun, 21 Apr 2019 06:56:08 -0700 Subject: [PATCH 022/395] Adding addressindex.h to Makefile.am Co-authored by: Daira Hopwood --- src/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile.am b/src/Makefile.am index 5733549ff91..c8bb46fb897 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -114,6 +114,7 @@ LIBZCASH_H = \ .PHONY: FORCE collate-libsnark check-symbols check-security # bitcoin core # BITCOIN_CORE_H = \ + addressindex.h \ addrman.h \ alert.h \ amount.h \ From 4c1a8884f41d83f9af67447fa0e749b7164a431c Mon Sep 17 00:00:00 2001 From: Simon Date: Fri, 19 Apr 2019 10:54:51 -0700 Subject: [PATCH 023/395] Add testnet and regtest experimental feature: -developersetpoolsizezero --- src/chainparams.cpp | 9 +++++++++ src/init.cpp | 5 +++-- src/main.cpp | 19 +++++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 45b77a09ede..5857b0776bc 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -491,6 +491,10 @@ class CRegTestParams : public CChainParams { assert(idx > Consensus::BASE_SPROUT && idx < Consensus::MAX_NETWORK_UPGRADES); consensus.vUpgrades[idx].nActivationHeight = nActivationHeight; } + + void SetRegTestZIP209Enabled() { + fZIP209Enabled = true; + } }; static CRegTestParams regTestParams; @@ -523,6 +527,11 @@ void SelectParams(CBaseChainParams::Network network) { if (network == CBaseChainParams::REGTEST && mapArgs.count("-regtestprotectcoinbase")) { regTestParams.SetRegTestCoinbaseMustBeProtected(); } + + // When a developer is debugging turnstile violations in regtest mode, enable ZIP209 + if (network == CBaseChainParams::REGTEST && mapArgs.count("-developersetpoolsizezero")) { + regTestParams.SetRegTestZIP209Enabled(); + } } bool SelectParamsFromCommandLine() diff --git a/src/init.cpp b/src/init.cpp index ec459e36b21..d52e1baa36f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -834,8 +834,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (!fExperimentalMode) { if (mapArgs.count("-developerencryptwallet")) { return InitError(_("Wallet encryption requires -experimentalfeatures.")); - } - else if (mapArgs.count("-paymentdisclosure")) { + } else if (mapArgs.count("-developersetpoolsizezero")) { + return InitError(_("Setting the size of shielded pools to zero requires -experimentalfeatures.")); + } else if (mapArgs.count("-paymentdisclosure")) { return InitError(_("Payment disclosure requires -experimentalfeatures.")); } else if (mapArgs.count("-zmergetoaddress")) { return InitError(_("RPC method z_mergetoaddress requires -experimentalfeatures.")); diff --git a/src/main.cpp b/src/main.cpp index 4c47cfa0c80..72744b61a72 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3457,6 +3457,14 @@ void FallbackSproutValuePoolBalance( return; } + // When developer option -developersetpoolsizezero is enabled, we don't need a fallback balance. + if ((chainparams.NetworkIDString() == "test" || chainparams.NetworkIDString() == "regtest") && + fExperimentalMode && + mapArgs.count("-developersetpoolsizezero")) + { + return; + } + // Check if the height of this block matches the checkpoint if (pindex->nHeight == chainparams.SproutValuePoolCheckpointHeight()) { if (pindex->GetBlockHash() == chainparams.SproutValuePoolCheckpointBlockHash()) { @@ -4243,6 +4251,17 @@ bool static LoadBlockIndexDB() // Fall back to hardcoded Sprout value pool balance FallbackSproutValuePoolBalance(pindex, chainparams); + + // If developer option -developersetpoolsizezero has been enabled on testnet or in regtest mode, + // override and set the in-memory size of shielded pools to zero. An unshielding transaction + // can then be used to trigger and test the handling of turnstile violations. + if ((chainparams.NetworkIDString() == "test" || chainparams.NetworkIDString() == "regtest") && + fExperimentalMode && + mapArgs.count("-developersetpoolsizezero")) + { + pindex->nChainSproutValue = 0; + pindex->nChainSaplingValue = 0; + } } // Construct in-memory chain of branch IDs. // Relies on invariant: a block that does not activate a network upgrade From 3d018ab5560cf6115fcd4e3291a3ddebeb66482f Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Tue, 23 Apr 2019 11:06:23 -0600 Subject: [PATCH 024/395] add -spentindex changes for bitcore insight block explorer --- src/Makefile.am | 1 + src/main.cpp | 53 ++++++++++++++++++----- src/main.h | 4 ++ src/script/script.cpp | 3 +- src/spentindex.h | 97 +++++++++++++++++++++++++++++++++++++++++++ src/txdb.cpp | 18 +++++++- src/txdb.h | 5 +++ 7 files changed, 169 insertions(+), 12 deletions(-) create mode 100644 src/spentindex.h diff --git a/src/Makefile.am b/src/Makefile.am index c8bb46fb897..f3d20b8c431 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -189,6 +189,7 @@ BITCOIN_CORE_H = \ script/sign.h \ script/standard.h \ serialize.h \ + spentindex.h \ streams.h \ support/allocators/secure.h \ support/allocators/zeroafterfree.h \ diff --git a/src/main.cpp b/src/main.cpp index 4c47cfa0c80..6164406cb22 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -69,6 +69,7 @@ bool fReindex = false; bool fTxIndex = false; bool fInsightExplorer = false; // insightexplorer bool fAddressIndex = false; // insightexplorer +bool fSpentIndex = false; // insightexplorer bool fHavePruned = false; bool fPruneMode = false; bool fIsBareMultisigStd = true; @@ -2229,10 +2230,10 @@ enum DisconnectResult /** Undo the effects of this block (with given index) on the UTXO set represented by coins. * When UNCLEAN or FAILED is returned, view is left in an indeterminate state. - * The addressIndex will be updated if requested. + * The addressIndex and spentIndex will be updated if requested. */ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& state, - const CBlockIndex* pindex, CCoinsViewCache& view, const bool fUpdateAddressIndex) + const CBlockIndex* pindex, CCoinsViewCache& view, bool const updateIndices) { assert(pindex->GetBlockHash() == view.GetBestBlock()); @@ -2255,6 +2256,7 @@ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& s } std::vector addressIndex; std::vector addressUnspentIndex; + std::vector spentIndex; // undo transactions in reverse order for (int i = block.vtx.size() - 1; i >= 0; i--) { @@ -2263,7 +2265,7 @@ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& s // insightexplorer // https://github.com/bitpay/bitcoin/commit/017f548ea6d89423ef568117447e61dd5707ec42#diff-7ec3c68a81efff79b6ca22ac1f1eabbaR2236 - if (fAddressIndex && fUpdateAddressIndex) { + if (fAddressIndex && updateIndices) { for (unsigned int k = tx.vout.size(); k-- > 0;) { const CTxOut &out = tx.vout[k]; int const scriptType = out.scriptPubKey.Type(); @@ -2320,8 +2322,8 @@ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& s // insightexplorer // https://github.com/bitpay/bitcoin/commit/017f548ea6d89423ef568117447e61dd5707ec42#diff-7ec3c68a81efff79b6ca22ac1f1eabbaR2304 - if (fAddressIndex && fUpdateAddressIndex) { - const CTxIn input = tx.vin[j]; + const CTxIn input = tx.vin[j]; + if (fAddressIndex && updateIndices) { const CTxOut &prevout = view.GetOutputFor(input); int const scriptType = prevout.scriptPubKey.Type(); if (scriptType > 0) { @@ -2338,6 +2340,13 @@ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& s CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight))); } } + // insightexplorer + if (fSpentIndex && updateIndices) { + // undo and delete the spent index + spentIndex.push_back(make_pair( + CSpentIndexKey(input.prevout.hash, input.prevout.n), + CSpentIndexValue())); + } } } } @@ -2360,7 +2369,7 @@ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& s view.SetBestBlock(pindex->pprev->GetBlockHash()); // insightexplorer - if (fAddressIndex && fUpdateAddressIndex) { + if (fAddressIndex && updateIndices) { if (!pblocktree->EraseAddressIndex(addressIndex)) { AbortNode(state, "Failed to delete address index"); return DISCONNECT_FAILED; @@ -2370,6 +2379,13 @@ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& s return DISCONNECT_FAILED; } } + // insightexplorer + if (fSpentIndex && updateIndices) { + if (!pblocktree->UpdateSpentIndex(spentIndex)) { + AbortNode(state, "Failed to write transaction index"); + return DISCONNECT_FAILED; + } + } return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN; } @@ -2568,6 +2584,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin blockundo.vtxundo.reserve(block.vtx.size() - 1); std::vector addressIndex; std::vector addressUnspentIndex; + std::vector spentIndex; // Construct the incremental merkle tree at the current // block position, @@ -2619,15 +2636,14 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // insightexplorer // https://github.com/bitpay/bitcoin/commit/017f548ea6d89423ef568117447e61dd5707ec42#diff-7ec3c68a81efff79b6ca22ac1f1eabbaR2597 - if (fAddressIndex) { + if (fAddressIndex || fSpentIndex) { for (size_t j = 0; j < tx.vin.size(); j++) { const CTxIn input = tx.vin[j]; const CTxOut &prevout = view.GetOutputFor(tx.vin[j]); int const scriptType = prevout.scriptPubKey.Type(); - if (scriptType > 0) { - uint160 const addrHash = prevout.scriptPubKey.AddressHash(); - + const uint160 addrHash = prevout.scriptPubKey.AddressHash(); + if (fAddressIndex && scriptType > 0) { // record spending activity addressIndex.push_back(make_pair( CAddressIndexKey(scriptType, addrHash, pindex->nHeight, i, hash, j, true), @@ -2638,6 +2654,15 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin CAddressUnspentKey(scriptType, addrHash, input.prevout.hash, input.prevout.n), CAddressUnspentValue())); } + if (fSpentIndex) { + // Add the spent index to determine the txid and input that spent an output + // and to find the amount and address from an input. + // If we do not recognize the script type, we still add an entry to the + // spentindex db, with a script type of 0 and addrhash of all zeroes. + spentIndex.push_back(make_pair( + CSpentIndexKey(input.prevout.hash, input.prevout.n), + CSpentIndexValue(hash, j, pindex->nHeight, prevout.nValue, scriptType, addrHash))); + } } } @@ -2785,6 +2810,12 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return AbortNode(state, "Failed to write address unspent index"); } } + // insightexplorer + if (fSpentIndex) { + if (!pblocktree->UpdateSpentIndex(spentIndex)) { + return AbortNode(state, "Failed to write spent index"); + } + } // add this block to the view's block chain view.SetBestBlock(pindex->GetBlockHash()); @@ -4321,6 +4352,7 @@ bool static LoadBlockIndexDB() pblocktree->ReadFlag("insightexplorer", fInsightExplorer); LogPrintf("%s: insight explorer %s\n", __func__, fAddressIndex ? "enabled" : "disabled"); fAddressIndex = fInsightExplorer; + fSpentIndex = fInsightExplorer; // Fill in-memory data BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex) @@ -4663,6 +4695,7 @@ bool InitBlockIndex() { fInsightExplorer = GetBoolArg("-insightexplorer", false); pblocktree->WriteFlag("insightexplorer", fInsightExplorer); fAddressIndex = fInsightExplorer; + fSpentIndex = fInsightExplorer; LogPrintf("Initializing databases...\n"); diff --git a/src/main.h b/src/main.h index 3b8c6aff9db..f19fc84ff38 100644 --- a/src/main.h +++ b/src/main.h @@ -27,6 +27,7 @@ #include "txmempool.h" #include "uint256.h" #include "addressindex.h" +#include "spentindex.h" #include #include @@ -143,6 +144,9 @@ extern bool fInsightExplorer; // Maintain a full address index, used to query for the balance, txids and unspent outputs for addresses extern bool fAddressIndex; +// Maintain a full spent index, used to query the spending txid and input index for an outpoint +extern bool fSpentIndex; + // END insightexplorer extern bool fIsBareMultisigStd; diff --git a/src/script/script.cpp b/src/script/script.cpp index 32fe34b5949..9d13fd040cd 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -262,8 +262,9 @@ uint160 CScript::AddressHash() const else if (this->IsPayToScriptHash()) start = 2; else { - // unknown script type; return an empty vector + // unknown script type; return zeros vector hashBytes; + hashBytes.resize(20); return uint160(hashBytes); } vector hashBytes(this->begin()+start, this->begin()+start+20); diff --git a/src/spentindex.h b/src/spentindex.h new file mode 100644 index 00000000000..3e11b60809a --- /dev/null +++ b/src/spentindex.h @@ -0,0 +1,97 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_SPENTINDEX_H +#define BITCOIN_SPENTINDEX_H + +#include "uint256.h" +#include "amount.h" + +struct CSpentIndexKey { + uint256 txid; + unsigned int outputIndex; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(txid); + READWRITE(outputIndex); + } + + CSpentIndexKey(uint256 t, unsigned int i) { + txid = t; + outputIndex = i; + } + + CSpentIndexKey() { + SetNull(); + } + + void SetNull() { + txid.SetNull(); + outputIndex = 0; + } +}; + +struct CSpentIndexValue { + uint256 txid; + unsigned int inputIndex; + int blockHeight; + CAmount satoshis; + int addressType; + uint160 addressHash; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(txid); + READWRITE(inputIndex); + READWRITE(blockHeight); + READWRITE(satoshis); + READWRITE(addressType); + READWRITE(addressHash); + } + + CSpentIndexValue(uint256 t, unsigned int i, int h, CAmount s, int type, uint160 a) { + txid = t; + inputIndex = i; + blockHeight = h; + satoshis = s; + addressType = type; + addressHash = a; + } + + CSpentIndexValue() { + SetNull(); + } + + void SetNull() { + txid.SetNull(); + inputIndex = 0; + blockHeight = 0; + satoshis = 0; + addressType = 0; + addressHash.SetNull(); + } + + bool IsNull() const { + return txid.IsNull(); + } +}; + +struct CSpentIndexKeyCompare +{ + bool operator()(const CSpentIndexKey& a, const CSpentIndexKey& b) const { + if (a.txid == b.txid) { + return a.outputIndex < b.outputIndex; + } else { + return a.txid < b.txid; + } + } +}; + +#endif // BITCOIN_SPENTINDEX_H diff --git a/src/txdb.cpp b/src/txdb.cpp index 162a790140b..b0c89f7d367 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -38,7 +38,7 @@ static const char DB_LAST_BLOCK = 'l'; // insightexplorer static const char DB_ADDRESSINDEX = 'd'; static const char DB_ADDRESSUNSPENTINDEX = 'u'; - +static const char DB_SPENTINDEX = 'p'; CCoinsViewDB::CCoinsViewDB(std::string dbName, size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / dbName, nCacheSize, fMemory, fWipe) { } @@ -374,6 +374,22 @@ bool CBlockTreeDB::ReadAddressIndex( } return true; } + +bool CBlockTreeDB::ReadSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value) { + return Read(make_pair(DB_SPENTINDEX, key), value); +} + +bool CBlockTreeDB::UpdateSpentIndex(const std::vector &vect) { + CDBBatch batch(*this); + for (std::vector::const_iterator it=vect.begin(); it!=vect.end(); it++) { + if (it->second.IsNull()) { + batch.Erase(make_pair(DB_SPENTINDEX, it->first)); + } else { + batch.Write(make_pair(DB_SPENTINDEX, it->first), it->second); + } + } + return WriteBatch(batch); +} // END insightexplorer bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) { diff --git a/src/txdb.h b/src/txdb.h index 305e93e9c15..f1f78085184 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -24,9 +24,12 @@ struct CAddressUnspentValue; struct CAddressIndexKey; struct CAddressIndexIteratorKey; struct CAddressIndexIteratorHeightKey; +struct CSpentIndexKey; +struct CSpentIndexValue; typedef std::pair CAddressUnspentDbEntry; typedef std::pair CAddressIndexDbEntry; +typedef std::pair CSpentIndexDbEntry; // END insightexplorer class uint256; @@ -89,6 +92,8 @@ class CBlockTreeDB : public CDBWrapper bool WriteAddressIndex(const std::vector &vect); bool EraseAddressIndex(const std::vector &vect); bool ReadAddressIndex(uint160 addressHash, int type, std::vector &addressIndex, int start = 0, int end = 0); + bool ReadSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value); + bool UpdateSpentIndex(const std::vector &vect); // END insightexplorer bool WriteFlag(const std::string &name, bool fValue); From c17d828ffdbce43d1fa0dc18a75d7d5a98945645 Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Fri, 12 Apr 2019 12:25:13 -0600 Subject: [PATCH 025/395] Update boost from v1.69.0 to v1.70.0. #3947 --- depends/packages/boost.mk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index 3e274c7e48d..a5c90cece97 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -1,8 +1,8 @@ package=boost -$(package)_version=1_69_0 -$(package)_download_path=https://dl.bintray.com/boostorg/release/1.69.0/source +$(package)_version=1_70_0 +$(package)_download_path=https://dl.bintray.com/boostorg/release/1.70.0/source $(package)_file_name=$(package)_$($(package)_version).tar.bz2 -$(package)_sha256_hash=8f32d4617390d1c2d16f26a27ab60d97807b35440d45891fa340fc2648b04406 +$(package)_sha256_hash=430ae8354789de4fd19ee52f3b1f739e1fba576f0aded0897c3c2bc00fb38778 define $(package)_set_vars $(package)_config_opts_release=variant=release From d6b47948bf04800e603708d034eb9dc9883e24e7 Mon Sep 17 00:00:00 2001 From: Simon Date: Fri, 19 Apr 2019 10:57:12 -0700 Subject: [PATCH 026/395] Add qa test for experimental feature: -developersetpoolsizezero --- qa/pull-tester/rpc-tests.sh | 1 + qa/rpc-tests/turnstile.py | 204 ++++++++++++++++++++++++++++++++++++ 2 files changed, 205 insertions(+) create mode 100755 qa/rpc-tests/turnstile.py diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index 3d6be26dd5c..19c65a0b5f6 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -71,6 +71,7 @@ testScripts=( 'p2p_node_bloom.py' 'regtest_signrawtransaction.py' 'finalsaplingroot.py' + 'turnstile.py' ); testScriptsExt=( 'getblocktemplate_longpoll.py' diff --git a/qa/rpc-tests/turnstile.py b/qa/rpc-tests/turnstile.py new file mode 100755 index 00000000000..89d680f0b13 --- /dev/null +++ b/qa/rpc-tests/turnstile.py @@ -0,0 +1,204 @@ +#!/usr/bin/env python +# Copyright (c) 2019 The Zcash developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Test Sprout and Sapling turnstile violations +# +# Experimental feature -developersetpoolsizezero will, upon node launch, +# set the in-memory size of shielded pools to zero. +# +# An unshielding operation can then be used to verify: +# 1. Turnstile violating transactions are excluded by the miner +# 2. Turnstile violating blocks are rejected by nodes +# +# By default, ZIP209 support is disabled in regtest mode, but gets enabled +# when experimental feature -developersetpoolsizezero is switched on. +# +# To perform a manual turnstile test on testnet: +# 1. Launch zcashd +# 2. Shield transparent funds +# 3. Wait for transaction to be mined +# 4. Restart zcashd, enabling experimental feature -developersetpoolsizezero +# 5. Unshield funds +# 6. Wait for transaction to be mined (using testnet explorer or another node) +# 7. Verify zcashd rejected the block +# + +import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + assert_equal, + get_coinbase_address, + start_node, start_nodes, + sync_blocks, sync_mempools, + initialize_chain_clean, connect_nodes_bi, + wait_and_assert_operationid_status, + bitcoind_processes +) +from decimal import Decimal + +NUPARAMS_ARGS = ['-nuparams=5ba81b19:100', # Overwinter + '-nuparams=76b809bb:101'] # Sapling +TURNSTILE_ARGS = ['-experimentalfeatures', + '-developersetpoolsizezero'] + +class TurnstileTest (BitcoinTestFramework): + + def setup_chain(self): + print("Initializing test directory " + self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 3) + + def setup_network(self, split=False): + self.nodes = start_nodes(3, self.options.tmpdir, + extra_args=[NUPARAMS_ARGS] * 3) + connect_nodes_bi(self.nodes,0,1) + connect_nodes_bi(self.nodes,1,2) + self.is_network_split=False + self.sync_all() + + # Helper method to verify the size of a shielded value pool for a given node + def assert_pool_balance(self, node, name, balance): + pools = node.getblockchaininfo()['valuePools'] + for pool in pools: + if pool['id'] == name: + assert_equal(pool['chainValue'], balance, message="for pool named %r" % (name,)) + return + assert False, "pool named %r not found" % (name,) + + # Helper method to start a single node with extra args and sync to the network + def start_and_sync_node(self, index, args=[]): + self.nodes[index] = start_node(index, self.options.tmpdir, extra_args=NUPARAMS_ARGS + args) + connect_nodes_bi(self.nodes,0,1) + connect_nodes_bi(self.nodes,1,2) + connect_nodes_bi(self.nodes,0,2) + self.sync_all() + + # Helper method to stop and restart a single node with extra args and sync to the network + def restart_and_sync_node(self, index, args=[]): + self.nodes[index].stop() + bitcoind_processes[index].wait() + self.start_and_sync_node(index, args) + + def run_test(self): + # Sanity-check the test harness + self.nodes[0].generate(101) + assert_equal(self.nodes[0].getblockcount(), 101) + self.sync_all() + + # Node 0 shields some funds + dest_addr = self.nodes[0].z_getnewaddress(POOL_NAME.lower()) + taddr0 = get_coinbase_address(self.nodes[0]) + recipients = [] + recipients.append({"address": dest_addr, "amount": Decimal('10')}) + myopid = self.nodes[0].z_sendmany(taddr0, recipients, 1, 0) + wait_and_assert_operationid_status(self.nodes[0], myopid) + self.sync_all() + self.nodes[0].generate(1) + self.sync_all() + assert_equal(self.nodes[0].z_getbalance(dest_addr), Decimal('10')) + + # Verify size of shielded pool + self.assert_pool_balance(self.nodes[0], POOL_NAME.lower(), Decimal('10')) + self.assert_pool_balance(self.nodes[1], POOL_NAME.lower(), Decimal('10')) + self.assert_pool_balance(self.nodes[2], POOL_NAME.lower(), Decimal('10')) + + # Relaunch node 0 with in-memory size of value pools set to zero. + self.restart_and_sync_node(0, TURNSTILE_ARGS) + + # Verify size of shielded pool + self.assert_pool_balance(self.nodes[0], POOL_NAME.lower(), Decimal('0')) + self.assert_pool_balance(self.nodes[1], POOL_NAME.lower(), Decimal('10')) + self.assert_pool_balance(self.nodes[2], POOL_NAME.lower(), Decimal('10')) + + # Node 0 creates an unshielding transaction + recipients = [] + recipients.append({"address": taddr0, "amount": Decimal('1')}) + myopid = self.nodes[0].z_sendmany(dest_addr, recipients, 1, 0) + mytxid = wait_and_assert_operationid_status(self.nodes[0], myopid) + + # Verify transaction appears in mempool of nodes + self.sync_all() + assert(mytxid in self.nodes[0].getrawmempool()) + assert(mytxid in self.nodes[1].getrawmempool()) + assert(mytxid in self.nodes[2].getrawmempool()) + + # Node 0 mines a block + count = self.nodes[0].getblockcount() + self.nodes[0].generate(1) + self.sync_all() + + # Verify the mined block does not contain the unshielding transaction + block = self.nodes[0].getblock(self.nodes[0].getbestblockhash()) + assert_equal(len(block["tx"]), 1) + assert_equal(block["height"], count + 1) + + # Stop node 0 and check logs to verify the miner excluded the transaction from the block + self.nodes[0].stop() + bitcoind_processes[0].wait() + logpath = self.options.tmpdir + "/node0/regtest/debug.log" + foundErrorMsg = False + with open(logpath, "r") as myfile: + logdata = myfile.readlines() + for logline in logdata: + if "CreateNewBlock(): tx " + mytxid + " appears to violate " + POOL_NAME.capitalize() + " turnstile" in logline: + foundErrorMsg = True + break + assert(foundErrorMsg) + + # Launch node 0 with in-memory size of value pools set to zero. + self.start_and_sync_node(0, TURNSTILE_ARGS) + + # Node 1 mines a block + oldhash = self.nodes[0].getbestblockhash() + self.nodes[1].generate(1) + newhash = self.nodes[1].getbestblockhash() + + # Verify block contains the unshielding transaction + assert(mytxid in self.nodes[1].getblock(newhash)["tx"]) + + # Verify nodes 1 and 2 have accepted the block as valid + sync_blocks(self.nodes[1:3]) + sync_mempools(self.nodes[1:3]) + assert_equal(len(self.nodes[1].getrawmempool()), 0) + assert_equal(len(self.nodes[2].getrawmempool()), 0) + + # Verify node 0 has not accepted the block + assert_equal(oldhash, self.nodes[0].getbestblockhash()) + assert(mytxid in self.nodes[0].getrawmempool()) + self.assert_pool_balance(self.nodes[0], POOL_NAME.lower(), Decimal('0')) + + # Verify size of shielded pool + self.assert_pool_balance(self.nodes[0], POOL_NAME.lower(), Decimal('0')) + self.assert_pool_balance(self.nodes[1], POOL_NAME.lower(), Decimal('9')) + self.assert_pool_balance(self.nodes[2], POOL_NAME.lower(), Decimal('9')) + + # Stop node 0 and check logs to verify the block was rejected as a turnstile violation + self.nodes[0].stop() + bitcoind_processes[0].wait() + logpath = self.options.tmpdir + "/node0/regtest/debug.log" + foundConnectBlockErrorMsg = False + foundInvalidBlockErrorMsg = False + foundConnectTipErrorMsg = False + with open(logpath, "r") as myfile: + logdata = myfile.readlines() + for logline in logdata: + if "ConnectBlock(): turnstile violation in " + POOL_NAME.capitalize() + " shielded value pool" in logline: + foundConnectBlockErrorMsg = True + elif "InvalidChainFound: invalid block=" + newhash in logline: + foundInvalidBlockErrorMsg = True + elif "ConnectTip(): ConnectBlock " + newhash + " failed" in logline: + foundConnectTipErrorMsg = True + assert(foundConnectBlockErrorMsg and foundInvalidBlockErrorMsg and foundConnectTipErrorMsg) + + # Launch node 0 without overriding the pool size, so the node can sync with rest of network. + self.start_and_sync_node(0) + assert_equal(newhash, self.nodes[0].getbestblockhash()) + +if __name__ == '__main__': + POOL_NAME = "SPROUT" + TurnstileTest().main() + POOL_NAME = "SAPLING" + TurnstileTest().main() From fc79a848fba6d8ce51af933ccf7dac807db6f0c3 Mon Sep 17 00:00:00 2001 From: Simon Date: Tue, 23 Apr 2019 22:57:30 -0700 Subject: [PATCH 027/395] Enable ZIP209 on mainnet and set fallback Sprout pool balance. --- src/chainparams.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 5857b0776bc..e0769fcae5f 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -193,6 +193,14 @@ class CMainParams : public CChainParams { // total number of tx / (checkpoint block height / (24 * 24)) }; + // Hardcoded fallback value for the Sprout shielded value pool balance + // for nodes that have not reindexed since the introduction of monitoring + // in #2795. + nSproutValuePoolCheckpointHeight = 520633; + nSproutValuePoolCheckpointBalance = 22145062442933; + fZIP209Enabled = true; + hashSproutValuePoolCheckpointBlock = uint256S("0000000000c7b46b6bc04b4cbf87d8bb08722aebd51232619b214f7273f8460e"); + // Founders reward script expects a vector of 2-of-3 multisig addresses vFoundersRewardAddress = { "t3Vz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd", /* main-index: 0*/ From 867786d777a90fb1301772330460dff6a33f0c43 Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 24 Apr 2019 08:40:17 -0700 Subject: [PATCH 028/395] Enable experimental feature -developersetpoolsizezero on mainnet. --- src/main.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 72744b61a72..927435ffe1a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3451,17 +3451,12 @@ void FallbackSproutValuePoolBalance( const CChainParams& chainparams ) { - // We might not want to enable the checkpointing for mainnet - // yet. if (!chainparams.ZIP209Enabled()) { return; } // When developer option -developersetpoolsizezero is enabled, we don't need a fallback balance. - if ((chainparams.NetworkIDString() == "test" || chainparams.NetworkIDString() == "regtest") && - fExperimentalMode && - mapArgs.count("-developersetpoolsizezero")) - { + if (fExperimentalMode && mapArgs.count("-developersetpoolsizezero")) { return; } @@ -4252,13 +4247,10 @@ bool static LoadBlockIndexDB() // Fall back to hardcoded Sprout value pool balance FallbackSproutValuePoolBalance(pindex, chainparams); - // If developer option -developersetpoolsizezero has been enabled on testnet or in regtest mode, + // If developer option -developersetpoolsizezero has been enabled, // override and set the in-memory size of shielded pools to zero. An unshielding transaction // can then be used to trigger and test the handling of turnstile violations. - if ((chainparams.NetworkIDString() == "test" || chainparams.NetworkIDString() == "regtest") && - fExperimentalMode && - mapArgs.count("-developersetpoolsizezero")) - { + if (fExperimentalMode && mapArgs.count("-developersetpoolsizezero")) { pindex->nChainSproutValue = 0; pindex->nChainSaplingValue = 0; } From 81a45d6984ef656f3b82829b20717a0c9d497d5b Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Mon, 18 Mar 2019 20:33:02 -0600 Subject: [PATCH 029/395] Add rpc to enable and disable Sprout to Sapling migration --- qa/pull-tester/rpc-tests.sh | 1 + qa/rpc-tests/sprout_sapling_migration.py | 96 +++++++++ qa/rpc-tests/test_framework/util.py | 13 +- src/Makefile.am | 2 + src/main.cpp | 5 + src/main.h | 1 + src/validationinterface.cpp | 3 + src/validationinterface.h | 3 + .../asyncrpcoperation_saplingmigration.cpp | 196 ++++++++++++++++++ .../asyncrpcoperation_saplingmigration.h | 31 +++ src/wallet/rpcwallet.cpp | 22 ++ src/wallet/wallet.cpp | 47 +++++ src/wallet/wallet.h | 6 + 13 files changed, 421 insertions(+), 5 deletions(-) create mode 100755 qa/rpc-tests/sprout_sapling_migration.py create mode 100644 src/wallet/asyncrpcoperation_saplingmigration.cpp create mode 100644 src/wallet/asyncrpcoperation_saplingmigration.h diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index 19c65a0b5f6..d072898b26d 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -71,6 +71,7 @@ testScripts=( 'p2p_node_bloom.py' 'regtest_signrawtransaction.py' 'finalsaplingroot.py' + 'sprout_sapling_migration.py' 'turnstile.py' ); testScriptsExt=( diff --git a/qa/rpc-tests/sprout_sapling_migration.py b/qa/rpc-tests/sprout_sapling_migration.py new file mode 100755 index 00000000000..726e5e2aa61 --- /dev/null +++ b/qa/rpc-tests/sprout_sapling_migration.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python +# Copyright (c) 2019 The Zcash developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." + +from decimal import Decimal +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import assert_equal, assert_true, get_coinbase_address, \ + initialize_chain_clean, start_nodes, wait_and_assert_operationid_status + + +class SproutSaplingMigration(BitcoinTestFramework): + def setup_nodes(self): + return start_nodes(4, self.options.tmpdir, [[ + '-nuparams=5ba81b19:100', # Overwinter + '-nuparams=76b809bb:100', # Sapling + ]] * 4) + + def setup_chain(self): + print("Initializing test directory " + self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 4) + + def run_test(self): + print "Mining blocks..." + self.nodes[0].generate(101) + self.sync_all() + + # Send some ZEC to a Sprout address + tAddr = get_coinbase_address(self.nodes[0]) + sproutAddr = self.nodes[0].z_getnewaddress('sprout') + saplingAddr = self.nodes[0].z_getnewaddress('sapling') + + opid = self.nodes[0].z_sendmany(tAddr, [{"address": sproutAddr, "amount": Decimal('10')}], 1, 0) + wait_and_assert_operationid_status(self.nodes[0], opid) + self.nodes[0].generate(1) + self.sync_all() + + assert_equal(self.nodes[0].z_getbalance(sproutAddr), Decimal('10')) + assert_equal(self.nodes[0].z_getbalance(saplingAddr), Decimal('0')) + + # Migrate + assert_equal(True, self.nodes[0].z_setmigration(True)) + print "Mining to block 494..." + self.nodes[0].generate(392) # 102 -> 494 + self.sync_all() + + # At 494 we should have no async operations + assert_equal(0, len(self.nodes[0].z_getoperationstatus()), "num async operations at 494") + + self.nodes[0].generate(1) + self.sync_all() + + # At 495 we should have an async operation + operationstatus = self.nodes[0].z_getoperationstatus() + assert_equal(1, len(operationstatus), "num async operations at 495") + assert_equal('saplingmigration', operationstatus[0]['method']) + assert_equal(500, operationstatus[0]['target_height']) + + print "migration operation: {}".format(operationstatus) + migration_opid = operationstatus[0]['id'] + result = wait_and_assert_operationid_status(self.nodes[0], migration_opid) + print "result: {}".format(result) + assert_equal(0, len(self.nodes[0].getrawmempool()), "mempool size at 495") + + self.nodes[0].generate(3) + self.sync_all() + + # At 498 the mempool will be empty and no funds will have moved + assert_equal(0, len(self.nodes[0].getrawmempool()), "mempool size at 498") + assert_equal(self.nodes[0].z_getbalance(sproutAddr), Decimal('10')) + assert_equal(self.nodes[0].z_getbalance(saplingAddr), Decimal('0')) + + self.nodes[0].generate(1) + self.sync_all() + + # At 499 there will be a transaction in the mempool and the note will be locked + assert_equal(1, len(self.nodes[0].getrawmempool()), "mempool size at 499") + assert_equal(self.nodes[0].z_getbalance(sproutAddr), Decimal('0')) + assert_equal(self.nodes[0].z_getbalance(saplingAddr), Decimal('0')) + assert_true(self.nodes[0].z_getbalance(saplingAddr, 0) > Decimal('0'), "Unconfirmed sapling") + + self.nodes[0].generate(1) + self.sync_all() + + # At 500 funds will have moved + sprout_balance = self.nodes[0].z_getbalance(sproutAddr) + sapling_balance = self.nodes[0].z_getbalance(saplingAddr) + print "sprout balance: {}, sapling balance: {}".format(sprout_balance, sapling_balance) + assert_true(sprout_balance < Decimal('10'), "Should have less Sprout funds") + assert_true(sapling_balance > Decimal('0'), "Should have more Sapling funds") + + +if __name__ == '__main__': + SproutSaplingMigration().main() diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index 77abec55dcd..7d15ec063c7 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -399,26 +399,29 @@ def wait_and_assert_operationid_status(node, myopid, in_status='success', in_err assert_true(result is not None, "timeout occured") status = result['status'] - txid = None + ret = None errormsg = None if status == "failed": errormsg = result['error']['message'] elif status == "success": - txid = result['result']['txid'] + if type(result['result']) is dict and result['result'].get('txid'): + ret = result['result']['txid'] + else: + ret = result['result'] if os.getenv("PYTHON_DEBUG", ""): print('...returned status: {}'.format(status)) if errormsg is not None: print('...returned error: {}'.format(errormsg)) - + assert_equal(in_status, status, "Operation returned mismatched status. Error Message: {}".format(errormsg)) if errormsg is not None: assert_true(in_errormsg is not None, "No error retured. Expected: {}".format(errormsg)) assert_true(in_errormsg in errormsg, "Error returned: {}. Error expected: {}".format(errormsg, in_errormsg)) - return result # if there was an error return the result + return result # if there was an error return the result else: - return txid # otherwise return the txid + return ret # otherwise return the txid # Find a coinbase address on the node, filtering by the number of UTXOs it has. # If no filter is provided, returns the coinbase address on the node containing diff --git a/src/Makefile.am b/src/Makefile.am index 16951f9d223..5924abfb6c6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -215,6 +215,7 @@ BITCOIN_CORE_H = \ validationinterface.h \ version.h \ wallet/asyncrpcoperation_mergetoaddress.h \ + wallet/asyncrpcoperation_saplingmigration.h \ wallet/asyncrpcoperation_sendmany.h \ wallet/asyncrpcoperation_shieldcoinbase.h \ wallet/crypter.h \ @@ -304,6 +305,7 @@ libbitcoin_wallet_a_SOURCES = \ zcbenchmarks.cpp \ zcbenchmarks.h \ wallet/asyncrpcoperation_mergetoaddress.cpp \ + wallet/asyncrpcoperation_saplingmigration.cpp \ wallet/asyncrpcoperation_sendmany.cpp \ wallet/asyncrpcoperation_shieldcoinbase.cpp \ wallet/crypter.cpp \ diff --git a/src/main.cpp b/src/main.cpp index 72744b61a72..782ab69b07f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -78,6 +78,7 @@ bool fCoinbaseEnforcedProtectionEnabled = true; size_t nCoinCacheUsage = 5000 * 300; uint64_t nPruneTarget = 0; bool fAlerts = DEFAULT_ALERTS; +bool fSaplingMigrationEnabled = false; /* If the tip is older than this (in seconds), the node is considered to be in initial block download. */ int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; @@ -3104,6 +3105,10 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * EnforceNodeDeprecation(pindexNew->nHeight); + if (fSaplingMigrationEnabled) { + GetMainSignals().RunSaplingMigration(pindexNew->nHeight); + } + int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1; LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001); LogPrint("bench", "- Connect block: %.2fms [%.2fs]\n", (nTime6 - nTime1) * 0.001, nTimeTotal * 0.000001); diff --git a/src/main.h b/src/main.h index 3b8c6aff9db..0e1fa669410 100644 --- a/src/main.h +++ b/src/main.h @@ -154,6 +154,7 @@ extern bool fCoinbaseEnforcedProtectionEnabled; extern size_t nCoinCacheUsage; extern CFeeRate minRelayTxFee; extern bool fAlerts; +extern bool fSaplingMigrationEnabled; extern int64_t nMaxTipAge; /** Best header we've seen so far (used for getheaders queries' starting points). */ diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 1dc3351ab27..bb3f800fc33 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -18,6 +18,7 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.EraseTransaction.connect(boost::bind(&CValidationInterface::EraseFromWallet, pwalletIn, _1)); g_signals.UpdatedTransaction.connect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1)); g_signals.ChainTip.connect(boost::bind(&CValidationInterface::ChainTip, pwalletIn, _1, _2, _3, _4, _5)); + g_signals.RunSaplingMigration.connect(boost::bind(&CValidationInterface::RunSaplingMigration, pwalletIn, _1)); g_signals.SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); g_signals.Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1)); @@ -33,6 +34,7 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1)); g_signals.Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); g_signals.ChainTip.disconnect(boost::bind(&CValidationInterface::ChainTip, pwalletIn, _1, _2, _3, _4, _5)); + g_signals.RunSaplingMigration.disconnect(boost::bind(&CValidationInterface::RunSaplingMigration, pwalletIn, _1)); g_signals.SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); g_signals.UpdatedTransaction.disconnect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1)); g_signals.EraseTransaction.disconnect(boost::bind(&CValidationInterface::EraseFromWallet, pwalletIn, _1)); @@ -47,6 +49,7 @@ void UnregisterAllValidationInterfaces() { g_signals.Broadcast.disconnect_all_slots(); g_signals.Inventory.disconnect_all_slots(); g_signals.ChainTip.disconnect_all_slots(); + g_signals.RunSaplingMigration.disconnect_all_slots(); g_signals.SetBestChain.disconnect_all_slots(); g_signals.UpdatedTransaction.disconnect_all_slots(); g_signals.EraseTransaction.disconnect_all_slots(); diff --git a/src/validationinterface.h b/src/validationinterface.h index 7b02bd9da4a..9e443d13459 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -37,6 +37,7 @@ class CValidationInterface { virtual void SyncTransaction(const CTransaction &tx, const CBlock *pblock) {} virtual void EraseFromWallet(const uint256 &hash) {} virtual void ChainTip(const CBlockIndex *pindex, const CBlock *pblock, SproutMerkleTree sproutTree, SaplingMerkleTree saplingTree, bool added) {} + virtual void RunSaplingMigration(int blockHeight) {} virtual void SetBestChain(const CBlockLocator &locator) {} virtual void UpdatedTransaction(const uint256 &hash) {} virtual void Inventory(const uint256 &hash) {} @@ -60,6 +61,8 @@ struct CMainSignals { boost::signals2::signal UpdatedTransaction; /** Notifies listeners of a change to the tip of the active block chain. */ boost::signals2::signal ChainTip; + /** Notifies listeners that they may need to update the status of the Sprout->Sapling migration */ + boost::signals2::signal RunSaplingMigration; /** Notifies listeners of a new active block chain. */ boost::signals2::signal SetBestChain; /** Notifies listeners about an inventory item being seen on the network. */ diff --git a/src/wallet/asyncrpcoperation_saplingmigration.cpp b/src/wallet/asyncrpcoperation_saplingmigration.cpp new file mode 100644 index 00000000000..6a043f9bf35 --- /dev/null +++ b/src/wallet/asyncrpcoperation_saplingmigration.cpp @@ -0,0 +1,196 @@ +#include "assert.h" +#include "boost/variant/static_visitor.hpp" +#include "asyncrpcoperation_saplingmigration.h" +#include "init.h" +#include "rpc/protocol.h" +#include "random.h" +#include "sync.h" +#include "tinyformat.h" +#include "transaction_builder.h" +#include "util.h" +#include "wallet.h" + +const CAmount FEE = 10000; + +AsyncRPCOperation_saplingmigration::AsyncRPCOperation_saplingmigration(int targetHeight) : targetHeight_(targetHeight) {} + +AsyncRPCOperation_saplingmigration::~AsyncRPCOperation_saplingmigration() {} + +void AsyncRPCOperation_saplingmigration::main() { + if (isCancelled()) + return; + + set_state(OperationStatus::EXECUTING); + start_execution_clock(); + + bool success = false; + + try { + success = main_impl(); + } catch (const UniValue& objError) { + int code = find_value(objError, "code").get_int(); + std::string message = find_value(objError, "message").get_str(); + set_error_code(code); + set_error_message(message); + } catch (const runtime_error& e) { + set_error_code(-1); + set_error_message("runtime error: " + string(e.what())); + } catch (const logic_error& e) { + set_error_code(-1); + set_error_message("logic error: " + string(e.what())); + } catch (const exception& e) { + set_error_code(-1); + set_error_message("general exception: " + string(e.what())); + } catch (...) { + set_error_code(-2); + set_error_message("unknown error"); + } + + stop_execution_clock(); + + if (success) { + set_state(OperationStatus::SUCCESS); + } else { + set_state(OperationStatus::FAILED); + } + + std::string s = strprintf("%s: Sprout->Sapling transactions sent. (status=%s", getId(), getStateAsString()); + if (success) { + s += strprintf(", success)\n"); + } else { + s += strprintf(", error=%s)\n", getErrorMessage()); + } + + LogPrintf("%s", s); +} + +bool AsyncRPCOperation_saplingmigration::main_impl() { + std::vector sproutEntries; + std::vector saplingEntries; + { + LOCK2(cs_main, pwalletMain->cs_wallet); + // Consider, should notes be sorted? + pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, "", 0); + } + if (sproutEntries.empty()) { // Consider, should the migration remain enabled? + fSaplingMigrationEnabled = false; + return true; + } + CAmount availableFunds = 0; + for (const CSproutNotePlaintextEntry& sproutEntry : sproutEntries) { + availableFunds = sproutEntry.plaintext.value(); + } + // If the remaining amount to be migrated is less than 0.01 ZEC, end the migration. + if (availableFunds < CENT) { + fSaplingMigrationEnabled = false; + return true; + } + + HDSeed seed; + if (!pwalletMain->GetHDSeed(seed)) { + throw JSONRPCError( + RPC_WALLET_ERROR, + "AsyncRPCOperation_AsyncRPCOperation_saplingmigration: HD seed not found"); + } + + libzcash::SaplingPaymentAddress migrationDestAddress = getMigrationDestAddress(seed); + + auto consensusParams = Params().GetConsensus(); + + // Up to the limit of 5, as many transactions are sent as are needed to migrate the remaining funds + int numTxCreated = 0; + int noteIndex = 0; + do { + CAmount amountToSend = chooseAmount(availableFunds); + auto builder = TransactionBuilder(consensusParams, targetHeight_, pwalletMain, pzcashParams); + std::vector fromNotes; + CAmount fromNoteAmount = 0; + while (fromNoteAmount < amountToSend) { + auto sproutEntry = sproutEntries[noteIndex++]; + fromNotes.push_back(sproutEntry); + fromNoteAmount += sproutEntry.plaintext.value(); + } + availableFunds -= fromNoteAmount; + for (const CSproutNotePlaintextEntry& sproutEntry : fromNotes) { + libzcash::SproutNote sproutNote = sproutEntry.plaintext.note(sproutEntry.address); + libzcash::SproutSpendingKey sproutSk; + pwalletMain->GetSproutSpendingKey(sproutEntry.address, sproutSk); + std::vector vOutPoints = {sproutEntry.jsop}; + // Each migration transaction SHOULD specify an anchor at height N-10 + // for each Sprout JoinSplit description + // TODO: the above functionality (in comment) is not implemented in zcashd + uint256 inputAnchor; + std::vector> vInputWitnesses; + pwalletMain->GetSproutNoteWitnesses(vOutPoints, vInputWitnesses, inputAnchor); + builder.AddSproutInput(sproutSk, sproutNote, vInputWitnesses[0].get()); + } + // The amount chosen *includes* the 0.0001 ZEC fee for this transaction, i.e. + // the value of the Sapling output will be 0.0001 ZEC less. + builder.SetFee(FEE); + builder.AddSaplingOutput(ovkForShieldingFromTaddr(seed), migrationDestAddress, amountToSend - FEE); + CTransaction tx = builder.Build().GetTxOrThrow(); + if (isCancelled()) { + break; + } + pwalletMain->AddPendingSaplingMigrationTx(tx); + ++numTxCreated; + } while (numTxCreated < 5 && availableFunds > CENT); + + UniValue res(UniValue::VOBJ); + res.push_back(Pair("num_tx_created", numTxCreated)); + set_result(res); + return true; +} + +CAmount AsyncRPCOperation_saplingmigration::chooseAmount(const CAmount& availableFunds) { + CAmount amount = 0; + do { + // 1. Choose an integer exponent uniformly in the range 6 to 8 inclusive. + int exponent = GetRand(3) + 6; + // 2. Choose an integer mantissa uniformly in the range 1 to 99 inclusive. + uint64_t mantissa = GetRand(99) + 1; + // 3. Calculate amount := (mantissa * 10^exponent) zatoshi. + int pow = std::pow(10, exponent); + amount = mantissa * pow; + // 4. If amount is greater than the amount remaining to send, repeat from step 1. + } while (amount > availableFunds); + return amount; +} + +// Unless otherwise specified, the migration destination address is the address for Sapling account 0 +libzcash::SaplingPaymentAddress AsyncRPCOperation_saplingmigration::getMigrationDestAddress(const HDSeed& seed) { + // Derive the address for Sapling account 0 + auto m = libzcash::SaplingExtendedSpendingKey::Master(seed); + uint32_t bip44CoinType = Params().BIP44CoinType(); + + // We use a fixed keypath scheme of m/32'/coin_type'/account' + // Derive m/32' + auto m_32h = m.Derive(32 | ZIP32_HARDENED_KEY_LIMIT); + // Derive m/32'/coin_type' + auto m_32h_cth = m_32h.Derive(bip44CoinType | ZIP32_HARDENED_KEY_LIMIT); + + // Derive account key at next index, skip keys already known to the wallet + libzcash::SaplingExtendedSpendingKey xsk = m_32h_cth.Derive(0 | ZIP32_HARDENED_KEY_LIMIT); + + libzcash::SaplingPaymentAddress toAddress = xsk.DefaultAddress(); + + // Refactor: this is similar logic as in the visitor HaveSpendingKeyForPaymentAddress and is used elsewhere + libzcash::SaplingIncomingViewingKey ivk; + libzcash::SaplingFullViewingKey fvk; + if (!(pwalletMain->GetSaplingIncomingViewingKey(toAddress, ivk) && + pwalletMain->GetSaplingFullViewingKey(ivk, fvk) && + pwalletMain->HaveSaplingSpendingKey(fvk))) { + // Sapling account 0 must be the first address returned by GenerateNewSaplingZKey + assert(pwalletMain->GenerateNewSaplingZKey() == toAddress); + } + + return toAddress; +} + +UniValue AsyncRPCOperation_saplingmigration::getStatus() const { + UniValue v = AsyncRPCOperation::getStatus(); + UniValue obj = v.get_obj(); + obj.push_back(Pair("method", "saplingmigration")); + obj.push_back(Pair("target_height", targetHeight_)); + return obj; +} diff --git a/src/wallet/asyncrpcoperation_saplingmigration.h b/src/wallet/asyncrpcoperation_saplingmigration.h new file mode 100644 index 00000000000..b520db408ff --- /dev/null +++ b/src/wallet/asyncrpcoperation_saplingmigration.h @@ -0,0 +1,31 @@ +#include "amount.h" +#include "asyncrpcoperation.h" +#include "univalue.h" +#include "zcash/Address.hpp" +#include "zcash/zip32.h" + +class AsyncRPCOperation_saplingmigration : public AsyncRPCOperation +{ +public: + AsyncRPCOperation_saplingmigration(int targetHeight); + virtual ~AsyncRPCOperation_saplingmigration(); + + // We don't want to be copied or moved around + AsyncRPCOperation_saplingmigration(AsyncRPCOperation_saplingmigration const&) = delete; // Copy construct + AsyncRPCOperation_saplingmigration(AsyncRPCOperation_saplingmigration&&) = delete; // Move construct + AsyncRPCOperation_saplingmigration& operator=(AsyncRPCOperation_saplingmigration const&) = delete; // Copy assign + AsyncRPCOperation_saplingmigration& operator=(AsyncRPCOperation_saplingmigration&&) = delete; // Move assign + + virtual void main(); + + virtual UniValue getStatus() const; + +private: + int targetHeight_; + + bool main_impl(); + + CAmount chooseAmount(const CAmount& availableFunds); + + libzcash::SaplingPaymentAddress getMigrationDestAddress(const HDSeed& seed); +}; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 4275f897f85..7cf5429a7b4 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3906,6 +3906,27 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) return operationId; } +UniValue z_setmigration(const UniValue& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return NullUniValue; + if (fHelp || params.size() != 1) + throw runtime_error( + "z_setmigration enabled\n" + "When enabled the Sprout to Sapling migration will attempt to migrate all funds from this wallet’s\n" + "Sprout addresses to either the address for Sapling account 0 or one specified by the parameter\n" + "'-migrationdestaddress'. This migration is designed to minimize information leakage. As a result,\n" + "for wallets with a significant Sprout balance, this process may take several weeks. The migration\n" + "works by sending, up to 5, as many transactions as possible whenever the blockchain reaches a height\n" + "equal to 499 modulo 500. The transaction amounts are picked according to the random distribution\n" + "specified in ZIP 308. The migration will end once the wallet’s Sprout balance is below 0.01 " + CURRENCY_UNIT + ".\n" + "\nArguments:\n" + "1. enabled (boolean, required) 'true' or 'false' to enable or disable respectively.\n" + "\nResult:\n" + "enabled (boolean) Whether or not migration is enabled (echos the argument).\n" + ); + fSaplingMigrationEnabled = params[0].get_bool(); + return fSaplingMigrationEnabled; +} /** When estimating the number of coinbase utxos we can shield in a single transaction: @@ -4660,6 +4681,7 @@ static const CRPCCommand commands[] = { "wallet", "z_gettotalbalance", &z_gettotalbalance, false }, { "wallet", "z_mergetoaddress", &z_mergetoaddress, false }, { "wallet", "z_sendmany", &z_sendmany, false }, + { "wallet", "z_setmigration", &z_setmigration, false }, { "wallet", "z_shieldcoinbase", &z_shieldcoinbase, false }, { "wallet", "z_getoperationstatus", &z_getoperationstatus, true }, { "wallet", "z_getoperationresult", &z_getoperationresult, true }, diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 6dfa150252c..4ddf5a0737d 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -5,8 +5,10 @@ #include "wallet/wallet.h" +#include "asyncrpcqueue.h" #include "checkpoints.h" #include "coincontrol.h" +#include "core_io.h" #include "consensus/upgrades.h" #include "consensus/validation.h" #include "consensus/consensus.h" @@ -15,12 +17,14 @@ #include "main.h" #include "net.h" #include "rpc/protocol.h" +#include "rpc/server.h" #include "script/script.h" #include "script/sign.h" #include "timedata.h" #include "utilmoneystr.h" #include "zcash/Note.hpp" #include "crypter.h" +#include "wallet/asyncrpcoperation_saplingmigration.h" #include "zcash/zip32.h" #include @@ -32,6 +36,8 @@ using namespace std; using namespace libzcash; +extern UniValue sendrawtransaction(const UniValue& params, bool fHelp); + /** * Settings */ @@ -566,6 +572,47 @@ void CWallet::ChainTip(const CBlockIndex *pindex, UpdateSaplingNullifierNoteMapForBlock(pblock); } +void CWallet::RunSaplingMigration(int blockHeight) { + if (!NetworkUpgradeActive(blockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) { + return; + } + LOCK(cs_wallet); + // The migration transactions to be sent in a particular batch can take + // significant time to generate, and this time depends on the speed of the user's + // computer. If they were generated only after a block is seen at the target + // height minus 1, then this could leak information. Therefore, for target + // height N, implementations SHOULD start generating the transactions at around + // height N-5 + if (blockHeight % 500 == 495) { + if (saplingMigrationOperation != nullptr) { + saplingMigrationOperation->cancel(); + } + pendingSaplingMigrationTxs.clear(); + std::shared_ptr q = getAsyncRPCQueue(); + std::shared_ptr operation(new AsyncRPCOperation_saplingmigration(blockHeight + 5)); + saplingMigrationOperation = operation; + q->addOperation(operation); + } else if (blockHeight % 500 == 499) { + for (const CTransaction& transaction : pendingSaplingMigrationTxs) { + // The following is taken from z_sendmany/z_mergetoaddress + // Send the transaction + // TODO: Use CWallet::CommitTransaction instead of sendrawtransaction + auto signedtxn = EncodeHexTx(transaction); + UniValue params = UniValue(UniValue::VARR); + params.push_back(signedtxn); + UniValue sendResultValue = sendrawtransaction(params, false); + if (sendResultValue.isNull()) { + throw JSONRPCError(RPC_WALLET_ERROR, "sendrawtransaction did not return an error or a txid."); + } + } + pendingSaplingMigrationTxs.clear(); + } +} + +void CWallet::AddPendingSaplingMigrationTx(const CTransaction& tx) { + pendingSaplingMigrationTxs.push_back(tx); +} + void CWallet::SetBestChain(const CBlockLocator& loc) { CWalletDB walletdb(strWalletFile); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 3f43e434e83..9c2d602267e 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -7,6 +7,7 @@ #define BITCOIN_WALLET_WALLET_H #include "amount.h" +#include "asyncrpcoperation.h" #include "coins.h" #include "key.h" #include "keystore.h" @@ -755,6 +756,9 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface TxNullifiers mapTxSproutNullifiers; TxNullifiers mapTxSaplingNullifiers; + std::vector pendingSaplingMigrationTxs; + std::shared_ptr saplingMigrationOperation = nullptr; + void AddToTransparentSpends(const COutPoint& outpoint, const uint256& wtxid); void AddToSproutSpends(const uint256& nullifier, const uint256& wtxid); void AddToSaplingSpends(const uint256& nullifier, const uint256& wtxid); @@ -1183,6 +1187,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface CAmount GetCredit(const CTransaction& tx, const isminefilter& filter) const; CAmount GetChange(const CTransaction& tx) const; void ChainTip(const CBlockIndex *pindex, const CBlock *pblock, SproutMerkleTree sproutTree, SaplingMerkleTree saplingTree, bool added); + void RunSaplingMigration(int blockHeight); + void AddPendingSaplingMigrationTx(const CTransaction& tx); /** Saves witness caches and best block locator to disk. */ void SetBestChain(const CBlockLocator& loc); std::set> GetNullifiersForAddresses(const std::set & addresses); From 162bfc3a1edac35bb803438dcc2f72e183122da9 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Tue, 16 Apr 2019 19:05:15 -0600 Subject: [PATCH 030/395] Move migration logic to ChainTip --- src/main.cpp | 5 ----- src/main.h | 1 - src/validationinterface.cpp | 3 --- src/validationinterface.h | 3 --- .../asyncrpcoperation_saplingmigration.cpp | 4 ++-- src/wallet/rpcwallet.cpp | 5 +++-- src/wallet/wallet.cpp | 19 ++++++++++++++++--- src/wallet/wallet.h | 2 ++ 8 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 782ab69b07f..72744b61a72 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -78,7 +78,6 @@ bool fCoinbaseEnforcedProtectionEnabled = true; size_t nCoinCacheUsage = 5000 * 300; uint64_t nPruneTarget = 0; bool fAlerts = DEFAULT_ALERTS; -bool fSaplingMigrationEnabled = false; /* If the tip is older than this (in seconds), the node is considered to be in initial block download. */ int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; @@ -3105,10 +3104,6 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * EnforceNodeDeprecation(pindexNew->nHeight); - if (fSaplingMigrationEnabled) { - GetMainSignals().RunSaplingMigration(pindexNew->nHeight); - } - int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1; LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001); LogPrint("bench", "- Connect block: %.2fms [%.2fs]\n", (nTime6 - nTime1) * 0.001, nTimeTotal * 0.000001); diff --git a/src/main.h b/src/main.h index 0e1fa669410..3b8c6aff9db 100644 --- a/src/main.h +++ b/src/main.h @@ -154,7 +154,6 @@ extern bool fCoinbaseEnforcedProtectionEnabled; extern size_t nCoinCacheUsage; extern CFeeRate minRelayTxFee; extern bool fAlerts; -extern bool fSaplingMigrationEnabled; extern int64_t nMaxTipAge; /** Best header we've seen so far (used for getheaders queries' starting points). */ diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index bb3f800fc33..1dc3351ab27 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -18,7 +18,6 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.EraseTransaction.connect(boost::bind(&CValidationInterface::EraseFromWallet, pwalletIn, _1)); g_signals.UpdatedTransaction.connect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1)); g_signals.ChainTip.connect(boost::bind(&CValidationInterface::ChainTip, pwalletIn, _1, _2, _3, _4, _5)); - g_signals.RunSaplingMigration.connect(boost::bind(&CValidationInterface::RunSaplingMigration, pwalletIn, _1)); g_signals.SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); g_signals.Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1)); @@ -34,7 +33,6 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1)); g_signals.Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); g_signals.ChainTip.disconnect(boost::bind(&CValidationInterface::ChainTip, pwalletIn, _1, _2, _3, _4, _5)); - g_signals.RunSaplingMigration.disconnect(boost::bind(&CValidationInterface::RunSaplingMigration, pwalletIn, _1)); g_signals.SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); g_signals.UpdatedTransaction.disconnect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1)); g_signals.EraseTransaction.disconnect(boost::bind(&CValidationInterface::EraseFromWallet, pwalletIn, _1)); @@ -49,7 +47,6 @@ void UnregisterAllValidationInterfaces() { g_signals.Broadcast.disconnect_all_slots(); g_signals.Inventory.disconnect_all_slots(); g_signals.ChainTip.disconnect_all_slots(); - g_signals.RunSaplingMigration.disconnect_all_slots(); g_signals.SetBestChain.disconnect_all_slots(); g_signals.UpdatedTransaction.disconnect_all_slots(); g_signals.EraseTransaction.disconnect_all_slots(); diff --git a/src/validationinterface.h b/src/validationinterface.h index 9e443d13459..7b02bd9da4a 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -37,7 +37,6 @@ class CValidationInterface { virtual void SyncTransaction(const CTransaction &tx, const CBlock *pblock) {} virtual void EraseFromWallet(const uint256 &hash) {} virtual void ChainTip(const CBlockIndex *pindex, const CBlock *pblock, SproutMerkleTree sproutTree, SaplingMerkleTree saplingTree, bool added) {} - virtual void RunSaplingMigration(int blockHeight) {} virtual void SetBestChain(const CBlockLocator &locator) {} virtual void UpdatedTransaction(const uint256 &hash) {} virtual void Inventory(const uint256 &hash) {} @@ -61,8 +60,6 @@ struct CMainSignals { boost::signals2::signal UpdatedTransaction; /** Notifies listeners of a change to the tip of the active block chain. */ boost::signals2::signal ChainTip; - /** Notifies listeners that they may need to update the status of the Sprout->Sapling migration */ - boost::signals2::signal RunSaplingMigration; /** Notifies listeners of a new active block chain. */ boost::signals2::signal SetBestChain; /** Notifies listeners about an inventory item being seen on the network. */ diff --git a/src/wallet/asyncrpcoperation_saplingmigration.cpp b/src/wallet/asyncrpcoperation_saplingmigration.cpp index 6a043f9bf35..fd40fb74a86 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.cpp +++ b/src/wallet/asyncrpcoperation_saplingmigration.cpp @@ -73,7 +73,7 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, "", 0); } if (sproutEntries.empty()) { // Consider, should the migration remain enabled? - fSaplingMigrationEnabled = false; + pwalletMain->fSaplingMigrationEnabled = false; return true; } CAmount availableFunds = 0; @@ -82,7 +82,7 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { } // If the remaining amount to be migrated is less than 0.01 ZEC, end the migration. if (availableFunds < CENT) { - fSaplingMigrationEnabled = false; + pwalletMain->fSaplingMigrationEnabled = false; return true; } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 7cf5429a7b4..ea70b0a91c5 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3924,8 +3924,9 @@ UniValue z_setmigration(const UniValue& params, bool fHelp) { "\nResult:\n" "enabled (boolean) Whether or not migration is enabled (echos the argument).\n" ); - fSaplingMigrationEnabled = params[0].get_bool(); - return fSaplingMigrationEnabled; + LOCK(pwalletMain->cs_wallet); + pwalletMain->fSaplingMigrationEnabled = params[0].get_bool(); + return pwalletMain->fSaplingMigrationEnabled; } /** diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4ddf5a0737d..9c310743600 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -558,6 +558,15 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, return false; } +void CWallet::ChainTipAdded(const CBlockIndex *pindex, + const CBlock *pblock, + SproutMerkleTree sproutTree, + SaplingMerkleTree saplingTree) +{ + IncrementNoteWitnesses(pindex, pblock, sproutTree, saplingTree); + UpdateSaplingNullifierNoteMapForBlock(pblock); +} + void CWallet::ChainTip(const CBlockIndex *pindex, const CBlock *pblock, SproutMerkleTree sproutTree, @@ -565,11 +574,12 @@ void CWallet::ChainTip(const CBlockIndex *pindex, bool added) { if (added) { - IncrementNoteWitnesses(pindex, pblock, sproutTree, saplingTree); + ChainTipAdded(pindex, pblock, sproutTree, saplingTree); + RunSaplingMigration(pindex->nHeight); } else { DecrementNoteWitnesses(pindex); + UpdateSaplingNullifierNoteMapForBlock(pblock); } - UpdateSaplingNullifierNoteMapForBlock(pblock); } void CWallet::RunSaplingMigration(int blockHeight) { @@ -577,6 +587,9 @@ void CWallet::RunSaplingMigration(int blockHeight) { return; } LOCK(cs_wallet); + if (!fSaplingMigrationEnabled) { + return; + } // The migration transactions to be sent in a particular batch can take // significant time to generate, and this time depends on the speed of the user's // computer. If they were generated only after a block is seen at the target @@ -2491,7 +2504,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) } } // Increment note witness caches - ChainTip(pindex, &block, sproutTree, saplingTree, true); + ChainTipAdded(pindex, &block, sproutTree, saplingTree); pindex = chainActive.Next(pindex); if (GetTime() >= nNow + 60) { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 9c2d602267e..7cd808b6250 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -771,6 +771,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * incremental witness cache in any transaction in mapWallet. */ int64_t nWitnessCacheSize; + bool fSaplingMigrationEnabled = false; void ClearNoteWitnessCache(); @@ -836,6 +837,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface private: template void SyncMetaData(std::pair::iterator, typename TxSpendMap::iterator>); + void ChainTipAdded(const CBlockIndex *pindex, const CBlock *pblock, SproutMerkleTree sproutTree, SaplingMerkleTree saplingTree); protected: bool UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx); From 699288b4b4330996dec6d356d405774e6751a9b2 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Tue, 16 Apr 2019 19:12:53 -0600 Subject: [PATCH 031/395] Documentation cleanup --- qa/rpc-tests/sprout_sapling_migration.py | 2 +- .../asyncrpcoperation_saplingmigration.cpp | 2 +- src/wallet/rpcwallet.cpp | 18 +++++++++--------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/qa/rpc-tests/sprout_sapling_migration.py b/qa/rpc-tests/sprout_sapling_migration.py index 726e5e2aa61..b888fb8e2eb 100755 --- a/qa/rpc-tests/sprout_sapling_migration.py +++ b/qa/rpc-tests/sprout_sapling_migration.py @@ -41,7 +41,7 @@ def run_test(self): assert_equal(self.nodes[0].z_getbalance(saplingAddr), Decimal('0')) # Migrate - assert_equal(True, self.nodes[0].z_setmigration(True)) + self.nodes[0].z_setmigration(True) print "Mining to block 494..." self.nodes[0].generate(392) # 102 -> 494 self.sync_all() diff --git a/src/wallet/asyncrpcoperation_saplingmigration.cpp b/src/wallet/asyncrpcoperation_saplingmigration.cpp index fd40fb74a86..22157c68214 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.cpp +++ b/src/wallet/asyncrpcoperation_saplingmigration.cpp @@ -169,7 +169,7 @@ libzcash::SaplingPaymentAddress AsyncRPCOperation_saplingmigration::getMigration // Derive m/32'/coin_type' auto m_32h_cth = m_32h.Derive(bip44CoinType | ZIP32_HARDENED_KEY_LIMIT); - // Derive account key at next index, skip keys already known to the wallet + // Derive m/32'/coin_type'/0' libzcash::SaplingExtendedSpendingKey xsk = m_32h_cth.Derive(0 | ZIP32_HARDENED_KEY_LIMIT); libzcash::SaplingPaymentAddress toAddress = xsk.DefaultAddress(); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index ea70b0a91c5..347d65b189f 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3913,20 +3913,20 @@ UniValue z_setmigration(const UniValue& params, bool fHelp) { throw runtime_error( "z_setmigration enabled\n" "When enabled the Sprout to Sapling migration will attempt to migrate all funds from this wallet’s\n" - "Sprout addresses to either the address for Sapling account 0 or one specified by the parameter\n" - "'-migrationdestaddress'. This migration is designed to minimize information leakage. As a result,\n" - "for wallets with a significant Sprout balance, this process may take several weeks. The migration\n" - "works by sending, up to 5, as many transactions as possible whenever the blockchain reaches a height\n" - "equal to 499 modulo 500. The transaction amounts are picked according to the random distribution\n" - "specified in ZIP 308. The migration will end once the wallet’s Sprout balance is below 0.01 " + CURRENCY_UNIT + ".\n" + "Sprout addresses to either the address for Sapling account 0 or the address specified by the parameter\n" + "'-migrationdestaddress'.\n" + "\n" + "This migration is designed to minimize information leakage. As a result for wallets with a significant\n" + "Sprout balance, this process may take several weeks. The migration works by sending, up to 5, as many\n" + "transactions as possible whenever the blockchain reaches a height equal to 499 modulo 500. The transaction\n" + "amounts are picked according to the random distribution specified in ZIP 308. The migration will end once\n" + "the wallet’s Sprout balance is below" + strprintf("%s %s", FormatMoney(CENT), CURRENCY_UNIT) + ".\n" "\nArguments:\n" "1. enabled (boolean, required) 'true' or 'false' to enable or disable respectively.\n" - "\nResult:\n" - "enabled (boolean) Whether or not migration is enabled (echos the argument).\n" ); LOCK(pwalletMain->cs_wallet); pwalletMain->fSaplingMigrationEnabled = params[0].get_bool(); - return pwalletMain->fSaplingMigrationEnabled; + return NullUniValue; } /** From 7c4ad6e2986907e621496cd992010b264b37c63c Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Tue, 16 Apr 2019 19:35:04 -0600 Subject: [PATCH 032/395] Additional locking and race condition prevention --- src/wallet/wallet.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 9c310743600..07fafe42f1a 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -606,6 +606,9 @@ void CWallet::RunSaplingMigration(int blockHeight) { saplingMigrationOperation = operation; q->addOperation(operation); } else if (blockHeight % 500 == 499) { + if (saplingMigrationOperation != nullptr) { + saplingMigrationOperation->cancel(); + } for (const CTransaction& transaction : pendingSaplingMigrationTxs) { // The following is taken from z_sendmany/z_mergetoaddress // Send the transaction @@ -623,6 +626,7 @@ void CWallet::RunSaplingMigration(int blockHeight) { } void CWallet::AddPendingSaplingMigrationTx(const CTransaction& tx) { + LOCK(cs_wallet); pendingSaplingMigrationTxs.push_back(tx); } From d2a584e35a1f85e28919b4b74bb97a6da3abaa9d Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Thu, 18 Apr 2019 15:41:27 -0600 Subject: [PATCH 033/395] Refactor wait_and_assert_operationid_status to allow returning the result --- qa/rpc-tests/sprout_sapling_migration.py | 12 +++++--- qa/rpc-tests/test_framework/util.py | 35 ++++++++++++------------ qa/rpc-tests/wallet_protectcoinbase.py | 4 +-- 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/qa/rpc-tests/sprout_sapling_migration.py b/qa/rpc-tests/sprout_sapling_migration.py index b888fb8e2eb..0e606fb5eb6 100755 --- a/qa/rpc-tests/sprout_sapling_migration.py +++ b/qa/rpc-tests/sprout_sapling_migration.py @@ -8,7 +8,8 @@ from decimal import Decimal from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, assert_true, get_coinbase_address, \ - initialize_chain_clean, start_nodes, wait_and_assert_operationid_status + initialize_chain_clean, start_nodes, wait_and_assert_operationid_status, \ + wait_and_assert_operationid_status_result class SproutSaplingMigration(BitcoinTestFramework): @@ -54,14 +55,17 @@ def run_test(self): # At 495 we should have an async operation operationstatus = self.nodes[0].z_getoperationstatus() + print "migration operation: {}".format(operationstatus) assert_equal(1, len(operationstatus), "num async operations at 495") assert_equal('saplingmigration', operationstatus[0]['method']) assert_equal(500, operationstatus[0]['target_height']) - print "migration operation: {}".format(operationstatus) - migration_opid = operationstatus[0]['id'] - result = wait_and_assert_operationid_status(self.nodes[0], migration_opid) + result = wait_and_assert_operationid_status_result(self.nodes[0], operationstatus[0]['id']) print "result: {}".format(result) + assert_equal('saplingmigration', result['method']) + assert_equal(500, result['target_height']) + assert_equal(1, result['result']['num_tx_created']) + assert_equal(0, len(self.nodes[0].getrawmempool()), "mempool size at 495") self.nodes[0].generate(3) diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index 7d15ec063c7..590cb2d48a1 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -385,8 +385,9 @@ def assert_raises(exc, fun, *args, **kwds): def fail(message=""): raise AssertionError(message) -# Returns txid if operation was a success or None -def wait_and_assert_operationid_status(node, myopid, in_status='success', in_errormsg=None, timeout=300): + +# Returns an async operation result +def wait_and_assert_operationid_status_result(node, myopid, in_status='success', in_errormsg=None, timeout=300): print('waiting for async operation {}'.format(myopid)) result = None for _ in xrange(1, timeout): @@ -399,29 +400,29 @@ def wait_and_assert_operationid_status(node, myopid, in_status='success', in_err assert_true(result is not None, "timeout occured") status = result['status'] - ret = None + debug = os.getenv("PYTHON_DEBUG", "") + if debug: + print('...returned status: {}'.format(status)) + errormsg = None if status == "failed": errormsg = result['error']['message'] - elif status == "success": - if type(result['result']) is dict and result['result'].get('txid'): - ret = result['result']['txid'] - else: - ret = result['result'] - - if os.getenv("PYTHON_DEBUG", ""): - print('...returned status: {}'.format(status)) - if errormsg is not None: + if debug: print('...returned error: {}'.format(errormsg)) + assert_equal(in_errormsg, errormsg) assert_equal(in_status, status, "Operation returned mismatched status. Error Message: {}".format(errormsg)) - if errormsg is not None: - assert_true(in_errormsg is not None, "No error retured. Expected: {}".format(errormsg)) - assert_true(in_errormsg in errormsg, "Error returned: {}. Error expected: {}".format(errormsg, in_errormsg)) - return result # if there was an error return the result + return result + + +# Returns txid if operation was a success or None +def wait_and_assert_operationid_status(node, myopid, in_status='success', in_errormsg=None, timeout=300): + result = wait_and_assert_operationid_status_result(node, myopid, in_status, in_errormsg, timeout) + if result['status'] == "success": + return result['result']['txid'] else: - return ret # otherwise return the txid + return None # Find a coinbase address on the node, filtering by the number of UTXOs it has. # If no filter is provided, returns the coinbase address on the node containing diff --git a/qa/rpc-tests/wallet_protectcoinbase.py b/qa/rpc-tests/wallet_protectcoinbase.py index 85109931163..5eaed7c3a52 100755 --- a/qa/rpc-tests/wallet_protectcoinbase.py +++ b/qa/rpc-tests/wallet_protectcoinbase.py @@ -10,7 +10,7 @@ from test_framework.mininode import COIN from test_framework.util import assert_equal, initialize_chain_clean, \ start_nodes, connect_nodes_bi, wait_and_assert_operationid_status, \ - get_coinbase_address + wait_and_assert_operationid_status_result, get_coinbase_address import sys import timeit @@ -92,7 +92,7 @@ def run_test (self): recipients.append({"address":myzaddr, "amount":Decimal('1.23456789')}) myopid = self.nodes[0].z_sendmany(mytaddr, recipients) - error_result = wait_and_assert_operationid_status(self.nodes[0], myopid, "failed", "wallet does not allow any change", 10) + error_result = wait_and_assert_operationid_status_result(self.nodes[0], myopid, "failed", "wallet does not allow any change", 10) # Test that the returned status object contains a params field with the operation's input parameters assert_equal(error_result["method"], "z_sendmany") From 5519d16997c07c02932804e17dc23625be656e8b Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Thu, 25 Apr 2019 13:43:23 -0600 Subject: [PATCH 034/395] Set min depth when selecting notes to migrate --- qa/rpc-tests/sprout_sapling_migration.py | 1 + .../asyncrpcoperation_saplingmigration.cpp | 18 ++++++++++-------- .../asyncrpcoperation_saplingmigration.h | 2 ++ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/qa/rpc-tests/sprout_sapling_migration.py b/qa/rpc-tests/sprout_sapling_migration.py index 0e606fb5eb6..13dc2189001 100755 --- a/qa/rpc-tests/sprout_sapling_migration.py +++ b/qa/rpc-tests/sprout_sapling_migration.py @@ -94,6 +94,7 @@ def run_test(self): print "sprout balance: {}, sapling balance: {}".format(sprout_balance, sapling_balance) assert_true(sprout_balance < Decimal('10'), "Should have less Sprout funds") assert_true(sapling_balance > Decimal('0'), "Should have more Sapling funds") + assert_true(sprout_balance + sapling_balance, Decimal('9.9999')) if __name__ == '__main__': diff --git a/src/wallet/asyncrpcoperation_saplingmigration.cpp b/src/wallet/asyncrpcoperation_saplingmigration.cpp index 22157c68214..85962f75a9b 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.cpp +++ b/src/wallet/asyncrpcoperation_saplingmigration.cpp @@ -54,7 +54,7 @@ void AsyncRPCOperation_saplingmigration::main() { set_state(OperationStatus::FAILED); } - std::string s = strprintf("%s: Sprout->Sapling transactions sent. (status=%s", getId(), getStateAsString()); + std::string s = strprintf("%s: Sprout->Sapling transactions created. (status=%s", getId(), getStateAsString()); if (success) { s += strprintf(", success)\n"); } else { @@ -69,12 +69,10 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { std::vector saplingEntries; { LOCK2(cs_main, pwalletMain->cs_wallet); + // We set minDepth to 11 to avoid unconfirmed notes and in anticipation of specifying + // an anchor at height N-10 for each Sprout JoinSplit description // Consider, should notes be sorted? - pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, "", 0); - } - if (sproutEntries.empty()) { // Consider, should the migration remain enabled? - pwalletMain->fSaplingMigrationEnabled = false; - return true; + pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, "", 11); } CAmount availableFunds = 0; for (const CSproutNotePlaintextEntry& sproutEntry : sproutEntries) { @@ -82,7 +80,7 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { } // If the remaining amount to be migrated is less than 0.01 ZEC, end the migration. if (availableFunds < CENT) { - pwalletMain->fSaplingMigrationEnabled = false; + setMigrationResult(0); return true; } @@ -136,10 +134,14 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { ++numTxCreated; } while (numTxCreated < 5 && availableFunds > CENT); + setMigrationResult(numTxCreated); + return true; +} + +void AsyncRPCOperation_saplingmigration::setMigrationResult(int numTxCreated) { UniValue res(UniValue::VOBJ); res.push_back(Pair("num_tx_created", numTxCreated)); set_result(res); - return true; } CAmount AsyncRPCOperation_saplingmigration::chooseAmount(const CAmount& availableFunds) { diff --git a/src/wallet/asyncrpcoperation_saplingmigration.h b/src/wallet/asyncrpcoperation_saplingmigration.h index b520db408ff..af26281f613 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.h +++ b/src/wallet/asyncrpcoperation_saplingmigration.h @@ -25,6 +25,8 @@ class AsyncRPCOperation_saplingmigration : public AsyncRPCOperation bool main_impl(); + void setMigrationResult(int numTxCreated); + CAmount chooseAmount(const CAmount& availableFunds); libzcash::SaplingPaymentAddress getMigrationDestAddress(const HDSeed& seed); From 7fb8088288196ee9659bf14967ff1ea1b05b3b83 Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Thu, 21 Feb 2019 14:01:12 -0700 Subject: [PATCH 035/395] add -timestampindex for bitcore insight block explorer --- src/Makefile.am | 1 + src/main.cpp | 26 ++++++++- src/main.h | 1 + src/timestampindex.h | 131 +++++++++++++++++++++++++++++++++++++++++++ src/txdb.cpp | 52 +++++++++++++++++ src/txdb.h | 10 ++++ 6 files changed, 219 insertions(+), 2 deletions(-) create mode 100644 src/timestampindex.h diff --git a/src/Makefile.am b/src/Makefile.am index 181ae7ec012..d698e124585 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -199,6 +199,7 @@ BITCOIN_CORE_H = \ sync.h \ threadsafety.h \ timedata.h \ + timestampindex.h \ tinyformat.h \ torcontrol.h \ transaction_builder.h \ diff --git a/src/main.cpp b/src/main.cpp index 33cb99320ca..e5c6c19b0b3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -70,6 +70,7 @@ bool fTxIndex = false; bool fInsightExplorer = false; // insightexplorer bool fAddressIndex = false; // insightexplorer bool fSpentIndex = false; // insightexplorer +bool fTimestampIndex = false; // insightexplorer bool fHavePruned = false; bool fPruneMode = false; bool fIsBareMultisigStd = true; @@ -2801,7 +2802,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (!pblocktree->WriteTxIndex(vPos)) return AbortNode(state, "Failed to write transaction index"); - // insightexplorer + // START insightexplorer if (fAddressIndex) { if (!pblocktree->WriteAddressIndex(addressIndex)) { return AbortNode(state, "Failed to write address index"); @@ -2810,12 +2811,32 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return AbortNode(state, "Failed to write address unspent index"); } } - // insightexplorer if (fSpentIndex) { if (!pblocktree->UpdateSpentIndex(spentIndex)) { return AbortNode(state, "Failed to write spent index"); } } + if (fTimestampIndex) { + unsigned int logicalTS = pindex->nTime; + unsigned int prevLogicalTS = 0; + + // retrieve logical timestamp of the previous block + if (pindex->pprev) + if (!pblocktree->ReadTimestampBlockIndex(pindex->pprev->GetBlockHash(), prevLogicalTS)) + LogPrintf("%s: Failed to read previous block's logical timestamp\n", __func__); + + if (logicalTS <= prevLogicalTS) { + logicalTS = prevLogicalTS + 1; + LogPrintf("%s: Previous logical timestamp is newer Actual[%d] prevLogical[%d] Logical[%d]\n", __func__, pindex->nTime, prevLogicalTS, logicalTS); + } + + if (!pblocktree->WriteTimestampIndex(CTimestampIndexKey(logicalTS, pindex->GetBlockHash()))) + return AbortNode(state, "Failed to write timestamp index"); + + if (!pblocktree->WriteTimestampBlockIndex(CTimestampBlockIndexKey(pindex->GetBlockHash()), CTimestampBlockIndexValue(logicalTS))) + return AbortNode(state, "Failed to write blockhash index"); + } + // END insightexplorer // add this block to the view's block chain view.SetBestBlock(pindex->GetBlockHash()); @@ -4715,6 +4736,7 @@ bool InitBlockIndex() { pblocktree->WriteFlag("insightexplorer", fInsightExplorer); fAddressIndex = fInsightExplorer; fSpentIndex = fInsightExplorer; + fTimestampIndex = fInsightExplorer; LogPrintf("Initializing databases...\n"); diff --git a/src/main.h b/src/main.h index f19fc84ff38..df9e7ea3ab5 100644 --- a/src/main.h +++ b/src/main.h @@ -28,6 +28,7 @@ #include "uint256.h" #include "addressindex.h" #include "spentindex.h" +#include "timestampindex.h" #include #include diff --git a/src/timestampindex.h b/src/timestampindex.h new file mode 100644 index 00000000000..3e402872cf4 --- /dev/null +++ b/src/timestampindex.h @@ -0,0 +1,131 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_TIMESTAMPINDEX_H +#define BITCOIN_TIMESTAMPINDEX_H + +#include "uint256.h" + +struct CTimestampIndexIteratorKey { + unsigned int timestamp; + + size_t GetSerializeSize(int nType, int nVersion) const { + return 4; + } + template + void Serialize(Stream& s) const { + ser_writedata32be(s, timestamp); + } + template + void Unserialize(Stream& s) { + timestamp = ser_readdata32be(s); + } + + CTimestampIndexIteratorKey(unsigned int time) { + timestamp = time; + } + + CTimestampIndexIteratorKey() { + SetNull(); + } + + void SetNull() { + timestamp = 0; + } +}; + +struct CTimestampIndexKey { + unsigned int timestamp; + uint256 blockHash; + + size_t GetSerializeSize(int nType, int nVersion) const { + return 36; + } + template + void Serialize(Stream& s) const { + ser_writedata32be(s, timestamp); + blockHash.Serialize(s); + } + template + void Unserialize(Stream& s) { + timestamp = ser_readdata32be(s); + blockHash.Unserialize(s); + } + + CTimestampIndexKey(unsigned int time, uint256 hash) { + timestamp = time; + blockHash = hash; + } + + CTimestampIndexKey() { + SetNull(); + } + + void SetNull() { + timestamp = 0; + blockHash.SetNull(); + } +}; + +struct CTimestampBlockIndexKey { + uint256 blockHash; + + size_t GetSerializeSize(int nType, int nVersion) const { + return 32; + } + + template + void Serialize(Stream& s) const { + blockHash.Serialize(s); + } + + template + void Unserialize(Stream& s) { + blockHash.Unserialize(s); + } + + CTimestampBlockIndexKey(uint256 hash) { + blockHash = hash; + } + + CTimestampBlockIndexKey() { + SetNull(); + } + + void SetNull() { + blockHash.SetNull(); + } +}; + +struct CTimestampBlockIndexValue { + unsigned int ltimestamp; + size_t GetSerializeSize(int nType, int nVersion) const { + return 4; + } + + template + void Serialize(Stream& s) const { + ser_writedata32be(s, ltimestamp); + } + + template + void Unserialize(Stream& s) { + ltimestamp = ser_readdata32be(s); + } + + CTimestampBlockIndexValue (unsigned int time) { + ltimestamp = time; + } + + CTimestampBlockIndexValue() { + SetNull(); + } + + void SetNull() { + ltimestamp = 0; + } +}; + +#endif // BITCOIN_TIMESTAMPINDEX_H diff --git a/src/txdb.cpp b/src/txdb.cpp index b0c89f7d367..5ed75f3c969 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -39,6 +39,8 @@ static const char DB_LAST_BLOCK = 'l'; static const char DB_ADDRESSINDEX = 'd'; static const char DB_ADDRESSUNSPENTINDEX = 'u'; static const char DB_SPENTINDEX = 'p'; +static const char DB_TIMESTAMPINDEX = 'T'; +static const char DB_BLOCKHASHINDEX = 'h'; CCoinsViewDB::CCoinsViewDB(std::string dbName, size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / dbName, nCacheSize, fMemory, fWipe) { } @@ -390,6 +392,56 @@ bool CBlockTreeDB::UpdateSpentIndex(const std::vector &vect) } return WriteBatch(batch); } + +bool CBlockTreeDB::WriteTimestampIndex(const CTimestampIndexKey ×tampIndex) { + CDBBatch batch(*this); + batch.Write(make_pair(DB_TIMESTAMPINDEX, timestampIndex), 0); + return WriteBatch(batch); +} + +bool CBlockTreeDB::ReadTimestampIndex(const unsigned int &high, const unsigned int &low, + const bool fActiveOnly, std::vector > &hashes) +{ + boost::scoped_ptr pcursor(NewIterator()); + + pcursor->Seek(make_pair(DB_TIMESTAMPINDEX, CTimestampIndexIteratorKey(low))); + + while (pcursor->Valid()) { + boost::this_thread::interruption_point(); + std::pair key; + if (!(pcursor->GetKey(key) && key.first == DB_TIMESTAMPINDEX && key.second.timestamp < high)) { + break; + } + if (fActiveOnly) { + CBlockIndex* pblockindex = mapBlockIndex[key.second.blockHash]; + if (chainActive.Contains(pblockindex)) { + hashes.push_back(std::make_pair(key.second.blockHash, key.second.timestamp)); + } + } else { + hashes.push_back(std::make_pair(key.second.blockHash, key.second.timestamp)); + } + pcursor->Next(); + } + return true; +} + +bool CBlockTreeDB::WriteTimestampBlockIndex(const CTimestampBlockIndexKey &blockhashIndex, + const CTimestampBlockIndexValue &logicalts) +{ + CDBBatch batch(*this); + batch.Write(make_pair(DB_BLOCKHASHINDEX, blockhashIndex), logicalts); + return WriteBatch(batch); +} + +bool CBlockTreeDB::ReadTimestampBlockIndex(const uint256 &hash, unsigned int <imestamp) +{ + CTimestampBlockIndexValue(lts); + if (!Read(std::make_pair(DB_BLOCKHASHINDEX, hash), lts)) + return false; + + ltimestamp = lts.ltimestamp; + return true; +} // END insightexplorer bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) { diff --git a/src/txdb.h b/src/txdb.h index f1f78085184..c00b2d68a11 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -26,6 +26,10 @@ struct CAddressIndexIteratorKey; struct CAddressIndexIteratorHeightKey; struct CSpentIndexKey; struct CSpentIndexValue; +struct CTimestampIndexKey; +struct CTimestampIndexIteratorKey; +struct CTimestampBlockIndexKey; +struct CTimestampBlockIndexValue; typedef std::pair CAddressUnspentDbEntry; typedef std::pair CAddressIndexDbEntry; @@ -94,6 +98,12 @@ class CBlockTreeDB : public CDBWrapper bool ReadAddressIndex(uint160 addressHash, int type, std::vector &addressIndex, int start = 0, int end = 0); bool ReadSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value); bool UpdateSpentIndex(const std::vector &vect); + bool WriteTimestampIndex(const CTimestampIndexKey ×tampIndex); + bool ReadTimestampIndex(const unsigned int &high, const unsigned int &low, + const bool fActiveOnly, std::vector > &vect); + bool WriteTimestampBlockIndex(const CTimestampBlockIndexKey &blockhashIndex, + const CTimestampBlockIndexValue &logicalts); + bool ReadTimestampBlockIndex(const uint256 &hash, unsigned int &logicalTS); // END insightexplorer bool WriteFlag(const std::string &name, bool fValue); From 6acb37bcee606aac23a8895ef4a7b2bbc32b3634 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Fri, 26 Apr 2019 19:01:23 -0600 Subject: [PATCH 036/395] Check for full failure message in test case --- qa/rpc-tests/wallet_protectcoinbase.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/wallet_protectcoinbase.py b/qa/rpc-tests/wallet_protectcoinbase.py index 5eaed7c3a52..e7a3b9e5a1c 100755 --- a/qa/rpc-tests/wallet_protectcoinbase.py +++ b/qa/rpc-tests/wallet_protectcoinbase.py @@ -84,7 +84,7 @@ def run_test (self): recipients= [{"address":myzaddr, "amount": Decimal('1')}] myopid = self.nodes[3].z_sendmany(mytaddr, recipients) - wait_and_assert_operationid_status(self.nodes[3], myopid, "failed", "no UTXOs found for taddr from address", 10) + wait_and_assert_operationid_status(self.nodes[3], myopid, "failed", "Insufficient funds, no UTXOs found for taddr from address.", 10) # This send will fail because our wallet does not allow any change when protecting a coinbase utxo, # as it's currently not possible to specify a change address in z_sendmany. @@ -92,7 +92,9 @@ def run_test (self): recipients.append({"address":myzaddr, "amount":Decimal('1.23456789')}) myopid = self.nodes[0].z_sendmany(mytaddr, recipients) - error_result = wait_and_assert_operationid_status_result(self.nodes[0], myopid, "failed", "wallet does not allow any change", 10) + error_result = wait_and_assert_operationid_status_result(self.nodes[0], myopid, "failed", ("Change 8.76533211 not allowed. " + "When shielding coinbase funds, the wallet does not allow any change " + "as there is currently no way to specify a change address in z_sendmany."), 10) # Test that the returned status object contains a params field with the operation's input parameters assert_equal(error_result["method"], "z_sendmany") From 8ffd63af2dc47deceaa4db3ee9d8b4435a9b7dff Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Mon, 29 Apr 2019 09:36:26 -0600 Subject: [PATCH 037/395] Add migration options to conf file Co-authored-by: Simon --- src/init.cpp | 14 ++++++++++++++ src/wallet/asyncrpcoperation_saplingmigration.cpp | 8 ++++++++ 2 files changed, 22 insertions(+) diff --git a/src/init.cpp b/src/init.cpp index 188e84490c0..7829ee8c214 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -37,6 +37,7 @@ #include "utilmoneystr.h" #include "validationinterface.h" #ifdef ENABLE_WALLET +#include "key_io.h" #include "wallet/wallet.h" #include "wallet/walletdb.h" #endif @@ -405,6 +406,8 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageGroup(_("Wallet options:")); strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls")); strUsage += HelpMessageOpt("-keypool=", strprintf(_("Set key pool size to (default: %u)"), 100)); + strUsage += HelpMessageOpt("--migration=", _("Set to true to enable the Sprout to Sapling migration.")); + strUsage += HelpMessageOpt("-migrationdestaddress=", _("Set the Sapling migration address")); if (showDebug) strUsage += HelpMessageOpt("-mintxfee=", strprintf("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)", CURRENCY_UNIT, FormatMoney(CWallet::minTxFee.GetFeePerK()))); @@ -1070,6 +1073,14 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) fSendFreeTransactions = GetBoolArg("-sendfreetransactions", false); std::string strWalletFile = GetArg("-wallet", "wallet.dat"); + // Check Sapling migration address if set and is a valid Sapling address + if (mapArgs.count("-migrationdestaddress")) { + std::string migrationDestAddress = mapArgs["-migrationdestaddress"]; + libzcash::PaymentAddress address = DecodePaymentAddress(migrationDestAddress); + if (boost::get(&address) == nullptr) { + return InitError(_("-migrationdestaddress must be a valid Sapling address.")); + } + } #endif // ENABLE_WALLET fIsBareMultisigStd = GetBoolArg("-permitbaremultisig", true); @@ -1671,6 +1682,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } } + // Set sapling migration status + pwalletMain->fSaplingMigrationEnabled = GetBoolArg("-migration", false); + if (fFirstRun) { // Create new keyUser and set as default key diff --git a/src/wallet/asyncrpcoperation_saplingmigration.cpp b/src/wallet/asyncrpcoperation_saplingmigration.cpp index 85962f75a9b..4076415eaa2 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.cpp +++ b/src/wallet/asyncrpcoperation_saplingmigration.cpp @@ -2,6 +2,7 @@ #include "boost/variant/static_visitor.hpp" #include "asyncrpcoperation_saplingmigration.h" #include "init.h" +#include "key_io.h" #include "rpc/protocol.h" #include "random.h" #include "sync.h" @@ -161,6 +162,13 @@ CAmount AsyncRPCOperation_saplingmigration::chooseAmount(const CAmount& availabl // Unless otherwise specified, the migration destination address is the address for Sapling account 0 libzcash::SaplingPaymentAddress AsyncRPCOperation_saplingmigration::getMigrationDestAddress(const HDSeed& seed) { + if (mapArgs.count("-migrationdestaddress")) { + std::string migrationDestAddress = mapArgs["-migrationdestaddress"]; + auto address = DecodePaymentAddress(migrationDestAddress); + auto saplingAddress = boost::get(&address); + assert(saplingAddress != nullptr); // This is checked in init.cpp + return *saplingAddress; + } // Derive the address for Sapling account 0 auto m = libzcash::SaplingExtendedSpendingKey::Master(seed); uint32_t bip44CoinType = Params().BIP44CoinType(); From b9c7f274a472b61386dcfe294cc8590ff460fd7e Mon Sep 17 00:00:00 2001 From: str4d Date: Mon, 29 Apr 2019 09:55:07 -0600 Subject: [PATCH 038/395] remove extra hyphen Co-Authored-By: Eirik0 --- src/init.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index 7829ee8c214..653a05fcb31 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -406,7 +406,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageGroup(_("Wallet options:")); strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls")); strUsage += HelpMessageOpt("-keypool=", strprintf(_("Set key pool size to (default: %u)"), 100)); - strUsage += HelpMessageOpt("--migration=", _("Set to true to enable the Sprout to Sapling migration.")); + strUsage += HelpMessageOpt("-migration=", _("Set to true to enable the Sprout to Sapling migration.")); strUsage += HelpMessageOpt("-migrationdestaddress=", _("Set the Sapling migration address")); if (showDebug) strUsage += HelpMessageOpt("-mintxfee=", strprintf("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)", From 52cfa9c1ee43e90c96e31a712b42926b857b8ee6 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Wed, 24 Apr 2019 16:20:08 -0600 Subject: [PATCH 039/395] Create method for getting HD seed in RPCs --- src/wallet/asyncrpcoperation_mergetoaddress.cpp | 7 +------ src/wallet/asyncrpcoperation_saplingmigration.cpp | 8 +------- src/wallet/asyncrpcoperation_sendmany.cpp | 7 +------ src/wallet/asyncrpcoperation_shieldcoinbase.cpp | 7 +------ src/wallet/rpcdump.cpp | 3 +-- src/wallet/wallet.cpp | 8 ++++++++ src/wallet/wallet.h | 3 +++ 7 files changed, 16 insertions(+), 27 deletions(-) diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index a0b414614b3..b3870e6029d 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -348,12 +348,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() // generate a common one from the HD seed. This ensures the data is // recoverable, while keeping it logically separate from the ZIP 32 // Sapling key hierarchy, which the user might not be using. - HDSeed seed; - if (!pwalletMain->GetHDSeed(seed)) { - throw JSONRPCError( - RPC_WALLET_ERROR, - "AsyncRPCOperation_sendmany: HD seed not found"); - } + HDSeed seed = pwalletMain->GetHDSeedForRPC(); ovk = ovkForShieldingFromTaddr(seed); } if (!ovk) { diff --git a/src/wallet/asyncrpcoperation_saplingmigration.cpp b/src/wallet/asyncrpcoperation_saplingmigration.cpp index 4076415eaa2..ab44bf76077 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.cpp +++ b/src/wallet/asyncrpcoperation_saplingmigration.cpp @@ -85,13 +85,7 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { return true; } - HDSeed seed; - if (!pwalletMain->GetHDSeed(seed)) { - throw JSONRPCError( - RPC_WALLET_ERROR, - "AsyncRPCOperation_AsyncRPCOperation_saplingmigration: HD seed not found"); - } - + HDSeed seed = pwalletMain->GetHDSeedForRPC(); libzcash::SaplingPaymentAddress migrationDestAddress = getMigrationDestAddress(seed); auto consensusParams = Params().GetConsensus(); diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index e33440a4d0e..e30c0748373 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -381,12 +381,7 @@ bool AsyncRPCOperation_sendmany::main_impl() { // generate a common one from the HD seed. This ensures the data is // recoverable, while keeping it logically separate from the ZIP 32 // Sapling key hierarchy, which the user might not be using. - HDSeed seed; - if (!pwalletMain->GetHDSeed(seed)) { - throw JSONRPCError( - RPC_WALLET_ERROR, - "AsyncRPCOperation_sendmany::main_impl(): HD seed not found"); - } + HDSeed seed = pwalletMain->GetHDSeedForRPC(); ovk = ovkForShieldingFromTaddr(seed); } diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp index 4280ac2f15c..84811c6868e 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp @@ -247,12 +247,7 @@ bool ShieldToAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) c // generate a common one from the HD seed. This ensures the data is // recoverable, while keeping it logically separate from the ZIP 32 // Sapling key hierarchy, which the user might not be using. - HDSeed seed; - if (!pwalletMain->GetHDSeed(seed)) { - throw JSONRPCError( - RPC_WALLET_ERROR, - "CWallet::GenerateNewSaplingZKey(): HD seed not found"); - } + HDSeed seed = pwalletMain->GetHDSeedForRPC(); uint256 ovk = ovkForShieldingFromTaddr(seed); // Add transparent inputs diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 600d0de8bb0..8105f51768e 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -506,8 +506,7 @@ UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys) file << strprintf("# * Best block at time of backup was %i (%s),\n", chainActive.Height(), chainActive.Tip()->GetBlockHash().ToString()); file << strprintf("# mined on %s\n", EncodeDumpTime(chainActive.Tip()->GetBlockTime())); { - HDSeed hdSeed; - pwalletMain->GetHDSeed(hdSeed); + HDSeed hdSeed = pwalletMain->GetHDSeedForRPC(); auto rawSeed = hdSeed.RawSeed(); file << strprintf("# HDSeed=%s fingerprint=%s", HexStr(rawSeed.begin(), rawSeed.end()), hdSeed.Fingerprint().GetHex()); file << "\n"; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 93e668923c8..cf220fcf2a6 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2156,6 +2156,14 @@ bool CWallet::SetCryptedHDSeed(const uint256& seedFp, const std::vectorGetHDSeed(seed)) { + throw JSONRPCError(RPC_WALLET_ERROR, "HD seed not found"); + } + return seed; +} + void CWallet::SetHDChain(const CHDChain& chain, bool memonly) { LOCK(cs_wallet); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 7cd808b6250..6e4c239d9de 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1288,6 +1288,9 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool SetHDSeed(const HDSeed& seed); bool SetCryptedHDSeed(const uint256& seedFp, const std::vector &vchCryptedSecret); + /* Returns the wallet's HD seed or throw JSONRPCError(...) */ + HDSeed GetHDSeedForRPC() const; + /* Set the HD chain model (chain child index counters) */ void SetHDChain(const CHDChain& chain, bool memonly); const CHDChain& GetHDChain() const { return hdChain; } From 6e82d72852ec81624ad8f833e1fc429786f4dfce Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Fri, 26 Apr 2019 15:31:57 -0600 Subject: [PATCH 040/395] Add rpc to get Sprout to Sapling migration status --- qa/rpc-tests/sprout_sapling_migration.py | 48 ++++++++-- .../asyncrpcoperation_saplingmigration.h | 4 +- src/wallet/rpcwallet.cpp | 96 +++++++++++++++++++ 3 files changed, 140 insertions(+), 8 deletions(-) diff --git a/qa/rpc-tests/sprout_sapling_migration.py b/qa/rpc-tests/sprout_sapling_migration.py index 13dc2189001..cdfaa5393cd 100755 --- a/qa/rpc-tests/sprout_sapling_migration.py +++ b/qa/rpc-tests/sprout_sapling_migration.py @@ -11,12 +11,36 @@ initialize_chain_clean, start_nodes, wait_and_assert_operationid_status, \ wait_and_assert_operationid_status_result +SAPLING_ADDR = 'zregtestsapling1ssqj3f3majnl270985gqcdqedd9t4nlttjqskccwevj2v20sc25deqspv3masufnwcdy67cydyy' +SAPLING_KEY = 'secret-extended-key-regtest1qv62zt2fqyqqpqrh2qzc08h7gncf4447jh9kvnnnhjg959fkwt7mhw9j8e9at7attx8z6u3953u86vcnsujdc2ckdlcmztjt44x3uxpah5mxtncxd0mqcnz9eq8rghh5m4j44ep5d9702sdvvwawqassulktfegrcp4twxgqdxx4eww3lau0mywuaeztpla2cmvagr5nj98elt45zh6fjznadl6wz52n2uyhdwcm2wlsu8fnxstrk6s4t55t8dy6jkgx5g0cwpchh5qffp8x5' + + +def check_migration_status( + node, + enabled, + non_zero_unmigrated_amount, + non_zero_unfinalized_migrated_amount, + non_zero_finalized_migrated_amount, + finalized_migration_transactions, + len_migration_txids +): + status = node.z_getmigrationstatus() + assert_equal(enabled, status['enabled']) + assert_equal(SAPLING_ADDR, status['destination_address']) + assert_equal(non_zero_unmigrated_amount, Decimal(status['unmigrated_amount']) > Decimal('0.00')) + assert_equal(non_zero_unfinalized_migrated_amount, Decimal(status['unfinalized_migrated_amount']) > Decimal('0')) + assert_equal(non_zero_finalized_migrated_amount, Decimal(status['finalized_migrated_amount']) > Decimal('0')) + assert_equal(finalized_migration_transactions, status['finalized_migration_transactions']) + assert_equal(len_migration_txids, len(status['migration_txids'])) + class SproutSaplingMigration(BitcoinTestFramework): def setup_nodes(self): return start_nodes(4, self.options.tmpdir, [[ '-nuparams=5ba81b19:100', # Overwinter '-nuparams=76b809bb:100', # Sapling + '-migration', + '-migrationdestaddress=' + SAPLING_ADDR ]] * 4) def setup_chain(self): @@ -24,6 +48,10 @@ def setup_chain(self): initialize_chain_clean(self.options.tmpdir, 4) def run_test(self): + check_migration_status(self.nodes[0], True, False, False, False, 0, 0) + self.nodes[0].z_setmigration(False) + check_migration_status(self.nodes[0], False, False, False, False, 0, 0) + print "Mining blocks..." self.nodes[0].generate(101) self.sync_all() @@ -31,7 +59,8 @@ def run_test(self): # Send some ZEC to a Sprout address tAddr = get_coinbase_address(self.nodes[0]) sproutAddr = self.nodes[0].z_getnewaddress('sprout') - saplingAddr = self.nodes[0].z_getnewaddress('sapling') + # Import a previously generated key to test '-migrationdestaddress' + self.nodes[0].z_importkey(SAPLING_KEY) opid = self.nodes[0].z_sendmany(tAddr, [{"address": sproutAddr, "amount": Decimal('10')}], 1, 0) wait_and_assert_operationid_status(self.nodes[0], opid) @@ -39,7 +68,7 @@ def run_test(self): self.sync_all() assert_equal(self.nodes[0].z_getbalance(sproutAddr), Decimal('10')) - assert_equal(self.nodes[0].z_getbalance(saplingAddr), Decimal('0')) + assert_equal(self.nodes[0].z_getbalance(SAPLING_ADDR), Decimal('0')) # Migrate self.nodes[0].z_setmigration(True) @@ -49,6 +78,7 @@ def run_test(self): # At 494 we should have no async operations assert_equal(0, len(self.nodes[0].z_getoperationstatus()), "num async operations at 494") + check_migration_status(self.nodes[0], True, True, False, False, 0, 0) self.nodes[0].generate(1) self.sync_all() @@ -74,7 +104,7 @@ def run_test(self): # At 498 the mempool will be empty and no funds will have moved assert_equal(0, len(self.nodes[0].getrawmempool()), "mempool size at 498") assert_equal(self.nodes[0].z_getbalance(sproutAddr), Decimal('10')) - assert_equal(self.nodes[0].z_getbalance(saplingAddr), Decimal('0')) + assert_equal(self.nodes[0].z_getbalance(SAPLING_ADDR), Decimal('0')) self.nodes[0].generate(1) self.sync_all() @@ -82,20 +112,26 @@ def run_test(self): # At 499 there will be a transaction in the mempool and the note will be locked assert_equal(1, len(self.nodes[0].getrawmempool()), "mempool size at 499") assert_equal(self.nodes[0].z_getbalance(sproutAddr), Decimal('0')) - assert_equal(self.nodes[0].z_getbalance(saplingAddr), Decimal('0')) - assert_true(self.nodes[0].z_getbalance(saplingAddr, 0) > Decimal('0'), "Unconfirmed sapling") + assert_equal(self.nodes[0].z_getbalance(SAPLING_ADDR), Decimal('0')) + assert_true(self.nodes[0].z_getbalance(SAPLING_ADDR, 0) > Decimal('0'), "Unconfirmed sapling") self.nodes[0].generate(1) self.sync_all() # At 500 funds will have moved sprout_balance = self.nodes[0].z_getbalance(sproutAddr) - sapling_balance = self.nodes[0].z_getbalance(saplingAddr) + sapling_balance = self.nodes[0].z_getbalance(SAPLING_ADDR) print "sprout balance: {}, sapling balance: {}".format(sprout_balance, sapling_balance) assert_true(sprout_balance < Decimal('10'), "Should have less Sprout funds") assert_true(sapling_balance > Decimal('0'), "Should have more Sapling funds") assert_true(sprout_balance + sapling_balance, Decimal('9.9999')) + check_migration_status(self.nodes[0], True, True, True, False, 0, 1) + # At 510 the transactions will be considered 'finalized' + self.nodes[0].generate(10) + self.sync_all() + check_migration_status(self.nodes[0], True, True, False, True, 1, 1) + if __name__ == '__main__': SproutSaplingMigration().main() diff --git a/src/wallet/asyncrpcoperation_saplingmigration.h b/src/wallet/asyncrpcoperation_saplingmigration.h index af26281f613..e077c8eca32 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.h +++ b/src/wallet/asyncrpcoperation_saplingmigration.h @@ -16,6 +16,8 @@ class AsyncRPCOperation_saplingmigration : public AsyncRPCOperation AsyncRPCOperation_saplingmigration& operator=(AsyncRPCOperation_saplingmigration const&) = delete; // Copy assign AsyncRPCOperation_saplingmigration& operator=(AsyncRPCOperation_saplingmigration&&) = delete; // Move assign + static libzcash::SaplingPaymentAddress getMigrationDestAddress(const HDSeed& seed); + virtual void main(); virtual UniValue getStatus() const; @@ -28,6 +30,4 @@ class AsyncRPCOperation_saplingmigration : public AsyncRPCOperation void setMigrationResult(int numTxCreated); CAmount chooseAmount(const CAmount& availableFunds); - - libzcash::SaplingPaymentAddress getMigrationDestAddress(const HDSeed& seed); }; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 347d65b189f..c48ed2c158a 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -27,6 +27,7 @@ #include "asyncrpcoperation.h" #include "asyncrpcqueue.h" #include "wallet/asyncrpcoperation_mergetoaddress.h" +#include "wallet/asyncrpcoperation_saplingmigration.h" #include "wallet/asyncrpcoperation_sendmany.h" #include "wallet/asyncrpcoperation_shieldcoinbase.h" @@ -3929,6 +3930,100 @@ UniValue z_setmigration(const UniValue& params, bool fHelp) { return NullUniValue; } +UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return NullUniValue; + if (fHelp || params.size() != 0) + throw runtime_error( + "z_getmigrationstatus\n" + "Returns information about the status of the Sprout to Sapling migration.\n" + "In the result a transactions is defined as finalized iff it has ten confirmations.\n" + "Note: It is possible that manually created transactions invloving this wallet\n" + "will be included in the result.\n" + "\nResult:\n" + "{\n" + " \"enabled\": true|false, (boolean) Whether or not migration is enabled\n" + " \"destination_address\": \"zaddr\", (string) The Sapling address which will receive Sprout funds\n" + " \"unmigrated_amount\": nnn.n, (numeric) The total amount of unmigrated " + CURRENCY_UNIT +" \n" + " \"unfinalized_migrated_amount\": nnn.n, (numeric) The total amount of unfinalized " + CURRENCY_UNIT + " \n" + " \"finalized_migrated_amount\": nnn.n, (numeric) The total amount of finalized " + CURRENCY_UNIT + " \n" + " \"finalized_migration_transactions\": nnn, (numeric) The number of migration transactions involving this wallet\n" + " \"time_started\": ttt, (numeric, optional) The block time of the first migration transaction\n" + " \"migration_txids\": [txids] (json array of strings) An array of all migration txids involving this wallet\n" + "}\n" + ); + LOCK2(cs_main, pwalletMain->cs_wallet); + UniValue migrationStatus(UniValue::VOBJ); + migrationStatus.push_back(Pair("enabled", pwalletMain->fSaplingMigrationEnabled)); + // The "destination_address" field MAY be omitted if the "-migrationaddress" + // parameter is not set and no default address has yet been generated. + // Note: The following function may return the default address even if it has not been added to the wallet + auto destinationAddress = AsyncRPCOperation_saplingmigration::getMigrationDestAddress(pwalletMain->GetHDSeedForRPC()); + migrationStatus.push_back(Pair("destination_address", EncodePaymentAddress(destinationAddress))); + // The values of "unmigrated_amount" and "migrated_amount" MUST take into + // account failed transactions, that were not mined within their expiration + // height. + { + std::vector sproutEntries; + std::vector saplingEntries; + pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, "", 1); + CAmount unmigratedAmount = 0; + for (const auto& sproutEntry : sproutEntries) { + unmigratedAmount += sproutEntry.plaintext.value(); + } + migrationStatus.push_back(Pair("unmigrated_amount", FormatMoney(unmigratedAmount))); + } + // "migration_txids" is a list of strings representing transaction IDs of all + // known migration transactions involving this wallet, as lowercase hexadecimal + // in RPC byte order. + UniValue migrationTxids(UniValue::VARR); + int currentHeight = chainActive.Height(); + CAmount unfinalizedMigratedAmount = 0; + CAmount finalizedMigratedAmount = 0; + int numFinalizedMigrationTxs = 0; + uint64_t timeStarted = 0; + for (const auto& txPair : pwalletMain->mapWallet) { + CWalletTx tx = txPair.second; + // A given transaction is defined as a migration transaction iff it has: + // * one or more Sprout JoinSplits with nonzero vpub_new field; and + // * no Sapling Spends, and; + // * one or more Sapling Outputs. + if (tx.vjoinsplit.size() > 0 && tx.vShieldedSpend.empty() && tx.vShieldedOutput.size() > 0) { + CAmount migrationAmount = 0; + for (const auto& js : tx.vjoinsplit) { + migrationAmount += js.vpub_new; + } + if (migrationAmount == 0) { + continue; + } + migrationTxids.push_back(txPair.first.ToString()); + CBlockIndex* blockIndex = mapBlockIndex[tx.hashBlock]; + // A transaction is "finalized" iff it has 10 confirmations. + // TODO: subject to change, if the recommended number of confirmations changes. + if (currentHeight >= blockIndex->nHeight + 10) { + finalizedMigratedAmount += migrationAmount; + ++numFinalizedMigrationTxs; + } else { + unfinalizedMigratedAmount += migrationAmount; + } + // The value of "time_started" is the earliest Unix timestamp of any known + // migration transaction involving this wallet; if there is no such transaction, + // then the field is absent. + if (timeStarted == 0 || timeStarted > blockIndex->GetBlockTime()) { + timeStarted = blockIndex->GetBlockTime(); + } + } + } + migrationStatus.push_back(Pair("unfinalized_migrated_amount", FormatMoney(unfinalizedMigratedAmount))); + migrationStatus.push_back(Pair("finalized_migrated_amount", FormatMoney(finalizedMigratedAmount))); + migrationStatus.push_back(Pair("finalized_migration_transactions", numFinalizedMigrationTxs)); + if (timeStarted > 0) { + migrationStatus.push_back(Pair("time_started", timeStarted)); + } + migrationStatus.push_back(Pair("migration_txids", migrationTxids)); + return migrationStatus; +} + /** When estimating the number of coinbase utxos we can shield in a single transaction: 1. Joinsplit description is 1802 bytes. @@ -4683,6 +4778,7 @@ static const CRPCCommand commands[] = { "wallet", "z_mergetoaddress", &z_mergetoaddress, false }, { "wallet", "z_sendmany", &z_sendmany, false }, { "wallet", "z_setmigration", &z_setmigration, false }, + { "wallet", "z_getmigrationstatus", &z_getmigrationstatus, false }, { "wallet", "z_shieldcoinbase", &z_shieldcoinbase, false }, { "wallet", "z_getoperationstatus", &z_getoperationstatus, true }, { "wallet", "z_getoperationresult", &z_getoperationresult, true }, From 5969bd8f553f53d52ee961a750d1e26b3b147c52 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Mon, 29 Apr 2019 10:39:05 -0600 Subject: [PATCH 041/395] Fix help message --- src/init.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index 653a05fcb31..30bdccd51ff 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -406,7 +406,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageGroup(_("Wallet options:")); strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls")); strUsage += HelpMessageOpt("-keypool=", strprintf(_("Set key pool size to (default: %u)"), 100)); - strUsage += HelpMessageOpt("-migration=", _("Set to true to enable the Sprout to Sapling migration.")); + strUsage += HelpMessageOpt("-migration", _("Enable the Sprout to Sapling migration")); strUsage += HelpMessageOpt("-migrationdestaddress=", _("Set the Sapling migration address")); if (showDebug) strUsage += HelpMessageOpt("-mintxfee=", strprintf("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)", From 2276133bb36af999d7b80842b320c9687512205b Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Mon, 29 Apr 2019 13:53:29 -0600 Subject: [PATCH 042/395] Test migration using both the parameter and the default Sapling address --- qa/rpc-tests/sprout_sapling_migration.py | 150 ++++++++++++++--------- 1 file changed, 92 insertions(+), 58 deletions(-) diff --git a/qa/rpc-tests/sprout_sapling_migration.py b/qa/rpc-tests/sprout_sapling_migration.py index cdfaa5393cd..e364a2c87e5 100755 --- a/qa/rpc-tests/sprout_sapling_migration.py +++ b/qa/rpc-tests/sprout_sapling_migration.py @@ -18,6 +18,7 @@ def check_migration_status( node, enabled, + destination_address, non_zero_unmigrated_amount, non_zero_unfinalized_migrated_amount, non_zero_finalized_migrated_amount, @@ -26,7 +27,7 @@ def check_migration_status( ): status = node.z_getmigrationstatus() assert_equal(enabled, status['enabled']) - assert_equal(SAPLING_ADDR, status['destination_address']) + assert_equal(destination_address, status['destination_address']) assert_equal(non_zero_unmigrated_amount, Decimal(status['unmigrated_amount']) > Decimal('0.00')) assert_equal(non_zero_unfinalized_migrated_amount, Decimal(status['unfinalized_migrated_amount']) > Decimal('0')) assert_equal(non_zero_finalized_migrated_amount, Decimal(status['finalized_migrated_amount']) > Decimal('0')) @@ -36,101 +37,134 @@ def check_migration_status( class SproutSaplingMigration(BitcoinTestFramework): def setup_nodes(self): - return start_nodes(4, self.options.tmpdir, [[ + # Activate overwinter/sapling on all nodes + extra_args = [[ '-nuparams=5ba81b19:100', # Overwinter '-nuparams=76b809bb:100', # Sapling + ]] * 4 + # Add migration parameters to nodes[0] + extra_args[0] = extra_args[0] + [ '-migration', '-migrationdestaddress=' + SAPLING_ADDR - ]] * 4) + ] + assert_equal(4, len(extra_args[0])) + assert_equal(2, len(extra_args[1])) + return start_nodes(4, self.options.tmpdir, extra_args) def setup_chain(self): print("Initializing test directory " + self.options.tmpdir) initialize_chain_clean(self.options.tmpdir, 4) - def run_test(self): - check_migration_status(self.nodes[0], True, False, False, False, 0, 0) - self.nodes[0].z_setmigration(False) - check_migration_status(self.nodes[0], False, False, False, False, 0, 0) - - print "Mining blocks..." - self.nodes[0].generate(101) - self.sync_all() - - # Send some ZEC to a Sprout address - tAddr = get_coinbase_address(self.nodes[0]) - sproutAddr = self.nodes[0].z_getnewaddress('sprout') - # Import a previously generated key to test '-migrationdestaddress' - self.nodes[0].z_importkey(SAPLING_KEY) - - opid = self.nodes[0].z_sendmany(tAddr, [{"address": sproutAddr, "amount": Decimal('10')}], 1, 0) - wait_and_assert_operationid_status(self.nodes[0], opid) - self.nodes[0].generate(1) - self.sync_all() - - assert_equal(self.nodes[0].z_getbalance(sproutAddr), Decimal('10')) - assert_equal(self.nodes[0].z_getbalance(SAPLING_ADDR), Decimal('0')) + def run_migration_test(self, node, sproutAddr, saplingAddr, target_height): + # Make sure we are in a good state to run the test + assert_equal(102, node.getblockcount() % 500, "Should be at block 102 % 500") + assert_equal(node.z_getbalance(sproutAddr), Decimal('10')) + assert_equal(node.z_getbalance(saplingAddr), Decimal('0')) + check_migration_status(node, False, saplingAddr, True, False, False, 0, 0) # Migrate - self.nodes[0].z_setmigration(True) - print "Mining to block 494..." - self.nodes[0].generate(392) # 102 -> 494 + node.z_setmigration(True) + print "Mining to block 494 % 500..." + node.generate(392) # 102 % 500 -> 494 % 500 self.sync_all() - # At 494 we should have no async operations - assert_equal(0, len(self.nodes[0].z_getoperationstatus()), "num async operations at 494") - check_migration_status(self.nodes[0], True, True, False, False, 0, 0) + # At 494 % 500 we should have no async operations + assert_equal(0, len(node.z_getoperationstatus()), "num async operations at 494 % 500") + check_migration_status(node, True, saplingAddr, True, False, False, 0, 0) - self.nodes[0].generate(1) + node.generate(1) self.sync_all() - # At 495 we should have an async operation - operationstatus = self.nodes[0].z_getoperationstatus() + # At 495 % 500 we should have an async operation + operationstatus = node.z_getoperationstatus() print "migration operation: {}".format(operationstatus) - assert_equal(1, len(operationstatus), "num async operations at 495") + assert_equal(1, len(operationstatus), "num async operations at 495 % 500") assert_equal('saplingmigration', operationstatus[0]['method']) - assert_equal(500, operationstatus[0]['target_height']) + assert_equal(target_height, operationstatus[0]['target_height']) - result = wait_and_assert_operationid_status_result(self.nodes[0], operationstatus[0]['id']) + result = wait_and_assert_operationid_status_result(node, operationstatus[0]['id']) print "result: {}".format(result) assert_equal('saplingmigration', result['method']) - assert_equal(500, result['target_height']) + assert_equal(target_height, result['target_height']) assert_equal(1, result['result']['num_tx_created']) - assert_equal(0, len(self.nodes[0].getrawmempool()), "mempool size at 495") + assert_equal(0, len(node.getrawmempool()), "mempool size at 495 % 500") - self.nodes[0].generate(3) + node.generate(3) self.sync_all() - # At 498 the mempool will be empty and no funds will have moved - assert_equal(0, len(self.nodes[0].getrawmempool()), "mempool size at 498") - assert_equal(self.nodes[0].z_getbalance(sproutAddr), Decimal('10')) - assert_equal(self.nodes[0].z_getbalance(SAPLING_ADDR), Decimal('0')) + # At 498 % 500 the mempool will be empty and no funds will have moved + assert_equal(0, len(node.getrawmempool()), "mempool size at 498 % 500") + assert_equal(node.z_getbalance(sproutAddr), Decimal('10')) + assert_equal(node.z_getbalance(saplingAddr), Decimal('0')) - self.nodes[0].generate(1) + node.generate(1) self.sync_all() - # At 499 there will be a transaction in the mempool and the note will be locked - assert_equal(1, len(self.nodes[0].getrawmempool()), "mempool size at 499") - assert_equal(self.nodes[0].z_getbalance(sproutAddr), Decimal('0')) - assert_equal(self.nodes[0].z_getbalance(SAPLING_ADDR), Decimal('0')) - assert_true(self.nodes[0].z_getbalance(SAPLING_ADDR, 0) > Decimal('0'), "Unconfirmed sapling") + # At 499 % 500 there will be a transaction in the mempool and the note will be locked + assert_equal(1, len(node.getrawmempool()), "mempool size at 499 % 500") + assert_equal(node.z_getbalance(sproutAddr), Decimal('0')) + assert_equal(node.z_getbalance(saplingAddr), Decimal('0')) + assert_true(node.z_getbalance(saplingAddr, 0) > Decimal('0'), "Unconfirmed sapling balance at 499") - self.nodes[0].generate(1) + node.generate(1) self.sync_all() - # At 500 funds will have moved - sprout_balance = self.nodes[0].z_getbalance(sproutAddr) - sapling_balance = self.nodes[0].z_getbalance(SAPLING_ADDR) + # At 0 % 500 funds will have moved + sprout_balance = node.z_getbalance(sproutAddr) + sapling_balance = node.z_getbalance(saplingAddr) print "sprout balance: {}, sapling balance: {}".format(sprout_balance, sapling_balance) assert_true(sprout_balance < Decimal('10'), "Should have less Sprout funds") assert_true(sapling_balance > Decimal('0'), "Should have more Sapling funds") assert_true(sprout_balance + sapling_balance, Decimal('9.9999')) - check_migration_status(self.nodes[0], True, True, True, False, 0, 1) - # At 510 the transactions will be considered 'finalized' - self.nodes[0].generate(10) + check_migration_status(node, True, saplingAddr, True, True, False, 0, 1) + # At 10 % 500 the transactions will be considered 'finalized' + node.generate(10) + self.sync_all() + check_migration_status(node, True, saplingAddr, True, False, True, 1, 1) + + def send_to_sprout_zaddr(self, tAddr, sproutAddr): + # Send some ZEC to a Sprout address + opid = self.nodes[0].z_sendmany(tAddr, [{"address": sproutAddr, "amount": Decimal('10')}], 1, 0) + wait_and_assert_operationid_status(self.nodes[0], opid) + self.nodes[0].generate(1) + self.sync_all() + + def run_test(self): + # Check enabling via '-migration' and disabling via rpc + check_migration_status(self.nodes[0], True, SAPLING_ADDR, False, False, False, 0, 0) + self.nodes[0].z_setmigration(False) + check_migration_status(self.nodes[0], False, SAPLING_ADDR, False, False, False, 0, 0) + + # 1. Test using self.nodes[0] which has the parameter + print "Runing test using '-migrationdestaddress'..." + print "Mining blocks..." + self.nodes[0].generate(101) self.sync_all() - check_migration_status(self.nodes[0], True, True, False, True, 1, 1) + tAddr = get_coinbase_address(self.nodes[0]) + + # Import a previously generated key to test '-migrationdestaddress' + self.nodes[0].z_importkey(SAPLING_KEY) + sproutAddr0 = self.nodes[0].z_getnewaddress('sprout') + + self.send_to_sprout_zaddr(tAddr, sproutAddr0) + self.run_migration_test(self.nodes[0], sproutAddr0, SAPLING_ADDR, 500) + # Disable migration so only self.nodes[1] has a transaction in the mempool at block 999 + self.nodes[0].z_setmigration(False) + + # 2. Test using self.nodes[1] which will use the default Sapling address + print "Runing test using default Sapling address..." + # Mine more blocks so we start at 102 % 500 + print "Mining blocks..." + self.nodes[1].generate(91) # 511 -> 602 + self.sync_all() + + sproutAddr1 = self.nodes[1].z_getnewaddress('sprout') + saplingAddr1 = self.nodes[1].z_getnewaddress('sapling') + + self.send_to_sprout_zaddr(tAddr, sproutAddr1) + self.run_migration_test(self.nodes[1], sproutAddr1, saplingAddr1, 1000) if __name__ == '__main__': From 108e587c14f2fd3155af506bcc22d16510172437 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Mon, 29 Apr 2019 14:42:48 -0600 Subject: [PATCH 043/395] Fix typos and update documentation --- qa/rpc-tests/sprout_sapling_migration.py | 6 +++--- src/wallet/rpcwallet.cpp | 9 +++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/qa/rpc-tests/sprout_sapling_migration.py b/qa/rpc-tests/sprout_sapling_migration.py index e364a2c87e5..2287f0740a4 100755 --- a/qa/rpc-tests/sprout_sapling_migration.py +++ b/qa/rpc-tests/sprout_sapling_migration.py @@ -105,7 +105,7 @@ def run_migration_test(self, node, sproutAddr, saplingAddr, target_height): assert_equal(1, len(node.getrawmempool()), "mempool size at 499 % 500") assert_equal(node.z_getbalance(sproutAddr), Decimal('0')) assert_equal(node.z_getbalance(saplingAddr), Decimal('0')) - assert_true(node.z_getbalance(saplingAddr, 0) > Decimal('0'), "Unconfirmed sapling balance at 499") + assert_true(node.z_getbalance(saplingAddr, 0) > Decimal('0'), "Unconfirmed sapling balance at 499 % 500") node.generate(1) self.sync_all() @@ -138,7 +138,7 @@ def run_test(self): check_migration_status(self.nodes[0], False, SAPLING_ADDR, False, False, False, 0, 0) # 1. Test using self.nodes[0] which has the parameter - print "Runing test using '-migrationdestaddress'..." + print "Running test using '-migrationdestaddress'..." print "Mining blocks..." self.nodes[0].generate(101) self.sync_all() @@ -154,7 +154,7 @@ def run_test(self): self.nodes[0].z_setmigration(False) # 2. Test using self.nodes[1] which will use the default Sapling address - print "Runing test using default Sapling address..." + print "Running test using default Sapling address..." # Mine more blocks so we start at 102 % 500 print "Mining blocks..." self.nodes[1].generate(91) # 511 -> 602 diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index c48ed2c158a..5fe0a7b1d4b 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3937,13 +3937,14 @@ UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) { throw runtime_error( "z_getmigrationstatus\n" "Returns information about the status of the Sprout to Sapling migration.\n" - "In the result a transactions is defined as finalized iff it has ten confirmations.\n" - "Note: It is possible that manually created transactions invloving this wallet\n" + "In the result a transactions is defined as finalized if and only if it has\n" + "at least ten confirmations.\n" + "Note: It is possible that manually created transactions involving this wallet\n" "will be included in the result.\n" "\nResult:\n" "{\n" " \"enabled\": true|false, (boolean) Whether or not migration is enabled\n" - " \"destination_address\": \"zaddr\", (string) The Sapling address which will receive Sprout funds\n" + " \"destination_address\": \"zaddr\", (string) The Sapling address that will receive Sprout funds\n" " \"unmigrated_amount\": nnn.n, (numeric) The total amount of unmigrated " + CURRENCY_UNIT +" \n" " \"unfinalized_migrated_amount\": nnn.n, (numeric) The total amount of unfinalized " + CURRENCY_UNIT + " \n" " \"finalized_migrated_amount\": nnn.n, (numeric) The total amount of finalized " + CURRENCY_UNIT + " \n" @@ -3955,7 +3956,7 @@ UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) { LOCK2(cs_main, pwalletMain->cs_wallet); UniValue migrationStatus(UniValue::VOBJ); migrationStatus.push_back(Pair("enabled", pwalletMain->fSaplingMigrationEnabled)); - // The "destination_address" field MAY be omitted if the "-migrationaddress" + // The "destination_address" field MAY be omitted if the "-migrationdestaddress" // parameter is not set and no default address has yet been generated. // Note: The following function may return the default address even if it has not been added to the wallet auto destinationAddress = AsyncRPCOperation_saplingmigration::getMigrationDestAddress(pwalletMain->GetHDSeedForRPC()); From e9530f40f22d33acee648252a109a2eba0babb56 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Mon, 29 Apr 2019 17:00:26 -0600 Subject: [PATCH 044/395] use -valueBalance rather than vpub_new to calculate migrated amount --- qa/rpc-tests/sprout_sapling_migration.py | 4 ++++ src/wallet/rpcwallet.cpp | 18 +++++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/qa/rpc-tests/sprout_sapling_migration.py b/qa/rpc-tests/sprout_sapling_migration.py index 2287f0740a4..fd81c573052 100755 --- a/qa/rpc-tests/sprout_sapling_migration.py +++ b/qa/rpc-tests/sprout_sapling_migration.py @@ -123,6 +123,10 @@ def run_migration_test(self, node, sproutAddr, saplingAddr, target_height): node.generate(10) self.sync_all() check_migration_status(node, True, saplingAddr, True, False, True, 1, 1) + # Check exact migration status amounts to make sure we account for fee + status = node.z_getmigrationstatus() + assert_equal(sprout_balance, Decimal(status['unmigrated_amount'])) + assert_equal(sapling_balance, Decimal(status['finalized_migrated_amount'])) def send_to_sprout_zaddr(self, tAddr, sproutAddr): # Send some ZEC to a Sprout address diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 5fe0a7b1d4b..651c1e3289e 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3989,23 +3989,27 @@ UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) { // * one or more Sprout JoinSplits with nonzero vpub_new field; and // * no Sapling Spends, and; // * one or more Sapling Outputs. - if (tx.vjoinsplit.size() > 0 && tx.vShieldedSpend.empty() && tx.vShieldedOutput.size() > 0) { - CAmount migrationAmount = 0; + if (tx.vjoinsplit.size() > 0 && tx.vShieldedSpend.empty() && tx.vShieldedOutput.size() > 0 && + tx.vin.empty() && tx.vout.empty()) { + bool nonZeroVPubNew = false; for (const auto& js : tx.vjoinsplit) { - migrationAmount += js.vpub_new; + if (js.vpub_new > 0) { + nonZeroVPubNew = true; + break; + } } - if (migrationAmount == 0) { + if (!nonZeroVPubNew) { continue; } migrationTxids.push_back(txPair.first.ToString()); CBlockIndex* blockIndex = mapBlockIndex[tx.hashBlock]; - // A transaction is "finalized" iff it has 10 confirmations. + // A transaction is "finalized" iff it has at least 10 confirmations. // TODO: subject to change, if the recommended number of confirmations changes. if (currentHeight >= blockIndex->nHeight + 10) { - finalizedMigratedAmount += migrationAmount; + finalizedMigratedAmount -= tx.valueBalance; ++numFinalizedMigrationTxs; } else { - unfinalizedMigratedAmount += migrationAmount; + unfinalizedMigratedAmount -= tx.valueBalance; } // The value of "time_started" is the earliest Unix timestamp of any known // migration transaction involving this wallet; if there is no such transaction, From 345177cfc1085ee49e862760df8c03b8f6206923 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Tue, 30 Apr 2019 09:52:53 -0600 Subject: [PATCH 045/395] Do not look at vin/vout when determining migration txs and other cleanup --- qa/rpc-tests/sprout_sapling_migration.py | 16 ++++++++-------- src/wallet/rpcwallet.cpp | 5 ++--- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/qa/rpc-tests/sprout_sapling_migration.py b/qa/rpc-tests/sprout_sapling_migration.py index fd81c573052..5f47d779616 100755 --- a/qa/rpc-tests/sprout_sapling_migration.py +++ b/qa/rpc-tests/sprout_sapling_migration.py @@ -64,7 +64,7 @@ def run_migration_test(self, node, sproutAddr, saplingAddr, target_height): # Migrate node.z_setmigration(True) - print "Mining to block 494 % 500..." + print("Mining to block 494 % 500...") node.generate(392) # 102 % 500 -> 494 % 500 self.sync_all() @@ -77,13 +77,13 @@ def run_migration_test(self, node, sproutAddr, saplingAddr, target_height): # At 495 % 500 we should have an async operation operationstatus = node.z_getoperationstatus() - print "migration operation: {}".format(operationstatus) + print("migration operation: {}".format(operationstatus)) assert_equal(1, len(operationstatus), "num async operations at 495 % 500") assert_equal('saplingmigration', operationstatus[0]['method']) assert_equal(target_height, operationstatus[0]['target_height']) result = wait_and_assert_operationid_status_result(node, operationstatus[0]['id']) - print "result: {}".format(result) + print("result: {}".format(result)) assert_equal('saplingmigration', result['method']) assert_equal(target_height, result['target_height']) assert_equal(1, result['result']['num_tx_created']) @@ -113,7 +113,7 @@ def run_migration_test(self, node, sproutAddr, saplingAddr, target_height): # At 0 % 500 funds will have moved sprout_balance = node.z_getbalance(sproutAddr) sapling_balance = node.z_getbalance(saplingAddr) - print "sprout balance: {}, sapling balance: {}".format(sprout_balance, sapling_balance) + print("sprout balance: {}, sapling balance: {}".format(sprout_balance, sapling_balance)) assert_true(sprout_balance < Decimal('10'), "Should have less Sprout funds") assert_true(sapling_balance > Decimal('0'), "Should have more Sapling funds") assert_true(sprout_balance + sapling_balance, Decimal('9.9999')) @@ -142,8 +142,8 @@ def run_test(self): check_migration_status(self.nodes[0], False, SAPLING_ADDR, False, False, False, 0, 0) # 1. Test using self.nodes[0] which has the parameter - print "Running test using '-migrationdestaddress'..." - print "Mining blocks..." + print("Running test using '-migrationdestaddress'...") + print("Mining blocks...") self.nodes[0].generate(101) self.sync_all() tAddr = get_coinbase_address(self.nodes[0]) @@ -158,9 +158,9 @@ def run_test(self): self.nodes[0].z_setmigration(False) # 2. Test using self.nodes[1] which will use the default Sapling address - print "Running test using default Sapling address..." + print("Running test using default Sapling address...") # Mine more blocks so we start at 102 % 500 - print "Mining blocks..." + print("Mining blocks...") self.nodes[1].generate(91) # 511 -> 602 self.sync_all() diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 651c1e3289e..f8f0086665b 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3949,7 +3949,7 @@ UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) { " \"unfinalized_migrated_amount\": nnn.n, (numeric) The total amount of unfinalized " + CURRENCY_UNIT + " \n" " \"finalized_migrated_amount\": nnn.n, (numeric) The total amount of finalized " + CURRENCY_UNIT + " \n" " \"finalized_migration_transactions\": nnn, (numeric) The number of migration transactions involving this wallet\n" - " \"time_started\": ttt, (numeric, optional) The block time of the first migration transaction\n" + " \"time_started\": ttt, (numeric, optional) The block time of the first migration transaction as a Unix timestamp\n" " \"migration_txids\": [txids] (json array of strings) An array of all migration txids involving this wallet\n" "}\n" ); @@ -3989,8 +3989,7 @@ UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) { // * one or more Sprout JoinSplits with nonzero vpub_new field; and // * no Sapling Spends, and; // * one or more Sapling Outputs. - if (tx.vjoinsplit.size() > 0 && tx.vShieldedSpend.empty() && tx.vShieldedOutput.size() > 0 && - tx.vin.empty() && tx.vout.empty()) { + if (tx.vjoinsplit.size() > 0 && tx.vShieldedSpend.empty() && tx.vShieldedOutput.size() > 0) { bool nonZeroVPubNew = false; for (const auto& js : tx.vjoinsplit) { if (js.vpub_new > 0) { From e14cf96642de67ebe2043b701e16e64168ca5079 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Tue, 30 Apr 2019 11:06:08 -0600 Subject: [PATCH 046/395] Calculate the number of confimations in the canonical way --- src/wallet/rpcwallet.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index f8f0086665b..d0e67a1b2e7 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3978,7 +3978,6 @@ UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) { // known migration transactions involving this wallet, as lowercase hexadecimal // in RPC byte order. UniValue migrationTxids(UniValue::VARR); - int currentHeight = chainActive.Height(); CAmount unfinalizedMigratedAmount = 0; CAmount finalizedMigratedAmount = 0; int numFinalizedMigrationTxs = 0; @@ -4004,7 +4003,7 @@ UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) { CBlockIndex* blockIndex = mapBlockIndex[tx.hashBlock]; // A transaction is "finalized" iff it has at least 10 confirmations. // TODO: subject to change, if the recommended number of confirmations changes. - if (currentHeight >= blockIndex->nHeight + 10) { + if (tx.GetDepthInMainChain() >= 10) { finalizedMigratedAmount -= tx.valueBalance; ++numFinalizedMigrationTxs; } else { From 3cad5f454fcf1933640b1d92351837e0858c0d0c Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Tue, 30 Apr 2019 15:47:03 -0600 Subject: [PATCH 047/395] Do not throw an exception if HD Seed is not found when exporting wallet --- src/wallet/rpcdump.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 8105f51768e..600d0de8bb0 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -506,7 +506,8 @@ UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys) file << strprintf("# * Best block at time of backup was %i (%s),\n", chainActive.Height(), chainActive.Tip()->GetBlockHash().ToString()); file << strprintf("# mined on %s\n", EncodeDumpTime(chainActive.Tip()->GetBlockTime())); { - HDSeed hdSeed = pwalletMain->GetHDSeedForRPC(); + HDSeed hdSeed; + pwalletMain->GetHDSeed(hdSeed); auto rawSeed = hdSeed.RawSeed(); file << strprintf("# HDSeed=%s fingerprint=%s", HexStr(rawSeed.begin(), rawSeed.end()), hdSeed.Fingerprint().GetHex()); file << "\n"; From 4cbe0a9d02712d802c28ca47eda98d49f150c146 Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Wed, 1 May 2019 10:03:24 -0600 Subject: [PATCH 048/395] 3873 z_setmigration cli bool enable arg conversion --- src/rpc/client.cpp | 3 ++- src/test/rpc_wallet_tests.cpp | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 5288d977e60..8838bd27390 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -130,7 +130,8 @@ static const CRPCConvertParam vRPCConvertParams[] = { "z_importkey", 2 }, { "z_importviewingkey", 2 }, { "z_getpaymentdisclosure", 1}, - { "z_getpaymentdisclosure", 2} + { "z_getpaymentdisclosure", 2}, + { "z_setmigration", 0}, }; class CRPCConvertTable diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index bfcc8f88d5e..f2cc09903d4 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -296,6 +296,15 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) BOOST_CHECK_NO_THROW(CallRPC("getblock 0 2")); BOOST_CHECK_THROW(CallRPC("getblock 0 -1"), runtime_error); // bad verbosity BOOST_CHECK_THROW(CallRPC("getblock 0 3"), runtime_error); // bad verbosity + + /* + * migration (sprout to sapling) + */ + BOOST_CHECK_NO_THROW(CallRPC("z_setmigration true")); + BOOST_CHECK_NO_THROW(CallRPC("z_setmigration false")); + BOOST_CHECK_THROW(CallRPC("z_setmigration"), runtime_error); + BOOST_CHECK_THROW(CallRPC("z_setmigration nonboolean"), runtime_error); + BOOST_CHECK_THROW(CallRPC("z_setmigration 1"), runtime_error); } BOOST_AUTO_TEST_CASE(rpc_wallet_getbalance) From 6c47e6fe7b67918700a970e2b1725e580f485b29 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Wed, 1 May 2019 14:15:14 -0600 Subject: [PATCH 049/395] make-release.py: Versioning changes for 2.0.5-rc1. --- README.md | 2 +- configure.ac | 4 ++-- contrib/gitian-descriptors/gitian-linux.yml | 2 +- src/clientversion.h | 4 ++-- src/deprecation.h | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d1c12009834..ebb83c2d482 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Zcash 2.0.4 +Zcash 2.0.5-rc1 =========== diff --git a/configure.ac b/configure.ac index 654d1f27f27..76001643263 100644 --- a/configure.ac +++ b/configure.ac @@ -2,8 +2,8 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 2) define(_CLIENT_VERSION_MINOR, 0) -define(_CLIENT_VERSION_REVISION, 4) -define(_CLIENT_VERSION_BUILD, 50) +define(_CLIENT_VERSION_REVISION, 5) +define(_CLIENT_VERSION_BUILD, 25) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 1d946ab8f6f..1dcdc6b8c04 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "zcash-2.0.4" +name: "zcash-2.0.5-rc1" enable_cache: true distro: "debian" suites: diff --git a/src/clientversion.h b/src/clientversion.h index 2ccd6aebe30..ace0b04d841 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -17,8 +17,8 @@ //! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 2 #define CLIENT_VERSION_MINOR 0 -#define CLIENT_VERSION_REVISION 4 -#define CLIENT_VERSION_BUILD 50 +#define CLIENT_VERSION_REVISION 5 +#define CLIENT_VERSION_BUILD 25 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/deprecation.h b/src/deprecation.h index 1ad95209a33..6c6076156ce 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -8,7 +8,7 @@ // Deprecation policy: // * Shut down 16 weeks' worth of blocks after the estimated release block height. // * A warning is shown during the 2 weeks' worth of blocks prior to shut down. -static const int APPROX_RELEASE_HEIGHT = 504600; +static const int APPROX_RELEASE_HEIGHT = 525525; static const int WEEKS_UNTIL_DEPRECATION = 16; static const int DEPRECATION_HEIGHT = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 24); From cf0a5ca28deb01a8c4b6e97aacfeb558ade2bc29 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Wed, 1 May 2019 14:16:08 -0600 Subject: [PATCH 050/395] make-release.py: Updated manpages for 2.0.5-rc1. --- doc/man/zcash-cli.1 | 10 +++++----- doc/man/zcash-tx.1 | 10 +++++----- doc/man/zcashd.1 | 18 +++++++++++++----- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/doc/man/zcash-cli.1 b/doc/man/zcash-cli.1 index 3bb439b340e..e4c0ea7c6be 100644 --- a/doc/man/zcash-cli.1 +++ b/doc/man/zcash-cli.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-CLI "1" "March 2019" "zcash-cli v2.0.4" "User Commands" +.TH ZCASH-CLI "1" "May 2019" "zcash-cli v2.0.5-rc1" "User Commands" .SH NAME -zcash-cli \- manual page for zcash-cli v2.0.4 +zcash-cli \- manual page for zcash-cli v2.0.5-rc1 .SH DESCRIPTION -Zcash RPC client version v2.0.4 +Zcash RPC client version v2.0.5\-rc1 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . @@ -75,8 +75,8 @@ Read extra arguments from standard input, one per line until EOF/Ctrl\-D In order to ensure you are adequately protecting your privacy when using Zcash, please see . -Copyright (C) 2009-2018 The Bitcoin Core Developers -Copyright (C) 2015-2018 The Zcash Developers +Copyright (C) 2009-2019 The Bitcoin Core Developers +Copyright (C) 2015-2019 The Zcash Developers This is experimental software. diff --git a/doc/man/zcash-tx.1 b/doc/man/zcash-tx.1 index 20466cb239d..3e494c23227 100644 --- a/doc/man/zcash-tx.1 +++ b/doc/man/zcash-tx.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-TX "1" "March 2019" "zcash-tx v2.0.4" "User Commands" +.TH ZCASH-TX "1" "May 2019" "zcash-tx v2.0.5-rc1" "User Commands" .SH NAME -zcash-tx \- manual page for zcash-tx v2.0.4 +zcash-tx \- manual page for zcash-tx v2.0.5-rc1 .SH DESCRIPTION -Zcash zcash\-tx utility version v2.0.4 +Zcash zcash\-tx utility version v2.0.5\-rc1 .SS "Usage:" .TP zcash\-tx [options] [commands] @@ -88,8 +88,8 @@ Set register NAME to given JSON\-STRING In order to ensure you are adequately protecting your privacy when using Zcash, please see . -Copyright (C) 2009-2018 The Bitcoin Core Developers -Copyright (C) 2015-2018 The Zcash Developers +Copyright (C) 2009-2019 The Bitcoin Core Developers +Copyright (C) 2015-2019 The Zcash Developers This is experimental software. diff --git a/doc/man/zcashd.1 b/doc/man/zcashd.1 index f993c77a7a8..5e11981fcdb 100644 --- a/doc/man/zcashd.1 +++ b/doc/man/zcashd.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASHD "1" "March 2019" "zcashd v2.0.4" "User Commands" +.TH ZCASHD "1" "May 2019" "zcashd v2.0.5-rc1" "User Commands" .SH NAME -zcashd \- manual page for zcashd v2.0.4 +zcashd \- manual page for zcashd v2.0.5-rc1 .SH DESCRIPTION -Zcash Daemon version v2.0.4 +Zcash Daemon version v2.0.5\-rc1 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . @@ -240,6 +240,14 @@ Do not load the wallet and disable wallet RPC calls .IP Set key pool size to (default: 100) .HP +\fB\-migration\fR +.IP +Enable the Sprout to Sapling migration +.HP +\fB\-migrationdestaddress=\fR +.IP +Set the Sapling migration address +.HP \fB\-paytxfee=\fR .IP Fee (in ZEC/kB) to add to transactions you send (default: 0.00) @@ -470,8 +478,8 @@ console, 600 otherwise) In order to ensure you are adequately protecting your privacy when using Zcash, please see . -Copyright (C) 2009-2018 The Bitcoin Core Developers -Copyright (C) 2015-2018 The Zcash Developers +Copyright (C) 2009-2019 The Bitcoin Core Developers +Copyright (C) 2015-2019 The Zcash Developers This is experimental software. From 12a9e172e5901c2ffa428fa52790eb1453e0b0c0 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Wed, 1 May 2019 14:16:08 -0600 Subject: [PATCH 051/395] make-release.py: Updated release notes and changelog for 2.0.5-rc1. --- contrib/debian/changelog | 6 ++ doc/release-notes/release-notes-2.0.5-rc1.md | 73 ++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 doc/release-notes/release-notes-2.0.5-rc1.md diff --git a/contrib/debian/changelog b/contrib/debian/changelog index 896237ef4b2..827d338b9d1 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,9 @@ +zcash (2.0.5~rc1) stable; urgency=medium + + * 2.0.5-rc1 release. + + -- Electric Coin Company Wed, 01 May 2019 14:16:08 -0600 + zcash (2.0.4) stable; urgency=medium * 2.0.4 release. diff --git a/doc/release-notes/release-notes-2.0.5-rc1.md b/doc/release-notes/release-notes-2.0.5-rc1.md new file mode 100644 index 00000000000..08640b1f443 --- /dev/null +++ b/doc/release-notes/release-notes-2.0.5-rc1.md @@ -0,0 +1,73 @@ +Changelog +========= + +Braydon Fuller (1): + tests: adds unit test for IsPayToPublicKeyHash method + +Dimitris Apostolou (1): + Electric Coin Company + +Eirik0 (22): + Split test in to multiple parts + Use a custom error type if creating joinsplit descriptions fails + Rename and update comment + Add rpc to enable and disable Sprout to Sapling migration + Move migration logic to ChainTip + Documentation cleanup + Additional locking and race condition prevention + Refactor wait_and_assert_operationid_status to allow returning the result + Set min depth when selecting notes to migrate + Check for full failure message in test case + Add migration options to conf file + Create method for getting HD seed in RPCs + Add rpc to get Sprout to Sapling migration status + Fix help message + Test migration using both the parameter and the default Sapling address + Fix typos and update documentation + use -valueBalance rather than vpub_new to calculate migrated amount + Do not look at vin/vout when determining migration txs and other cleanup + Calculate the number of confimations in the canonical way + Do not throw an exception if HD Seed is not found when exporting wallet + make-release.py: Versioning changes for 2.0.5-rc1. + make-release.py: Updated manpages for 2.0.5-rc1. + +Gareth Davies (1): + Adding addressindex.h to Makefile.am + +Jack Grigg (9): + Add Sprout support to TransactionBuilder + depends: Use full path to cargo binary + depends: Generalise the rust package cross-compilation functions + depends: Add rust-std hash for aarch64-unknown-linux-gnu + depends: Compile bdb with --disable-atomics on aarch64 + depends: Update .gitignore + configure: Guess -march for libsnark OPTFLAGS instead of hard-coding + Add Blossom to upgrade list + init: Fix new HD seed generation for previously-encrypted wallets + +Larry Ruane (6): + fix enable-debug build DB_COINS undefined + add -addressindex changes for bitcore insight block explorer + add -spentindex changes for bitcore insight block explorer + Update boost from v1.69.0 to v1.70.0. #3947 + add -timestampindex for bitcore insight block explorer + 3873 z_setmigration cli bool enable arg conversion + +Marius Kjærstad (1): + Update _COPYRIGHT_YEAR in configure.ac to 2019 + +Mary Moore-Simmons (1): + Creates checklist template for new PRs being opened and addresses Str4d's suggestion for using GitHub handles + +Simon Liu (4): + Add testnet and regtest experimental feature: -developersetpoolsizezero + Add qa test for experimental feature: -developersetpoolsizezero + Enable ZIP209 on mainnet and set fallback Sprout pool balance. + Enable experimental feature -developersetpoolsizezero on mainnet. + +Jack Grigg (1): + remove extra hyphen + +zebambam (1): + Minor speling changes + From 5bff7238079909643ba909cd832367c3820bf8ee Mon Sep 17 00:00:00 2001 From: Ian Munoz Date: Thu, 2 May 2019 11:47:25 -0400 Subject: [PATCH 052/395] add curl to package list for gitian lxc container --- contrib/gitian-descriptors/gitian-linux.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index d7f702b816e..3d150d5678f 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -7,6 +7,7 @@ suites: architectures: - "amd64" packages: +- "curl" - "autoconf" - "automake" - "bsdmainutils" From 68c17ffec83fb89ecc49bb874d2110a3156fe297 Mon Sep 17 00:00:00 2001 From: Simon Date: Thu, 2 May 2019 14:37:50 -0700 Subject: [PATCH 053/395] Update chain work and checkpoint using block 525000. --- src/chainparams.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index e0769fcae5f..5f8dba4d2b2 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -111,7 +111,7 @@ class CMainParams : public CChainParams { Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; // The best chain should have at least this much work. - consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000000c12875ded911cf"); + consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000000eeaf43c4e72d49"); /** * The message start string should be awesome! ⓩ❤ @@ -185,11 +185,12 @@ class CMainParams : public CChainParams { (270000, uint256S("0x00000000025c1cfa0258e33ab050aaa9338a3d4aaa3eb41defefc887779a9729")) (304600, uint256S("0x00000000028324e022a45014c4a4dc51e95d41e6bceb6ad554c5b65d5cea3ea5")) (410100, uint256S("0x0000000002c565958f783a24a4ac17cde898ff525e75ed9baf66861b0b9fcada")) - (497000, uint256S("0x0000000000abd333f0acca6ffdf78a167699686d6a7d25c33fca5f295061ffff")), - 1552501838, // * UNIX timestamp of last checkpoint block - 4463933, // * total number of transactions between genesis and last checkpoint + (497000, uint256S("0x0000000000abd333f0acca6ffdf78a167699686d6a7d25c33fca5f295061ffff")) + (525000, uint256S("0x0000000001a36c500378be8862d9bf1bea8f1616da6e155971b608139cc7e39b")), + 1556722044, // * UNIX timestamp of last checkpoint block + 4653556, // * total number of transactions between genesis and last checkpoint // (the tx=... number in the SetBestChain debug.log lines) - 5173 // * estimated number of transactions per day after checkpoint + 5106 // * estimated number of transactions per day after checkpoint // total number of tx / (checkpoint block height / (24 * 24)) }; From 95fe7ae6764e55ea9c2bba0eb94e51d8fa2f3e64 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Thu, 2 May 2019 19:34:52 -0600 Subject: [PATCH 054/395] Notable changes for v2.0.5 --- doc/release-notes.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index a29094b5174..944e8e79473 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,3 +4,47 @@ release-notes at release time) Notable changes =============== +Sprout to Sapling Migration Tool +-------------------------------- +This release includes the addition of a tool that will enable users to migrate +shielded funds from the Sprout pool to the Sapling pool while minimizing +information leakage. + +The migration can be enabled using the RPC `z_setmigration` or by including +`-migration` in the `zcash.conf` file. Unless otherwise specified funds will be +migrated to the wallet's default Sapling address; it is also possible to set the +receiving Sapling address using the `-migrationdestaddress` option in `zcash.conf`. + +See [ZIP308](https://github.com/zcash/zips/blob/master/zip-0308.rst) for full details. + + +New consensus rule: Reject blocks that violate turnstile +-------------------------------------------------------- +In the 2.0.4 release the consensus rules were changed on testnet to enforce a +consensus rule which marks blocks as invalid if they would lead to a turnstile +violation in the Sprout or Shielded value pools. +**This release enforces the consensus rule change on mainnet** + +The motivations and deployment details can be found in the accompanying +[ZIP draft](https://github.com/zcash/zips/pull/210) and +[PR 3968](https://github.com/zcash/zcash/pull/3968). + +Developers can use a new experimental feature `-developersetpoolsizezero` to test +Sprout and Sapling turnstile violations. See [PR 3964](https://github.com/zcash/zcash/pull/3964) for more details. + + +64-bit ARMv8 support +-------------------- +Added ARMv8 (AArch64) support. This enables users to build zcash on even more +devices. + +For information on how to build see the [User Guide](https://zcash.readthedocs.io/en/latest/rtd_pages/user_guide.html#build) + +Users on the Zcash forum have reported successes with both the Pine64 Rock64Pro +and Odroid C2 which contain 4GB and 2GB of RAM respectively. + +Just released, the Odroid N2 looks a great solution with 4GB of RAM. The newly +released Jetson Nano Developer Kit from Nvidia (also 4GB of RAM) is also worth +a look. The NanoPC-T3 Plus is another option but for the simplest/best +experience choose a board with 4GB of RAM. Just make sure before purchase that +the CPU supports the 64-bit ARMv8 architecture. From e152af3c7c8477f218c57b6b698531243ad264a9 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Fri, 3 May 2019 09:30:26 -0600 Subject: [PATCH 055/395] Add missing word to release notes --- doc/release-notes.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index 944e8e79473..d7935ff1b2c 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -43,8 +43,8 @@ For information on how to build see the [User Guide](https://zcash.readthedocs.i Users on the Zcash forum have reported successes with both the Pine64 Rock64Pro and Odroid C2 which contain 4GB and 2GB of RAM respectively. -Just released, the Odroid N2 looks a great solution with 4GB of RAM. The newly -released Jetson Nano Developer Kit from Nvidia (also 4GB of RAM) is also worth -a look. The NanoPC-T3 Plus is another option but for the simplest/best +Just released, the Odroid N2 looks like a great solution with 4GB of RAM. The +newly released Jetson Nano Developer Kit from Nvidia (also 4GB of RAM) is also +worth a look. The NanoPC-T3 Plus is another option but for the simplest/best experience choose a board with 4GB of RAM. Just make sure before purchase that the CPU supports the 64-bit ARMv8 architecture. From c1daa11d7b12d45258502fa4fe501a0e3d7ada26 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Fri, 3 May 2019 16:30:13 -0600 Subject: [PATCH 056/395] make-release.py: Versioning changes for 2.0.5. --- README.md | 2 +- configure.ac | 2 +- contrib/gitian-descriptors/gitian-linux.yml | 2 +- src/clientversion.h | 2 +- src/deprecation.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ebb83c2d482..4b55fb9decd 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Zcash 2.0.5-rc1 +Zcash 2.0.5 =========== diff --git a/configure.ac b/configure.ac index 76001643263..797b71c73e6 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 2) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_REVISION, 5) -define(_CLIENT_VERSION_BUILD, 25) +define(_CLIENT_VERSION_BUILD, 50) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 80c2be98c0e..df50d864163 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "zcash-2.0.5-rc1" +name: "zcash-2.0.5" enable_cache: true distro: "debian" suites: diff --git a/src/clientversion.h b/src/clientversion.h index ace0b04d841..0e21ca63e5e 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -18,7 +18,7 @@ #define CLIENT_VERSION_MAJOR 2 #define CLIENT_VERSION_MINOR 0 #define CLIENT_VERSION_REVISION 5 -#define CLIENT_VERSION_BUILD 25 +#define CLIENT_VERSION_BUILD 50 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/deprecation.h b/src/deprecation.h index 6c6076156ce..d9abbebf1bb 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -8,7 +8,7 @@ // Deprecation policy: // * Shut down 16 weeks' worth of blocks after the estimated release block height. // * A warning is shown during the 2 weeks' worth of blocks prior to shut down. -static const int APPROX_RELEASE_HEIGHT = 525525; +static const int APPROX_RELEASE_HEIGHT = 528000; static const int WEEKS_UNTIL_DEPRECATION = 16; static const int DEPRECATION_HEIGHT = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 24); From 380babed987cf8749b0c2d3c9474ee87a8993859 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Fri, 3 May 2019 16:35:30 -0600 Subject: [PATCH 057/395] make-release.py: Updated manpages for 2.0.5. --- doc/man/zcash-cli.1 | 6 +++--- doc/man/zcash-tx.1 | 6 +++--- doc/man/zcashd.1 | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/man/zcash-cli.1 b/doc/man/zcash-cli.1 index e4c0ea7c6be..a54c9c7d265 100644 --- a/doc/man/zcash-cli.1 +++ b/doc/man/zcash-cli.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-CLI "1" "May 2019" "zcash-cli v2.0.5-rc1" "User Commands" +.TH ZCASH-CLI "1" "May 2019" "zcash-cli v2.0.5" "User Commands" .SH NAME -zcash-cli \- manual page for zcash-cli v2.0.5-rc1 +zcash-cli \- manual page for zcash-cli v2.0.5 .SH DESCRIPTION -Zcash RPC client version v2.0.5\-rc1 +Zcash RPC client version v2.0.5 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . diff --git a/doc/man/zcash-tx.1 b/doc/man/zcash-tx.1 index 3e494c23227..df99ae127f2 100644 --- a/doc/man/zcash-tx.1 +++ b/doc/man/zcash-tx.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-TX "1" "May 2019" "zcash-tx v2.0.5-rc1" "User Commands" +.TH ZCASH-TX "1" "May 2019" "zcash-tx v2.0.5" "User Commands" .SH NAME -zcash-tx \- manual page for zcash-tx v2.0.5-rc1 +zcash-tx \- manual page for zcash-tx v2.0.5 .SH DESCRIPTION -Zcash zcash\-tx utility version v2.0.5\-rc1 +Zcash zcash\-tx utility version v2.0.5 .SS "Usage:" .TP zcash\-tx [options] [commands] diff --git a/doc/man/zcashd.1 b/doc/man/zcashd.1 index 5e11981fcdb..d03182682e6 100644 --- a/doc/man/zcashd.1 +++ b/doc/man/zcashd.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASHD "1" "May 2019" "zcashd v2.0.5-rc1" "User Commands" +.TH ZCASHD "1" "May 2019" "zcashd v2.0.5" "User Commands" .SH NAME -zcashd \- manual page for zcashd v2.0.5-rc1 +zcashd \- manual page for zcashd v2.0.5 .SH DESCRIPTION -Zcash Daemon version v2.0.5\-rc1 +Zcash Daemon version v2.0.5 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . From 5d69949aaac6d86e11b6925e9321d00f8eb4eed1 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Fri, 3 May 2019 16:35:30 -0600 Subject: [PATCH 058/395] make-release.py: Updated release notes and changelog for 2.0.5. --- contrib/debian/changelog | 6 ++ doc/authors.md | 18 ++-- doc/release-notes.md | 44 -------- doc/release-notes/release-notes-2.0.5.md | 130 +++++++++++++++++++++++ 4 files changed, 147 insertions(+), 51 deletions(-) create mode 100644 doc/release-notes/release-notes-2.0.5.md diff --git a/contrib/debian/changelog b/contrib/debian/changelog index 827d338b9d1..b9b8c076751 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,9 @@ +zcash (2.0.5) stable; urgency=medium + + * 2.0.5 release. + + -- Electric Coin Company Fri, 03 May 2019 16:35:30 -0600 + zcash (2.0.5~rc1) stable; urgency=medium * 2.0.5-rc1 release. diff --git a/doc/authors.md b/doc/authors.md index e82945efc15..95018c4b572 100644 --- a/doc/authors.md +++ b/doc/authors.md @@ -1,8 +1,8 @@ Zcash Contributors ================== -Jack Grigg (862) -Simon Liu (443) +Jack Grigg (863) +Simon Liu (448) Sean Bowe (278) Daira Hopwood (110) Eirik Ogilvie-Wigley (102) @@ -14,9 +14,10 @@ Nathan Wilcox (56) Pieter Wuille (54) Kevin Gallagher (38) Cory Fields (35) +Eirik0 (27) mdr0id (22) +Larry Ruane (22) Jonathan "Duke" Leto (17) -Larry Ruane (16) syd (15) Matt Corallo (13) Paige Peterson (11) @@ -27,12 +28,12 @@ kozyilmaz (8) fanquake (8) Jeff Garzik (7) Gregory Maxwell (7) +Marius Kjærstad (6) Luke Dashjr (6) David Mercer (6) Daniel Cousens (6) Suhas Daftuar (5) Pavel Janík (5) -Marius Kjærstad (5) Karl-Johan Alm (5) Johnathan Corgan (5) Charlie O'Keefe (5) @@ -44,16 +45,17 @@ Patrick Strateman (4) João Barbosa (4) Jorge Timón (4) George Tankersley (4) +Gareth Davies (4) +zebambam (3) lpescher (3) ca333 (3) Per Grön (3) Patick Strateman (3) Jason Davies (3) James O'Beirne (3) -Gareth Davies (3) +Dimitris Apostolou (3) Daniel Kraft (3) Alfie John (3) -zebambam (2) rofl0r (2) paveljanik (2) mruddy (2) @@ -71,7 +73,6 @@ Joe Turgeon (2) Jack Gavigan (2) ITH4Coinomia (2) Gavin Andresen (2) -Dimitris Apostolou (2) Brad Miller (2) Bjorn Hjortsberg (2) Amgad Abdelhafez (2) @@ -109,6 +110,7 @@ Nathaniel Mahieu (1) Murilo Santana (1) Maxwell Gubler (1) Matt Quinn (1) +Mary Moore-Simmons (1) Mark Friedenbach (1) Louis Nyffenegger (1) Leo Arias (1) @@ -118,6 +120,7 @@ Kevin Pan (1) Jonas Nick (1) Jeremy Rubin (1) Jeffrey Walton (1) +Ian Munoz (1) Ian Kelling (1) Gaurav Rana (1) Forrest Voight (1) @@ -131,6 +134,7 @@ Casey Rodarmor (1) Cameron Boehmer (1) Bryan Stitt (1) Bruno Arueira (1) +Braydon Fuller (1) Boris Hajduk (1) Bob McElrath (1) Bitcoin Error Log (1) diff --git a/doc/release-notes.md b/doc/release-notes.md index d7935ff1b2c..a29094b5174 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,47 +4,3 @@ release-notes at release time) Notable changes =============== -Sprout to Sapling Migration Tool --------------------------------- -This release includes the addition of a tool that will enable users to migrate -shielded funds from the Sprout pool to the Sapling pool while minimizing -information leakage. - -The migration can be enabled using the RPC `z_setmigration` or by including -`-migration` in the `zcash.conf` file. Unless otherwise specified funds will be -migrated to the wallet's default Sapling address; it is also possible to set the -receiving Sapling address using the `-migrationdestaddress` option in `zcash.conf`. - -See [ZIP308](https://github.com/zcash/zips/blob/master/zip-0308.rst) for full details. - - -New consensus rule: Reject blocks that violate turnstile --------------------------------------------------------- -In the 2.0.4 release the consensus rules were changed on testnet to enforce a -consensus rule which marks blocks as invalid if they would lead to a turnstile -violation in the Sprout or Shielded value pools. -**This release enforces the consensus rule change on mainnet** - -The motivations and deployment details can be found in the accompanying -[ZIP draft](https://github.com/zcash/zips/pull/210) and -[PR 3968](https://github.com/zcash/zcash/pull/3968). - -Developers can use a new experimental feature `-developersetpoolsizezero` to test -Sprout and Sapling turnstile violations. See [PR 3964](https://github.com/zcash/zcash/pull/3964) for more details. - - -64-bit ARMv8 support --------------------- -Added ARMv8 (AArch64) support. This enables users to build zcash on even more -devices. - -For information on how to build see the [User Guide](https://zcash.readthedocs.io/en/latest/rtd_pages/user_guide.html#build) - -Users on the Zcash forum have reported successes with both the Pine64 Rock64Pro -and Odroid C2 which contain 4GB and 2GB of RAM respectively. - -Just released, the Odroid N2 looks like a great solution with 4GB of RAM. The -newly released Jetson Nano Developer Kit from Nvidia (also 4GB of RAM) is also -worth a look. The NanoPC-T3 Plus is another option but for the simplest/best -experience choose a board with 4GB of RAM. Just make sure before purchase that -the CPU supports the 64-bit ARMv8 architecture. diff --git a/doc/release-notes/release-notes-2.0.5.md b/doc/release-notes/release-notes-2.0.5.md new file mode 100644 index 00000000000..520060f1784 --- /dev/null +++ b/doc/release-notes/release-notes-2.0.5.md @@ -0,0 +1,130 @@ +Notable changes +=============== + +Sprout to Sapling Migration Tool +-------------------------------- +This release includes the addition of a tool that will enable users to migrate +shielded funds from the Sprout pool to the Sapling pool while minimizing +information leakage. + +The migration can be enabled using the RPC `z_setmigration` or by including +`-migration` in the `zcash.conf` file. Unless otherwise specified funds will be +migrated to the wallet's default Sapling address; it is also possible to set the +receiving Sapling address using the `-migrationdestaddress` option in `zcash.conf`. + +See [ZIP308](https://github.com/zcash/zips/blob/master/zip-0308.rst) for full details. + + +New consensus rule: Reject blocks that violate turnstile +-------------------------------------------------------- +In the 2.0.4 release the consensus rules were changed on testnet to enforce a +consensus rule which marks blocks as invalid if they would lead to a turnstile +violation in the Sprout or Shielded value pools. +**This release enforces the consensus rule change on mainnet** + +The motivations and deployment details can be found in the accompanying +[ZIP draft](https://github.com/zcash/zips/pull/210) and +[PR 3968](https://github.com/zcash/zcash/pull/3968). + +Developers can use a new experimental feature `-developersetpoolsizezero` to test +Sprout and Sapling turnstile violations. See [PR 3964](https://github.com/zcash/zcash/pull/3964) for more details. + + +64-bit ARMv8 support +-------------------- +Added ARMv8 (AArch64) support. This enables users to build zcash on even more +devices. + +For information on how to build see the [User Guide](https://zcash.readthedocs.io/en/latest/rtd_pages/user_guide.html#build) + +Users on the Zcash forum have reported successes with both the Pine64 Rock64Pro +and Odroid C2 which contain 4GB and 2GB of RAM respectively. + +Just released, the Odroid N2 looks like a great solution with 4GB of RAM. The +newly released Jetson Nano Developer Kit from Nvidia (also 4GB of RAM) is also +worth a look. The NanoPC-T3 Plus is another option but for the simplest/best +experience choose a board with 4GB of RAM. Just make sure before purchase that +the CPU supports the 64-bit ARMv8 architecture. + +Changelog +========= + +Braydon Fuller (1): + tests: adds unit test for IsPayToPublicKeyHash method + +Dimitris Apostolou (1): + Electric Coin Company + +Eirik0 (27): + Split test in to multiple parts + Use a custom error type if creating joinsplit descriptions fails + Rename and update comment + Add rpc to enable and disable Sprout to Sapling migration + Move migration logic to ChainTip + Documentation cleanup + Additional locking and race condition prevention + Refactor wait_and_assert_operationid_status to allow returning the result + Set min depth when selecting notes to migrate + Check for full failure message in test case + Add migration options to conf file + Create method for getting HD seed in RPCs + Add rpc to get Sprout to Sapling migration status + Fix help message + Test migration using both the parameter and the default Sapling address + Fix typos and update documentation + use -valueBalance rather than vpub_new to calculate migrated amount + Do not look at vin/vout when determining migration txs and other cleanup + Calculate the number of confimations in the canonical way + Do not throw an exception if HD Seed is not found when exporting wallet + make-release.py: Versioning changes for 2.0.5-rc1. + make-release.py: Updated manpages for 2.0.5-rc1. + make-release.py: Updated release notes and changelog for 2.0.5-rc1. + Notable changes for v2.0.5 + Add missing word to release notes + make-release.py: Versioning changes for 2.0.5. + make-release.py: Updated manpages for 2.0.5. + +Gareth Davies (1): + Adding addressindex.h to Makefile.am + +Ian Munoz (1): + add curl to package list for gitian lxc container + +Jack Grigg (9): + Add Sprout support to TransactionBuilder + depends: Use full path to cargo binary + depends: Generalise the rust package cross-compilation functions + depends: Add rust-std hash for aarch64-unknown-linux-gnu + depends: Compile bdb with --disable-atomics on aarch64 + depends: Update .gitignore + configure: Guess -march for libsnark OPTFLAGS instead of hard-coding + Add Blossom to upgrade list + init: Fix new HD seed generation for previously-encrypted wallets + +Larry Ruane (6): + fix enable-debug build DB_COINS undefined + add -addressindex changes for bitcore insight block explorer + add -spentindex changes for bitcore insight block explorer + Update boost from v1.69.0 to v1.70.0. #3947 + add -timestampindex for bitcore insight block explorer + 3873 z_setmigration cli bool enable arg conversion + +Marius Kjærstad (1): + Update _COPYRIGHT_YEAR in configure.ac to 2019 + +Mary Moore-Simmons (1): + Creates checklist template for new PRs being opened and addresses Str4d's suggestion for using GitHub handles + +Simon Liu (5): + Add testnet and regtest experimental feature: -developersetpoolsizezero + Add qa test for experimental feature: -developersetpoolsizezero + Enable ZIP209 on mainnet and set fallback Sprout pool balance. + Enable experimental feature -developersetpoolsizezero on mainnet. + Update chain work and checkpoint using block 525000. + +Jack Grigg (1): + remove extra hyphen + +zebambam (1): + Minor speling changes + From 7cf4749d0d7f84b8906609d1d6c19d2fc8c7ce9b Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Sun, 5 May 2019 12:59:43 -0600 Subject: [PATCH 059/395] Correctly account for migration transactions in the mempool Co-authored-by: LarryRuane --- qa/rpc-tests/sprout_sapling_migration.py | 3 +++ src/wallet/rpcwallet.cpp | 9 +++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/sprout_sapling_migration.py b/qa/rpc-tests/sprout_sapling_migration.py index 5f47d779616..3e5a094cf6f 100755 --- a/qa/rpc-tests/sprout_sapling_migration.py +++ b/qa/rpc-tests/sprout_sapling_migration.py @@ -106,6 +106,9 @@ def run_migration_test(self, node, sproutAddr, saplingAddr, target_height): assert_equal(node.z_getbalance(sproutAddr), Decimal('0')) assert_equal(node.z_getbalance(saplingAddr), Decimal('0')) assert_true(node.z_getbalance(saplingAddr, 0) > Decimal('0'), "Unconfirmed sapling balance at 499 % 500") + # Check that unmigrated amount + unfinalized = starting balance - fee + status = node.z_getmigrationstatus() + assert_equal(Decimal('9.9999'), Decimal(status['unmigrated_amount']) + Decimal(status['unfinalized_migrated_amount'])) node.generate(1) self.sync_all() diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index d0e67a1b2e7..fa93af02ddd 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3967,7 +3967,8 @@ UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) { { std::vector sproutEntries; std::vector saplingEntries; - pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, "", 1); + std::set zaddrs; + pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, zaddrs, 0, INT_MAX, true, true, false); CAmount unmigratedAmount = 0; for (const auto& sproutEntry : sproutEntries) { unmigratedAmount += sproutEntry.plaintext.value(); @@ -4000,7 +4001,6 @@ UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) { continue; } migrationTxids.push_back(txPair.first.ToString()); - CBlockIndex* blockIndex = mapBlockIndex[tx.hashBlock]; // A transaction is "finalized" iff it has at least 10 confirmations. // TODO: subject to change, if the recommended number of confirmations changes. if (tx.GetDepthInMainChain() >= 10) { @@ -4009,6 +4009,11 @@ UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) { } else { unfinalizedMigratedAmount -= tx.valueBalance; } + // If the transaction is in the mempool it will not be associated with a block yet + if (tx.hashBlock.IsNull() || mapBlockIndex[tx.hashBlock] == nullptr) { + continue; + } + CBlockIndex* blockIndex = mapBlockIndex[tx.hashBlock]; // The value of "time_started" is the earliest Unix timestamp of any known // migration transaction involving this wallet; if there is no such transaction, // then the field is absent. From d48c3efca7960d08f3f54755f6205b4e55ec872f Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Mon, 6 May 2019 09:57:40 -0600 Subject: [PATCH 060/395] Store the migration operation id rather than the operation iteslf --- src/wallet/asyncrpcoperation_saplingmigration.cpp | 4 ++++ src/wallet/asyncrpcoperation_saplingmigration.h | 2 ++ src/wallet/wallet.cpp | 15 +++++++++------ src/wallet/wallet.h | 2 +- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/wallet/asyncrpcoperation_saplingmigration.cpp b/src/wallet/asyncrpcoperation_saplingmigration.cpp index ab44bf76077..cb3f2c9d2d4 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.cpp +++ b/src/wallet/asyncrpcoperation_saplingmigration.cpp @@ -191,6 +191,10 @@ libzcash::SaplingPaymentAddress AsyncRPCOperation_saplingmigration::getMigration return toAddress; } +void AsyncRPCOperation_saplingmigration::cancel() { + set_state(OperationStatus::CANCELLED); +} + UniValue AsyncRPCOperation_saplingmigration::getStatus() const { UniValue v = AsyncRPCOperation::getStatus(); UniValue obj = v.get_obj(); diff --git a/src/wallet/asyncrpcoperation_saplingmigration.h b/src/wallet/asyncrpcoperation_saplingmigration.h index e077c8eca32..2f790fc14d5 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.h +++ b/src/wallet/asyncrpcoperation_saplingmigration.h @@ -20,6 +20,8 @@ class AsyncRPCOperation_saplingmigration : public AsyncRPCOperation virtual void main(); + virtual void cancel(); + virtual UniValue getStatus() const; private: diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index cf220fcf2a6..07c0a105da2 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -603,17 +603,20 @@ void CWallet::RunSaplingMigration(int blockHeight) { // height N, implementations SHOULD start generating the transactions at around // height N-5 if (blockHeight % 500 == 495) { - if (saplingMigrationOperation != nullptr) { - saplingMigrationOperation->cancel(); + std::shared_ptr q = getAsyncRPCQueue(); + std::shared_ptr lastOperation = q->popOperationForId(saplingMigrationOperationId); + if (lastOperation != nullptr) { + lastOperation->cancel(); } pendingSaplingMigrationTxs.clear(); - std::shared_ptr q = getAsyncRPCQueue(); std::shared_ptr operation(new AsyncRPCOperation_saplingmigration(blockHeight + 5)); - saplingMigrationOperation = operation; + saplingMigrationOperationId = operation->getId(); q->addOperation(operation); } else if (blockHeight % 500 == 499) { - if (saplingMigrationOperation != nullptr) { - saplingMigrationOperation->cancel(); + std::shared_ptr q = getAsyncRPCQueue(); + std::shared_ptr lastOperation = q->popOperationForId(saplingMigrationOperationId); + if (lastOperation != nullptr) { + lastOperation->cancel(); } for (const CTransaction& transaction : pendingSaplingMigrationTxs) { // The following is taken from z_sendmany/z_mergetoaddress diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 6e4c239d9de..fa137011199 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -757,7 +757,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface TxNullifiers mapTxSaplingNullifiers; std::vector pendingSaplingMigrationTxs; - std::shared_ptr saplingMigrationOperation = nullptr; + AsyncRPCOperationId saplingMigrationOperationId; void AddToTransparentSpends(const COutPoint& outpoint, const uint256& wtxid); void AddToSproutSpends(const uint256& nullifier, const uint256& wtxid); From 94e419f95d345f66b4c7a29fd84f3b31e10b84d0 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Mon, 6 May 2019 11:46:16 -0600 Subject: [PATCH 061/395] Rename variable and add comment --- src/wallet/rpcwallet.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index fa93af02ddd..ca291255892 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3967,8 +3967,10 @@ UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) { { std::vector sproutEntries; std::vector saplingEntries; - std::set zaddrs; - pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, zaddrs, 0, INT_MAX, true, true, false); + std::set noFilter; + // Here we are looking for any and all Sprout notes for which we have the spending key, including those + // which are locked and/or only exist in the mempool, as they should be included in the unmigrated amount. + pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, noFilter, 0, INT_MAX, true, true, false); CAmount unmigratedAmount = 0; for (const auto& sproutEntry : sproutEntries) { unmigratedAmount += sproutEntry.plaintext.value(); From aa234062635368ba787adb0d8aa94dae43222f28 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Mon, 6 May 2019 15:51:21 -0600 Subject: [PATCH 062/395] Notable changes for v2.0.5-1 --- doc/release-notes.md | 50 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index a29094b5174..0d0f27e5b3b 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,3 +4,53 @@ release-notes at release time) Notable changes =============== +Sprout to Sapling Migration Tool +-------------------------------- +This release includes the addition of a tool that will enable users to migrate +shielded funds from the Sprout pool to the Sapling pool while minimizing +information leakage. + +The migration can be enabled using the RPC `z_setmigration` or by including +`-migration` in the `zcash.conf` file. Unless otherwise specified funds will be +migrated to the wallet's default Sapling address; it is also possible to set the +receiving Sapling address using the `-migrationdestaddress` option in `zcash.conf`. + +See [ZIP308](https://github.com/zcash/zips/blob/master/zip-0308.rst) for full details. + +Sprout to Sapling Migration Tool Fixes +-------------------------------------- +The 2.0.5-1 release includes fixes to the Sprout to Sapling Migration Tool +found in testing. We resolved an issue which would cause the zcash daemon to +crash if calling the RPC `z_getmigrationstatus` while a wallet's migration +transactions are in the mempool. + +New consensus rule: Reject blocks that violate turnstile +-------------------------------------------------------- +In the 2.0.4 release the consensus rules were changed on testnet to enforce a +consensus rule which marks blocks as invalid if they would lead to a turnstile +violation in the Sprout or Shielded value pools. +**This release enforces the consensus rule change on mainnet** + +The motivations and deployment details can be found in the accompanying +[ZIP draft](https://github.com/zcash/zips/pull/210) and +[PR 3968](https://github.com/zcash/zcash/pull/3968). + +Developers can use a new experimental feature `-developersetpoolsizezero` to test +Sprout and Sapling turnstile violations. See [PR 3964](https://github.com/zcash/zcash/pull/3964) for more details. + + +64-bit ARMv8 support +-------------------- +Added ARMv8 (AArch64) support. This enables users to build zcash on even more +devices. + +For information on how to build see the [User Guide](https://zcash.readthedocs.io/en/latest/rtd_pages/user_guide.html#build) + +Users on the Zcash forum have reported successes with both the Pine64 Rock64Pro +and Odroid C2 which contain 4GB and 2GB of RAM respectively. + +Just released, the Odroid N2 looks like a great solution with 4GB of RAM. The +newly released Jetson Nano Developer Kit from Nvidia (also 4GB of RAM) is also +worth a look. The NanoPC-T3 Plus is another option but for the simplest/best +experience choose a board with 4GB of RAM. Just make sure before purchase that +the CPU supports the 64-bit ARMv8 architecture. From f0f7b3f012d208609f183a6f266d832d5526ce7c Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Tue, 7 May 2019 08:55:26 -0600 Subject: [PATCH 063/395] Fix summing available funds --- src/wallet/asyncrpcoperation_saplingmigration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/asyncrpcoperation_saplingmigration.cpp b/src/wallet/asyncrpcoperation_saplingmigration.cpp index cb3f2c9d2d4..cb97bf04091 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.cpp +++ b/src/wallet/asyncrpcoperation_saplingmigration.cpp @@ -77,7 +77,7 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { } CAmount availableFunds = 0; for (const CSproutNotePlaintextEntry& sproutEntry : sproutEntries) { - availableFunds = sproutEntry.plaintext.value(); + availableFunds += sproutEntry.plaintext.value(); } // If the remaining amount to be migrated is less than 0.01 ZEC, end the migration. if (availableFunds < CENT) { From 5fd7af5f857cb3c7d439ec098f117c33ea2eca8a Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Tue, 7 May 2019 08:58:23 -0600 Subject: [PATCH 064/395] Add the amount migrated to the operation's result --- src/wallet/asyncrpcoperation_saplingmigration.cpp | 10 +++++++--- src/wallet/asyncrpcoperation_saplingmigration.h | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/wallet/asyncrpcoperation_saplingmigration.cpp b/src/wallet/asyncrpcoperation_saplingmigration.cpp index cb97bf04091..7a45e6e3132 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.cpp +++ b/src/wallet/asyncrpcoperation_saplingmigration.cpp @@ -9,6 +9,7 @@ #include "tinyformat.h" #include "transaction_builder.h" #include "util.h" +#include "utilmoneystr.h" #include "wallet.h" const CAmount FEE = 10000; @@ -81,7 +82,7 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { } // If the remaining amount to be migrated is less than 0.01 ZEC, end the migration. if (availableFunds < CENT) { - setMigrationResult(0); + setMigrationResult(0, 0); return true; } @@ -92,6 +93,7 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { // Up to the limit of 5, as many transactions are sent as are needed to migrate the remaining funds int numTxCreated = 0; + CAmount amountMigrated = 0; int noteIndex = 0; do { CAmount amountToSend = chooseAmount(availableFunds); @@ -127,15 +129,17 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { } pwalletMain->AddPendingSaplingMigrationTx(tx); ++numTxCreated; + amountMigrated += amountToSend; } while (numTxCreated < 5 && availableFunds > CENT); - setMigrationResult(numTxCreated); + setMigrationResult(numTxCreated, amountMigrated); return true; } -void AsyncRPCOperation_saplingmigration::setMigrationResult(int numTxCreated) { +void AsyncRPCOperation_saplingmigration::setMigrationResult(int numTxCreated, CAmount amountMigrated) { UniValue res(UniValue::VOBJ); res.push_back(Pair("num_tx_created", numTxCreated)); + res.push_back(Pair("amount_migrated", FormatMoney(amountMigrated))); set_result(res); } diff --git a/src/wallet/asyncrpcoperation_saplingmigration.h b/src/wallet/asyncrpcoperation_saplingmigration.h index 2f790fc14d5..64319968f92 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.h +++ b/src/wallet/asyncrpcoperation_saplingmigration.h @@ -29,7 +29,7 @@ class AsyncRPCOperation_saplingmigration : public AsyncRPCOperation bool main_impl(); - void setMigrationResult(int numTxCreated); + void setMigrationResult(int numTxCreated, CAmount amountMigrated); CAmount chooseAmount(const CAmount& availableFunds); }; From ea8823ce519595ba21bdcd94339126af27da4f61 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Tue, 7 May 2019 12:02:54 -0600 Subject: [PATCH 065/395] coinsView is required when using TransactionBuilder if there may be Sprout change --- src/transaction_builder.cpp | 4 ++++ src/wallet/asyncrpcoperation_saplingmigration.cpp | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/transaction_builder.cpp b/src/transaction_builder.cpp index fbe1043a5f6..64f8238b80d 100644 --- a/src/transaction_builder.cpp +++ b/src/transaction_builder.cpp @@ -524,6 +524,10 @@ void TransactionBuilder::CreateJSDescriptions() // Update tree state with previous joinsplit SproutMerkleTree tree; { + // assert that coinsView is not null + assert(coinsView); + // We do not check cs_coinView because we do not set this in testing + // assert(cs_coinsView); LOCK(cs_coinsView); auto it = intermediates.find(prevJoinSplit.anchor); if (it != intermediates.end()) { diff --git a/src/wallet/asyncrpcoperation_saplingmigration.cpp b/src/wallet/asyncrpcoperation_saplingmigration.cpp index 7a45e6e3132..ac82717be70 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.cpp +++ b/src/wallet/asyncrpcoperation_saplingmigration.cpp @@ -95,9 +95,10 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { int numTxCreated = 0; CAmount amountMigrated = 0; int noteIndex = 0; + CCoinsViewCache coinsView(pcoinsTip); do { CAmount amountToSend = chooseAmount(availableFunds); - auto builder = TransactionBuilder(consensusParams, targetHeight_, pwalletMain, pzcashParams); + auto builder = TransactionBuilder(consensusParams, targetHeight_, pwalletMain, pzcashParams, &coinsView, &cs_main); std::vector fromNotes; CAmount fromNoteAmount = 0; while (fromNoteAmount < amountToSend) { From f809ff997f00a1dcd5bb15cfa7f3e1605c4437d9 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Wed, 8 May 2019 06:50:57 -0600 Subject: [PATCH 066/395] make-release.py: Versioning changes for 2.0.5-1. --- README.md | 2 +- configure.ac | 2 +- contrib/gitian-descriptors/gitian-linux.yml | 2 +- src/clientversion.h | 2 +- src/deprecation.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4b55fb9decd..5d6c06c6104 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Zcash 2.0.5 +Zcash 2.0.5-1 =========== diff --git a/configure.ac b/configure.ac index 797b71c73e6..0dc14ccbe9a 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 2) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_REVISION, 5) -define(_CLIENT_VERSION_BUILD, 50) +define(_CLIENT_VERSION_BUILD, 51) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index df50d864163..f0e40fd4082 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "zcash-2.0.5" +name: "zcash-2.0.5-1" enable_cache: true distro: "debian" suites: diff --git a/src/clientversion.h b/src/clientversion.h index 0e21ca63e5e..5e6b49a9d5d 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -18,7 +18,7 @@ #define CLIENT_VERSION_MAJOR 2 #define CLIENT_VERSION_MINOR 0 #define CLIENT_VERSION_REVISION 5 -#define CLIENT_VERSION_BUILD 50 +#define CLIENT_VERSION_BUILD 51 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/deprecation.h b/src/deprecation.h index d9abbebf1bb..a0dd736bcef 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -8,7 +8,7 @@ // Deprecation policy: // * Shut down 16 weeks' worth of blocks after the estimated release block height. // * A warning is shown during the 2 weeks' worth of blocks prior to shut down. -static const int APPROX_RELEASE_HEIGHT = 528000; +static const int APPROX_RELEASE_HEIGHT = 529250; static const int WEEKS_UNTIL_DEPRECATION = 16; static const int DEPRECATION_HEIGHT = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 24); From eceff9bed6ec74c3f87ea3aa3ba4f1a9755f2a3e Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Wed, 8 May 2019 06:57:28 -0600 Subject: [PATCH 067/395] make-release.py: Updated manpages for 2.0.5-1. --- doc/man/zcash-cli.1 | 6 +++--- doc/man/zcash-tx.1 | 6 +++--- doc/man/zcashd.1 | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/man/zcash-cli.1 b/doc/man/zcash-cli.1 index a54c9c7d265..a13df414a5a 100644 --- a/doc/man/zcash-cli.1 +++ b/doc/man/zcash-cli.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-CLI "1" "May 2019" "zcash-cli v2.0.5" "User Commands" +.TH ZCASH-CLI "1" "May 2019" "zcash-cli v2.0.5-1" "User Commands" .SH NAME -zcash-cli \- manual page for zcash-cli v2.0.5 +zcash-cli \- manual page for zcash-cli v2.0.5-1 .SH DESCRIPTION -Zcash RPC client version v2.0.5 +Zcash RPC client version v2.0.5\-1 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . diff --git a/doc/man/zcash-tx.1 b/doc/man/zcash-tx.1 index df99ae127f2..fc0810578fd 100644 --- a/doc/man/zcash-tx.1 +++ b/doc/man/zcash-tx.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-TX "1" "May 2019" "zcash-tx v2.0.5" "User Commands" +.TH ZCASH-TX "1" "May 2019" "zcash-tx v2.0.5-1" "User Commands" .SH NAME -zcash-tx \- manual page for zcash-tx v2.0.5 +zcash-tx \- manual page for zcash-tx v2.0.5-1 .SH DESCRIPTION -Zcash zcash\-tx utility version v2.0.5 +Zcash zcash\-tx utility version v2.0.5\-1 .SS "Usage:" .TP zcash\-tx [options] [commands] diff --git a/doc/man/zcashd.1 b/doc/man/zcashd.1 index d03182682e6..f47b35710ee 100644 --- a/doc/man/zcashd.1 +++ b/doc/man/zcashd.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASHD "1" "May 2019" "zcashd v2.0.5" "User Commands" +.TH ZCASHD "1" "May 2019" "zcashd v2.0.5-1" "User Commands" .SH NAME -zcashd \- manual page for zcashd v2.0.5 +zcashd \- manual page for zcashd v2.0.5-1 .SH DESCRIPTION -Zcash Daemon version v2.0.5 +Zcash Daemon version v2.0.5\-1 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . From dfa40412af4df0c1f7eb0cfd70746c8a573a63f0 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Wed, 8 May 2019 06:57:28 -0600 Subject: [PATCH 068/395] make-release.py: Updated release notes and changelog for 2.0.5-1. --- contrib/debian/changelog | 6 ++ doc/authors.md | 2 +- doc/release-notes.md | 50 ---------------- doc/release-notes/release-notes-2.0.5-1.md | 68 ++++++++++++++++++++++ 4 files changed, 75 insertions(+), 51 deletions(-) create mode 100644 doc/release-notes/release-notes-2.0.5-1.md diff --git a/contrib/debian/changelog b/contrib/debian/changelog index b9b8c076751..3814043023d 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,9 @@ +zcash (2.0.5+1) stable; urgency=medium + + * 2.0.5-1 release. + + -- Electric Coin Company Wed, 08 May 2019 06:57:28 -0600 + zcash (2.0.5) stable; urgency=medium * 2.0.5 release. diff --git a/doc/authors.md b/doc/authors.md index 95018c4b572..c196c34a06e 100644 --- a/doc/authors.md +++ b/doc/authors.md @@ -13,8 +13,8 @@ Jonas Schnelli (62) Nathan Wilcox (56) Pieter Wuille (54) Kevin Gallagher (38) +Eirik0 (36) Cory Fields (35) -Eirik0 (27) mdr0id (22) Larry Ruane (22) Jonathan "Duke" Leto (17) diff --git a/doc/release-notes.md b/doc/release-notes.md index 0d0f27e5b3b..a29094b5174 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,53 +4,3 @@ release-notes at release time) Notable changes =============== -Sprout to Sapling Migration Tool --------------------------------- -This release includes the addition of a tool that will enable users to migrate -shielded funds from the Sprout pool to the Sapling pool while minimizing -information leakage. - -The migration can be enabled using the RPC `z_setmigration` or by including -`-migration` in the `zcash.conf` file. Unless otherwise specified funds will be -migrated to the wallet's default Sapling address; it is also possible to set the -receiving Sapling address using the `-migrationdestaddress` option in `zcash.conf`. - -See [ZIP308](https://github.com/zcash/zips/blob/master/zip-0308.rst) for full details. - -Sprout to Sapling Migration Tool Fixes --------------------------------------- -The 2.0.5-1 release includes fixes to the Sprout to Sapling Migration Tool -found in testing. We resolved an issue which would cause the zcash daemon to -crash if calling the RPC `z_getmigrationstatus` while a wallet's migration -transactions are in the mempool. - -New consensus rule: Reject blocks that violate turnstile --------------------------------------------------------- -In the 2.0.4 release the consensus rules were changed on testnet to enforce a -consensus rule which marks blocks as invalid if they would lead to a turnstile -violation in the Sprout or Shielded value pools. -**This release enforces the consensus rule change on mainnet** - -The motivations and deployment details can be found in the accompanying -[ZIP draft](https://github.com/zcash/zips/pull/210) and -[PR 3968](https://github.com/zcash/zcash/pull/3968). - -Developers can use a new experimental feature `-developersetpoolsizezero` to test -Sprout and Sapling turnstile violations. See [PR 3964](https://github.com/zcash/zcash/pull/3964) for more details. - - -64-bit ARMv8 support --------------------- -Added ARMv8 (AArch64) support. This enables users to build zcash on even more -devices. - -For information on how to build see the [User Guide](https://zcash.readthedocs.io/en/latest/rtd_pages/user_guide.html#build) - -Users on the Zcash forum have reported successes with both the Pine64 Rock64Pro -and Odroid C2 which contain 4GB and 2GB of RAM respectively. - -Just released, the Odroid N2 looks like a great solution with 4GB of RAM. The -newly released Jetson Nano Developer Kit from Nvidia (also 4GB of RAM) is also -worth a look. The NanoPC-T3 Plus is another option but for the simplest/best -experience choose a board with 4GB of RAM. Just make sure before purchase that -the CPU supports the 64-bit ARMv8 architecture. diff --git a/doc/release-notes/release-notes-2.0.5-1.md b/doc/release-notes/release-notes-2.0.5-1.md new file mode 100644 index 00000000000..ef02d80b571 --- /dev/null +++ b/doc/release-notes/release-notes-2.0.5-1.md @@ -0,0 +1,68 @@ +Notable changes +=============== + +Sprout to Sapling Migration Tool +-------------------------------- +This release includes the addition of a tool that will enable users to migrate +shielded funds from the Sprout pool to the Sapling pool while minimizing +information leakage. + +The migration can be enabled using the RPC `z_setmigration` or by including +`-migration` in the `zcash.conf` file. Unless otherwise specified funds will be +migrated to the wallet's default Sapling address; it is also possible to set the +receiving Sapling address using the `-migrationdestaddress` option in `zcash.conf`. + +See [ZIP308](https://github.com/zcash/zips/blob/master/zip-0308.rst) for full details. + +Sprout to Sapling Migration Tool Fixes +-------------------------------------- +The 2.0.5-1 release includes fixes to the Sprout to Sapling Migration Tool +found in testing. We resolved an issue which would cause the zcash daemon to +crash if calling the RPC `z_getmigrationstatus` while a wallet's migration +transactions are in the mempool. + +New consensus rule: Reject blocks that violate turnstile +-------------------------------------------------------- +In the 2.0.4 release the consensus rules were changed on testnet to enforce a +consensus rule which marks blocks as invalid if they would lead to a turnstile +violation in the Sprout or Shielded value pools. +**This release enforces the consensus rule change on mainnet** + +The motivations and deployment details can be found in the accompanying +[ZIP draft](https://github.com/zcash/zips/pull/210) and +[PR 3968](https://github.com/zcash/zcash/pull/3968). + +Developers can use a new experimental feature `-developersetpoolsizezero` to test +Sprout and Sapling turnstile violations. See [PR 3964](https://github.com/zcash/zcash/pull/3964) for more details. + + +64-bit ARMv8 support +-------------------- +Added ARMv8 (AArch64) support. This enables users to build zcash on even more +devices. + +For information on how to build see the [User Guide](https://zcash.readthedocs.io/en/latest/rtd_pages/user_guide.html#build) + +Users on the Zcash forum have reported successes with both the Pine64 Rock64Pro +and Odroid C2 which contain 4GB and 2GB of RAM respectively. + +Just released, the Odroid N2 looks like a great solution with 4GB of RAM. The +newly released Jetson Nano Developer Kit from Nvidia (also 4GB of RAM) is also +worth a look. The NanoPC-T3 Plus is another option but for the simplest/best +experience choose a board with 4GB of RAM. Just make sure before purchase that +the CPU supports the 64-bit ARMv8 architecture. + +Changelog +========= + +Eirik0 (9): + Correctly account for migration transactions in the mempool + Store the migration operation id rather than the operation iteslf + Rename variable and add comment + Notable changes for v2.0.5-1 + Fix summing available funds + Add the amount migrated to the operation's result + coinsView is required when using TransactionBuilder if there may be Sprout change + make-release.py: Versioning changes for 2.0.5-1. + make-release.py: Updated manpages for 2.0.5-1. + From bda85eb06a6b7aa2342d7f3cdc2af52fa1250039 Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 8 May 2019 20:32:04 -0700 Subject: [PATCH 069/395] Remove unused specifier from format string. The extra specifier meant that a runtime error would be thrown during Sprout to Sapling migration if `zrpcunsafe` logging was enabled: "tinyformat: Too many conversion specifiers in format string" --- src/transaction_builder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transaction_builder.cpp b/src/transaction_builder.cpp index 64f8238b80d..6c9da0656bc 100644 --- a/src/transaction_builder.cpp +++ b/src/transaction_builder.cpp @@ -677,7 +677,7 @@ void TransactionBuilder::CreateJSDescription( std::array& inputMap, std::array& outputMap) { - LogPrint("zrpcunsafe", "%s: creating joinsplit at index %d (vpub_old=%s, vpub_new=%s, in[0]=%s, in[1]=%s, out[0]=%s, out[1]=%s)\n", + LogPrint("zrpcunsafe", "CreateJSDescription: creating joinsplit at index %d (vpub_old=%s, vpub_new=%s, in[0]=%s, in[1]=%s, out[0]=%s, out[1]=%s)\n", mtx.vjoinsplit.size(), FormatMoney(vpub_old), FormatMoney(vpub_new), FormatMoney(vjsin[0].note.value()), FormatMoney(vjsin[1].note.value()), From 6921c81b9ddff1b3ac7731661a5778bd4f59aa9b Mon Sep 17 00:00:00 2001 From: Simon Date: Thu, 9 May 2019 09:32:09 -0700 Subject: [PATCH 070/395] Don't allow migration when node is syncing at launch or after waking up. --- src/wallet/wallet.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 07c0a105da2..bde0eb9d119 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -581,7 +581,13 @@ void CWallet::ChainTip(const CBlockIndex *pindex, { if (added) { ChainTipAdded(pindex, pblock, sproutTree, saplingTree); - RunSaplingMigration(pindex->nHeight); + // Prevent migration transactions from being created when node is syncing after launch, + // and also when node wakes up from suspension/hibernation and incoming blocks are old. + if (!IsInitialBlockDownload() && + pblock->GetBlockTime() > GetAdjustedTime() - 3 * 60 * 60) + { + RunSaplingMigration(pindex->nHeight); + } } else { DecrementNoteWitnesses(pindex); UpdateSaplingNullifierNoteMapForBlock(pblock); From 5eb7129d951aa7b2221124ab6f904fc0ca19946e Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 10 May 2019 11:39:03 +0100 Subject: [PATCH 071/395] Generalize TransactionBuilder and CreateNewContextualCMutableTransaction to allow choosing the expiry delta. Signed-off-by: Daira Hopwood --- src/main.cpp | 11 +++++++++-- src/main.h | 5 ++++- src/transaction_builder.cpp | 3 ++- src/transaction_builder.h | 1 + src/wallet/asyncrpcoperation_saplingmigration.cpp | 3 ++- src/wallet/rpcwallet.cpp | 6 +++--- 6 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index f7569a5ee62..ea105227427 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6612,12 +6612,19 @@ static class CMainCleanup // Set default values of new CMutableTransaction based on consensus rules at given height. CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight) { - CMutableTransaction mtx; + return CreateNewContextualCMutableTransaction(consensusParams, nHeight, expiryDelta); +} +CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight, int nExpiryDelta) { + CMutableTransaction mtx; bool isOverwintered = NetworkUpgradeActive(nHeight, consensusParams, Consensus::UPGRADE_OVERWINTER); if (isOverwintered) { mtx.fOverwintered = true; - mtx.nExpiryHeight = nHeight + expiryDelta; + mtx.nExpiryHeight = nHeight + nExpiryDelta; + + if (mtx.nExpiryHeight <= 0 || mtx.nExpiryHeight >= TX_EXPIRY_HEIGHT_THRESHOLD) { + throw new std::runtime_error("CreateNewContextualCMutableTransaction: invalid expiry height"); + } // NOTE: If the expiry height crosses into an incompatible consensus epoch, and it is changed to the last block // of the current epoch (see below: Overwinter->Sapling), the transaction will be rejected if it falls within diff --git a/src/main.h b/src/main.h index df9e7ea3ab5..b78c1d831e9 100644 --- a/src/main.h +++ b/src/main.h @@ -595,7 +595,10 @@ int GetSpendHeight(const CCoinsViewCache& inputs); uint64_t CalculateCurrentUsage(); -/** Return a CMutableTransaction with contextual default values based on set of consensus rules at height */ +/** Return a CMutableTransaction with contextual default values based on set of consensus rules at nHeight, and the default expiry delta. */ CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight); +/** Return a CMutableTransaction with contextual default values based on set of consensus rules at nHeight, and given expiry delta. */ +CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight, int nExpiryDelta); + #endif // BITCOIN_MAIN_H diff --git a/src/transaction_builder.cpp b/src/transaction_builder.cpp index 6c9da0656bc..687c1a42024 100644 --- a/src/transaction_builder.cpp +++ b/src/transaction_builder.cpp @@ -50,6 +50,7 @@ std::string TransactionBuilderResult::GetError() { TransactionBuilder::TransactionBuilder( const Consensus::Params& consensusParams, int nHeight, + int nExpiryDelta, CKeyStore* keystore, ZCJoinSplit* sproutParams, CCoinsViewCache* coinsView, @@ -61,7 +62,7 @@ TransactionBuilder::TransactionBuilder( coinsView(coinsView), cs_coinsView(cs_coinsView) { - mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight); + mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight, nExpiryDelta); } // This exception is thrown in certain scenarios when building JoinSplits fails. diff --git a/src/transaction_builder.h b/src/transaction_builder.h index ee3c4e7ae45..46f38481ecc 100644 --- a/src/transaction_builder.h +++ b/src/transaction_builder.h @@ -95,6 +95,7 @@ class TransactionBuilder TransactionBuilder( const Consensus::Params& consensusParams, int nHeight, + int nExpiryDelta, CKeyStore* keyStore = nullptr, ZCJoinSplit* sproutParams = nullptr, CCoinsViewCache* coinsView = nullptr, diff --git a/src/wallet/asyncrpcoperation_saplingmigration.cpp b/src/wallet/asyncrpcoperation_saplingmigration.cpp index ac82717be70..5f34eaeee75 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.cpp +++ b/src/wallet/asyncrpcoperation_saplingmigration.cpp @@ -98,7 +98,8 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { CCoinsViewCache coinsView(pcoinsTip); do { CAmount amountToSend = chooseAmount(availableFunds); - auto builder = TransactionBuilder(consensusParams, targetHeight_, pwalletMain, pzcashParams, &coinsView, &cs_main); + auto builder = TransactionBuilder(consensusParams, targetHeight_, expiryDelta, pwalletMain, pzcashParams, + &coinsView, &cs_main); std::vector fromNotes; CAmount fromNoteAmount = 0; while (fromNoteAmount < amountToSend) { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index ca291255892..61dd9e5869b 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3888,7 +3888,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) // Builder (used if Sapling addresses are involved) boost::optional builder; if (noSproutAddrs) { - builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, pwalletMain); + builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, expiryDelta, pwalletMain); } // Contextual transaction we will build on @@ -4229,7 +4229,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp) // Builder (used if Sapling addresses are involved) TransactionBuilder builder = TransactionBuilder( - Params().GetConsensus(), nextBlockHeight, pwalletMain); + Params().GetConsensus(), nextBlockHeight, expiryDelta, pwalletMain); // Contextual transaction we will build on // (used if no Sapling addresses are involved) @@ -4646,7 +4646,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) // Builder (used if Sapling addresses are involved) boost::optional builder; if (isToSaplingZaddr || saplingNoteInputs.size() > 0) { - builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, pwalletMain); + builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, expiryDelta, pwalletMain); } // Create operation and add to global queue std::shared_ptr q = getAsyncRPCQueue(); From 9cd34fc10af2d54dc93925dca1afd7cc0307aa68 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 10 May 2019 11:39:57 +0100 Subject: [PATCH 072/395] Repair calls to TransactionBuilder from tests. Signed-off-by: Daira Hopwood --- src/gtest/test_transaction_builder.cpp | 34 +++++++++++++------------- src/test/rpc_wallet_tests.cpp | 2 +- src/utiltest.cpp | 2 +- src/wallet/gtest/test_wallet.cpp | 24 +++++++++--------- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/gtest/test_transaction_builder.cpp b/src/gtest/test_transaction_builder.cpp index 6676ef21eec..3fe71d21b31 100644 --- a/src/gtest/test_transaction_builder.cpp +++ b/src/gtest/test_transaction_builder.cpp @@ -93,7 +93,7 @@ TEST(TransactionBuilder, TransparentToSapling) // Create a shielding transaction from transparent to Sapling // 0.0005 t-ZEC in, 0.0004 z-ZEC out, 0.0001 t-ZEC fee - auto builder = TransactionBuilder(consensusParams, 1, &keystore); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore); builder.AddTransparentInput(COutPoint(), scriptPubKey, 50000); builder.AddSaplingOutput(fvk_from.ovk, pk, 40000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -125,7 +125,7 @@ TEST(TransactionBuilder, SaplingToSapling) { // Create a Sapling-only transaction // 0.0004 z-ZEC in, 0.00025 z-ZEC out, 0.0001 t-ZEC fee, 0.00005 z-ZEC change - auto builder = TransactionBuilder(consensusParams, 2); + auto builder = TransactionBuilder(consensusParams, 2, expiryDelta); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); // Check that trying to add a different anchor fails @@ -166,7 +166,7 @@ TEST(TransactionBuilder, SaplingToSprout) { // - 0.0004 Sapling-ZEC in - 0.00025 Sprout-ZEC out // - 0.00005 Sapling-ZEC change // - 0.0001 t-ZEC fee - auto builder = TransactionBuilder(consensusParams, 2, nullptr, params); + auto builder = TransactionBuilder(consensusParams, 2, expiryDelta, nullptr, params); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSproutOutput(sproutAddr, 25000); auto tx = builder.Build().GetTxOrThrow(); @@ -218,7 +218,7 @@ TEST(TransactionBuilder, SproutToSproutAndSapling) { // - 0.00005 Sprout-ZEC change // - 0.00005 Sapling-ZEC out // - 0.00005 t-ZEC fee - auto builder = TransactionBuilder(consensusParams, 2, nullptr, params, &view); + auto builder = TransactionBuilder(consensusParams, 2, expiryDelta, nullptr, params, &view); builder.SetFee(5000); builder.AddSproutInput(sproutSk, sproutNote, sproutWitness); builder.AddSproutOutput(sproutAddr, 6000); @@ -255,7 +255,7 @@ TEST(TransactionBuilder, ThrowsOnSproutOutputWithoutParams) auto sk = libzcash::SproutSpendingKey::random(); auto addr = sk.address(); - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); ASSERT_THROW(builder.AddSproutOutput(addr, 10), std::runtime_error); } @@ -264,7 +264,7 @@ TEST(TransactionBuilder, ThrowsOnTransparentInputWithoutKeyStore) SelectParams(CBaseChainParams::REGTEST); auto consensusParams = Params().GetConsensus(); - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); ASSERT_THROW(builder.AddTransparentInput(COutPoint(), CScript(), 1), std::runtime_error); } @@ -275,7 +275,7 @@ TEST(TransactionBuilder, RejectsInvalidTransparentOutput) // Default CTxDestination type is an invalid address CTxDestination taddr; - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); ASSERT_THROW(builder.AddTransparentOutput(taddr, 50), UniValue); } @@ -286,7 +286,7 @@ TEST(TransactionBuilder, RejectsInvalidTransparentChangeAddress) // Default CTxDestination type is an invalid address CTxDestination taddr; - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); ASSERT_THROW(builder.SendChangeTo(taddr), UniValue); } @@ -311,13 +311,13 @@ TEST(TransactionBuilder, FailsWithNegativeChange) // Fail if there is only a Sapling output // 0.0005 z-ZEC out, 0.0001 t-ZEC fee - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); builder.AddSaplingOutput(fvk.ovk, pa, 50000, {}); EXPECT_EQ("Change cannot be negative", builder.Build().GetError()); // Fail if there is only a transparent output // 0.0005 t-ZEC out, 0.0001 t-ZEC fee - builder = TransactionBuilder(consensusParams, 1, &keystore); + builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore); builder.AddTransparentOutput(taddr, 50000); EXPECT_EQ("Change cannot be negative", builder.Build().GetError()); @@ -359,14 +359,14 @@ TEST(TransactionBuilder, ChangeOutput) // No change address and no Sapling spends { - auto builder = TransactionBuilder(consensusParams, 1, &keystore); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore); builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000); EXPECT_EQ("Could not determine change address", builder.Build().GetError()); } // Change to the same address as the first Sapling spend { - auto builder = TransactionBuilder(consensusParams, 1, &keystore); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore); builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); auto tx = builder.Build().GetTxOrThrow(); @@ -381,7 +381,7 @@ TEST(TransactionBuilder, ChangeOutput) // Change to a Sapling address { - auto builder = TransactionBuilder(consensusParams, 1, &keystore); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore); builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000); builder.SendChangeTo(zChangeAddr, fvkOut.ovk); auto tx = builder.Build().GetTxOrThrow(); @@ -396,7 +396,7 @@ TEST(TransactionBuilder, ChangeOutput) // Change to a transparent address { - auto builder = TransactionBuilder(consensusParams, 1, &keystore); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore); builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000); builder.SendChangeTo(taddr); auto tx = builder.Build().GetTxOrThrow(); @@ -428,7 +428,7 @@ TEST(TransactionBuilder, SetFee) // Default fee { - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -443,7 +443,7 @@ TEST(TransactionBuilder, SetFee) // Configured fee { - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); builder.SetFee(20000); @@ -472,7 +472,7 @@ TEST(TransactionBuilder, CheckSaplingTxVersion) auto pk = sk.default_address(); // Cannot add Sapling outputs to a non-Sapling transaction - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); try { builder.AddSaplingOutput(uint256(), pk, 12345, {}); } catch (std::runtime_error const & err) { diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index f2cc09903d4..f04d3f2c216 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -1302,7 +1302,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_taddr_to_sapling) pwalletMain->AddToWallet(wtx, true, NULL); // Context that z_sendmany requires - auto builder = TransactionBuilder(consensusParams, nextBlockHeight, pwalletMain); + auto builder = TransactionBuilder(consensusParams, nextBlockHeight, expiryDelta, pwalletMain); mtx = CreateNewContextualCMutableTransaction(consensusParams, nextBlockHeight); std::vector recipients = { SendManyRecipient(zaddr1, 1 * COIN, "ABCD") }; diff --git a/src/utiltest.cpp b/src/utiltest.cpp index 8eb23249f27..e62c5611be3 100644 --- a/src/utiltest.cpp +++ b/src/utiltest.cpp @@ -232,7 +232,7 @@ CWalletTx GetValidSaplingReceive(const Consensus::Params& consensusParams, auto fvk = sk.expsk.full_viewing_key(); auto pa = sk.DefaultAddress(); - auto builder = TransactionBuilder(consensusParams, 1, &keyStore); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keyStore); builder.SetFee(0); builder.AddTransparentInput(COutPoint(), scriptPubKey, value); builder.AddSaplingOutput(fvk.ovk, pa, value, {}); diff --git a/src/wallet/gtest/test_wallet.cpp b/src/wallet/gtest/test_wallet.cpp index 9af4aa0609a..6d07bee388e 100644 --- a/src/wallet/gtest/test_wallet.cpp +++ b/src/wallet/gtest/test_wallet.cpp @@ -379,7 +379,7 @@ TEST(WalletTests, SetSaplingNoteAddrsInCWalletTx) { ASSERT_TRUE(nf); uint256 nullifier = nf.get(); - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); builder.AddSaplingSpend(expsk, note, anchor, witness); builder.AddSaplingOutput(fvk.ovk, pk, 50000, {}); builder.SetFee(0); @@ -506,7 +506,7 @@ TEST(WalletTests, FindMySaplingNotes) { auto testNote = GetTestSaplingNote(pa, 50000); // Generate transaction - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -638,7 +638,7 @@ TEST(WalletTests, GetConflictedSaplingNotes) { auto witness = saplingTree.witness(); // Generate tx to create output note B - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); builder.AddSaplingSpend(expsk, note, anchor, witness); builder.AddSaplingOutput(fvk.ovk, pk, 35000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -692,13 +692,13 @@ TEST(WalletTests, GetConflictedSaplingNotes) { anchor = saplingTree.root(); // Create transaction to spend note B - auto builder2 = TransactionBuilder(consensusParams, 2); + auto builder2 = TransactionBuilder(consensusParams, 2, expiryDelta); builder2.AddSaplingSpend(expsk, note2, anchor, spend_note_witness); builder2.AddSaplingOutput(fvk.ovk, pk, 20000, {}); auto tx2 = builder2.Build().GetTxOrThrow(); // Create conflicting transaction which also spends note B - auto builder3 = TransactionBuilder(consensusParams, 2); + auto builder3 = TransactionBuilder(consensusParams, 2, expiryDelta); builder3.AddSaplingSpend(expsk, note2, anchor, spend_note_witness); builder3.AddSaplingOutput(fvk.ovk, pk, 19999, {}); auto tx3 = builder3.Build().GetTxOrThrow(); @@ -785,7 +785,7 @@ TEST(WalletTests, SaplingNullifierIsSpent) { auto testNote = GetTestSaplingNote(pa, 50000); // Generate transaction - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -868,7 +868,7 @@ TEST(WalletTests, NavigateFromSaplingNullifierToNote) { auto testNote = GetTestSaplingNote(pa, 50000); // Generate transaction - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -996,7 +996,7 @@ TEST(WalletTests, SpentSaplingNoteIsFromMe) { auto witness = saplingTree.witness(); // Generate transaction, which sends funds to note B - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); builder.AddSaplingSpend(expsk, note, anchor, witness); builder.AddSaplingOutput(fvk.ovk, pk, 25000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -1066,7 +1066,7 @@ TEST(WalletTests, SpentSaplingNoteIsFromMe) { anchor = saplingTree.root(); // Create transaction to spend note B - auto builder2 = TransactionBuilder(consensusParams, 2); + auto builder2 = TransactionBuilder(consensusParams, 2, expiryDelta); builder2.AddSaplingSpend(expsk, note2, anchor, spend_note_witness); builder2.AddSaplingOutput(fvk.ovk, pk, 12500, {}); auto tx2 = builder2.Build().GetTxOrThrow(); @@ -1771,7 +1771,7 @@ TEST(WalletTests, UpdatedSaplingNoteData) { auto testNote = GetTestSaplingNote(pa, 50000); // Generate transaction - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingOutput(fvk.ovk, pa2, 25000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -1912,7 +1912,7 @@ TEST(WalletTests, MarkAffectedSaplingTransactionsDirty) { // Generate shielding tx from transparent to Sapling // 0.0005 t-ZEC in, 0.0004 z-ZEC out, 0.0001 t-ZEC fee - auto builder = TransactionBuilder(consensusParams, 1, &keystore); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore); builder.AddTransparentInput(COutPoint(), scriptPubKey, 50000); builder.AddSaplingOutput(fvk.ovk, pk, 40000, {}); auto tx1 = builder.Build().GetTxOrThrow(); @@ -1967,7 +1967,7 @@ TEST(WalletTests, MarkAffectedSaplingTransactionsDirty) { // Create a Sapling-only transaction // 0.0004 z-ZEC in, 0.00025 z-ZEC out, 0.0001 t-ZEC fee, 0.00005 z-ZEC change - auto builder2 = TransactionBuilder(consensusParams, 2); + auto builder2 = TransactionBuilder(consensusParams, 2, expiryDelta); builder2.AddSaplingSpend(expsk, note, anchor, witness); builder2.AddSaplingOutput(fvk.ovk, pk, 25000, {}); auto tx2 = builder2.Build().GetTxOrThrow(); From 14c0be6f27bcce3caaafde89d6e145fb54692cd6 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 10 May 2019 11:41:44 +0100 Subject: [PATCH 073/395] Change expiry delta for migration transactions to 450 blocks. Signed-off-by: Daira Hopwood --- src/wallet/asyncrpcoperation_saplingmigration.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/wallet/asyncrpcoperation_saplingmigration.cpp b/src/wallet/asyncrpcoperation_saplingmigration.cpp index 5f34eaeee75..db478f27cb3 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.cpp +++ b/src/wallet/asyncrpcoperation_saplingmigration.cpp @@ -13,6 +13,7 @@ #include "wallet.h" const CAmount FEE = 10000; +const int MIGRATION_EXPIRY_DELTA = 450; AsyncRPCOperation_saplingmigration::AsyncRPCOperation_saplingmigration(int targetHeight) : targetHeight_(targetHeight) {} @@ -98,7 +99,7 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { CCoinsViewCache coinsView(pcoinsTip); do { CAmount amountToSend = chooseAmount(availableFunds); - auto builder = TransactionBuilder(consensusParams, targetHeight_, expiryDelta, pwalletMain, pzcashParams, + auto builder = TransactionBuilder(consensusParams, targetHeight_, MIGRATION_EXPIRY_DELTA, pwalletMain, pzcashParams, &coinsView, &cs_main); std::vector fromNotes; CAmount fromNoteAmount = 0; @@ -183,7 +184,7 @@ libzcash::SaplingPaymentAddress AsyncRPCOperation_saplingmigration::getMigration libzcash::SaplingExtendedSpendingKey xsk = m_32h_cth.Derive(0 | ZIP32_HARDENED_KEY_LIMIT); libzcash::SaplingPaymentAddress toAddress = xsk.DefaultAddress(); - + // Refactor: this is similar logic as in the visitor HaveSpendingKeyForPaymentAddress and is used elsewhere libzcash::SaplingIncomingViewingKey ivk; libzcash::SaplingFullViewingKey fvk; From e7529049fb825a5d496f84f145c16f2ee30cc993 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 10 May 2019 13:48:24 +0100 Subject: [PATCH 074/395] Test the expiry height of migration transactions. Signed-off-by: Daira Hopwood --- qa/rpc-tests/sprout_sapling_migration.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/qa/rpc-tests/sprout_sapling_migration.py b/qa/rpc-tests/sprout_sapling_migration.py index 3e5a094cf6f..c9ef9797a36 100755 --- a/qa/rpc-tests/sprout_sapling_migration.py +++ b/qa/rpc-tests/sprout_sapling_migration.py @@ -102,14 +102,25 @@ def run_migration_test(self, node, sproutAddr, saplingAddr, target_height): self.sync_all() # At 499 % 500 there will be a transaction in the mempool and the note will be locked - assert_equal(1, len(node.getrawmempool()), "mempool size at 499 % 500") + mempool = node.getrawmempool() + print("mempool: {}".format(mempool)) + assert_equal(1, len(mempool), "mempool size at 499 % 500") assert_equal(node.z_getbalance(sproutAddr), Decimal('0')) assert_equal(node.z_getbalance(saplingAddr), Decimal('0')) assert_true(node.z_getbalance(saplingAddr, 0) > Decimal('0'), "Unconfirmed sapling balance at 499 % 500") # Check that unmigrated amount + unfinalized = starting balance - fee status = node.z_getmigrationstatus() + print("status: {}".format(status)) assert_equal(Decimal('9.9999'), Decimal(status['unmigrated_amount']) + Decimal(status['unfinalized_migrated_amount'])) + # The transaction in the mempool should be the one listed in migration_txids, + # and it should expire at the next 450 % 500. + assert_equal(1, len(status['migration_txids'])) + txid = status['migration_txids'][0] + assert_equal(txid, mempool[0]) + tx = node.getrawtransaction(txid, 1) + assert_equal(target_height + 450, tx['expiryheight']) + node.generate(1) self.sync_all() From 9615caa8f9df8a7bae62cc5b1f1cb9d218ae01f7 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 10 May 2019 16:08:03 +0100 Subject: [PATCH 075/395] Fix cosmetic spacing issue in z_setmigration help. Signed-off-by: Daira Hopwood --- src/wallet/rpcwallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 61dd9e5869b..2fc71bbf445 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3921,7 +3921,7 @@ UniValue z_setmigration(const UniValue& params, bool fHelp) { "Sprout balance, this process may take several weeks. The migration works by sending, up to 5, as many\n" "transactions as possible whenever the blockchain reaches a height equal to 499 modulo 500. The transaction\n" "amounts are picked according to the random distribution specified in ZIP 308. The migration will end once\n" - "the wallet’s Sprout balance is below" + strprintf("%s %s", FormatMoney(CENT), CURRENCY_UNIT) + ".\n" + "the wallet’s Sprout balance is below " + strprintf("%s %s", FormatMoney(CENT), CURRENCY_UNIT) + ".\n" "\nArguments:\n" "1. enabled (boolean, required) 'true' or 'false' to enable or disable respectively.\n" ); From 3220d99360808edf7be86bce3c987eb3b69652ca Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Fri, 10 May 2019 11:44:40 -0600 Subject: [PATCH 076/395] Use CommitTransaction() rather than sendrawtransaction() --- .../asyncrpcoperation_mergetoaddress.cpp | 50 +++++-------------- src/wallet/asyncrpcoperation_sendmany.cpp | 49 +++++------------- .../asyncrpcoperation_shieldcoinbase.cpp | 49 +++++------------- src/wallet/wallet.cpp | 21 +++----- src/wallet/wallet.h | 2 +- 5 files changed, 44 insertions(+), 127 deletions(-) diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index b3870e6029d..f2110a71533 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -33,8 +33,6 @@ using namespace libzcash; -extern UniValue sendrawtransaction(const UniValue& params, bool fHelp); - int mta_find_output(UniValue obj, int n) { UniValue outputMapValue = find_value(obj, "outputmap"); @@ -362,27 +360,19 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() tx_ = builder_.Build().GetTxOrThrow(); // Send the transaction - // TODO: Use CWallet::CommitTransaction instead of sendrawtransaction - auto signedtxn = EncodeHexTx(tx_); if (!testmode) { - UniValue params = UniValue(UniValue::VARR); - params.push_back(signedtxn); - UniValue sendResultValue = sendrawtransaction(params, false); - if (sendResultValue.isNull()) { - throw JSONRPCError(RPC_WALLET_ERROR, "sendrawtransaction did not return an error or a txid."); - } - - auto txid = sendResultValue.get_str(); + CWalletTx wtx(pwalletMain, tx_); + pwalletMain->CommitTransaction(wtx, boost::none); UniValue o(UniValue::VOBJ); - o.push_back(Pair("txid", txid)); + o.push_back(Pair("txid", tx_.GetHash().ToString())); set_result(o); } else { // Test mode does not send the transaction to the network. UniValue o(UniValue::VOBJ); o.push_back(Pair("test", 1)); o.push_back(Pair("txid", tx_.GetHash().ToString())); - o.push_back(Pair("hex", signedtxn)); + o.push_back(Pair("hex", EncodeHexTx(tx_))); set_result(o); } @@ -775,41 +765,25 @@ void AsyncRPCOperation_mergetoaddress::sign_send_raw_transaction(UniValue obj) throw JSONRPCError(RPC_WALLET_ERROR, "Missing hex data for signed transaction"); } std::string signedtxn = hexValue.get_str(); - + CDataStream stream(ParseHex(signedtxn), SER_NETWORK, PROTOCOL_VERSION); + CTransaction tx; + stream >> tx; + tx_ = tx; // Send the signed transaction if (!testmode) { - params.clear(); - params.setArray(); - params.push_back(signedtxn); - UniValue sendResultValue = sendrawtransaction(params, false); - if (sendResultValue.isNull()) { - throw JSONRPCError(RPC_WALLET_ERROR, "Send raw transaction did not return an error or a txid."); - } - - std::string txid = sendResultValue.get_str(); - + CWalletTx wtx(pwalletMain, tx_); + pwalletMain->CommitTransaction(wtx, boost::none); UniValue o(UniValue::VOBJ); - o.push_back(Pair("txid", txid)); + o.push_back(Pair("txid", tx_.GetHash().ToString())); set_result(o); } else { // Test mode does not send the transaction to the network. - - CDataStream stream(ParseHex(signedtxn), SER_NETWORK, PROTOCOL_VERSION); - CTransaction tx; - stream >> tx; - UniValue o(UniValue::VOBJ); o.push_back(Pair("test", 1)); - o.push_back(Pair("txid", tx.GetHash().ToString())); + o.push_back(Pair("txid", tx_.GetHash().ToString())); o.push_back(Pair("hex", signedtxn)); set_result(o); } - - // Keep the signed transaction so we can hash to the same txid - CDataStream stream(ParseHex(signedtxn), SER_NETWORK, PROTOCOL_VERSION); - CTransaction tx; - stream >> tx; - tx_ = tx; } diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index e30c0748373..1037e27d733 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -35,7 +35,6 @@ using namespace libzcash; extern UniValue signrawtransaction(const UniValue& params, bool fHelp); -extern UniValue sendrawtransaction(const UniValue& params, bool fHelp); int find_output(UniValue obj, int n) { UniValue outputMapValue = find_value(obj, "outputmap"); @@ -462,27 +461,19 @@ bool AsyncRPCOperation_sendmany::main_impl() { tx_ = builder_.Build().GetTxOrThrow(); // Send the transaction - // TODO: Use CWallet::CommitTransaction instead of sendrawtransaction - auto signedtxn = EncodeHexTx(tx_); if (!testmode) { - UniValue params = UniValue(UniValue::VARR); - params.push_back(signedtxn); - UniValue sendResultValue = sendrawtransaction(params, false); - if (sendResultValue.isNull()) { - throw JSONRPCError(RPC_WALLET_ERROR, "sendrawtransaction did not return an error or a txid."); - } - - auto txid = sendResultValue.get_str(); + CWalletTx wtx(pwalletMain, tx_); + pwalletMain->CommitTransaction(wtx, boost::none); UniValue o(UniValue::VOBJ); - o.push_back(Pair("txid", txid)); + o.push_back(Pair("txid", tx_.GetHash().ToString())); set_result(o); } else { // Test mode does not send the transaction to the network. UniValue o(UniValue::VOBJ); o.push_back(Pair("test", 1)); o.push_back(Pair("txid", tx_.GetHash().ToString())); - o.push_back(Pair("hex", signedtxn)); + o.push_back(Pair("hex", EncodeHexTx(tx_))); set_result(o); } @@ -941,41 +932,25 @@ void AsyncRPCOperation_sendmany::sign_send_raw_transaction(UniValue obj) throw JSONRPCError(RPC_WALLET_ERROR, "Missing hex data for signed transaction"); } std::string signedtxn = hexValue.get_str(); - + CDataStream stream(ParseHex(signedtxn), SER_NETWORK, PROTOCOL_VERSION); + CTransaction tx; + stream >> tx; + tx_ = tx; // Send the signed transaction if (!testmode) { - params.clear(); - params.setArray(); - params.push_back(signedtxn); - UniValue sendResultValue = sendrawtransaction(params, false); - if (sendResultValue.isNull()) { - throw JSONRPCError(RPC_WALLET_ERROR, "Send raw transaction did not return an error or a txid."); - } - - std::string txid = sendResultValue.get_str(); - + CWalletTx wtx(pwalletMain, tx_); + pwalletMain->CommitTransaction(wtx, boost::none); UniValue o(UniValue::VOBJ); - o.push_back(Pair("txid", txid)); + o.push_back(Pair("txid", tx_.GetHash().ToString())); set_result(o); } else { // Test mode does not send the transaction to the network. - - CDataStream stream(ParseHex(signedtxn), SER_NETWORK, PROTOCOL_VERSION); - CTransaction tx; - stream >> tx; - UniValue o(UniValue::VOBJ); o.push_back(Pair("test", 1)); - o.push_back(Pair("txid", tx.GetHash().ToString())); + o.push_back(Pair("txid", tx_.GetHash().ToString())); o.push_back(Pair("hex", signedtxn)); set_result(o); } - - // Keep the signed transaction so we can hash to the same txid - CDataStream stream(ParseHex(signedtxn), SER_NETWORK, PROTOCOL_VERSION); - CTransaction tx; - stream >> tx; - tx_ = tx; } diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp index 84811c6868e..b4f6eff15b3 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp @@ -238,7 +238,6 @@ bool ShieldToAddress::operator()(const libzcash::SproutPaymentAddress &zaddr) co extern UniValue signrawtransaction(const UniValue& params, bool fHelp); -extern UniValue sendrawtransaction(const UniValue& params, bool fHelp); bool ShieldToAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) const { m_op->builder_.SetFee(m_op->fee_); @@ -262,27 +261,19 @@ bool ShieldToAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) c m_op->tx_ = m_op->builder_.Build().GetTxOrThrow(); // Send the transaction - // TODO: Use CWallet::CommitTransaction instead of sendrawtransaction - auto signedtxn = EncodeHexTx(m_op->tx_); if (!m_op->testmode) { - UniValue params = UniValue(UniValue::VARR); - params.push_back(signedtxn); - UniValue sendResultValue = sendrawtransaction(params, false); - if (sendResultValue.isNull()) { - throw JSONRPCError(RPC_WALLET_ERROR, "sendrawtransaction did not return an error or a txid."); - } - - auto txid = sendResultValue.get_str(); + CWalletTx wtx(pwalletMain, m_op->tx_); + pwalletMain->CommitTransaction(wtx, boost::none); UniValue o(UniValue::VOBJ); - o.push_back(Pair("txid", txid)); + o.push_back(Pair("txid", m_op->tx_.GetHash().ToString())); m_op->set_result(o); } else { // Test mode does not send the transaction to the network. UniValue o(UniValue::VOBJ); o.push_back(Pair("test", 1)); o.push_back(Pair("txid", m_op->tx_.GetHash().ToString())); - o.push_back(Pair("hex", signedtxn)); + o.push_back(Pair("hex", EncodeHexTx(m_op->tx_))); m_op->set_result(o); } @@ -323,41 +314,25 @@ void AsyncRPCOperation_shieldcoinbase::sign_send_raw_transaction(UniValue obj) throw JSONRPCError(RPC_WALLET_ERROR, "Missing hex data for signed transaction"); } std::string signedtxn = hexValue.get_str(); - + CDataStream stream(ParseHex(signedtxn), SER_NETWORK, PROTOCOL_VERSION); + CTransaction tx; + stream >> tx; + tx_ = tx; // Send the signed transaction if (!testmode) { - params.clear(); - params.setArray(); - params.push_back(signedtxn); - UniValue sendResultValue = sendrawtransaction(params, false); - if (sendResultValue.isNull()) { - throw JSONRPCError(RPC_WALLET_ERROR, "Send raw transaction did not return an error or a txid."); - } - - std::string txid = sendResultValue.get_str(); - + CWalletTx wtx(pwalletMain, tx_); + pwalletMain->CommitTransaction(wtx, boost::none); UniValue o(UniValue::VOBJ); - o.push_back(Pair("txid", txid)); + o.push_back(Pair("txid", tx_.GetHash().ToString())); set_result(o); } else { // Test mode does not send the transaction to the network. - - CDataStream stream(ParseHex(signedtxn), SER_NETWORK, PROTOCOL_VERSION); - CTransaction tx; - stream >> tx; - UniValue o(UniValue::VOBJ); o.push_back(Pair("test", 1)); - o.push_back(Pair("txid", tx.GetHash().ToString())); + o.push_back(Pair("txid", tx_.GetHash().ToString())); o.push_back(Pair("hex", signedtxn)); set_result(o); } - - // Keep the signed transaction so we can hash to the same txid - CDataStream stream(ParseHex(signedtxn), SER_NETWORK, PROTOCOL_VERSION); - CTransaction tx; - stream >> tx; - tx_ = tx; } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 07c0a105da2..e1ebad427cf 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -36,8 +36,6 @@ using namespace std; using namespace libzcash; -extern UniValue sendrawtransaction(const UniValue& params, bool fHelp); - /** * Settings */ @@ -619,16 +617,9 @@ void CWallet::RunSaplingMigration(int blockHeight) { lastOperation->cancel(); } for (const CTransaction& transaction : pendingSaplingMigrationTxs) { - // The following is taken from z_sendmany/z_mergetoaddress // Send the transaction - // TODO: Use CWallet::CommitTransaction instead of sendrawtransaction - auto signedtxn = EncodeHexTx(transaction); - UniValue params = UniValue(UniValue::VARR); - params.push_back(signedtxn); - UniValue sendResultValue = sendrawtransaction(params, false); - if (sendResultValue.isNull()) { - throw JSONRPCError(RPC_WALLET_ERROR, "sendrawtransaction did not return an error or a txid."); - } + CWalletTx wtx(this, transaction); + CommitTransaction(wtx, boost::none); } pendingSaplingMigrationTxs.clear(); } @@ -3595,7 +3586,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt /** * Call after CreateTransaction unless you want to abort */ -bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) +bool CWallet::CommitTransaction(CWalletTx& wtxNew, boost::optional reservekey) { { LOCK2(cs_main, cs_wallet); @@ -3606,8 +3597,10 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) // maybe makes sense; please don't do it anywhere else. CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r+") : NULL; - // Take key pair from key pool so it won't be used again - reservekey.KeepKey(); + if (reservekey) { + // Take key pair from key pool so it won't be used again + reservekey.get().KeepKey(); + } // Add tx to wallet, because if it has change it's also ours, // otherwise just for transaction history. diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index fa137011199..779ad7227bf 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1137,7 +1137,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason); bool CreateTransaction(const std::vector& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true); - bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey); + bool CommitTransaction(CWalletTx& wtxNew, boost::optional reservekey); static CFeeRate minTxFee; static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool); From a7a52d2424d5c0f795356a3a89360dcea29ff223 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Fri, 10 May 2019 12:20:52 -0600 Subject: [PATCH 077/395] Move reused async rpc send logic to separate file --- src/Makefile.am | 2 + src/wallet/asyncrpcoperation_common.cpp | 22 ++++++++++ src/wallet/asyncrpcoperation_common.h | 13 ++++++ .../asyncrpcoperation_mergetoaddress.cpp | 38 +++------------- src/wallet/asyncrpcoperation_sendmany.cpp | 40 ++++------------- .../asyncrpcoperation_shieldcoinbase.cpp | 43 ++++--------------- 6 files changed, 60 insertions(+), 98 deletions(-) create mode 100644 src/wallet/asyncrpcoperation_common.cpp create mode 100644 src/wallet/asyncrpcoperation_common.h diff --git a/src/Makefile.am b/src/Makefile.am index a7c7b12bc5d..7e88c63456c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -216,6 +216,7 @@ BITCOIN_CORE_H = \ utiltime.h \ validationinterface.h \ version.h \ + wallet/asyncrpcoperation_common.h \ wallet/asyncrpcoperation_mergetoaddress.h \ wallet/asyncrpcoperation_saplingmigration.h \ wallet/asyncrpcoperation_sendmany.h \ @@ -306,6 +307,7 @@ libbitcoin_wallet_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_wallet_a_SOURCES = \ zcbenchmarks.cpp \ zcbenchmarks.h \ + wallet/asyncrpcoperation_common.cpp \ wallet/asyncrpcoperation_mergetoaddress.cpp \ wallet/asyncrpcoperation_saplingmigration.cpp \ wallet/asyncrpcoperation_sendmany.cpp \ diff --git a/src/wallet/asyncrpcoperation_common.cpp b/src/wallet/asyncrpcoperation_common.cpp new file mode 100644 index 00000000000..bdbb0a96ca3 --- /dev/null +++ b/src/wallet/asyncrpcoperation_common.cpp @@ -0,0 +1,22 @@ +#include "asyncrpcoperation_common.h" + +#include "core_io.h" +#include "init.h" +#include "wallet.h" + +UniValue SendTransaction(CTransaction& tx, bool testmode) { + UniValue o(UniValue::VOBJ); + // Send the transaction + if (!testmode) { + CWalletTx wtx(pwalletMain, tx); + pwalletMain->CommitTransaction(wtx, boost::none); + o.push_back(Pair("txid", tx.GetHash().ToString())); + } else { + // Test mode does not send the transaction to the network. + UniValue o(UniValue::VOBJ); + o.push_back(Pair("test", 1)); + o.push_back(Pair("txid", tx.GetHash().ToString())); + o.push_back(Pair("hex", EncodeHexTx(tx))); + } + return o; +} \ No newline at end of file diff --git a/src/wallet/asyncrpcoperation_common.h b/src/wallet/asyncrpcoperation_common.h new file mode 100644 index 00000000000..4b65d1f32c1 --- /dev/null +++ b/src/wallet/asyncrpcoperation_common.h @@ -0,0 +1,13 @@ +// Copyright (c) 2019 The Zcash developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef ASYNCRPCOPERATION_COMMON_H +#define ASYNCRPCOPERATION_COMMON_H + +#include "primitives/transaction.h" +#include "univalue.h" + +UniValue SendTransaction(CTransaction& tx, bool testmode); + +#endif /* ASYNCRPCOPERATION_COMMON_H */ diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index f2110a71533..e7e1084a48c 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -5,6 +5,7 @@ #include "asyncrpcoperation_mergetoaddress.h" #include "amount.h" +#include "asyncrpcoperation_common.h" #include "asyncrpcqueue.h" #include "core_io.h" #include "init.h" @@ -355,26 +356,11 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() builder_.AddSaplingOutput(ovk.get(), *saplingPaymentAddress, sendAmount, hexMemo); } - // Build the transaction tx_ = builder_.Build().GetTxOrThrow(); - // Send the transaction - if (!testmode) { - CWalletTx wtx(pwalletMain, tx_); - pwalletMain->CommitTransaction(wtx, boost::none); - - UniValue o(UniValue::VOBJ); - o.push_back(Pair("txid", tx_.GetHash().ToString())); - set_result(o); - } else { - // Test mode does not send the transaction to the network. - UniValue o(UniValue::VOBJ); - o.push_back(Pair("test", 1)); - o.push_back(Pair("txid", tx_.GetHash().ToString())); - o.push_back(Pair("hex", EncodeHexTx(tx_))); - set_result(o); - } + UniValue sendResult = SendTransaction(tx_, testmode); + set_result(sendResult); return true; } @@ -769,21 +755,9 @@ void AsyncRPCOperation_mergetoaddress::sign_send_raw_transaction(UniValue obj) CTransaction tx; stream >> tx; tx_ = tx; - // Send the signed transaction - if (!testmode) { - CWalletTx wtx(pwalletMain, tx_); - pwalletMain->CommitTransaction(wtx, boost::none); - UniValue o(UniValue::VOBJ); - o.push_back(Pair("txid", tx_.GetHash().ToString())); - set_result(o); - } else { - // Test mode does not send the transaction to the network. - UniValue o(UniValue::VOBJ); - o.push_back(Pair("test", 1)); - o.push_back(Pair("txid", tx_.GetHash().ToString())); - o.push_back(Pair("hex", signedtxn)); - set_result(o); - } + + UniValue sendResult = SendTransaction(tx_, testmode); + set_result(sendResult); } diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index 1037e27d733..fe04ce351fc 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -3,8 +3,10 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "asyncrpcoperation_sendmany.h" -#include "asyncrpcqueue.h" + #include "amount.h" +#include "asyncrpcoperation_common.h" +#include "asyncrpcqueue.h" #include "consensus/upgrades.h" #include "core_io.h" #include "init.h" @@ -460,22 +462,8 @@ bool AsyncRPCOperation_sendmany::main_impl() { // Build the transaction tx_ = builder_.Build().GetTxOrThrow(); - // Send the transaction - if (!testmode) { - CWalletTx wtx(pwalletMain, tx_); - pwalletMain->CommitTransaction(wtx, boost::none); - - UniValue o(UniValue::VOBJ); - o.push_back(Pair("txid", tx_.GetHash().ToString())); - set_result(o); - } else { - // Test mode does not send the transaction to the network. - UniValue o(UniValue::VOBJ); - o.push_back(Pair("test", 1)); - o.push_back(Pair("txid", tx_.GetHash().ToString())); - o.push_back(Pair("hex", EncodeHexTx(tx_))); - set_result(o); - } + UniValue sendResult = SendTransaction(tx_, testmode); + set_result(sendResult); return true; } @@ -936,21 +924,9 @@ void AsyncRPCOperation_sendmany::sign_send_raw_transaction(UniValue obj) CTransaction tx; stream >> tx; tx_ = tx; - // Send the signed transaction - if (!testmode) { - CWalletTx wtx(pwalletMain, tx_); - pwalletMain->CommitTransaction(wtx, boost::none); - UniValue o(UniValue::VOBJ); - o.push_back(Pair("txid", tx_.GetHash().ToString())); - set_result(o); - } else { - // Test mode does not send the transaction to the network. - UniValue o(UniValue::VOBJ); - o.push_back(Pair("test", 1)); - o.push_back(Pair("txid", tx_.GetHash().ToString())); - o.push_back(Pair("hex", signedtxn)); - set_result(o); - } + + UniValue sendResult = SendTransaction(tx_, testmode); + set_result(sendResult); } diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp index b4f6eff15b3..f2376780d52 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp @@ -2,8 +2,11 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "asyncrpcqueue.h" +#include "asyncrpcoperation_shieldcoinbase.h" + #include "amount.h" +#include "asyncrpcoperation_common.h" +#include "asyncrpcqueue.h" #include "consensus/upgrades.h" #include "core_io.h" #include "init.h" @@ -31,8 +34,6 @@ #include #include -#include "asyncrpcoperation_shieldcoinbase.h" - using namespace libzcash; static int find_output(UniValue obj, int n) { @@ -260,22 +261,8 @@ bool ShieldToAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) c // Build the transaction m_op->tx_ = m_op->builder_.Build().GetTxOrThrow(); - // Send the transaction - if (!m_op->testmode) { - CWalletTx wtx(pwalletMain, m_op->tx_); - pwalletMain->CommitTransaction(wtx, boost::none); - - UniValue o(UniValue::VOBJ); - o.push_back(Pair("txid", m_op->tx_.GetHash().ToString())); - m_op->set_result(o); - } else { - // Test mode does not send the transaction to the network. - UniValue o(UniValue::VOBJ); - o.push_back(Pair("test", 1)); - o.push_back(Pair("txid", m_op->tx_.GetHash().ToString())); - o.push_back(Pair("hex", EncodeHexTx(m_op->tx_))); - m_op->set_result(o); - } + UniValue sendResult = SendTransaction(m_op->tx_, m_op->testmode); + m_op->set_result(sendResult); return true; } @@ -318,21 +305,9 @@ void AsyncRPCOperation_shieldcoinbase::sign_send_raw_transaction(UniValue obj) CTransaction tx; stream >> tx; tx_ = tx; - // Send the signed transaction - if (!testmode) { - CWalletTx wtx(pwalletMain, tx_); - pwalletMain->CommitTransaction(wtx, boost::none); - UniValue o(UniValue::VOBJ); - o.push_back(Pair("txid", tx_.GetHash().ToString())); - set_result(o); - } else { - // Test mode does not send the transaction to the network. - UniValue o(UniValue::VOBJ); - o.push_back(Pair("test", 1)); - o.push_back(Pair("txid", tx_.GetHash().ToString())); - o.push_back(Pair("hex", signedtxn)); - set_result(o); - } + + UniValue sendResult = SendTransaction(tx_, testmode); + set_result(sendResult); } From 0e06801e12f927a5b88d6ce20103b915192afde8 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Fri, 10 May 2019 12:45:14 -0600 Subject: [PATCH 078/395] Move reused sign and send logic --- src/wallet/asyncrpcoperation_common.cpp | 36 +++++++++++++++++++ src/wallet/asyncrpcoperation_common.h | 17 +++++++++ .../asyncrpcoperation_mergetoaddress.cpp | 35 ++---------------- src/wallet/asyncrpcoperation_sendmany.cpp | 33 ++--------------- .../asyncrpcoperation_shieldcoinbase.cpp | 33 ++--------------- 5 files changed, 62 insertions(+), 92 deletions(-) diff --git a/src/wallet/asyncrpcoperation_common.cpp b/src/wallet/asyncrpcoperation_common.cpp index bdbb0a96ca3..f2deac557af 100644 --- a/src/wallet/asyncrpcoperation_common.cpp +++ b/src/wallet/asyncrpcoperation_common.cpp @@ -2,8 +2,11 @@ #include "core_io.h" #include "init.h" +#include "rpc/protocol.h" #include "wallet.h" +extern UniValue signrawtransaction(const UniValue& params, bool fHelp); + UniValue SendTransaction(CTransaction& tx, bool testmode) { UniValue o(UniValue::VOBJ); // Send the transaction @@ -19,4 +22,37 @@ UniValue SendTransaction(CTransaction& tx, bool testmode) { o.push_back(Pair("hex", EncodeHexTx(tx))); } return o; +} + +std::pair SignSendRawTransaction(UniValue obj, bool testmode) { + // Sign the raw transaction + UniValue rawtxnValue = find_value(obj, "rawtxn"); + if (rawtxnValue.isNull()) { + throw JSONRPCError(RPC_WALLET_ERROR, "Missing hex data for raw transaction"); + } + std::string rawtxn = rawtxnValue.get_str(); + + UniValue params = UniValue(UniValue::VARR); + params.push_back(rawtxn); + UniValue signResultValue = signrawtransaction(params, false); + UniValue signResultObject = signResultValue.get_obj(); + UniValue completeValue = find_value(signResultObject, "complete"); + bool complete = completeValue.get_bool(); + if (!complete) { + // TODO: #1366 Maybe get "errors" and print array vErrors into a string + throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Failed to sign transaction"); + } + + UniValue hexValue = find_value(signResultObject, "hex"); + if (hexValue.isNull()) { + throw JSONRPCError(RPC_WALLET_ERROR, "Missing hex data for signed transaction"); + } + std::string signedtxn = hexValue.get_str(); + CDataStream stream(ParseHex(signedtxn), SER_NETWORK, PROTOCOL_VERSION); + CTransaction tx; + stream >> tx; + + UniValue sendResult = SendTransaction(tx, testmode); + + return std::make_pair(tx, sendResult); } \ No newline at end of file diff --git a/src/wallet/asyncrpcoperation_common.h b/src/wallet/asyncrpcoperation_common.h index 4b65d1f32c1..d22e072a86f 100644 --- a/src/wallet/asyncrpcoperation_common.h +++ b/src/wallet/asyncrpcoperation_common.h @@ -8,6 +8,23 @@ #include "primitives/transaction.h" #include "univalue.h" +/** + * Sends a given transaction. + * + * If testmode is false, commit the transaction to the wallet, + * return {"txid": tx.GetHash().ToString()} + * + * If testmode is true, do not commit the transaction, + * return {"test": 1, "txid": tx.GetHash().ToString(), "hex": EncodeHexTx(tx)} + */ UniValue SendTransaction(CTransaction& tx, bool testmode); +/** + * Sign and send a raw transaction. + * Raw transaction as hex string should be in object field "rawtxn" + * + * Returns a pair of (the parsed transaction, and the result of sending) + */ +std::pair SignSendRawTransaction(UniValue obj, bool testmode); + #endif /* ASYNCRPCOPERATION_COMMON_H */ diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index e7e1084a48c..c551fbe0114 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -720,44 +720,15 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() } -extern UniValue signrawtransaction(const UniValue& params, bool fHelp); - /** * Sign and send a raw transaction. * Raw transaction as hex string should be in object field "rawtxn" */ void AsyncRPCOperation_mergetoaddress::sign_send_raw_transaction(UniValue obj) { - // Sign the raw transaction - UniValue rawtxnValue = find_value(obj, "rawtxn"); - if (rawtxnValue.isNull()) { - throw JSONRPCError(RPC_WALLET_ERROR, "Missing hex data for raw transaction"); - } - std::string rawtxn = rawtxnValue.get_str(); - - UniValue params = UniValue(UniValue::VARR); - params.push_back(rawtxn); - UniValue signResultValue = signrawtransaction(params, false); - UniValue signResultObject = signResultValue.get_obj(); - UniValue completeValue = find_value(signResultObject, "complete"); - bool complete = completeValue.get_bool(); - if (!complete) { - // TODO: #1366 Maybe get "errors" and print array vErrors into a string - throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Failed to sign transaction"); - } - - UniValue hexValue = find_value(signResultObject, "hex"); - if (hexValue.isNull()) { - throw JSONRPCError(RPC_WALLET_ERROR, "Missing hex data for signed transaction"); - } - std::string signedtxn = hexValue.get_str(); - CDataStream stream(ParseHex(signedtxn), SER_NETWORK, PROTOCOL_VERSION); - CTransaction tx; - stream >> tx; - tx_ = tx; - - UniValue sendResult = SendTransaction(tx_, testmode); - set_result(sendResult); + auto txAndResult = SignSendRawTransaction(obj, testmode); + tx_ = txAndResult.first; + set_result(txAndResult.second); } diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index fe04ce351fc..d0b10420302 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -897,36 +897,9 @@ bool AsyncRPCOperation_sendmany::main_impl() { */ void AsyncRPCOperation_sendmany::sign_send_raw_transaction(UniValue obj) { - // Sign the raw transaction - UniValue rawtxnValue = find_value(obj, "rawtxn"); - if (rawtxnValue.isNull()) { - throw JSONRPCError(RPC_WALLET_ERROR, "Missing hex data for raw transaction"); - } - std::string rawtxn = rawtxnValue.get_str(); - - UniValue params = UniValue(UniValue::VARR); - params.push_back(rawtxn); - UniValue signResultValue = signrawtransaction(params, false); - UniValue signResultObject = signResultValue.get_obj(); - UniValue completeValue = find_value(signResultObject, "complete"); - bool complete = completeValue.get_bool(); - if (!complete) { - // TODO: #1366 Maybe get "errors" and print array vErrors into a string - throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Failed to sign transaction"); - } - - UniValue hexValue = find_value(signResultObject, "hex"); - if (hexValue.isNull()) { - throw JSONRPCError(RPC_WALLET_ERROR, "Missing hex data for signed transaction"); - } - std::string signedtxn = hexValue.get_str(); - CDataStream stream(ParseHex(signedtxn), SER_NETWORK, PROTOCOL_VERSION); - CTransaction tx; - stream >> tx; - tx_ = tx; - - UniValue sendResult = SendTransaction(tx_, testmode); - set_result(sendResult); + auto txAndResult = SignSendRawTransaction(obj, testmode); + tx_ = txAndResult.first; + set_result(txAndResult.second); } diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp index f2376780d52..14d9d988b11 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp @@ -278,36 +278,9 @@ bool ShieldToAddress::operator()(const libzcash::InvalidEncoding& no) const { */ void AsyncRPCOperation_shieldcoinbase::sign_send_raw_transaction(UniValue obj) { - // Sign the raw transaction - UniValue rawtxnValue = find_value(obj, "rawtxn"); - if (rawtxnValue.isNull()) { - throw JSONRPCError(RPC_WALLET_ERROR, "Missing hex data for raw transaction"); - } - std::string rawtxn = rawtxnValue.get_str(); - - UniValue params = UniValue(UniValue::VARR); - params.push_back(rawtxn); - UniValue signResultValue = signrawtransaction(params, false); - UniValue signResultObject = signResultValue.get_obj(); - UniValue completeValue = find_value(signResultObject, "complete"); - bool complete = completeValue.get_bool(); - if (!complete) { - // TODO: #1366 Maybe get "errors" and print array vErrors into a string - throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Failed to sign transaction"); - } - - UniValue hexValue = find_value(signResultObject, "hex"); - if (hexValue.isNull()) { - throw JSONRPCError(RPC_WALLET_ERROR, "Missing hex data for signed transaction"); - } - std::string signedtxn = hexValue.get_str(); - CDataStream stream(ParseHex(signedtxn), SER_NETWORK, PROTOCOL_VERSION); - CTransaction tx; - stream >> tx; - tx_ = tx; - - UniValue sendResult = SendTransaction(tx_, testmode); - set_result(sendResult); + auto txAndResult = SignSendRawTransaction(obj, testmode); + tx_ = txAndResult.first; + set_result(txAndResult.second); } From a84125aacd62ef4df79f67b7e8dfd844cb712d1c Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Fri, 10 May 2019 12:58:11 -0600 Subject: [PATCH 079/395] Fix tree depth in comment --- src/gtest/test_merkletree.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gtest/test_merkletree.cpp b/src/gtest/test_merkletree.cpp index 23c39c04467..d55cb13179c 100644 --- a/src/gtest/test_merkletree.cpp +++ b/src/gtest/test_merkletree.cpp @@ -249,7 +249,7 @@ TEST(merkletree, EmptyrootsSapling) { } TEST(merkletree, emptyroot) { - // This literal is the depth-20 empty tree root with the bytes reversed to + // This literal is the depth-29 empty tree root with the bytes reversed to // account for the fact that uint256S() loads a big-endian representation of // an integer which converted to little-endian internally. uint256 expected = uint256S("59d2cde5e65c1414c32ba54f0fe4bdb3d67618125286e6a191317917c812c6d7"); @@ -258,7 +258,7 @@ TEST(merkletree, emptyroot) { } TEST(merkletree, EmptyrootSapling) { - // This literal is the depth-20 empty tree root with the bytes reversed to + // This literal is the depth-32 empty tree root with the bytes reversed to // account for the fact that uint256S() loads a big-endian representation of // an integer which converted to little-endian internally. uint256 expected = uint256S("3e49b5f954aa9d3545bc6c37744661eea48d7c34e3000d82b7f0010c30f4c2fb"); From 7470ae8885cc1a5ede41abab3dab4104d9f0ce91 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Thu, 9 May 2019 11:56:37 -0600 Subject: [PATCH 080/395] Do not automatically remove async migration operations and return txids --- qa/rpc-tests/sprout_sapling_migration.py | 2 ++ src/wallet/asyncrpcoperation_saplingmigration.cpp | 15 +++++++++++---- src/wallet/asyncrpcoperation_saplingmigration.h | 2 +- src/wallet/wallet.cpp | 4 ++-- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/qa/rpc-tests/sprout_sapling_migration.py b/qa/rpc-tests/sprout_sapling_migration.py index c9ef9797a36..de2c68cc83b 100755 --- a/qa/rpc-tests/sprout_sapling_migration.py +++ b/qa/rpc-tests/sprout_sapling_migration.py @@ -87,6 +87,8 @@ def run_migration_test(self, node, sproutAddr, saplingAddr, target_height): assert_equal('saplingmigration', result['method']) assert_equal(target_height, result['target_height']) assert_equal(1, result['result']['num_tx_created']) + assert_equal(1, len(result['result']['migration_txids'])) + assert_true(result['result']['amount_migrated'] > Decimal('0')) assert_equal(0, len(node.getrawmempool()), "mempool size at 495 % 500") diff --git a/src/wallet/asyncrpcoperation_saplingmigration.cpp b/src/wallet/asyncrpcoperation_saplingmigration.cpp index db478f27cb3..465e18ee599 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.cpp +++ b/src/wallet/asyncrpcoperation_saplingmigration.cpp @@ -83,7 +83,7 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { } // If the remaining amount to be migrated is less than 0.01 ZEC, end the migration. if (availableFunds < CENT) { - setMigrationResult(0, 0); + setMigrationResult(0, 0, std::vector()); return true; } @@ -95,6 +95,7 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { // Up to the limit of 5, as many transactions are sent as are needed to migrate the remaining funds int numTxCreated = 0; CAmount amountMigrated = 0; + std::vector migrationTxIds; int noteIndex = 0; CCoinsViewCache coinsView(pcoinsTip); do { @@ -132,17 +133,23 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { } pwalletMain->AddPendingSaplingMigrationTx(tx); ++numTxCreated; - amountMigrated += amountToSend; + amountMigrated += amountToSend - FEE; + migrationTxIds.push_back(tx.GetHash().ToString()); } while (numTxCreated < 5 && availableFunds > CENT); - setMigrationResult(numTxCreated, amountMigrated); + setMigrationResult(numTxCreated, amountMigrated, migrationTxIds); return true; } -void AsyncRPCOperation_saplingmigration::setMigrationResult(int numTxCreated, CAmount amountMigrated) { +void AsyncRPCOperation_saplingmigration::setMigrationResult(int numTxCreated, const CAmount& amountMigrated, const std::vector& migrationTxIds) { UniValue res(UniValue::VOBJ); res.push_back(Pair("num_tx_created", numTxCreated)); res.push_back(Pair("amount_migrated", FormatMoney(amountMigrated))); + UniValue txIds(UniValue::VARR); + for (const std::string& txId : migrationTxIds) { + txIds.push_back(txId); + } + res.push_back(Pair("migration_txids", txIds)); set_result(res); } diff --git a/src/wallet/asyncrpcoperation_saplingmigration.h b/src/wallet/asyncrpcoperation_saplingmigration.h index 64319968f92..6e0c452f932 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.h +++ b/src/wallet/asyncrpcoperation_saplingmigration.h @@ -29,7 +29,7 @@ class AsyncRPCOperation_saplingmigration : public AsyncRPCOperation bool main_impl(); - void setMigrationResult(int numTxCreated, CAmount amountMigrated); + void setMigrationResult(int numTxCreated, const CAmount& amountMigrated, const std::vector& migrationTxIds); CAmount chooseAmount(const CAmount& availableFunds); }; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index bde0eb9d119..23030257a89 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -610,7 +610,7 @@ void CWallet::RunSaplingMigration(int blockHeight) { // height N-5 if (blockHeight % 500 == 495) { std::shared_ptr q = getAsyncRPCQueue(); - std::shared_ptr lastOperation = q->popOperationForId(saplingMigrationOperationId); + std::shared_ptr lastOperation = q->getOperationForId(saplingMigrationOperationId); if (lastOperation != nullptr) { lastOperation->cancel(); } @@ -620,7 +620,7 @@ void CWallet::RunSaplingMigration(int blockHeight) { q->addOperation(operation); } else if (blockHeight % 500 == 499) { std::shared_ptr q = getAsyncRPCQueue(); - std::shared_ptr lastOperation = q->popOperationForId(saplingMigrationOperationId); + std::shared_ptr lastOperation = q->getOperationForId(saplingMigrationOperationId); if (lastOperation != nullptr) { lastOperation->cancel(); } From 58348c79b3415435bbceceafaef64d78563a15f8 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Thu, 9 May 2019 15:13:10 -0600 Subject: [PATCH 081/395] Add logging for Sprout to Sapling migration transaction generation --- .../asyncrpcoperation_saplingmigration.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/wallet/asyncrpcoperation_saplingmigration.cpp b/src/wallet/asyncrpcoperation_saplingmigration.cpp index 465e18ee599..21eddcfecd3 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.cpp +++ b/src/wallet/asyncrpcoperation_saplingmigration.cpp @@ -68,6 +68,7 @@ void AsyncRPCOperation_saplingmigration::main() { } bool AsyncRPCOperation_saplingmigration::main_impl() { + LogPrint("zrpcunsafe", "Beginning AsyncRPCOperation_saplingmigration. id=%s\n", getId()); std::vector sproutEntries; std::vector saplingEntries; { @@ -83,6 +84,8 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { } // If the remaining amount to be migrated is less than 0.01 ZEC, end the migration. if (availableFunds < CENT) { + LogPrint("zrpcunsafe", "%s: Available Sprout balance (%s) less than required minimum (%s). Stopping.\n", + getId(), FormatMoney(availableFunds), FormatMoney(CENT)); setMigrationResult(0, 0, std::vector()); return true; } @@ -102,6 +105,7 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { CAmount amountToSend = chooseAmount(availableFunds); auto builder = TransactionBuilder(consensusParams, targetHeight_, MIGRATION_EXPIRY_DELTA, pwalletMain, pzcashParams, &coinsView, &cs_main); + LogPrint("zrpcunsafe", "%s: Beginning creating transaction with Sapling output amount=%s\n", getId(), amountToSend - FEE); std::vector fromNotes; CAmount fromNoteAmount = 0; while (fromNoteAmount < amountToSend) { @@ -111,6 +115,15 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { } availableFunds -= fromNoteAmount; for (const CSproutNotePlaintextEntry& sproutEntry : fromNotes) { + std::string data(sproutEntry.plaintext.memo().begin(), sproutEntry.plaintext.memo().end()); + LogPrint("zrpcunsafe", "%s: Adding Sprout note input (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, memo=%s)\n", + getId(), + sproutEntry.jsop.hash.ToString().substr(0, 10), + sproutEntry.jsop.js, + int(sproutEntry.jsop.n), // uint8_t + FormatMoney(sproutEntry.plaintext.value()), + HexStr(data).substr(0, 10) + ); libzcash::SproutNote sproutNote = sproutEntry.plaintext.note(sproutEntry.address); libzcash::SproutSpendingKey sproutSk; pwalletMain->GetSproutSpendingKey(sproutEntry.address, sproutSk); @@ -129,14 +142,17 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { builder.AddSaplingOutput(ovkForShieldingFromTaddr(seed), migrationDestAddress, amountToSend - FEE); CTransaction tx = builder.Build().GetTxOrThrow(); if (isCancelled()) { + LogPrint("zrpcunsafe", "%s: Canceled. Stopping.\n"); break; } pwalletMain->AddPendingSaplingMigrationTx(tx); + LogPrint("zrpcunsafe", "%s: Added pending migration transaction with txid=%s\n", getId(), tx.GetHash().ToString()); ++numTxCreated; amountMigrated += amountToSend - FEE; migrationTxIds.push_back(tx.GetHash().ToString()); } while (numTxCreated < 5 && availableFunds > CENT); + LogPrint("zrpcunsafe", "%s: Created %d transactions with total Sapling output amount=%s\n", getId(), numTxCreated, FormatMoney(amountMigrated)); setMigrationResult(numTxCreated, amountMigrated, migrationTxIds); return true; } From 23d9826ef9d1425ded14b54575beffe5b4ab57e1 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Fri, 10 May 2019 13:29:50 -0600 Subject: [PATCH 082/395] Fix LogPrint statements --- qa/rpc-tests/sprout_sapling_migration.py | 5 +++-- src/wallet/asyncrpcoperation_mergetoaddress.cpp | 2 +- src/wallet/asyncrpcoperation_saplingmigration.cpp | 8 ++++---- src/wallet/asyncrpcoperation_sendmany.cpp | 4 ++-- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/qa/rpc-tests/sprout_sapling_migration.py b/qa/rpc-tests/sprout_sapling_migration.py index de2c68cc83b..03e1ccde77c 100755 --- a/qa/rpc-tests/sprout_sapling_migration.py +++ b/qa/rpc-tests/sprout_sapling_migration.py @@ -45,9 +45,10 @@ def setup_nodes(self): # Add migration parameters to nodes[0] extra_args[0] = extra_args[0] + [ '-migration', - '-migrationdestaddress=' + SAPLING_ADDR + '-migrationdestaddress=' + SAPLING_ADDR, + '-debug=zrpcunsafe' ] - assert_equal(4, len(extra_args[0])) + assert_equal(5, len(extra_args[0])) assert_equal(2, len(extra_args[1])) return start_nodes(4, self.options.tmpdir, extra_args) diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index b3870e6029d..0e5dd34096e 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -645,7 +645,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() wtxHeight = mapBlockIndex[wtx.hashBlock]->nHeight; wtxDepth = wtx.GetDepthInMainChain(); } - LogPrint("zrpcunsafe", "%s: spending note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, height=%d, confirmations=%d)\n", + LogPrint("zrpcunsafe", "%s: spending note (txid=%s, vjoinsplit=%d, jsoutindex=%d, amount=%s, height=%d, confirmations=%d)\n", getId(), jso.hash.ToString().substr(0, 10), jso.js, diff --git a/src/wallet/asyncrpcoperation_saplingmigration.cpp b/src/wallet/asyncrpcoperation_saplingmigration.cpp index 21eddcfecd3..8e1dda6159a 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.cpp +++ b/src/wallet/asyncrpcoperation_saplingmigration.cpp @@ -68,7 +68,7 @@ void AsyncRPCOperation_saplingmigration::main() { } bool AsyncRPCOperation_saplingmigration::main_impl() { - LogPrint("zrpcunsafe", "Beginning AsyncRPCOperation_saplingmigration. id=%s\n", getId()); + LogPrint("zrpcunsafe", "%s: Beginning AsyncRPCOperation_saplingmigration.\n", getId()); std::vector sproutEntries; std::vector saplingEntries; { @@ -105,7 +105,7 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { CAmount amountToSend = chooseAmount(availableFunds); auto builder = TransactionBuilder(consensusParams, targetHeight_, MIGRATION_EXPIRY_DELTA, pwalletMain, pzcashParams, &coinsView, &cs_main); - LogPrint("zrpcunsafe", "%s: Beginning creating transaction with Sapling output amount=%s\n", getId(), amountToSend - FEE); + LogPrint("zrpcunsafe", "%s: Beginning creating transaction with Sapling output amount=%s\n", getId(), FormatMoney(amountToSend - FEE)); std::vector fromNotes; CAmount fromNoteAmount = 0; while (fromNoteAmount < amountToSend) { @@ -116,7 +116,7 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { availableFunds -= fromNoteAmount; for (const CSproutNotePlaintextEntry& sproutEntry : fromNotes) { std::string data(sproutEntry.plaintext.memo().begin(), sproutEntry.plaintext.memo().end()); - LogPrint("zrpcunsafe", "%s: Adding Sprout note input (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, memo=%s)\n", + LogPrint("zrpcunsafe", "%s: Adding Sprout note input (txid=%s, vjoinsplit=%d, jsoutindex=%d, amount=%s, memo=%s)\n", getId(), sproutEntry.jsop.hash.ToString().substr(0, 10), sproutEntry.jsop.js, @@ -142,7 +142,7 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { builder.AddSaplingOutput(ovkForShieldingFromTaddr(seed), migrationDestAddress, amountToSend - FEE); CTransaction tx = builder.Build().GetTxOrThrow(); if (isCancelled()) { - LogPrint("zrpcunsafe", "%s: Canceled. Stopping.\n"); + LogPrint("zrpcunsafe", "%s: Canceled. Stopping.\n", getId()); break; } pwalletMain->AddPendingSaplingMigrationTx(tx); diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index e30c0748373..93ec59b539f 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -784,7 +784,7 @@ bool AsyncRPCOperation_sendmany::main_impl() { wtxHeight = mapBlockIndex[wtx.hashBlock]->nHeight; wtxDepth = wtx.GetDepthInMainChain(); } - LogPrint("zrpcunsafe", "%s: spending note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, height=%d, confirmations=%d)\n", + LogPrint("zrpcunsafe", "%s: spending note (txid=%s, vjoinsplit=%d, jsoutindex=%d, amount=%s, height=%d, confirmations=%d)\n", getId(), jso.hash.ToString().substr(0, 10), jso.js, @@ -1048,7 +1048,7 @@ bool AsyncRPCOperation_sendmany::find_unspent_notes() { for (CSproutNotePlaintextEntry & entry : sproutEntries) { z_sprout_inputs_.push_back(SendManyInputJSOP(entry.jsop, entry.plaintext.note(boost::get(frompaymentaddress_)), CAmount(entry.plaintext.value()))); std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end()); - LogPrint("zrpcunsafe", "%s: found unspent Sprout note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, memo=%s)\n", + LogPrint("zrpcunsafe", "%s: found unspent Sprout note (txid=%s, vjoinsplit=%d, jsoutindex=%d, amount=%s, memo=%s)\n", getId(), entry.jsop.hash.ToString().substr(0, 10), entry.jsop.js, From 5d1da630a24f06da5a798aa62629d03b83dc793c Mon Sep 17 00:00:00 2001 From: zebambam Date: Tue, 14 May 2019 07:51:08 -0700 Subject: [PATCH 083/395] Fixes #4013, added BitcoinABC as a disclosure partner --- responsible_disclosure.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/responsible_disclosure.md b/responsible_disclosure.md index 1f3c9401bba..718cf42d9c0 100644 --- a/responsible_disclosure.md +++ b/responsible_disclosure.md @@ -51,8 +51,9 @@ We have set up agreements with the following neighboring projects to share vulne Specifically, we have agreed to engage in responsible disclosures for security issues affecting Zcash technology with the following contacts: -- security@horizen.com via PGP -- ca333@komodoplatform.com via PGP +- Horizen security@horizen.com via PGP +- Komodo ca333@komodoplatform.com via PGP +- BitcoinABC https://github.com/Bitcoin-ABC/bitcoin-abc/blob/master/DISCLOSURE_POLICY.md ## Deviations from the Standard From 8c82f8f72f7a9ad690ea1d4ab6efb86067d831f3 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Tue, 14 May 2019 11:24:19 -0600 Subject: [PATCH 084/395] Notable changes for v2.0.5-2 --- doc/release-notes.md | 48 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index a29094b5174..1b6f60c88f5 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,3 +4,51 @@ release-notes at release time) Notable changes =============== +Sprout to Sapling Migration Tool +-------------------------------- +This release includes the addition of a tool that will enable users to migrate +shielded funds from the Sprout pool to the Sapling pool while minimizing +information leakage. + +The migration can be enabled using the RPC `z_setmigration` or by including +`migration=1` in the `zcash.conf` file. Unless otherwise specified funds will be +migrated to the wallet's default Sapling address; it is also possible to set the +receiving Sapling address using the `migrationdestaddress=` option in +`zcash.conf`. + +See [ZIP308](https://github.com/zcash/zips/blob/master/zip-0308.rst) for full details. + +Sprout to Sapling Migration Tool Fixes +-------------------------------------- +The 2.0.5-1 and 2.0.5-2 releases include fixes to the Sprout to Sapling +Migration Tool found in testing. For a complete list see the [2.0.5 milestone](https://github.com/zcash/zcash/milestone/79?closed=1) + +New consensus rule: Reject blocks that violate turnstile +-------------------------------------------------------- +In the 2.0.4 release the consensus rules were changed on testnet to enforce a +consensus rule which marks blocks as invalid if they would lead to a turnstile +violation in the Sprout or Shielded value pools. +**This release enforces the consensus rule change on mainnet** + +The motivations and deployment details can be found in the accompanying +[ZIP draft](https://github.com/zcash/zips/pull/210) and +[PR 3968](https://github.com/zcash/zcash/pull/3968). + +Developers can use a new experimental feature `-developersetpoolsizezero` to test +Sprout and Sapling turnstile violations. See [PR 3964](https://github.com/zcash/zcash/pull/3964) for more details. + +64-bit ARMv8 support +-------------------- +Added ARMv8 (AArch64) support. This enables users to build zcash on even more +devices. + +For information on how to build see the [User Guide](https://zcash.readthedocs.io/en/latest/rtd_pages/user_guide.html#build) + +Users on the Zcash forum have reported successes with both the Pine64 Rock64Pro +and Odroid C2 which contain 4GB and 2GB of RAM respectively. + +Just released, the Odroid N2 looks like a great solution with 4GB of RAM. The +newly released Jetson Nano Developer Kit from Nvidia (also 4GB of RAM) is also +worth a look. The NanoPC-T3 Plus is another option but for the simplest/best +experience choose a board with 4GB of RAM. Just make sure before purchase that +the CPU supports the 64-bit ARMv8 architecture. From 44905b21da1a88209fa033fe81954303fce38dbd Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Tue, 14 May 2019 13:31:25 -0600 Subject: [PATCH 085/395] Release notes wording and punctuation --- doc/release-notes.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index 1b6f60c88f5..560a5e43761 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -21,14 +21,16 @@ See [ZIP308](https://github.com/zcash/zips/blob/master/zip-0308.rst) for full de Sprout to Sapling Migration Tool Fixes -------------------------------------- The 2.0.5-1 and 2.0.5-2 releases include fixes to the Sprout to Sapling -Migration Tool found in testing. For a complete list see the [2.0.5 milestone](https://github.com/zcash/zcash/milestone/79?closed=1) +Migration Tool found in testing. + +For a complete list of changes in 2.0.5, 2.0.5-1 and 2.0.5-2, see the [2.0.5 milestone](https://github.com/zcash/zcash/milestone/79?closed=1). New consensus rule: Reject blocks that violate turnstile -------------------------------------------------------- In the 2.0.4 release the consensus rules were changed on testnet to enforce a consensus rule which marks blocks as invalid if they would lead to a turnstile violation in the Sprout or Shielded value pools. -**This release enforces the consensus rule change on mainnet** +**This release enforces the consensus rule change on mainnet.** The motivations and deployment details can be found in the accompanying [ZIP draft](https://github.com/zcash/zips/pull/210) and @@ -42,7 +44,7 @@ Sprout and Sapling turnstile violations. See [PR 3964](https://github.com/zcash/ Added ARMv8 (AArch64) support. This enables users to build zcash on even more devices. -For information on how to build see the [User Guide](https://zcash.readthedocs.io/en/latest/rtd_pages/user_guide.html#build) +For information on how to build see the [User Guide](https://zcash.readthedocs.io/en/latest/rtd_pages/user_guide.html#build). Users on the Zcash forum have reported successes with both the Pine64 Rock64Pro and Odroid C2 which contain 4GB and 2GB of RAM respectively. From c34d253fa67bac1479123e6af20c084340a31e2d Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Wed, 15 May 2019 09:49:44 -0600 Subject: [PATCH 086/395] make-release.py: Versioning changes for 2.0.5-2. --- README.md | 2 +- configure.ac | 2 +- contrib/gitian-descriptors/gitian-linux.yml | 2 +- src/clientversion.h | 2 +- src/deprecation.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 5d6c06c6104..7d02cf0d349 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Zcash 2.0.5-1 +Zcash 2.0.5-2 =========== diff --git a/configure.ac b/configure.ac index 0dc14ccbe9a..a78439eda44 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 2) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_REVISION, 5) -define(_CLIENT_VERSION_BUILD, 51) +define(_CLIENT_VERSION_BUILD, 52) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index f0e40fd4082..edc714f1074 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "zcash-2.0.5-1" +name: "zcash-2.0.5-2" enable_cache: true distro: "debian" suites: diff --git a/src/clientversion.h b/src/clientversion.h index 5e6b49a9d5d..2455c56b48e 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -18,7 +18,7 @@ #define CLIENT_VERSION_MAJOR 2 #define CLIENT_VERSION_MINOR 0 #define CLIENT_VERSION_REVISION 5 -#define CLIENT_VERSION_BUILD 51 +#define CLIENT_VERSION_BUILD 52 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/deprecation.h b/src/deprecation.h index a0dd736bcef..13c752c426e 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -8,7 +8,7 @@ // Deprecation policy: // * Shut down 16 weeks' worth of blocks after the estimated release block height. // * A warning is shown during the 2 weeks' worth of blocks prior to shut down. -static const int APPROX_RELEASE_HEIGHT = 529250; +static const int APPROX_RELEASE_HEIGHT = 533500; static const int WEEKS_UNTIL_DEPRECATION = 16; static const int DEPRECATION_HEIGHT = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 24); From 3fc90655bf8bb4a189c1c64225efe8f6d2e4eb9f Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Wed, 15 May 2019 09:56:01 -0600 Subject: [PATCH 087/395] make-release.py: Updated manpages for 2.0.5-2. --- doc/man/zcash-cli.1 | 6 +++--- doc/man/zcash-tx.1 | 6 +++--- doc/man/zcashd.1 | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/man/zcash-cli.1 b/doc/man/zcash-cli.1 index a13df414a5a..c2f1b3447ff 100644 --- a/doc/man/zcash-cli.1 +++ b/doc/man/zcash-cli.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-CLI "1" "May 2019" "zcash-cli v2.0.5-1" "User Commands" +.TH ZCASH-CLI "1" "May 2019" "zcash-cli v2.0.5-2" "User Commands" .SH NAME -zcash-cli \- manual page for zcash-cli v2.0.5-1 +zcash-cli \- manual page for zcash-cli v2.0.5-2 .SH DESCRIPTION -Zcash RPC client version v2.0.5\-1 +Zcash RPC client version v2.0.5\-2 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . diff --git a/doc/man/zcash-tx.1 b/doc/man/zcash-tx.1 index fc0810578fd..effac79bb36 100644 --- a/doc/man/zcash-tx.1 +++ b/doc/man/zcash-tx.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-TX "1" "May 2019" "zcash-tx v2.0.5-1" "User Commands" +.TH ZCASH-TX "1" "May 2019" "zcash-tx v2.0.5-2" "User Commands" .SH NAME -zcash-tx \- manual page for zcash-tx v2.0.5-1 +zcash-tx \- manual page for zcash-tx v2.0.5-2 .SH DESCRIPTION -Zcash zcash\-tx utility version v2.0.5\-1 +Zcash zcash\-tx utility version v2.0.5\-2 .SS "Usage:" .TP zcash\-tx [options] [commands] diff --git a/doc/man/zcashd.1 b/doc/man/zcashd.1 index f47b35710ee..73d50333e6d 100644 --- a/doc/man/zcashd.1 +++ b/doc/man/zcashd.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASHD "1" "May 2019" "zcashd v2.0.5-1" "User Commands" +.TH ZCASHD "1" "May 2019" "zcashd v2.0.5-2" "User Commands" .SH NAME -zcashd \- manual page for zcashd v2.0.5-1 +zcashd \- manual page for zcashd v2.0.5-2 .SH DESCRIPTION -Zcash Daemon version v2.0.5\-1 +Zcash Daemon version v2.0.5\-2 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . From c75fb97d3af5f0721d82289ab59a89ba2d05e4e7 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Wed, 15 May 2019 09:56:01 -0600 Subject: [PATCH 088/395] make-release.py: Updated release notes and changelog for 2.0.5-2. --- contrib/debian/changelog | 6 ++ doc/authors.md | 6 +- doc/release-notes.md | 50 -------------- doc/release-notes/release-notes-2.0.5-2.md | 77 ++++++++++++++++++++++ 4 files changed, 86 insertions(+), 53 deletions(-) create mode 100644 doc/release-notes/release-notes-2.0.5-2.md diff --git a/contrib/debian/changelog b/contrib/debian/changelog index 3814043023d..f48b6e7b6df 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,9 @@ +zcash (2.0.5+2) stable; urgency=medium + + * 2.0.5-2 release. + + -- Electric Coin Company Wed, 15 May 2019 09:56:01 -0600 + zcash (2.0.5+1) stable; urgency=medium * 2.0.5-1 release. diff --git a/doc/authors.md b/doc/authors.md index c196c34a06e..72d50f96b7e 100644 --- a/doc/authors.md +++ b/doc/authors.md @@ -2,9 +2,9 @@ Zcash Contributors ================== Jack Grigg (863) -Simon Liu (448) +Simon Liu (450) Sean Bowe (278) -Daira Hopwood (110) +Daira Hopwood (115) Eirik Ogilvie-Wigley (102) Jay Graber (89) Wladimir J. van der Laan (81) @@ -12,8 +12,8 @@ Taylor Hornby (73) Jonas Schnelli (62) Nathan Wilcox (56) Pieter Wuille (54) +Eirik0 (43) Kevin Gallagher (38) -Eirik0 (36) Cory Fields (35) mdr0id (22) Larry Ruane (22) diff --git a/doc/release-notes.md b/doc/release-notes.md index 560a5e43761..a29094b5174 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,53 +4,3 @@ release-notes at release time) Notable changes =============== -Sprout to Sapling Migration Tool --------------------------------- -This release includes the addition of a tool that will enable users to migrate -shielded funds from the Sprout pool to the Sapling pool while minimizing -information leakage. - -The migration can be enabled using the RPC `z_setmigration` or by including -`migration=1` in the `zcash.conf` file. Unless otherwise specified funds will be -migrated to the wallet's default Sapling address; it is also possible to set the -receiving Sapling address using the `migrationdestaddress=` option in -`zcash.conf`. - -See [ZIP308](https://github.com/zcash/zips/blob/master/zip-0308.rst) for full details. - -Sprout to Sapling Migration Tool Fixes --------------------------------------- -The 2.0.5-1 and 2.0.5-2 releases include fixes to the Sprout to Sapling -Migration Tool found in testing. - -For a complete list of changes in 2.0.5, 2.0.5-1 and 2.0.5-2, see the [2.0.5 milestone](https://github.com/zcash/zcash/milestone/79?closed=1). - -New consensus rule: Reject blocks that violate turnstile --------------------------------------------------------- -In the 2.0.4 release the consensus rules were changed on testnet to enforce a -consensus rule which marks blocks as invalid if they would lead to a turnstile -violation in the Sprout or Shielded value pools. -**This release enforces the consensus rule change on mainnet.** - -The motivations and deployment details can be found in the accompanying -[ZIP draft](https://github.com/zcash/zips/pull/210) and -[PR 3968](https://github.com/zcash/zcash/pull/3968). - -Developers can use a new experimental feature `-developersetpoolsizezero` to test -Sprout and Sapling turnstile violations. See [PR 3964](https://github.com/zcash/zcash/pull/3964) for more details. - -64-bit ARMv8 support --------------------- -Added ARMv8 (AArch64) support. This enables users to build zcash on even more -devices. - -For information on how to build see the [User Guide](https://zcash.readthedocs.io/en/latest/rtd_pages/user_guide.html#build). - -Users on the Zcash forum have reported successes with both the Pine64 Rock64Pro -and Odroid C2 which contain 4GB and 2GB of RAM respectively. - -Just released, the Odroid N2 looks like a great solution with 4GB of RAM. The -newly released Jetson Nano Developer Kit from Nvidia (also 4GB of RAM) is also -worth a look. The NanoPC-T3 Plus is another option but for the simplest/best -experience choose a board with 4GB of RAM. Just make sure before purchase that -the CPU supports the 64-bit ARMv8 architecture. diff --git a/doc/release-notes/release-notes-2.0.5-2.md b/doc/release-notes/release-notes-2.0.5-2.md new file mode 100644 index 00000000000..6e65ee083fc --- /dev/null +++ b/doc/release-notes/release-notes-2.0.5-2.md @@ -0,0 +1,77 @@ +Notable changes +=============== + +Sprout to Sapling Migration Tool +-------------------------------- +This release includes the addition of a tool that will enable users to migrate +shielded funds from the Sprout pool to the Sapling pool while minimizing +information leakage. + +The migration can be enabled using the RPC `z_setmigration` or by including +`migration=1` in the `zcash.conf` file. Unless otherwise specified funds will be +migrated to the wallet's default Sapling address; it is also possible to set the +receiving Sapling address using the `migrationdestaddress=` option in +`zcash.conf`. + +See [ZIP308](https://github.com/zcash/zips/blob/master/zip-0308.rst) for full details. + +Sprout to Sapling Migration Tool Fixes +-------------------------------------- +The 2.0.5-1 and 2.0.5-2 releases include fixes to the Sprout to Sapling +Migration Tool found in testing. + +For a complete list of changes in 2.0.5, 2.0.5-1 and 2.0.5-2, see the [2.0.5 milestone](https://github.com/zcash/zcash/milestone/79?closed=1). + +New consensus rule: Reject blocks that violate turnstile +-------------------------------------------------------- +In the 2.0.4 release the consensus rules were changed on testnet to enforce a +consensus rule which marks blocks as invalid if they would lead to a turnstile +violation in the Sprout or Shielded value pools. +**This release enforces the consensus rule change on mainnet.** + +The motivations and deployment details can be found in the accompanying +[ZIP draft](https://github.com/zcash/zips/pull/210) and +[PR 3968](https://github.com/zcash/zcash/pull/3968). + +Developers can use a new experimental feature `-developersetpoolsizezero` to test +Sprout and Sapling turnstile violations. See [PR 3964](https://github.com/zcash/zcash/pull/3964) for more details. + +64-bit ARMv8 support +-------------------- +Added ARMv8 (AArch64) support. This enables users to build zcash on even more +devices. + +For information on how to build see the [User Guide](https://zcash.readthedocs.io/en/latest/rtd_pages/user_guide.html#build). + +Users on the Zcash forum have reported successes with both the Pine64 Rock64Pro +and Odroid C2 which contain 4GB and 2GB of RAM respectively. + +Just released, the Odroid N2 looks like a great solution with 4GB of RAM. The +newly released Jetson Nano Developer Kit from Nvidia (also 4GB of RAM) is also +worth a look. The NanoPC-T3 Plus is another option but for the simplest/best +experience choose a board with 4GB of RAM. Just make sure before purchase that +the CPU supports the 64-bit ARMv8 architecture. + +Changelog +========= + +Daira Hopwood (5): + Generalize TransactionBuilder and CreateNewContextualCMutableTransaction to allow choosing the expiry delta. + Repair calls to TransactionBuilder from tests. + Change expiry delta for migration transactions to 450 blocks. + Test the expiry height of migration transactions. + Fix cosmetic spacing issue in z_setmigration help. + +Eirik0 (7): + Do not automatically remove async migration operations and return txids + Add logging for Sprout to Sapling migration transaction generation + Fix LogPrint statements + Notable changes for v2.0.5-2 + Release notes wording and punctuation + make-release.py: Versioning changes for 2.0.5-2. + make-release.py: Updated manpages for 2.0.5-2. + +Simon Liu (2): + Remove unused specifier from format string. + Don't allow migration when node is syncing at launch or after waking up. + From 408a1229521593adc7a678d0fd6b02b66de2d854 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Wed, 15 May 2019 10:45:25 -0600 Subject: [PATCH 089/395] Update ZIP reference --- doc/release-notes/release-notes-2.0.5-2.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/release-notes/release-notes-2.0.5-2.md b/doc/release-notes/release-notes-2.0.5-2.md index 6e65ee083fc..8d7dc947afd 100644 --- a/doc/release-notes/release-notes-2.0.5-2.md +++ b/doc/release-notes/release-notes-2.0.5-2.md @@ -29,8 +29,8 @@ consensus rule which marks blocks as invalid if they would lead to a turnstile violation in the Sprout or Shielded value pools. **This release enforces the consensus rule change on mainnet.** -The motivations and deployment details can be found in the accompanying -[ZIP draft](https://github.com/zcash/zips/pull/210) and +The motivations and deployment details can be found in +[ZIP209](https://github.com/zcash/zips/blob/master/zip-0209.rst) and [PR 3968](https://github.com/zcash/zcash/pull/3968). Developers can use a new experimental feature `-developersetpoolsizezero` to test From 831611edd36efa4dc0e3fc311e4df069827514a7 Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 15 May 2019 11:06:37 -0700 Subject: [PATCH 090/395] Fix typo and clean up help message for RPC z_getmigrationstatus. --- src/wallet/rpcwallet.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 2fc71bbf445..d9836a95820 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3937,8 +3937,7 @@ UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) { throw runtime_error( "z_getmigrationstatus\n" "Returns information about the status of the Sprout to Sapling migration.\n" - "In the result a transactions is defined as finalized if and only if it has\n" - "at least ten confirmations.\n" + "A transaction is defined as finalized if it has at least ten confirmations.\n" "Note: It is possible that manually created transactions involving this wallet\n" "will be included in the result.\n" "\nResult:\n" From 5222c39cd03cb5e4d3fe1b4af581d36cd22b47b3 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 22 May 2019 10:46:21 +0000 Subject: [PATCH 091/395] depends: Add FreeBSD to hosts and builders --- depends/Makefile | 2 ++ depends/builders/freebsd.mk | 2 ++ depends/hosts/freebsd.mk | 31 +++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 depends/builders/freebsd.mk create mode 100644 depends/hosts/freebsd.mk diff --git a/depends/Makefile b/depends/Makefile index 5c1fb9fdd34..e18ee7072b1 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -38,6 +38,7 @@ build_vendor=$(word 2,$(subst -, ,$(build))) full_build_os:=$(subst $(build_arch)-$(build_vendor)-,,$(build)) build_os:=$(findstring linux,$(full_build_os)) build_os+=$(findstring darwin,$(full_build_os)) +build_os+=$(findstring freebsd,$(full_build_os)) build_os:=$(strip $(build_os)) ifeq ($(build_os),) build_os=$(full_build_os) @@ -48,6 +49,7 @@ host_vendor=$(word 2,$(subst -, ,$(canonical_host))) full_host_os:=$(subst $(host_arch)-$(host_vendor)-,,$(canonical_host)) host_os:=$(findstring linux,$(full_host_os)) host_os+=$(findstring darwin,$(full_host_os)) +host_os+=$(findstring freebsd,$(full_host_os)) host_os+=$(findstring mingw32,$(full_host_os)) host_os:=$(strip $(host_os)) ifeq ($(host_os),) diff --git a/depends/builders/freebsd.mk b/depends/builders/freebsd.mk new file mode 100644 index 00000000000..fb2fefe2a2e --- /dev/null +++ b/depends/builders/freebsd.mk @@ -0,0 +1,2 @@ +build_freebsd_SHA256SUM = shasum -a 256 +build_freebsd_DOWNLOAD = curl --location --fail --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -o diff --git a/depends/hosts/freebsd.mk b/depends/hosts/freebsd.mk new file mode 100644 index 00000000000..07436aef86e --- /dev/null +++ b/depends/hosts/freebsd.mk @@ -0,0 +1,31 @@ +freebsd_CFLAGS=-pipe +freebsd_CXXFLAGS=$(freebsd_CFLAGS) + +freebsd_release_CFLAGS=-O1 +freebsd_release_CXXFLAGS=$(freebsd_release_CFLAGS) + +freebsd_debug_CFLAGS=-O1 +freebsd_debug_CXXFLAGS=$(freebsd_debug_CFLAGS) + +freebsd_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC + +ifeq (86,$(findstring 86,$(build_arch))) +i686_freebsd_CC=gcc -m32 +i686_freebsd_CXX=g++ -m32 +i686_freebsd_AR=ar +i686_freebsd_RANLIB=ranlib +i686_freebsd_NM=nm +i686_freebsd_STRIP=strip + +x86_64_freebsd_CC=gcc -m64 +x86_64_freebsd_CXX=g++ -m64 +x86_64_freebsd_AR=ar +x86_64_freebsd_RANLIB=ranlib +x86_64_freebsd_NM=nm +x86_64_freebsd_STRIP=strip +else +i686_freebsd_CC=$(default_host_CC) -m32 +i686_freebsd_CXX=$(default_host_CXX) -m32 +x86_64_freebsd_CC=$(default_host_CC) -m64 +x86_64_freebsd_CXX=$(default_host_CXX) -m64 +endif From 734e594c2c53c2fb9331ecf1890ffa240f39d257 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 22 May 2019 10:53:53 +0000 Subject: [PATCH 092/395] depends: Explicitly set Boost toolchain during configuration --- depends/packages/boost.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index a5c90cece97..2df3ebbcbf5 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -29,7 +29,7 @@ define $(package)_preprocess_cmds endef define $(package)_config_cmds - ./bootstrap.sh --without-icu --with-libraries=$(boost_config_libraries) + ./bootstrap.sh --without-icu --with-toolset=$($(package)_toolset_$(host_os)) --with-libraries=$(boost_config_libraries) endef define $(package)_build_cmds From dc0c977906d2d3b8da343a0baf9bb263ef432a1c Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 22 May 2019 11:03:42 +0000 Subject: [PATCH 093/395] depends: Add FreeBSD support to OpenSSL --- depends/packages/openssl.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/depends/packages/openssl.mk b/depends/packages/openssl.mk index a1d5439aa55..05b190ae324 100644 --- a/depends/packages/openssl.mk +++ b/depends/packages/openssl.mk @@ -87,6 +87,8 @@ $(package)_config_opts_mipsel_linux=linux-generic32 $(package)_config_opts_mips_linux=linux-generic32 $(package)_config_opts_powerpc_linux=linux-generic32 $(package)_config_opts_x86_64_darwin=darwin64-x86_64-cc +$(package)_config_opts_x86_64_freebsd=BSD-x86_64 +$(package)_config_opts_i686_freebsd=BSD-generic32 $(package)_config_opts_x86_64_mingw32=mingw64 $(package)_config_opts_i686_mingw32=mingw endef From bfc997c32e3e24d95acc25c382d45f993d688390 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 22 May 2019 11:37:56 +0000 Subject: [PATCH 094/395] depends: Patch libevent to detect arch4random_addrandom See details in https://github.com/libevent/libevent/issues/615. The patches can be dropped after we move to the next stable release. --- depends/packages/libevent.mk | 3 + .../detect-arch4random_addrandom-fix.patch | 43 +++++++++++ .../detect-arch4random_addrandom.patch | 77 +++++++++++++++++++ 3 files changed, 123 insertions(+) create mode 100644 depends/patches/libevent/detect-arch4random_addrandom-fix.patch create mode 100644 depends/patches/libevent/detect-arch4random_addrandom.patch diff --git a/depends/packages/libevent.mk b/depends/packages/libevent.mk index 2a1125fda25..6c54123c76c 100644 --- a/depends/packages/libevent.mk +++ b/depends/packages/libevent.mk @@ -4,8 +4,11 @@ $(package)_download_path=https://github.com/libevent/libevent/archive/ $(package)_file_name=$(package)-$($(package)_version).tar.gz $(package)_download_file=release-$($(package)_version)-stable.tar.gz $(package)_sha256_hash=316ddb401745ac5d222d7c529ef1eada12f58f6376a66c1118eee803cb70f83d +$(package)_patches=detect-arch4random_addrandom.patch detect-arch4random_addrandom-fix.patch define $(package)_preprocess_cmds + patch -p1 <$($(package)_patch_dir)/detect-arch4random_addrandom.patch && \ + patch -p1 <$($(package)_patch_dir)/detect-arch4random_addrandom-fix.patch && \ ./autogen.sh endef diff --git a/depends/patches/libevent/detect-arch4random_addrandom-fix.patch b/depends/patches/libevent/detect-arch4random_addrandom-fix.patch new file mode 100644 index 00000000000..69e55bf1109 --- /dev/null +++ b/depends/patches/libevent/detect-arch4random_addrandom-fix.patch @@ -0,0 +1,43 @@ +From 266f43af7798befa3d27bfabaa9ae699259c3924 Mon Sep 17 00:00:00 2001 +From: Azat Khuzhin +Date: Mon, 27 Mar 2017 15:50:23 +0300 +Subject: [PATCH] Fix arc4random_addrandom() detecting and fallback + (regression) + +But this is kind of hot-fix, we definitelly need more sane arc4random +compat layer. + +Fixes: #488 +Introduced-in: 6541168 ("Detect arch4random_addrandom() existence") +--- + event-config.h.cmake | 3 +++ + include/event2/util.h | 2 +- + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/event-config.h.cmake b/event-config.h.cmake +index b7f0be57c..5c233a3d9 100644 +--- a/event-config.h.cmake ++++ b/event-config.h.cmake +@@ -53,6 +53,9 @@ + /* Define to 1 if you have the `arc4random_buf' function. */ + #cmakedefine EVENT__HAVE_ARC4RANDOM_BUF 1 + ++/* Define to 1 if you have the `arc4random_addrandom' function. */ ++#cmakedefine EVENT__HAVE_ARC4RANDOM_ADDRANDOM 1 ++ + /* Define if clock_gettime is available in libc */ + #cmakedefine EVENT__DNS_USE_CPU_CLOCK_FOR_ID 1 + +diff --git a/include/event2/util.h b/include/event2/util.h +index c4af2bd60..ca4048944 100644 +--- a/include/event2/util.h ++++ b/include/event2/util.h +@@ -842,7 +842,7 @@ int evutil_secure_rng_init(void); + EVENT2_EXPORT_SYMBOL + int evutil_secure_rng_set_urandom_device_file(char *fname); + +-#ifdef EVENT__HAVE_ARC4RANDOM_ADDRANDOM ++#if !defined(EVENT__HAVE_ARC4RANDOM) || defined(EVENT__HAVE_ARC4RANDOM_ADDRANDOM) + /** Seed the random number generator with extra random bytes. + + You should almost never need to call this function; it should be diff --git a/depends/patches/libevent/detect-arch4random_addrandom.patch b/depends/patches/libevent/detect-arch4random_addrandom.patch new file mode 100644 index 00000000000..f8f2b947d23 --- /dev/null +++ b/depends/patches/libevent/detect-arch4random_addrandom.patch @@ -0,0 +1,77 @@ +From 6541168d7037457b8e5c51cc354f11bd94e618b6 Mon Sep 17 00:00:00 2001 +From: Marek Sebera +Date: Mon, 6 Mar 2017 00:55:16 +0300 +Subject: [PATCH] Detect arch4random_addrandom() existence + +Refs: #370 +Refs: #475 +--- + CMakeLists.txt | 1 + + configure.ac | 1 + + evutil_rand.c | 2 ++ + include/event2/util.h | 2 ++ + 4 files changed, 6 insertions(+) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index a861e7d96..f609d02d0 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -338,6 +338,7 @@ CHECK_FUNCTION_EXISTS_EX(sysctl EVENT__HAVE_SYSCTL) + CHECK_FUNCTION_EXISTS_EX(accept4 EVENT__HAVE_ACCEPT4) + CHECK_FUNCTION_EXISTS_EX(arc4random EVENT__HAVE_ARC4RANDOM) + CHECK_FUNCTION_EXISTS_EX(arc4random_buf EVENT__HAVE_ARC4RANDOM_BUF) ++CHECK_FUNCTION_EXISTS_EX(arc4random_addrandom EVENT__HAVE_ARC4RANDOM_ADDRANDOM) + CHECK_FUNCTION_EXISTS_EX(epoll_create1 EVENT__HAVE_EPOLL_CREATE1) + CHECK_FUNCTION_EXISTS_EX(getegid EVENT__HAVE_GETEGID) + CHECK_FUNCTION_EXISTS_EX(geteuid EVENT__HAVE_GETEUID) +diff --git a/configure.ac b/configure.ac +index a127bbc91..e73c29b14 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -342,6 +342,7 @@ AC_CHECK_FUNCS([ \ + accept4 \ + arc4random \ + arc4random_buf \ ++ arc4random_addrandom \ + eventfd \ + epoll_create1 \ + fcntl \ +diff --git a/evutil_rand.c b/evutil_rand.c +index 046a14b07..4be0b1c5e 100644 +--- a/evutil_rand.c ++++ b/evutil_rand.c +@@ -192,12 +192,14 @@ evutil_secure_rng_get_bytes(void *buf, size_t n) + ev_arc4random_buf(buf, n); + } + ++#if !defined(EVENT__HAVE_ARC4RANDOM) || defined(EVENT__HAVE_ARC4RANDOM_ADDRANDOM) + void + evutil_secure_rng_add_bytes(const char *buf, size_t n) + { + arc4random_addrandom((unsigned char*)buf, + n>(size_t)INT_MAX ? INT_MAX : (int)n); + } ++#endif + + void + evutil_free_secure_rng_globals_(void) +diff --git a/include/event2/util.h b/include/event2/util.h +index dd4bbb69d..c4af2bd60 100644 +--- a/include/event2/util.h ++++ b/include/event2/util.h +@@ -842,6 +842,7 @@ int evutil_secure_rng_init(void); + EVENT2_EXPORT_SYMBOL + int evutil_secure_rng_set_urandom_device_file(char *fname); + ++#ifdef EVENT__HAVE_ARC4RANDOM_ADDRANDOM + /** Seed the random number generator with extra random bytes. + + You should almost never need to call this function; it should be +@@ -858,6 +859,7 @@ int evutil_secure_rng_set_urandom_device_file(char *fname); + */ + EVENT2_EXPORT_SYMBOL + void evutil_secure_rng_add_bytes(const char *dat, size_t datlen); ++#endif + + #ifdef __cplusplus + } From 40d848dc04c297ff5bffdb233b77db97353b8a95 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 22 May 2019 12:08:59 +0000 Subject: [PATCH 095/395] depends: Add FreeBSD Rust binaries --- depends/packages/rust.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/depends/packages/rust.mk b/depends/packages/rust.mk index b892d8b7265..69378abb631 100644 --- a/depends/packages/rust.mk +++ b/depends/packages/rust.mk @@ -5,6 +5,8 @@ $(package)_file_name_linux=rust-$($(package)_version)-x86_64-unknown-linux-gnu.t $(package)_sha256_hash_linux=e024698320d76b74daf0e6e71be3681a1e7923122e3ebd03673fcac3ecc23810 $(package)_file_name_darwin=rust-$($(package)_version)-x86_64-apple-darwin.tar.gz $(package)_sha256_hash_darwin=f0dfba507192f9b5c330b5984ba71d57d434475f3d62bd44a39201e36fa76304 +$(package)_file_name_freebsd=rust-$($(package)_version)-x86_64-unknown-freebsd.tar.gz +$(package)_sha256_hash_freebsd=20d062493d01f1816014fe9dbe883bda06f1828a6ddbfb7ee5e4f1df20eb1c3a # Mapping from GCC canonical hosts to Rust targets # If a mapping is not present, we assume they are identical From dea27818e6967debd1c42ea9d40ca155b89cdb11 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 22 May 2019 12:09:43 +0000 Subject: [PATCH 096/395] depends: Explicitly call Rust install script using bash On FreeBSD 12, the bash package is not necessarily installed to /bin/bash, which the install script assumes is the location. Since we depend on bash for building anyway, we can just explicitly call it. --- depends/packages/rust.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/depends/packages/rust.mk b/depends/packages/rust.mk index 69378abb631..72f7778bd1c 100644 --- a/depends/packages/rust.mk +++ b/depends/packages/rust.mk @@ -40,12 +40,12 @@ define $(package)_extract_cmds endef define $(package)_stage_cmds - ./install.sh --destdir=$($(package)_staging_dir) --prefix=$(host_prefix)/native --disable-ldconfig && \ + bash ./install.sh --destdir=$($(package)_staging_dir) --prefix=$(host_prefix)/native --disable-ldconfig && \ ../$(canonical_host)/install.sh --destdir=$($(package)_staging_dir) --prefix=$(host_prefix)/native --disable-ldconfig endef else define $(package)_stage_cmds - ./install.sh --destdir=$($(package)_staging_dir) --prefix=$(host_prefix)/native --disable-ldconfig + bash ./install.sh --destdir=$($(package)_staging_dir) --prefix=$(host_prefix)/native --disable-ldconfig endef endif From b6d0996cecc15adb590241053e0b79bf33f2ecb4 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 22 May 2019 16:28:28 +0000 Subject: [PATCH 097/395] depends: Use project-config.jam to configure Boost instead of user-config.jam Per the Boost.Build documentation, user-config.jam is supposed to only be located in the user's home directory, and this appears to be enforced on FreeBSD. --- depends/packages/boost.mk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index 2df3ebbcbf5..9c9e3b2424d 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -7,7 +7,7 @@ $(package)_sha256_hash=430ae8354789de4fd19ee52f3b1f739e1fba576f0aded0897c3c2bc00 define $(package)_set_vars $(package)_config_opts_release=variant=release $(package)_config_opts_debug=variant=debug -$(package)_config_opts=--layout=system --user-config=user-config.jam +$(package)_config_opts=--layout=system $(package)_config_opts+=threading=multi link=static -sNO_BZIP2=1 -sNO_ZLIB=1 $(package)_config_opts_linux=threadapi=pthread runtime-link=shared $(package)_config_opts_darwin=--toolset=darwin-4.2.1 runtime-link=shared @@ -25,11 +25,11 @@ $(package)_cxxflags_linux=-fPIC endef define $(package)_preprocess_cmds - echo "using $(boost_toolset_$(host_os)) : : $($(package)_cxx) : \"$($(package)_cxxflags) $($(package)_cppflags)\" \"$($(package)_ldflags)\" \"$(boost_archiver_$(host_os))\" \"$(host_STRIP)\" \"$(host_RANLIB)\" \"$(host_WINDRES)\" : ;" > user-config.jam endef define $(package)_config_cmds - ./bootstrap.sh --without-icu --with-toolset=$($(package)_toolset_$(host_os)) --with-libraries=$(boost_config_libraries) + ./bootstrap.sh --without-icu --with-toolset=$($(package)_toolset_$(host_os)) --with-libraries=$($(package)_config_libraries) && \ + sed -i -e "s|using gcc ;|using $(boost_toolset_$(host_os)) : : $($(package)_cxx) : \"$($(package)_cxxflags) $($(package)_cppflags)\" \"$($(package)_ldflags)\" \"$(boost_archiver_$(host_os))\" \"$(host_STRIP)\" \"$(host_RANLIB)\" \"$(host_WINDRES)\" : ;|" project-config.jam endef define $(package)_build_cmds From ae6cee2731b3c0bbac3a7712cf043d1c6d8c6362 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 22 May 2019 16:56:45 +0000 Subject: [PATCH 098/395] depends: Set PIC flags for FreeBSD --- depends/packages/bdb.mk | 1 + depends/packages/boost.mk | 1 + depends/packages/googletest.mk | 1 + depends/packages/libevent.mk | 1 + depends/packages/openssl.mk | 1 + depends/packages/zeromq.mk | 1 + 6 files changed, 6 insertions(+) diff --git a/depends/packages/bdb.mk b/depends/packages/bdb.mk index 21019aeb71f..bb90748237e 100644 --- a/depends/packages/bdb.mk +++ b/depends/packages/bdb.mk @@ -9,6 +9,7 @@ define $(package)_set_vars $(package)_config_opts=--disable-shared --enable-cxx --disable-replication $(package)_config_opts_mingw32=--enable-mingw $(package)_config_opts_linux=--with-pic +$(package)_config_opts_freebsd=--with-pic $(package)_config_opts_aarch64=--disable-atomicsupport $(package)_cxxflags=-std=c++11 endef diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index 9c9e3b2424d..1300dc1f60f 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -22,6 +22,7 @@ $(package)_archiver_darwin=$($(package)_libtool) $(package)_config_libraries=chrono,filesystem,program_options,system,thread,test $(package)_cxxflags=-std=c++11 -fvisibility=hidden $(package)_cxxflags_linux=-fPIC +$(package)_cxxflags_freebsd=-fPIC endef define $(package)_preprocess_cmds diff --git a/depends/packages/googletest.mk b/depends/packages/googletest.mk index ad42d5b9c44..3e4a72fca6a 100644 --- a/depends/packages/googletest.mk +++ b/depends/packages/googletest.mk @@ -8,6 +8,7 @@ $(package)_sha256_hash=58a6f4277ca2bc8565222b3bbd58a177609e9c488e8a72649359ba514 define $(package)_set_vars $(package)_cxxflags+=-std=c++11 $(package)_cxxflags_linux=-fPIC +$(package)_cxxflags_freebsd=-fPIC endef define $(package)_build_cmds diff --git a/depends/packages/libevent.mk b/depends/packages/libevent.mk index 6c54123c76c..7119176f27b 100644 --- a/depends/packages/libevent.mk +++ b/depends/packages/libevent.mk @@ -16,6 +16,7 @@ define $(package)_set_vars $(package)_config_opts=--disable-shared --disable-openssl --disable-libevent-regress $(package)_config_opts_release=--disable-debug-mode $(package)_config_opts_linux=--with-pic + $(package)_config_opts_freebsd=--with-pic endef define $(package)_config_cmds diff --git a/depends/packages/openssl.mk b/depends/packages/openssl.mk index 05b190ae324..cca12fbaddb 100644 --- a/depends/packages/openssl.mk +++ b/depends/packages/openssl.mk @@ -79,6 +79,7 @@ $(package)_config_opts+=no-zlib-dynamic $(package)_config_opts+=$($(package)_cflags) $($(package)_cppflags) $(package)_config_opts+=-DPURIFY $(package)_config_opts_linux=-fPIC -Wa,--noexecstack +$(package)_config_opts_freebsd=-fPIC -Wa,--noexecstack $(package)_config_opts_x86_64_linux=linux-x86_64 $(package)_config_opts_i686_linux=linux-generic32 $(package)_config_opts_arm_linux=linux-generic32 diff --git a/depends/packages/zeromq.mk b/depends/packages/zeromq.mk index 79373f09a57..fee9e6e267e 100644 --- a/depends/packages/zeromq.mk +++ b/depends/packages/zeromq.mk @@ -7,6 +7,7 @@ $(package)_sha256_hash=bcbabe1e2c7d0eec4ed612e10b94b112dd5f06fcefa994a0c79a45d83 define $(package)_set_vars $(package)_config_opts=--without-documentation --disable-shared --disable-curve $(package)_config_opts_linux=--with-pic + $(package)_config_opts_freebsd=--with-pic $(package)_cxxflags=-std=c++11 endef From be04f76034c77f8dd634c51c402f00a7ea83d959 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Wed, 22 May 2019 15:47:05 -0600 Subject: [PATCH 099/395] Update author aliases --- zcutil/release-notes.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/zcutil/release-notes.py b/zcutil/release-notes.py index 6e0f277df32..4446e988f2d 100755 --- a/zcutil/release-notes.py +++ b/zcutil/release-notes.py @@ -20,14 +20,18 @@ ] author_aliases = { - 'Simon': 'Simon Liu', - 'bitcartel': 'Simon Liu', - 'EthanHeilman': 'Ethan Heilman', 'Ariel': 'Ariel Gabizon', 'arielgabizon': 'Ariel Gabizon', + 'bitcartel': 'Simon Liu', 'Charlie OKeefe': 'Charlie O\'Keefe', + 'Duke Leto': 'Jonathan \"Duke\" Leto', + 'Eirik0': 'Eirik Ogilvie-Wigley', + 'EthanHeilman': 'Ethan Heilman', + 'mdr0id': 'Marshall Gaucher', + 'paveljanik': 'Pavel Janik', + 'Simon': 'Simon Liu', 'str4d': 'Jack Grigg', - 'Duke Leto': 'Jonathan \"Duke\" Leto' + 'zebambam': 'Benjamin Winston' } def apply_author_aliases(name): From bb0a3e1cb54dac6ceca687034cc7021588bc199b Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Wed, 22 May 2019 16:01:50 -0600 Subject: [PATCH 100/395] Remove old mergetoaddress RPC test --- qa/rpc-tests/wallet_mergetoaddress.py | 368 -------------------------- 1 file changed, 368 deletions(-) delete mode 100755 qa/rpc-tests/wallet_mergetoaddress.py diff --git a/qa/rpc-tests/wallet_mergetoaddress.py b/qa/rpc-tests/wallet_mergetoaddress.py deleted file mode 100755 index 3c2f84aa85f..00000000000 --- a/qa/rpc-tests/wallet_mergetoaddress.py +++ /dev/null @@ -1,368 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2017 The Zcash developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." - -from test_framework.test_framework import BitcoinTestFramework -from test_framework.authproxy import JSONRPCException -from test_framework.util import assert_equal, initialize_chain_clean, \ - start_node, connect_nodes_bi, sync_blocks, sync_mempools, \ - wait_and_assert_operationid_status - -from decimal import Decimal - -class WalletMergeToAddressTest (BitcoinTestFramework): - - def setup_chain(self): - print("Initializing test directory "+self.options.tmpdir) - initialize_chain_clean(self.options.tmpdir, 4) - - def setup_network(self, split=False): - args = ['-debug=zrpcunsafe', '-experimentalfeatures', '-zmergetoaddress'] - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, args)) - self.nodes.append(start_node(1, self.options.tmpdir, args)) - args2 = ['-debug=zrpcunsafe', '-experimentalfeatures', '-zmergetoaddress', '-mempooltxinputlimit=7'] - self.nodes.append(start_node(2, self.options.tmpdir, args2)) - connect_nodes_bi(self.nodes,0,1) - connect_nodes_bi(self.nodes,1,2) - connect_nodes_bi(self.nodes,0,2) - self.is_network_split=False - self.sync_all() - - def run_test (self): - print "Mining blocks..." - - self.nodes[0].generate(1) - do_not_shield_taddr = self.nodes[0].getnewaddress() - - self.nodes[0].generate(4) - walletinfo = self.nodes[0].getwalletinfo() - assert_equal(walletinfo['immature_balance'], 50) - assert_equal(walletinfo['balance'], 0) - self.sync_all() - self.nodes[2].generate(1) - self.nodes[2].getnewaddress() - self.nodes[2].generate(1) - self.nodes[2].getnewaddress() - self.nodes[2].generate(1) - self.sync_all() - self.nodes[1].generate(101) - self.sync_all() - assert_equal(self.nodes[0].getbalance(), 50) - assert_equal(self.nodes[1].getbalance(), 10) - assert_equal(self.nodes[2].getbalance(), 30) - - # Shield the coinbase - myzaddr = self.nodes[0].z_getnewaddress('sprout') - result = self.nodes[0].z_shieldcoinbase("*", myzaddr, 0) - wait_and_assert_operationid_status(self.nodes[0], result['opid']) - self.sync_all() - self.nodes[1].generate(1) - self.sync_all() - - # Prepare some UTXOs and notes for merging - mytaddr = self.nodes[0].getnewaddress() - mytaddr2 = self.nodes[0].getnewaddress() - mytaddr3 = self.nodes[0].getnewaddress() - result = self.nodes[0].z_sendmany(myzaddr, [ - {'address': do_not_shield_taddr, 'amount': 10}, - {'address': mytaddr, 'amount': 10}, - {'address': mytaddr2, 'amount': 10}, - {'address': mytaddr3, 'amount': 10}, - ], 1, 0) - wait_and_assert_operationid_status(self.nodes[0], result) - self.sync_all() - self.nodes[1].generate(1) - self.sync_all() - - # Merging will fail because from arguments need to be in an array - try: - self.nodes[0].z_mergetoaddress("*", myzaddr) - assert(False) - except JSONRPCException,e: - errorString = e.error['message'] - assert_equal("JSON value is not an array as expected" in errorString, True) - - # Merging will fail when trying to spend from watch-only address - self.nodes[2].importaddress(mytaddr) - try: - self.nodes[2].z_mergetoaddress([mytaddr], myzaddr) - assert(False) - except JSONRPCException,e: - errorString = e.error['message'] - assert_equal("Could not find any funds to merge" in errorString, True) - - # Merging will fail because fee is negative - try: - self.nodes[0].z_mergetoaddress(["*"], myzaddr, -1) - assert(False) - except JSONRPCException,e: - errorString = e.error['message'] - assert_equal("Amount out of range" in errorString, True) - - # Merging will fail because fee is larger than MAX_MONEY - try: - self.nodes[0].z_mergetoaddress(["*"], myzaddr, Decimal('21000000.00000001')) - assert(False) - except JSONRPCException,e: - errorString = e.error['message'] - assert_equal("Amount out of range" in errorString, True) - - # Merging will fail because fee is larger than sum of UTXOs - try: - self.nodes[0].z_mergetoaddress(["*"], myzaddr, 999) - assert(False) - except JSONRPCException,e: - errorString = e.error['message'] - assert_equal("Insufficient funds" in errorString, True) - - # Merging will fail because transparent limit parameter must be at least 0 - try: - self.nodes[0].z_mergetoaddress(["*"], myzaddr, Decimal('0.001'), -1) - assert(False) - except JSONRPCException,e: - errorString = e.error['message'] - assert_equal("Limit on maximum number of UTXOs cannot be negative" in errorString, True) - - # Merging will fail because transparent limit parameter is absurdly large - try: - self.nodes[0].z_mergetoaddress(["*"], myzaddr, Decimal('0.001'), 99999999999999) - assert(False) - except JSONRPCException,e: - errorString = e.error['message'] - assert_equal("JSON integer out of range" in errorString, True) - - # Merging will fail because shielded limit parameter must be at least 0 - try: - self.nodes[0].z_mergetoaddress(["*"], myzaddr, Decimal('0.001'), 50, -1) - assert(False) - except JSONRPCException,e: - errorString = e.error['message'] - assert_equal("Limit on maximum number of notes cannot be negative" in errorString, True) - - # Merging will fail because shielded limit parameter is absurdly large - try: - self.nodes[0].z_mergetoaddress(["*"], myzaddr, Decimal('0.001'), 50, 99999999999999) - assert(False) - except JSONRPCException,e: - errorString = e.error['message'] - assert_equal("JSON integer out of range" in errorString, True) - - # Merging will fail for this specific case where it would spend a fee and do nothing - try: - self.nodes[0].z_mergetoaddress([mytaddr], mytaddr) - assert(False) - except JSONRPCException,e: - errorString = e.error['message'] - assert_equal("Destination address is also the only source address, and all its funds are already merged" in errorString, True) - - # Merge UTXOs from node 0 of value 30, standard fee of 0.00010000 - result = self.nodes[0].z_mergetoaddress([mytaddr, mytaddr2, mytaddr3], myzaddr) - wait_and_assert_operationid_status(self.nodes[0], result['opid']) - self.sync_all() - self.nodes[1].generate(1) - self.sync_all() - - # Confirm balances and that do_not_shield_taddr containing funds of 10 was left alone - assert_equal(self.nodes[0].getbalance(), 10) - assert_equal(self.nodes[0].z_getbalance(do_not_shield_taddr), Decimal('10.0')) - assert_equal(self.nodes[0].z_getbalance(myzaddr), Decimal('39.99990000')) - assert_equal(self.nodes[1].getbalance(), 40) - assert_equal(self.nodes[2].getbalance(), 30) - - # Shield all notes to another z-addr - myzaddr2 = self.nodes[0].z_getnewaddress('sprout') - result = self.nodes[0].z_mergetoaddress(["ANY_ZADDR"], myzaddr2, 0) - assert_equal(result["mergingUTXOs"], Decimal('0')) - assert_equal(result["remainingUTXOs"], Decimal('0')) - assert_equal(result["mergingNotes"], Decimal('2')) - assert_equal(result["remainingNotes"], Decimal('0')) - wait_and_assert_operationid_status(self.nodes[0], result['opid']) - self.sync_all() - blockhash = self.nodes[1].generate(1) - self.sync_all() - - assert_equal(len(self.nodes[0].getblock(blockhash[0])['tx']), 2) - assert_equal(self.nodes[0].z_getbalance(myzaddr), 0) - assert_equal(self.nodes[0].z_getbalance(myzaddr2), Decimal('39.99990000')) - - # Shield coinbase UTXOs from any node 2 taddr, and set fee to 0 - result = self.nodes[2].z_shieldcoinbase("*", myzaddr, 0) - wait_and_assert_operationid_status(self.nodes[2], result['opid']) - self.sync_all() - self.nodes[1].generate(1) - self.sync_all() - - assert_equal(self.nodes[0].getbalance(), 10) - assert_equal(self.nodes[0].z_getbalance(myzaddr), Decimal('30')) - assert_equal(self.nodes[0].z_getbalance(myzaddr2), Decimal('39.99990000')) - assert_equal(self.nodes[1].getbalance(), 60) - assert_equal(self.nodes[2].getbalance(), 0) - - # Merge all notes from node 0 into a node 0 taddr, and set fee to 0 - result = self.nodes[0].z_mergetoaddress(["ANY_ZADDR"], mytaddr, 0) - wait_and_assert_operationid_status(self.nodes[0], result['opid']) - self.sync_all() - self.nodes[1].generate(1) - self.sync_all() - - assert_equal(self.nodes[0].getbalance(), Decimal('79.99990000')) - assert_equal(self.nodes[0].z_getbalance(do_not_shield_taddr), Decimal('10.0')) - assert_equal(self.nodes[0].z_getbalance(mytaddr), Decimal('69.99990000')) - assert_equal(self.nodes[0].z_getbalance(myzaddr), 0) - assert_equal(self.nodes[0].z_getbalance(myzaddr2), 0) - assert_equal(self.nodes[1].getbalance(), 70) - assert_equal(self.nodes[2].getbalance(), 0) - - # Merge all node 0 UTXOs together into a node 1 taddr, and set fee to 0 - self.nodes[1].getnewaddress() # Ensure we have an empty address - n1taddr = self.nodes[1].getnewaddress() - result = self.nodes[0].z_mergetoaddress(["ANY_TADDR"], n1taddr, 0) - wait_and_assert_operationid_status(self.nodes[0], result['opid']) - self.sync_all() - self.nodes[1].generate(1) - self.sync_all() - - assert_equal(self.nodes[0].getbalance(), 0) - assert_equal(self.nodes[0].z_getbalance(do_not_shield_taddr), 0) - assert_equal(self.nodes[0].z_getbalance(mytaddr), 0) - assert_equal(self.nodes[0].z_getbalance(myzaddr), 0) - assert_equal(self.nodes[1].getbalance(), Decimal('159.99990000')) - assert_equal(self.nodes[1].z_getbalance(n1taddr), Decimal('79.99990000')) - assert_equal(self.nodes[2].getbalance(), 0) - - # Generate 800 regular UTXOs on node 0, and 20 regular UTXOs on node 2 - mytaddr = self.nodes[0].getnewaddress() - n2taddr = self.nodes[2].getnewaddress() - self.nodes[1].generate(1000) - self.sync_all() - for i in range(800): - self.nodes[1].sendtoaddress(mytaddr, 1) - for i in range(20): - self.nodes[1].sendtoaddress(n2taddr, 1) - self.nodes[1].generate(1) - self.sync_all() - - # Merging the 800 UTXOs will occur over two transactions, since max tx size is 100,000 bytes. - # We don't verify mergingTransparentValue as UTXOs are not selected in any specific order, so value can change on each test run. - # We set an unrealistically high limit parameter of 99999, to verify that max tx size will constrain the number of UTXOs. - result = self.nodes[0].z_mergetoaddress([mytaddr], myzaddr, 0, 99999) - assert_equal(result["mergingUTXOs"], Decimal('662')) - assert_equal(result["remainingUTXOs"], Decimal('138')) - assert_equal(result["mergingNotes"], Decimal('0')) - assert_equal(result["mergingShieldedValue"], Decimal('0')) - assert_equal(result["remainingNotes"], Decimal('0')) - assert_equal(result["remainingShieldedValue"], Decimal('0')) - remainingTransparentValue = result["remainingTransparentValue"] - opid1 = result['opid'] - - # Verify that UTXOs are locked (not available for selection) by queuing up another merging operation - result = self.nodes[0].z_mergetoaddress([mytaddr], myzaddr, 0, 0) - assert_equal(result["mergingUTXOs"], Decimal('138')) - assert_equal(result["mergingTransparentValue"], Decimal(remainingTransparentValue)) - assert_equal(result["remainingUTXOs"], Decimal('0')) - assert_equal(result["remainingTransparentValue"], Decimal('0')) - assert_equal(result["mergingNotes"], Decimal('0')) - assert_equal(result["mergingShieldedValue"], Decimal('0')) - assert_equal(result["remainingNotes"], Decimal('0')) - assert_equal(result["remainingShieldedValue"], Decimal('0')) - opid2 = result['opid'] - - # wait for both aysnc operations to complete - wait_and_assert_operationid_status(self.nodes[0], opid1) - wait_and_assert_operationid_status(self.nodes[0], opid2) - - # sync_all() invokes sync_mempool() but node 2's mempool limit will cause tx1 and tx2 to be rejected. - # So instead, we sync on blocks and mempool for node 0 and node 1, and after a new block is generated - # which mines tx1 and tx2, all nodes will have an empty mempool which can then be synced. - sync_blocks(self.nodes[:2]) - sync_mempools(self.nodes[:2]) - # Generate enough blocks to ensure all transactions are mined - while self.nodes[1].getmempoolinfo()['size'] > 0: - self.nodes[1].generate(1) - self.sync_all() - - # Verify maximum number of UTXOs which node 2 can shield is limited by option -mempooltxinputlimit - # This option is used when the limit parameter is set to 0. - result = self.nodes[2].z_mergetoaddress([n2taddr], myzaddr, Decimal('0.0001'), 0) - assert_equal(result["mergingUTXOs"], Decimal('7')) - assert_equal(result["remainingUTXOs"], Decimal('13')) - assert_equal(result["mergingNotes"], Decimal('0')) - assert_equal(result["remainingNotes"], Decimal('0')) - wait_and_assert_operationid_status(self.nodes[2], result['opid']) - self.sync_all() - self.nodes[1].generate(1) - self.sync_all() - - # Verify maximum number of UTXOs which node 0 can shield is set by default limit parameter of 50 - mytaddr = self.nodes[0].getnewaddress() - for i in range(100): - self.nodes[1].sendtoaddress(mytaddr, 1) - self.nodes[1].generate(1) - self.sync_all() - result = self.nodes[0].z_mergetoaddress([mytaddr], myzaddr, Decimal('0.0001')) - assert_equal(result["mergingUTXOs"], Decimal('50')) - assert_equal(result["remainingUTXOs"], Decimal('50')) - assert_equal(result["mergingNotes"], Decimal('0')) - # Remaining notes are only counted if we are trying to merge any notes - assert_equal(result["remainingNotes"], Decimal('0')) - wait_and_assert_operationid_status(self.nodes[0], result['opid']) - - # Verify maximum number of UTXOs which node 0 can shield can be set by the limit parameter - result = self.nodes[0].z_mergetoaddress([mytaddr], myzaddr, Decimal('0.0001'), 33) - assert_equal(result["mergingUTXOs"], Decimal('33')) - assert_equal(result["remainingUTXOs"], Decimal('17')) - assert_equal(result["mergingNotes"], Decimal('0')) - # Remaining notes are only counted if we are trying to merge any notes - assert_equal(result["remainingNotes"], Decimal('0')) - wait_and_assert_operationid_status(self.nodes[0], result['opid']) - # Don't sync node 2 which rejects the tx due to its mempooltxinputlimit - sync_blocks(self.nodes[:2]) - sync_mempools(self.nodes[:2]) - self.nodes[1].generate(1) - self.sync_all() - - # Verify maximum number of notes which node 0 can shield can be set by the limit parameter - # Also check that we can set off a second merge before the first one is complete - - # myzaddr has 5 notes at this point - result1 = self.nodes[0].z_mergetoaddress([myzaddr], myzaddr, 0.0001, 50, 2) - result2 = self.nodes[0].z_mergetoaddress([myzaddr], myzaddr, 0.0001, 50, 2) - - # First merge should select from all notes - assert_equal(result1["mergingUTXOs"], Decimal('0')) - # Remaining UTXOs are only counted if we are trying to merge any UTXOs - assert_equal(result1["remainingUTXOs"], Decimal('0')) - assert_equal(result1["mergingNotes"], Decimal('2')) - assert_equal(result1["remainingNotes"], Decimal('3')) - - # Second merge should ignore locked notes - assert_equal(result2["mergingUTXOs"], Decimal('0')) - assert_equal(result2["remainingUTXOs"], Decimal('0')) - assert_equal(result2["mergingNotes"], Decimal('2')) - assert_equal(result2["remainingNotes"], Decimal('1')) - wait_and_assert_operationid_status(self.nodes[0], result1['opid']) - wait_and_assert_operationid_status(self.nodes[0], result2['opid']) - - self.sync_all() - self.nodes[1].generate(1) - self.sync_all() - - # Shield both UTXOs and notes to a z-addr - result = self.nodes[0].z_mergetoaddress(["*"], myzaddr, 0, 10, 2) - assert_equal(result["mergingUTXOs"], Decimal('10')) - assert_equal(result["remainingUTXOs"], Decimal('7')) - assert_equal(result["mergingNotes"], Decimal('2')) - assert_equal(result["remainingNotes"], Decimal('1')) - wait_and_assert_operationid_status(self.nodes[0], result['opid']) - # Don't sync node 2 which rejects the tx due to its mempooltxinputlimit - sync_blocks(self.nodes[:2]) - sync_mempools(self.nodes[:2]) - self.nodes[1].generate(1) - self.sync_all() - -if __name__ == '__main__': - WalletMergeToAddressTest().main() From a630f503491effb3a4fa7e42a5b14cb50e6f5d03 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Thu, 23 May 2019 09:24:46 -0600 Subject: [PATCH 101/395] Replace CSproutNotePlaintextEntry with SproutNoteEntry to match Sapling --- .../asyncrpcoperation_saplingmigration.cpp | 19 ++++++------ src/wallet/asyncrpcoperation_sendmany.cpp | 10 +++---- src/wallet/gtest/test_wallet.cpp | 2 +- src/wallet/rpcwallet.cpp | 30 +++++++++---------- src/wallet/wallet.cpp | 7 +++-- src/wallet/wallet.h | 11 +++---- 6 files changed, 40 insertions(+), 39 deletions(-) diff --git a/src/wallet/asyncrpcoperation_saplingmigration.cpp b/src/wallet/asyncrpcoperation_saplingmigration.cpp index 8e1dda6159a..d99bc539fe0 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.cpp +++ b/src/wallet/asyncrpcoperation_saplingmigration.cpp @@ -69,7 +69,7 @@ void AsyncRPCOperation_saplingmigration::main() { bool AsyncRPCOperation_saplingmigration::main_impl() { LogPrint("zrpcunsafe", "%s: Beginning AsyncRPCOperation_saplingmigration.\n", getId()); - std::vector sproutEntries; + std::vector sproutEntries; std::vector saplingEntries; { LOCK2(cs_main, pwalletMain->cs_wallet); @@ -79,8 +79,8 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, "", 11); } CAmount availableFunds = 0; - for (const CSproutNotePlaintextEntry& sproutEntry : sproutEntries) { - availableFunds += sproutEntry.plaintext.value(); + for (const SproutNoteEntry& sproutEntry : sproutEntries) { + availableFunds += sproutEntry.note.value(); } // If the remaining amount to be migrated is less than 0.01 ZEC, end the migration. if (availableFunds < CENT) { @@ -106,25 +106,24 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { auto builder = TransactionBuilder(consensusParams, targetHeight_, MIGRATION_EXPIRY_DELTA, pwalletMain, pzcashParams, &coinsView, &cs_main); LogPrint("zrpcunsafe", "%s: Beginning creating transaction with Sapling output amount=%s\n", getId(), FormatMoney(amountToSend - FEE)); - std::vector fromNotes; + std::vector fromNotes; CAmount fromNoteAmount = 0; while (fromNoteAmount < amountToSend) { auto sproutEntry = sproutEntries[noteIndex++]; fromNotes.push_back(sproutEntry); - fromNoteAmount += sproutEntry.plaintext.value(); + fromNoteAmount += sproutEntry.note.value(); } availableFunds -= fromNoteAmount; - for (const CSproutNotePlaintextEntry& sproutEntry : fromNotes) { - std::string data(sproutEntry.plaintext.memo().begin(), sproutEntry.plaintext.memo().end()); + for (const SproutNoteEntry& sproutEntry : fromNotes) { + std::string data(sproutEntry.memo.begin(), sproutEntry.memo.end()); LogPrint("zrpcunsafe", "%s: Adding Sprout note input (txid=%s, vjoinsplit=%d, jsoutindex=%d, amount=%s, memo=%s)\n", getId(), sproutEntry.jsop.hash.ToString().substr(0, 10), sproutEntry.jsop.js, int(sproutEntry.jsop.n), // uint8_t - FormatMoney(sproutEntry.plaintext.value()), + FormatMoney(sproutEntry.note.value()), HexStr(data).substr(0, 10) ); - libzcash::SproutNote sproutNote = sproutEntry.plaintext.note(sproutEntry.address); libzcash::SproutSpendingKey sproutSk; pwalletMain->GetSproutSpendingKey(sproutEntry.address, sproutSk); std::vector vOutPoints = {sproutEntry.jsop}; @@ -134,7 +133,7 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { uint256 inputAnchor; std::vector> vInputWitnesses; pwalletMain->GetSproutNoteWitnesses(vOutPoints, vInputWitnesses, inputAnchor); - builder.AddSproutInput(sproutSk, sproutNote, vInputWitnesses[0].get()); + builder.AddSproutInput(sproutSk, sproutEntry.note, vInputWitnesses[0].get()); } // The amount chosen *includes* the 0.0001 ZEC fee for this transaction, i.e. // the value of the Sapling output will be 0.0001 ZEC less. diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index 93ec59b539f..9538a2736e6 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -1029,7 +1029,7 @@ bool AsyncRPCOperation_sendmany::find_utxos(bool fAcceptCoinbase=false) { bool AsyncRPCOperation_sendmany::find_unspent_notes() { - std::vector sproutEntries; + std::vector sproutEntries; std::vector saplingEntries; { LOCK2(cs_main, pwalletMain->cs_wallet); @@ -1045,15 +1045,15 @@ bool AsyncRPCOperation_sendmany::find_unspent_notes() { saplingEntries.clear(); } - for (CSproutNotePlaintextEntry & entry : sproutEntries) { - z_sprout_inputs_.push_back(SendManyInputJSOP(entry.jsop, entry.plaintext.note(boost::get(frompaymentaddress_)), CAmount(entry.plaintext.value()))); - std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end()); + for (SproutNoteEntry & entry : sproutEntries) { + z_sprout_inputs_.push_back(SendManyInputJSOP(entry.jsop, entry.note, CAmount(entry.note.value()))); + std::string data(entry.memo.begin(), entry.memo.end()); LogPrint("zrpcunsafe", "%s: found unspent Sprout note (txid=%s, vjoinsplit=%d, jsoutindex=%d, amount=%s, memo=%s)\n", getId(), entry.jsop.hash.ToString().substr(0, 10), entry.jsop.js, int(entry.jsop.n), // uint8_t - FormatMoney(entry.plaintext.value()), + FormatMoney(entry.note.value()), HexStr(data).substr(0, 10) ); } diff --git a/src/wallet/gtest/test_wallet.cpp b/src/wallet/gtest/test_wallet.cpp index 6d07bee388e..029753a9483 100644 --- a/src/wallet/gtest/test_wallet.cpp +++ b/src/wallet/gtest/test_wallet.cpp @@ -188,7 +188,7 @@ TEST(WalletTests, FindUnspentSproutNotes) { EXPECT_FALSE(wallet.IsSproutSpent(nullifier)); // We currently have an unspent and unconfirmed note in the wallet (depth of -1) - std::vector sproutEntries; + std::vector sproutEntries; std::vector saplingEntries; wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 0); EXPECT_EQ(0, sproutEntries.size()); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 2fc71bbf445..0fbda374a69 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2567,7 +2567,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp) UniValue results(UniValue::VARR); if (zaddrs.size() > 0) { - std::vector sproutEntries; + std::vector sproutEntries; std::vector saplingEntries; pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, zaddrs, nMinDepth, nMaxDepth, true, !fIncludeWatchonly, false); std::set> nullifierSet = pwalletMain->GetNullifiersForAddresses(zaddrs); @@ -2581,8 +2581,8 @@ UniValue z_listunspent(const UniValue& params, bool fHelp) bool hasSproutSpendingKey = pwalletMain->HaveSproutSpendingKey(boost::get(entry.address)); obj.push_back(Pair("spendable", hasSproutSpendingKey)); obj.push_back(Pair("address", EncodePaymentAddress(entry.address))); - obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value())))); - std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end()); + obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.note.value())))); + std::string data(entry.memo.begin(), entry.memo.end()); obj.push_back(Pair("memo", HexStr(data))); if (hasSproutSpendingKey) { obj.push_back(Pair("change", pwalletMain->IsNoteSproutChange(nullifierSet, entry.address, entry.jsop))); @@ -3291,12 +3291,12 @@ CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1, bool ign CAmount getBalanceZaddr(std::string address, int minDepth = 1, bool ignoreUnspendable=true) { CAmount balance = 0; - std::vector sproutEntries; + std::vector sproutEntries; std::vector saplingEntries; LOCK2(cs_main, pwalletMain->cs_wallet); pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, address, minDepth, true, ignoreUnspendable); for (auto & entry : sproutEntries) { - balance += CAmount(entry.plaintext.value()); + balance += CAmount(entry.note.value()); } for (auto & entry : saplingEntries) { balance += CAmount(entry.note.value()); @@ -3356,7 +3356,7 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp) } UniValue result(UniValue::VARR); - std::vector sproutEntries; + std::vector sproutEntries; std::vector saplingEntries; pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, fromaddress, nMinDepth, false, false); @@ -3367,11 +3367,11 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp) } if (boost::get(&zaddr) != nullptr) { - for (CSproutNotePlaintextEntry & entry : sproutEntries) { + for (SproutNoteEntry & entry : sproutEntries) { UniValue obj(UniValue::VOBJ); obj.push_back(Pair("txid", entry.jsop.hash.ToString())); - obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value())))); - std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end()); + obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.note.value())))); + std::string data(entry.memo.begin(), entry.memo.end()); obj.push_back(Pair("memo", HexStr(data))); obj.push_back(Pair("jsindex", entry.jsop.js)); obj.push_back(Pair("jsoutindex", entry.jsop.n)); @@ -3965,7 +3965,7 @@ UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) { // account failed transactions, that were not mined within their expiration // height. { - std::vector sproutEntries; + std::vector sproutEntries; std::vector saplingEntries; std::set noFilter; // Here we are looking for any and all Sprout notes for which we have the spending key, including those @@ -3973,7 +3973,7 @@ UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) { pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, noFilter, 0, INT_MAX, true, true, false); CAmount unmigratedAmount = 0; for (const auto& sproutEntry : sproutEntries) { - unmigratedAmount += sproutEntry.plaintext.value(); + unmigratedAmount += sproutEntry.note.value(); } migrationStatus.push_back(Pair("unmigrated_amount", FormatMoney(unmigratedAmount))); } @@ -4525,7 +4525,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) if (useAnySprout || useAnySapling || zaddrs.size() > 0) { // Get available notes - std::vector sproutEntries; + std::vector sproutEntries; std::vector saplingEntries; pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, zaddrs); @@ -4547,9 +4547,9 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) } // Find unspent notes and update estimated size - for (const CSproutNotePlaintextEntry& entry : sproutEntries) { + for (const SproutNoteEntry& entry : sproutEntries) { noteCounter++; - CAmount nValue = entry.plaintext.value(); + CAmount nValue = entry.note.value(); if (!maxedOutNotesFlag) { // If we haven't added any notes yet and the merge is to a @@ -4564,7 +4564,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) auto zaddr = entry.address; SproutSpendingKey zkey; pwalletMain->GetSproutSpendingKey(zaddr, zkey); - sproutNoteInputs.emplace_back(entry.jsop, entry.plaintext.note(zaddr), nValue, zkey); + sproutNoteInputs.emplace_back(entry.jsop, entry.note, nValue, zkey); mergedNoteValue += nValue; } } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 23030257a89..2a0e47b3a38 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4483,7 +4483,7 @@ bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectAbsurdFee) * These notes are decrypted and added to the output parameter vector, outEntries. */ void CWallet::GetFilteredNotes( - std::vector& sproutEntries, + std::vector& sproutEntries, std::vector& saplingEntries, std::string address, int minDepth, @@ -4505,7 +4505,7 @@ void CWallet::GetFilteredNotes( * These notes are decrypted and added to the output parameter vector, outEntries. */ void CWallet::GetFilteredNotes( - std::vector& sproutEntries, + std::vector& sproutEntries, std::vector& saplingEntries, std::set& filterAddresses, int minDepth, @@ -4572,7 +4572,8 @@ void CWallet::GetFilteredNotes( hSig, (unsigned char) j); - sproutEntries.push_back(CSproutNotePlaintextEntry{jsop, pa, plaintext, wtx.GetDepthInMainChain()}); + sproutEntries.push_back(SproutNoteEntry { + jsop, pa, plaintext.note(pa), plaintext.memo(), wtx.GetDepthInMainChain() }); } catch (const note_decryption_failed &err) { // Couldn't decrypt with this spending key diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index fa137011199..6486f54c3e3 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -312,12 +312,13 @@ class SaplingNoteData typedef std::map mapSproutNoteData_t; typedef std::map mapSaplingNoteData_t; -/** Decrypted note, its location in a transaction, and number of confirmations. */ -struct CSproutNotePlaintextEntry +/** Sprout note, its location in a transaction, and number of confirmations. */ +struct SproutNoteEntry { JSOutPoint jsop; libzcash::SproutPaymentAddress address; - libzcash::SproutNotePlaintext plaintext; + libzcash::SproutNote note; + std::array memo; int confirmations; }; @@ -1301,7 +1302,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool LoadCryptedHDSeed(const uint256& seedFp, const std::vector& seed); /* Find notes filtered by payment address, min depth, ability to spend */ - void GetFilteredNotes(std::vector& sproutEntries, + void GetFilteredNotes(std::vector& sproutEntries, std::vector& saplingEntries, std::string address, int minDepth=1, @@ -1310,7 +1311,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface /* Find notes filtered by payment addresses, min depth, max depth, if they are spent, if a spending key is required, and if they are locked */ - void GetFilteredNotes(std::vector& sproutEntries, + void GetFilteredNotes(std::vector& sproutEntries, std::vector& saplingEntries, std::set& filterAddresses, int minDepth=1, From 9a529fd2176e6bb189b36cfd7fc7a09cab18ed92 Mon Sep 17 00:00:00 2001 From: Daniel Kraft Date: Sat, 8 Aug 2015 18:18:41 +0200 Subject: [PATCH 102/395] Add some const declarations where they are appropriate. Declare some arguments of functions as "const" pointers where they are not meant to be modified. --- src/main.cpp | 12 ++++++------ src/main.h | 8 ++++---- src/miner.cpp | 4 ++-- src/miner.h | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index ea105227427..8806542cd97 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1677,7 +1677,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock // CBlock and CBlockIndex // -bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart) +bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart) { // Open history file to append CAutoFile fileout(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION); @@ -3093,7 +3093,7 @@ static int64_t nTimePostConnect = 0; * corresponding to pindexNew, to bypass loading it again from disk. * You probably want to call mempool.removeWithoutBranchId after this, with cs_main held. */ -bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *pblock) { +bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, const CBlock *pblock) { assert(pindexNew->pprev == chainActive.Tip()); // Read block from disk. int64_t nTime1 = GetTimeMicros(); @@ -3236,7 +3236,7 @@ static void PruneBlockIndexCandidates() { * Try to make some progress towards making pindexMostWork the active block. * pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork. */ -static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork, CBlock *pblock) { +static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork, const CBlock *pblock) { AssertLockHeld(cs_main); bool fInvalidFound = false; const CBlockIndex *pindexOldTip = chainActive.Tip(); @@ -3339,7 +3339,7 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo * or an activated best chain. pblock is either NULL or a pointer to a block * that is already loaded (to avoid loading it again from disk). */ -bool ActivateBestChain(CValidationState &state, CBlock *pblock) { +bool ActivateBestChain(CValidationState &state, const CBlock *pblock) { CBlockIndex *pindexNewTip = NULL; CBlockIndex *pindexMostWork = NULL; const CChainParams& chainParams = Params(); @@ -3938,7 +3938,7 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc return true; } -bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, bool fRequested, CDiskBlockPos* dbp) +bool AcceptBlock(const CBlock& block, CValidationState& state, CBlockIndex** ppindex, bool fRequested, CDiskBlockPos* dbp) { const CChainParams& chainparams = Params(); AssertLockHeld(cs_main); @@ -4017,7 +4017,7 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned } -bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp) +bool ProcessNewBlock(CValidationState &state, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp) { // Preliminary checks auto verifier = libzcash::ProofVerifier::Disabled(); diff --git a/src/main.h b/src/main.h index b78c1d831e9..b5f82cecad2 100644 --- a/src/main.h +++ b/src/main.h @@ -204,7 +204,7 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals); * @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location. * @return True if state.IsValid() */ -bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp); +bool ProcessNewBlock(CValidationState &state, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp); /** Check whether enough disk space is available for an incoming block */ bool CheckDiskSpace(uint64_t nAdditionalBytes = 0); /** Open a block file (blk?????.dat) */ @@ -241,7 +241,7 @@ std::string GetWarnings(const std::string& strFor); /** Retrieve a transaction (from memory pool, or from disk, if possible) */ bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, bool fAllowSlow = false); /** Find the best known block, and make it the tip of the block chain */ -bool ActivateBestChain(CValidationState &state, CBlock *pblock = NULL); +bool ActivateBestChain(CValidationState &state, const CBlock *pblock = NULL); CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams); /** @@ -461,7 +461,7 @@ class CScriptCheck /** Functions for disk access for blocks */ -bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart); +bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart); bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos); bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex); @@ -491,7 +491,7 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex * - The only caller of AcceptBlock verifies JoinSplit proofs elsewhere. * If dbp is non-NULL, the file is known to already reside on disk */ -bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex **pindex, bool fRequested, CDiskBlockPos* dbp); +bool AcceptBlock(const CBlock& block, CValidationState& state, CBlockIndex **pindex, bool fRequested, CDiskBlockPos* dbp); bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL); diff --git a/src/miner.cpp b/src/miner.cpp index f83acfe4921..a5258f39d88 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -477,7 +477,7 @@ void GetScriptForMinerAddress(boost::shared_ptr &script) script->reserveScript = CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG; } -void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce) +void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce) { // Update nExtraNonce static uint256 hashPrevBlock; @@ -496,7 +496,7 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& pblock->hashMerkleRoot = pblock->BuildMerkleTree(); } -static bool ProcessBlockFound(CBlock* pblock, const CChainParams& chainparams) +static bool ProcessBlockFound(const CBlock* pblock, const CChainParams& chainparams) { LogPrintf("%s\n", pblock->ToString()); LogPrintf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue)); diff --git a/src/miner.h b/src/miner.h index 07098905445..1d1ebaf9b4d 100644 --- a/src/miner.h +++ b/src/miner.h @@ -30,7 +30,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn); /** Get script for -mineraddress */ void GetScriptForMinerAddress(boost::shared_ptr &script); /** Modify the extranonce in a block */ -void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce); +void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce); /** Run the miner threads */ void GenerateBitcoins(bool fGenerate, int nThreads, const CChainParams& chainparams); #endif From cea06a4fd3a5ce5b18631c46fc451de663adb4e8 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 26 Jan 2018 23:31:44 +0000 Subject: [PATCH 103/395] Move Equihash parameters into consensus params --- src/chainparams.cpp | 24 ++++++++++++------------ src/chainparams.h | 4 ---- src/consensus/params.h | 2 ++ src/main.cpp | 4 ++-- src/miner.cpp | 4 ++-- src/pow.cpp | 6 +++--- src/pow.h | 2 +- src/rpc/mining.cpp | 4 ++-- src/test/miner_tests.cpp | 4 ++-- src/zcbenchmarks.cpp | 9 +++++---- 10 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 5f8dba4d2b2..01b65ddbe45 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -89,6 +89,10 @@ class CMainParams : public CChainParams { consensus.nMajorityEnforceBlockUpgrade = 750; consensus.nMajorityRejectBlockOutdated = 950; consensus.nMajorityWindow = 4000; + const size_t N = 200, K = 9; + BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K)); + consensus.nEquihashN = N; + consensus.nEquihashK = K; consensus.powLimit = uint256S("0007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.nPowAveragingWindow = 17; assert(maxUint/UintToArith256(consensus.powLimit) >= consensus.nPowAveragingWindow); @@ -123,10 +127,6 @@ class CMainParams : public CChainParams { vAlertPubKey = ParseHex("04b7ecf0baa90495ceb4e4090f6b2fd37eec1e9c85fac68a487f3ce11589692e4a317479316ee814e066638e1db54e37a10689b70286e6315b1087b6615d179264"); nDefaultPort = 8233; nPruneAfterHeight = 100000; - const size_t N = 200, K = 9; - BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K)); - nEquihashN = N; - nEquihashK = K; genesis = CreateGenesisBlock( 1477641360, @@ -280,6 +280,10 @@ class CTestNetParams : public CChainParams { consensus.nMajorityEnforceBlockUpgrade = 51; consensus.nMajorityRejectBlockOutdated = 75; consensus.nMajorityWindow = 400; + const size_t N = 200, K = 9; + BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K)); + consensus.nEquihashN = N; + consensus.nEquihashK = K; consensus.powLimit = uint256S("07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.nPowAveragingWindow = 17; assert(maxUint/UintToArith256(consensus.powLimit) >= consensus.nPowAveragingWindow); @@ -311,10 +315,6 @@ class CTestNetParams : public CChainParams { vAlertPubKey = ParseHex("044e7a1553392325c871c5ace5d6ad73501c66f4c185d6b0453cf45dec5a1322e705c672ac1a27ef7cdaf588c10effdf50ed5f95f85f2f54a5f6159fca394ed0c6"); nDefaultPort = 18233; nPruneAfterHeight = 1000; - const size_t N = 200, K = 9; - BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K)); - nEquihashN = N; - nEquihashK = K; genesis = CreateGenesisBlock( 1477648033, @@ -412,6 +412,10 @@ class CRegTestParams : public CChainParams { consensus.nMajorityEnforceBlockUpgrade = 750; consensus.nMajorityRejectBlockOutdated = 950; consensus.nMajorityWindow = 1000; + const size_t N = 48, K = 5; + BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K)); + consensus.nEquihashN = N; + consensus.nEquihashK = K; consensus.powLimit = uint256S("0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"); consensus.nPowAveragingWindow = 17; assert(maxUint/UintToArith256(consensus.powLimit) >= consensus.nPowAveragingWindow); @@ -444,10 +448,6 @@ class CRegTestParams : public CChainParams { pchMessageStart[3] = 0x5f; nDefaultPort = 18344; nPruneAfterHeight = 1000; - const size_t N = 48, K = 5; - BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K)); - nEquihashN = N; - nEquihashK = K; genesis = CreateGenesisBlock( 1296688602, diff --git a/src/chainparams.h b/src/chainparams.h index ce5c1d6a179..17ebe9d31a6 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -83,8 +83,6 @@ class CChainParams /** Policy: Filter transactions that do not match well-defined patterns */ bool RequireStandard() const { return fRequireStandard; } int64_t PruneAfterHeight() const { return nPruneAfterHeight; } - unsigned int EquihashN() const { return nEquihashN; } - unsigned int EquihashK() const { return nEquihashK; } std::string CurrencyUnits() const { return strCurrencyUnits; } uint32_t BIP44CoinType() const { return bip44CoinType; } /** Make miner stop after a block is found. In RPC, don't return until nGenProcLimit blocks are generated */ @@ -113,8 +111,6 @@ class CChainParams std::vector vAlertPubKey; int nDefaultPort = 0; uint64_t nPruneAfterHeight = 0; - unsigned int nEquihashN = 0; - unsigned int nEquihashK = 0; std::vector vSeeds; std::vector base58Prefixes[MAX_BASE58_TYPES]; std::string bech32HRPs[MAX_BECH32_TYPES]; diff --git a/src/consensus/params.h b/src/consensus/params.h index 77f30bf4e69..9cd3a84617d 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -93,6 +93,8 @@ struct Params { int nMajorityWindow; NetworkUpgrade vUpgrades[MAX_NETWORK_UPGRADES]; /** Proof of work parameters */ + unsigned int nEquihashN = 0; + unsigned int nEquihashK = 0; uint256 powLimit; boost::optional nPowAllowMinDifficultyBlocksAfterHeight; int64_t nPowAveragingWindow; diff --git a/src/main.cpp b/src/main.cpp index 8806542cd97..7c374108639 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1716,7 +1716,7 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos) } // Check the header - if (!(CheckEquihashSolution(&block, Params()) && + if (!(CheckEquihashSolution(&block, Params().GetConsensus()) && CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus()))) return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString()); @@ -3717,7 +3717,7 @@ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool f REJECT_INVALID, "version-too-low"); // Check Equihash solution is valid - if (fCheckPOW && !CheckEquihashSolution(&block, Params())) + if (fCheckPOW && !CheckEquihashSolution(&block, Params().GetConsensus())) return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"), REJECT_INVALID, "invalid-solution"); diff --git a/src/miner.cpp b/src/miner.cpp index a5258f39d88..1ca5e264fd9 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -533,8 +533,8 @@ void static BitcoinMiner(const CChainParams& chainparams) boost::shared_ptr coinbaseScript; GetMainSignals().ScriptForMining(coinbaseScript); - unsigned int n = chainparams.EquihashN(); - unsigned int k = chainparams.EquihashK(); + unsigned int n = chainparams.GetConsensus().nEquihashN; + unsigned int k = chainparams.GetConsensus().nEquihashK; std::string solver = GetArg("-equihashsolver", "default"); assert(solver == "tromp" || solver == "default"); diff --git a/src/pow.cpp b/src/pow.cpp index 743df08ee30..ec0410acca2 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -91,10 +91,10 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg, return bnNew.GetCompact(); } -bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams& params) +bool CheckEquihashSolution(const CBlockHeader *pblock, const Consensus::Params& params) { - unsigned int n = params.EquihashN(); - unsigned int k = params.EquihashK(); + unsigned int n = params.nEquihashN; + unsigned int k = params.nEquihashK; // Hash state crypto_generichash_blake2b_state state; diff --git a/src/pow.h b/src/pow.h index 30d0f5e63b7..e3cf822d8dd 100644 --- a/src/pow.h +++ b/src/pow.h @@ -22,7 +22,7 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg, const Consensus::Params&); /** Check whether the Equihash solution in a block header is valid */ -bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams&); +bool CheckEquihashSolution(const CBlockHeader *pblock, const Consensus::Params&); /** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */ bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 73963da1994..0287df80483 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -195,8 +195,8 @@ UniValue generate(const UniValue& params, bool fHelp) } unsigned int nExtraNonce = 0; UniValue blockHashes(UniValue::VARR); - unsigned int n = Params().EquihashN(); - unsigned int k = Params().EquihashK(); + unsigned int n = Params().GetConsensus().nEquihashN; + unsigned int k = Params().GetConsensus().nEquihashK; while (nHeight < nHeightEnd) { std::unique_ptr pblocktemplate(CreateNewBlock(coinbaseScript->reserveScript)); diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 3f6a0af77ea..263ff841722 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -182,8 +182,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) /* { arith_uint256 try_nonce(0); - unsigned int n = Params().EquihashN(); - unsigned int k = Params().EquihashK(); + unsigned int n = Params().GetConsensus().nEquihashN; + unsigned int k = Params().GetConsensus().nEquihashK; // Hash state crypto_generichash_blake2b_state eh_state; diff --git a/src/zcbenchmarks.cpp b/src/zcbenchmarks.cpp index d91e36d730a..d257ce8ece9 100644 --- a/src/zcbenchmarks.cpp +++ b/src/zcbenchmarks.cpp @@ -172,8 +172,9 @@ double benchmark_solve_equihash() CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << I; - unsigned int n = Params(CBaseChainParams::MAIN).EquihashN(); - unsigned int k = Params(CBaseChainParams::MAIN).EquihashK(); + auto params = Params(CBaseChainParams::MAIN).GetConsensus(); + unsigned int n = params.nEquihashN; + unsigned int k = params.nEquihashK; crypto_generichash_blake2b_state eh_state; EhInitialiseState(n, k, eh_state); crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size()); @@ -217,11 +218,11 @@ std::vector benchmark_solve_equihash_threaded(int nThreads) double benchmark_verify_equihash() { CChainParams params = Params(CBaseChainParams::MAIN); - CBlock genesis = Params(CBaseChainParams::MAIN).GenesisBlock(); + CBlock genesis = params.GenesisBlock(); CBlockHeader genesis_header = genesis.GetBlockHeader(); struct timeval tv_start; timer_start(tv_start); - CheckEquihashSolution(&genesis_header, params); + CheckEquihashSolution(&genesis_header, params.GetConsensus()); return timer_stop(tv_start); } From 71cf6ba98bf80a68b4bc435de124a7fa672055a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Fri, 17 Apr 2015 14:19:21 +0200 Subject: [PATCH 104/395] Globals: Explicit Consensus::Params arg for main: -CheckBlockIndex -DisconnectTip -GetTransaction -InvalidateBlock -ProcessGetData -ReadBlockFromDisk --- src/amqp/amqppublishnotifier.cpp | 4 +- src/main.cpp | 73 +++++++++++++++++--------------- src/main.h | 12 +++--- src/rest.cpp | 5 ++- src/rpc/blockchain.cpp | 4 +- src/rpc/rawtransaction.cpp | 6 +-- src/wallet/rpcdisclosure.cpp | 4 +- src/wallet/wallet.cpp | 6 +-- src/zmq/zmqpublishnotifier.cpp | 4 +- 9 files changed, 63 insertions(+), 55 deletions(-) diff --git a/src/amqp/amqppublishnotifier.cpp b/src/amqp/amqppublishnotifier.cpp index 589eb151fb6..2704d94c2c5 100644 --- a/src/amqp/amqppublishnotifier.cpp +++ b/src/amqp/amqppublishnotifier.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "amqppublishnotifier.h" +#include "chainparams.h" #include "main.h" #include "util.h" @@ -152,11 +153,12 @@ bool AMQPPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex) { LogPrint("amqp", "amqp: Publish rawblock %s\n", pindex->GetBlockHash().GetHex()); + const Consensus::Params& consensusParams = Params().GetConsensus(); CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); { LOCK(cs_main); CBlock block; - if(!ReadBlockFromDisk(block, pindex)) { + if(!ReadBlockFromDisk(block, pindex, consensusParams)) { LogPrint("amqp", "amqp: Can't read block from disk"); return false; } diff --git a/src/main.cpp b/src/main.cpp index 7c374108639..00849af4048 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -104,7 +104,7 @@ void EraseOrphansFor(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main); * in the last Consensus::Params::nMajorityWindow blocks, starting at pstart and going backwards. */ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned nRequired, const Consensus::Params& consensusParams); -static void CheckBlockIndex(); +static void CheckBlockIndex(const Consensus::Params& consensusParams); /** Constant stuff for coinbase transactions we create: */ CScript COINBASE_FLAGS; @@ -1607,7 +1607,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } /** Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */ -bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow) +bool GetTransaction(const uint256 &hash, CTransaction &txOut, const Consensus::Params& consensusParams, uint256 &hashBlock, bool fAllowSlow) { CBlockIndex *pindexSlow = NULL; @@ -1653,7 +1653,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock if (pindexSlow) { CBlock block; - if (ReadBlockFromDisk(block, pindexSlow)) { + if (ReadBlockFromDisk(block, pindexSlow, consensusParams)) { BOOST_FOREACH(const CTransaction &tx, block.vtx) { if (tx.GetHash() == hash) { txOut = tx; @@ -1698,7 +1698,7 @@ bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHea return true; } -bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos) +bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus::Params& consensusParams) { block.SetNull(); @@ -1716,16 +1716,16 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos) } // Check the header - if (!(CheckEquihashSolution(&block, Params().GetConsensus()) && - CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus()))) + if (!(CheckEquihashSolution(&block, consensusParams) && + CheckProofOfWork(block.GetHash(), block.nBits, consensusParams))) return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString()); return true; } -bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex) +bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams) { - if (!ReadBlockFromDisk(block, pindex->GetBlockPos())) + if (!ReadBlockFromDisk(block, pindex->GetBlockPos(), consensusParams)) return false; if (block.GetHash() != pindex->GetBlockHash()) return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s", @@ -3019,12 +3019,12 @@ void static UpdateTip(CBlockIndex *pindexNew) { * Disconnect chainActive's tip. You probably want to call mempool.removeForReorg and * mempool.removeWithoutBranchId after this, with cs_main held. */ -bool static DisconnectTip(CValidationState &state, bool fBare = false) { +bool static DisconnectTip(CValidationState &state, const Consensus::Params& consensusParams, bool fBare = false) { CBlockIndex *pindexDelete = chainActive.Tip(); assert(pindexDelete); // Read block from disk. CBlock block; - if (!ReadBlockFromDisk(block, pindexDelete)) + if (!ReadBlockFromDisk(block, pindexDelete, consensusParams)) return AbortNode(state, "Failed to read block"); // Apply the block atomically to the chain state. uint256 sproutAnchorBeforeDisconnect = pcoinsTip->GetBestAnchor(SPROUT); @@ -3094,12 +3094,13 @@ static int64_t nTimePostConnect = 0; * You probably want to call mempool.removeWithoutBranchId after this, with cs_main held. */ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, const CBlock *pblock) { + const CChainParams& chainparams = Params(); assert(pindexNew->pprev == chainActive.Tip()); // Read block from disk. int64_t nTime1 = GetTimeMicros(); CBlock block; if (!pblock) { - if (!ReadBlockFromDisk(block, pindexNew)) + if (!ReadBlockFromDisk(block, pindexNew, chainparams.GetConsensus())) return AbortNode(state, "Failed to read block"); pblock = █ } @@ -3237,6 +3238,7 @@ static void PruneBlockIndexCandidates() { * pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork. */ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork, const CBlock *pblock) { + const CChainParams& chainparams = Params(); AssertLockHeld(cs_main); bool fInvalidFound = false; const CBlockIndex *pindexOldTip = chainActive.Tip(); @@ -3270,7 +3272,7 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo // Disconnect active blocks which are no longer in the best chain. bool fBlocksDisconnected = false; while (chainActive.Tip() && chainActive.Tip() != pindexFork) { - if (!DisconnectTip(state)) + if (!DisconnectTip(state, chainparams.GetConsensus())) return false; fBlocksDisconnected = true; } @@ -3342,7 +3344,7 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo bool ActivateBestChain(CValidationState &state, const CBlock *pblock) { CBlockIndex *pindexNewTip = NULL; CBlockIndex *pindexMostWork = NULL; - const CChainParams& chainParams = Params(); + const CChainParams& chainparams = Params(); do { boost::this_thread::interruption_point(); @@ -3369,7 +3371,7 @@ bool ActivateBestChain(CValidationState &state, const CBlock *pblock) { // Relay inventory, but don't relay old inventory during initial block download. int nBlockEstimate = 0; if (fCheckpointsEnabled) - nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(chainParams.Checkpoints()); + nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(chainparams.Checkpoints()); { LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) @@ -3381,7 +3383,7 @@ bool ActivateBestChain(CValidationState &state, const CBlock *pblock) { uiInterface.NotifyBlockTip(hashNewTip); } } while(pindexMostWork != chainActive.Tip()); - CheckBlockIndex(); + CheckBlockIndex(chainparams.GetConsensus()); // Write changes periodically to disk, after relay. if (!FlushStateToDisk(state, FLUSH_STATE_PERIODIC)) { @@ -3391,7 +3393,8 @@ bool ActivateBestChain(CValidationState &state, const CBlock *pblock) { return true; } -bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) { +bool InvalidateBlock(CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex *pindex) +{ AssertLockHeld(cs_main); // Mark the block itself as invalid. @@ -3406,10 +3409,10 @@ bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) { setBlockIndexCandidates.erase(pindexWalk); // ActivateBestChain considers blocks already in chainActive // unconditionally valid already, so force disconnect away from it. - if (!DisconnectTip(state)) { + if (!DisconnectTip(state, consensusParams)) { mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS); mempool.removeWithoutBranchId( - CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, Params().GetConsensus())); + CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, consensusParams)); return false; } } @@ -3427,7 +3430,7 @@ bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) { InvalidChainFound(pindex); mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS); mempool.removeWithoutBranchId( - CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, Params().GetConsensus())); + CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, consensusParams)); return true; } @@ -4019,6 +4022,7 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned bool ProcessNewBlock(CValidationState &state, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp) { + const CChainParams& chainparams = Params(); // Preliminary checks auto verifier = libzcash::ProofVerifier::Disabled(); bool checked = CheckBlock(*pblock, state, verifier); @@ -4037,7 +4041,7 @@ bool ProcessNewBlock(CValidationState &state, const CNode* pfrom, const CBlock* if (pindex && pfrom) { mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId(); } - CheckBlockIndex(); + CheckBlockIndex(chainparams.GetConsensus()); if (!ret) return error("%s: AcceptBlock FAILED", __func__); } @@ -4432,6 +4436,7 @@ CVerifyDB::~CVerifyDB() bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth) { + const CChainParams& chainparams = Params(); LOCK(cs_main); if (chainActive.Tip() == NULL || chainActive.Tip()->pprev == NULL) return true; @@ -4458,7 +4463,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth break; CBlock block; // check level 0: read from disk - if (!ReadBlockFromDisk(block, pindex)) + if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus())) return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); // check level 1: verify block validity if (nCheckLevel >= 1 && !CheckBlock(block, state, verifier)) @@ -4501,7 +4506,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, 100 - (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * 50)))); pindex = chainActive.Next(pindex); CBlock block; - if (!ReadBlockFromDisk(block, pindex)) + if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus())) return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); if (!ConnectBlock(block, state, pindex, coins)) return error("VerifyDB(): *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); @@ -4597,7 +4602,7 @@ bool RewindBlockIndex(const CChainParams& params, bool& clearWitnessCaches) // of the blockchain). break; } - if (!DisconnectTip(state, true)) { + if (!DisconnectTip(state, params.GetConsensus(), true)) { return error("RewindBlockIndex: unable to disconnect block at height %i", pindex->nHeight); } // Occasionally flush state to disk. @@ -4659,7 +4664,7 @@ bool RewindBlockIndex(const CChainParams& params, bool& clearWitnessCaches) PruneBlockIndexCandidates(); - CheckBlockIndex(); + CheckBlockIndex(params.GetConsensus()); if (!FlushStateToDisk(state, FLUSH_STATE_ALWAYS)) { return false; @@ -4837,7 +4842,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) std::pair::iterator, std::multimap::iterator> range = mapBlocksUnknownParent.equal_range(head); while (range.first != range.second) { std::multimap::iterator it = range.first; - if (ReadBlockFromDisk(block, it->second)) + if (ReadBlockFromDisk(block, it->second, chainparams.GetConsensus())) { LogPrintf("%s: Processing out of order child %s of %s\n", __func__, block.GetHash().ToString(), head.ToString()); @@ -4864,9 +4869,8 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) return nLoaded > 0; } -void static CheckBlockIndex() +void static CheckBlockIndex(const Consensus::Params& consensusParams) { - const Consensus::Params& consensusParams = Params().GetConsensus(); if (!fCheckBlockIndex) { return; } @@ -5151,7 +5155,7 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main) return true; } -void static ProcessGetData(CNode* pfrom) +void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParams) { int currentHeight = GetHeight(); @@ -5198,7 +5202,7 @@ void static ProcessGetData(CNode* pfrom) { // Send block from disk CBlock block; - if (!ReadBlockFromDisk(block, (*mi).second)) + if (!ReadBlockFromDisk(block, (*mi).second, consensusParams)) assert(!"cannot load block from disk"); if (inv.type == MSG_BLOCK) pfrom->PushMessage("block", block); @@ -5630,7 +5634,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, LogPrint("net", "received getdata for: %s peer=%d\n", vInv[0].ToString(), pfrom->id); pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end()); - ProcessGetData(pfrom); + ProcessGetData(pfrom, chainparams.GetConsensus()); } @@ -5904,7 +5908,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->PushMessage("getheaders", chainActive.GetLocator(pindexLast), uint256()); } - CheckBlockIndex(); + CheckBlockIndex(chainparams.GetConsensus()); } else if (strCommand == "block" && !fImporting && !fReindex) // Ignore blocks received while importing @@ -6208,6 +6212,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // requires LOCK(cs_vRecvMsg) bool ProcessMessages(CNode* pfrom) { + const CChainParams& chainparams = Params(); //if (fDebug) // LogPrintf("%s(%u messages)\n", __func__, pfrom->vRecvMsg.size()); @@ -6222,7 +6227,7 @@ bool ProcessMessages(CNode* pfrom) bool fOk = true; if (!pfrom->vRecvGetData.empty()) - ProcessGetData(pfrom); + ProcessGetData(pfrom, chainparams.GetConsensus()); // this maintains the order of responses if (!pfrom->vRecvGetData.empty()) return fOk; @@ -6249,7 +6254,7 @@ bool ProcessMessages(CNode* pfrom) it++; // Scan for message start - if (memcmp(msg.hdr.pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE) != 0) { + if (memcmp(msg.hdr.pchMessageStart, chainparams.MessageStart(), MESSAGE_START_SIZE) != 0) { LogPrintf("PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.hdr.GetCommand()), pfrom->id); fOk = false; break; @@ -6257,7 +6262,7 @@ bool ProcessMessages(CNode* pfrom) // Read header CMessageHeader& hdr = msg.hdr; - if (!hdr.IsValid(Params().MessageStart())) + if (!hdr.IsValid(chainparams.MessageStart())) { LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->id); continue; diff --git a/src/main.h b/src/main.h index b5f82cecad2..3e55f926970 100644 --- a/src/main.h +++ b/src/main.h @@ -239,7 +239,7 @@ bool IsInitialBlockDownload(); /** Format a string that describes several potential problems detected by the core */ std::string GetWarnings(const std::string& strFor); /** Retrieve a transaction (from memory pool, or from disk, if possible) */ -bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, bool fAllowSlow = false); +bool GetTransaction(const uint256 &hash, CTransaction &tx, const Consensus::Params& params, uint256 &hashBlock, bool fAllowSlow = false); /** Find the best known block, and make it the tip of the block chain */ bool ActivateBestChain(CValidationState &state, const CBlock *pblock = NULL); CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams); @@ -462,9 +462,8 @@ class CScriptCheck /** Functions for disk access for blocks */ bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart); -bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos); -bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex); - +bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus::Params& consensusParams); +bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams); /** Functions for validating blocks and updating the block tree */ @@ -492,8 +491,7 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex * If dbp is non-NULL, the file is known to already reside on disk */ bool AcceptBlock(const CBlock& block, CValidationState& state, CBlockIndex **pindex, bool fRequested, CDiskBlockPos* dbp); -bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL); - +bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex **ppindex= NULL); /** @@ -572,7 +570,7 @@ class CVerifyDB { CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator); /** Mark a block as invalid. */ -bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex); +bool InvalidateBlock(CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex *pindex); /** Remove invalidity status from a block and its descendants. */ bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex); diff --git a/src/rest.cpp b/src/rest.cpp index 4f92bbb0af7..e70ce517aac 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -3,6 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "chainparams.h" #include "primitives/block.h" #include "primitives/transaction.h" #include "main.h" @@ -214,7 +215,7 @@ static bool rest_block(HTTPRequest* req, if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not available (pruned data)"); - if (!ReadBlockFromDisk(block, pblockindex)) + if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found"); } @@ -355,7 +356,7 @@ static bool rest_tx(HTTPRequest* req, const std::string& strURIPart) CTransaction tx; uint256 hashBlock = uint256(); - if (!GetTransaction(hash, tx, hashBlock, true)) + if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true)) return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found"); CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 58089d0d676..235b682ce78 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -493,7 +493,7 @@ UniValue getblock(const UniValue& params, bool fHelp) if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); - if(!ReadBlockFromDisk(block, pblockindex)) + if(!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); if (verbosity == 0) @@ -976,7 +976,7 @@ UniValue invalidateblock(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); CBlockIndex* pblockindex = mapBlockIndex[hash]; - InvalidateBlock(state, pblockindex); + InvalidateBlock(state, Params().GetConsensus(), pblockindex); } if (state.IsValid()) { diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 90069112b8a..49768c24730 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -322,7 +322,7 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp) CTransaction tx; uint256 hashBlock; - if (!GetTransaction(hash, tx, hashBlock, true)) + if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction"); string strHex = EncodeHexTx(tx); @@ -392,7 +392,7 @@ UniValue gettxoutproof(const UniValue& params, bool fHelp) if (pblockindex == NULL) { CTransaction tx; - if (!GetTransaction(oneTxid, tx, hashBlock, false) || hashBlock.IsNull()) + if (!GetTransaction(oneTxid, tx, Params().GetConsensus(), hashBlock, false) || hashBlock.IsNull()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not yet in block"); if (!mapBlockIndex.count(hashBlock)) throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction index corrupt"); @@ -400,7 +400,7 @@ UniValue gettxoutproof(const UniValue& params, bool fHelp) } CBlock block; - if(!ReadBlockFromDisk(block, pblockindex)) + if(!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); unsigned int ntxFound = 0; diff --git a/src/wallet/rpcdisclosure.cpp b/src/wallet/rpcdisclosure.cpp index df35bb6ddf2..82d20b76ce2 100644 --- a/src/wallet/rpcdisclosure.cpp +++ b/src/wallet/rpcdisclosure.cpp @@ -82,7 +82,7 @@ UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp) uint256 hashBlock; // Check txid has been seen - if (!GetTransaction(hash, tx, hashBlock, true)) { + if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction"); } @@ -210,7 +210,7 @@ UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp) CTransaction tx; uint256 hashBlock; // Check if we have seen the transaction - if (!GetTransaction(hash, tx, hashBlock, true)) { + if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction"); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 23030257a89..659431f19a2 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1134,7 +1134,7 @@ void CWallet::IncrementNoteWitnesses(const CBlockIndex* pindex, const CBlock* pblock {pblockIn}; CBlock block; if (!pblock) { - ReadBlockFromDisk(block, pindex); + ReadBlockFromDisk(block, pindex, Params().GetConsensus()); pblock = █ } @@ -2432,7 +2432,7 @@ void CWallet::WitnessNoteCommitment(std::vector commitments, while (pindex) { CBlock block; - ReadBlockFromDisk(block, pindex); + ReadBlockFromDisk(block, pindex, Params().GetConsensus()); BOOST_FOREACH(const CTransaction& tx, block.vtx) { @@ -2511,7 +2511,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex, false) - dProgressStart) / (dProgressTip - dProgressStart) * 100)))); CBlock block; - ReadBlockFromDisk(block, pindex); + ReadBlockFromDisk(block, pindex, Params().GetConsensus()); BOOST_FOREACH(CTransaction& tx, block.vtx) { if (AddToWalletIfInvolvingMe(tx, &block, fUpdate)) { diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp index 4567f25b1f9..28cf2e597dc 100644 --- a/src/zmq/zmqpublishnotifier.cpp +++ b/src/zmq/zmqpublishnotifier.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "chainparams.h" #include "zmqpublishnotifier.h" #include "main.h" #include "util.h" @@ -164,11 +165,12 @@ bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex) { LogPrint("zmq", "zmq: Publish rawblock %s\n", pindex->GetBlockHash().GetHex()); + const Consensus::Params& consensusParams = Params().GetConsensus(); CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); { LOCK(cs_main); CBlock block; - if(!ReadBlockFromDisk(block, pindex)) + if(!ReadBlockFromDisk(block, pindex, consensusParams)) { zmqError("Can't read block from disk"); return false; From 94debefbcfb6a64b2b9c5804894c1308c3d3d642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Tue, 10 Nov 2015 19:28:56 +0100 Subject: [PATCH 105/395] Globals: Make AcceptBlockHeader static (Fix #6163) ..and at the same time prevent AcceptBlockHeader() from calling global function Params() --- src/main.cpp | 7 +++---- src/main.h | 1 - 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 00849af4048..e9611e19341 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3897,9 +3897,8 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn return true; } -bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex** ppindex) +static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex=NULL) { - const CChainParams& chainparams = Params(); AssertLockHeld(cs_main); // Check for duplicate uint256 hash = block.GetHash(); @@ -3948,7 +3947,7 @@ bool AcceptBlock(const CBlock& block, CValidationState& state, CBlockIndex** ppi CBlockIndex *&pindex = *ppindex; - if (!AcceptBlockHeader(block, state, &pindex)) + if (!AcceptBlockHeader(block, state, chainparams, &pindex)) return false; // Try to process all requested blocks that we don't have, but only @@ -5887,7 +5886,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, Misbehaving(pfrom->GetId(), 20); return error("non-continuous headers sequence"); } - if (!AcceptBlockHeader(header, state, &pindexLast)) { + if (!AcceptBlockHeader(header, state, chainparams, &pindexLast)) { int nDoS; if (state.IsInvalid(nDoS)) { if (nDoS > 0) diff --git a/src/main.h b/src/main.h index 3e55f926970..818936e9438 100644 --- a/src/main.h +++ b/src/main.h @@ -491,7 +491,6 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex * If dbp is non-NULL, the file is known to already reside on disk */ bool AcceptBlock(const CBlock& block, CValidationState& state, CBlockIndex **pindex, bool fRequested, CDiskBlockPos* dbp); -bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex **ppindex= NULL); /** From 8e5d8ca52a687ddf606fe6c589a52782eb0556a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Mon, 20 Apr 2015 00:17:11 +0200 Subject: [PATCH 106/395] Chainparams: Explicit CChainParams arg for main (pre miner): -ProcessNewBlock -TestBlockValidity --- src/main.cpp | 11 +++++------ src/main.h | 5 +++-- src/miner.cpp | 4 ++-- src/rpc/mining.cpp | 6 +++--- src/test/miner_tests.cpp | 3 ++- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index e9611e19341..c8e01725bb7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4019,9 +4019,8 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned } -bool ProcessNewBlock(CValidationState &state, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp) +bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, CDiskBlockPos* dbp) { - const CChainParams& chainparams = Params(); // Preliminary checks auto verifier = libzcash::ProofVerifier::Disabled(); bool checked = CheckBlock(*pblock, state, verifier); @@ -4051,7 +4050,7 @@ bool ProcessNewBlock(CValidationState &state, const CNode* pfrom, const CBlock* return true; } -bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex * const pindexPrev, bool fCheckPOW, bool fCheckMerkleRoot) +bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW, bool fCheckMerkleRoot) { AssertLockHeld(cs_main); assert(pindexPrev == chainActive.Tip()); @@ -4824,7 +4823,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) // process in case the block isn't known yet if (mapBlockIndex.count(hash) == 0 || (mapBlockIndex[hash]->nStatus & BLOCK_HAVE_DATA) == 0) { CValidationState state; - if (ProcessNewBlock(state, NULL, &block, true, dbp)) + if (ProcessNewBlock(state, chainparams, NULL, &block, true, dbp)) nLoaded++; if (state.IsError()) break; @@ -4846,7 +4845,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) LogPrintf("%s: Processing out of order child %s of %s\n", __func__, block.GetHash().ToString(), head.ToString()); CValidationState dummy; - if (ProcessNewBlock(dummy, NULL, &block, true, &it->second)) + if (ProcessNewBlock(dummy, chainparams, NULL, &block, true, &it->second)) { nLoaded++; queue.push_back(block.GetHash()); @@ -5926,7 +5925,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Such an unrequested block may still be processed, subject to the // conditions in AcceptBlock(). bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload(); - ProcessNewBlock(state, pfrom, &block, forceProcessing, NULL); + ProcessNewBlock(state, chainparams, pfrom, &block, forceProcessing, NULL); int nDoS; if (state.IsInvalid(nDoS)) { pfrom->PushMessage("reject", strCommand, state.GetRejectCode(), diff --git a/src/main.h b/src/main.h index 818936e9438..1e3a5a4bcab 100644 --- a/src/main.h +++ b/src/main.h @@ -44,6 +44,7 @@ class CBlockIndex; class CBlockTreeDB; class CBloomFilter; +class CChainParams; class CInv; class CScriptCheck; class CValidationInterface; @@ -204,7 +205,7 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals); * @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location. * @return True if state.IsValid() */ -bool ProcessNewBlock(CValidationState &state, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp); +bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, CDiskBlockPos* dbp); /** Check whether enough disk space is available for an incoming block */ bool CheckDiskSpace(uint64_t nAdditionalBytes = 0); /** Open a block file (blk?????.dat) */ @@ -481,7 +482,7 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex *pindexPrev); /** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */ -bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex *pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true); +bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true); /** * Store block on disk. diff --git a/src/miner.cpp b/src/miner.cpp index 1ca5e264fd9..5c921ca037e 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -439,7 +439,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]); CValidationState state; - if (!TestBlockValidity(state, *pblock, pindexPrev, false, false)) + if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) throw std::runtime_error("CreateNewBlock(): TestBlockValidity failed"); } @@ -513,7 +513,7 @@ static bool ProcessBlockFound(const CBlock* pblock, const CChainParams& chainpar // Process this block the same as if we had received it from another node CValidationState state; - if (!ProcessNewBlock(state, NULL, pblock, true, NULL)) + if (!ProcessNewBlock(state, chainparams, NULL, pblock, true, NULL)) return error("ZcashMiner: ProcessNewBlock, block not accepted"); TrackMinedBlock(pblock->GetHash()); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 0287df80483..1cd0848885a 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -247,7 +247,7 @@ UniValue generate(const UniValue& params, bool fHelp) } endloop: CValidationState state; - if (!ProcessNewBlock(state, NULL, pblock, true, NULL)) + if (!ProcessNewBlock(state, Params(), NULL, pblock, true, NULL)) throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted"); ++nHeight; blockHashes.push_back(pblock->GetHash().GetHex()); @@ -523,7 +523,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) if (block.hashPrevBlock != pindexPrev->GetBlockHash()) return "inconclusive-not-best-prevblk"; CValidationState state; - TestBlockValidity(state, block, pindexPrev, false, true); + TestBlockValidity(state, Params(), block, pindexPrev, false, true); return BIP22ValidationResult(state); } } @@ -782,7 +782,7 @@ UniValue submitblock(const UniValue& params, bool fHelp) CValidationState state; submitblock_StateCatcher sc(block.GetHash()); RegisterValidationInterface(&sc); - bool fAccepted = ProcessNewBlock(state, NULL, &block, true, NULL); + bool fAccepted = ProcessNewBlock(state, Params(), NULL, &block, true, NULL); UnregisterValidationInterface(&sc); if (fBlockPresent) { diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 263ff841722..4c19f691657 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -138,6 +138,7 @@ struct { // NOTE: These tests rely on CreateNewBlock doing its own self-validation! BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) { + const CChainParams& chainparams = Params(CBaseChainParams::MAIN); CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG; CBlockTemplate *pblocktemplate; CMutableTransaction tx,tx2; @@ -264,7 +265,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) pblock->hashFinalSaplingRoot = uint256(); CValidationState state; - BOOST_CHECK(ProcessNewBlock(state, NULL, pblock, true, NULL)); + BOOST_CHECK(ProcessNewBlock(state, chainparams, NULL, pblock, true, NULL)); BOOST_CHECK_MESSAGE(state.IsValid(), state.GetRejectReason()); pblock->hashPrevBlock = pblock->GetHash(); From 793a72e31f081dcf42da1a6b6f0474d8c0d9831b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Fri, 17 Apr 2015 14:19:52 +0200 Subject: [PATCH 107/395] Chainparams: Explicit CChainParams arg for miner: -BitcoinMiner -CreateNewBlock -GenerateBitcoins -ProcessBlockFound --- src/init.cpp | 2 +- src/miner.cpp | 13 ++++++------- src/miner.h | 2 +- src/rpc/mining.cpp | 4 ++-- src/test/miner_tests.cpp | 26 +++++++++++++------------- 5 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 30bdccd51ff..ae27f9fb845 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1868,7 +1868,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) #ifdef ENABLE_MINING // Generate coins in the background - GenerateBitcoins(GetBoolArg("-gen", false), GetArg("-genproclimit", 1), Params()); + GenerateBitcoins(GetBoolArg("-gen", false), GetArg("-genproclimit", 1), chainparams); #endif // ********************************************************* Step 11: finished diff --git a/src/miner.cpp b/src/miner.cpp index 5c921ca037e..ee37c44c7ab 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -106,9 +106,8 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, } } -CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) +CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& scriptPubKeyIn) { - const CChainParams& chainparams = Params(); // Create new block std::unique_ptr pblocktemplate(new CBlockTemplate()); if(!pblocktemplate.get()) @@ -117,7 +116,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) // -regtest only: allow overriding block.nVersion with // -blockversion=N to test forking scenarios - if (Params().MineBlocksOnDemand()) + if (chainparams.MineBlocksOnDemand()) pblock->nVersion = GetArg("-blockversion", pblock->nVersion); // Add dummy coinbase tx as first transaction @@ -324,7 +323,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) // create only contains transactions that are valid in new blocks. CValidationState state; PrecomputedTransactionData txdata(tx); - if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId)) + if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, chainparams.GetConsensus(), consensusBranchId)) continue; if (chainparams.ZIP209Enabled() && monitoring_pool_balances) { @@ -433,8 +432,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) // Fill in header pblock->hashPrevBlock = pindexPrev->GetBlockHash(); pblock->hashFinalSaplingRoot = sapling_tree.root(); - UpdateTime(pblock, Params().GetConsensus(), pindexPrev); - pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus()); + UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); + pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus()); pblock->nSolution.clear(); pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]); @@ -579,7 +578,7 @@ void static BitcoinMiner(const CChainParams& chainparams) unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); CBlockIndex* pindexPrev = chainActive.Tip(); - unique_ptr pblocktemplate(CreateNewBlock(coinbaseScript->reserveScript)); + unique_ptr pblocktemplate(CreateNewBlock(chainparams, coinbaseScript->reserveScript)); if (!pblocktemplate.get()) { if (GetArg("-mineraddress", "").empty()) { diff --git a/src/miner.h b/src/miner.h index 1d1ebaf9b4d..9059be633e5 100644 --- a/src/miner.h +++ b/src/miner.h @@ -24,7 +24,7 @@ struct CBlockTemplate }; /** Generate a new block, without valid proof-of-work */ -CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn); +CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& scriptPubKeyIn); #ifdef ENABLE_MINING /** Get script for -mineraddress */ diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 1cd0848885a..670d2edd4f3 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -199,7 +199,7 @@ UniValue generate(const UniValue& params, bool fHelp) unsigned int k = Params().GetConsensus().nEquihashK; while (nHeight < nHeightEnd) { - std::unique_ptr pblocktemplate(CreateNewBlock(coinbaseScript->reserveScript)); + std::unique_ptr pblocktemplate(CreateNewBlock(Params(), coinbaseScript->reserveScript)); if (!pblocktemplate.get()) throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block"); CBlock *pblock = &pblocktemplate->block; @@ -614,7 +614,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) if (!coinbaseScript->reserveScript.size()) throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available (mining requires a wallet or -mineraddress)"); - pblocktemplate = CreateNewBlock(coinbaseScript->reserveScript); + pblocktemplate = CreateNewBlock(Params(), coinbaseScript->reserveScript); if (!pblocktemplate) throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 4c19f691657..23e7634abbd 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -159,7 +159,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) for (unsigned int i = 0; i < sizeof(blockinfo)/sizeof(*blockinfo); ++i) { // Simple block creation, nothing special yet: - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); CBlock *pblock = &pblocktemplate->block; // pointer for convenience pblock->nVersion = 4; @@ -274,7 +274,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) } // Just to make sure we can still make simple blocks - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; // block sigops > limit: 1000 CHECKMULTISIG + 1 @@ -293,7 +293,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); tx.vin[0].prevout.hash = hash; } - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; mempool.clear(); @@ -314,14 +314,14 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); tx.vin[0].prevout.hash = hash; } - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; mempool.clear(); // orphan in mempool hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Time(GetTime()).FromTx(tx)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; mempool.clear(); @@ -339,7 +339,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue = 49000LL; hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; mempool.clear(); @@ -350,7 +350,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue = 0; hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; mempool.clear(); @@ -368,7 +368,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue -= 10000; hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; mempool.clear(); @@ -382,17 +382,17 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].scriptPubKey = CScript() << OP_2; hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; mempool.clear(); // subsidy changing int nHeight = chainActive.Height(); chainActive.Tip()->nHeight = 209999; - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; chainActive.Tip()->nHeight = 210000; - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; chainActive.Tip()->nHeight = nHeight; @@ -424,7 +424,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(true).FromTx(tx2)); BOOST_CHECK(!CheckFinalTx(tx2, LOCKTIME_MEDIAN_TIME_PAST)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); // Neither tx should have made it into the template. BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 1); @@ -439,7 +439,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) //BOOST_CHECK(CheckFinalTx(tx)); //BOOST_CHECK(CheckFinalTx(tx2)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 2); delete pblocktemplate; From 44b2d060efecc94fcc4f93ff4cc6720076c1cf8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Fri, 17 Apr 2015 14:40:24 +0200 Subject: [PATCH 108/395] Globals: Remove a bunch of Params() calls from main.cpp: 1) Chainparams: Explicit CChainParams arg for main: -AcceptBlock -AcceptBlockHeader -ActivateBestChain -ConnectTip -InitBlockIndex -LoadExternalBlockFile -VerifyDB parametric constructor 2) Also pickup more Params()\. in main.cpp 3) Pass nPruneAfterHeight explicitly to new FindFilesToPrune() in main.cpp --- src/init.cpp | 15 +++++----- src/main.cpp | 62 ++++++++++++++++++++------------------- src/main.h | 19 ++++-------- src/rpc/blockchain.cpp | 6 ++-- src/test/test_bitcoin.cpp | 3 +- 5 files changed, 50 insertions(+), 55 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index ae27f9fb845..2743f473104 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -606,6 +606,7 @@ void CleanupBlockRevFiles() void ThreadImport(std::vector vImportFiles) { + const CChainParams& chainparams = Params(); RenameThread("zcash-loadblk"); // -reindex if (fReindex) { @@ -619,14 +620,14 @@ void ThreadImport(std::vector vImportFiles) if (!file) break; // This error is logged in OpenBlockFile LogPrintf("Reindexing block file blk%05u.dat...\n", (unsigned int)nFile); - LoadExternalBlockFile(file, &pos); + LoadExternalBlockFile(chainparams, file, &pos); nFile++; } pblocktree->WriteReindexing(false); fReindex = false; LogPrintf("Reindexing finished\n"); // To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked): - InitBlockIndex(); + InitBlockIndex(chainparams); } // hardcoded $DATADIR/bootstrap.dat @@ -637,7 +638,7 @@ void ThreadImport(std::vector vImportFiles) CImportingNow imp; boost::filesystem::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old"; LogPrintf("Importing bootstrap.dat...\n"); - LoadExternalBlockFile(file); + LoadExternalBlockFile(chainparams, file); RenameOver(pathBootstrap, pathBootstrapOld); } else { LogPrintf("Warning: Could not open bootstrap file %s\n", pathBootstrap.string()); @@ -650,7 +651,7 @@ void ThreadImport(std::vector vImportFiles) if (file) { CImportingNow imp; LogPrintf("Importing blocks file %s...\n", path.string()); - LoadExternalBlockFile(file); + LoadExternalBlockFile(chainparams, file); } else { LogPrintf("Warning: Could not open blocks file %s\n", path.string()); } @@ -1515,7 +1516,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?")); // Initialize the block index (no-op if non-empty database was already loaded) - if (!InitBlockIndex()) { + if (!InitBlockIndex(chainparams)) { strLoadError = _("Error initializing block database"); break; } @@ -1552,7 +1553,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) LogPrintf("Prune: pruned datadir may not have more than %d blocks; -checkblocks=%d may fail\n", MIN_BLOCKS_TO_KEEP, GetArg("-checkblocks", 288)); } - if (!CVerifyDB().VerifyDB(pcoinsdbview, GetArg("-checklevel", 3), + if (!CVerifyDB().VerifyDB(chainparams, pcoinsdbview, GetArg("-checklevel", 3), GetArg("-checkblocks", 288))) { strLoadError = _("Corrupted block database detected"); break; @@ -1822,7 +1823,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) uiInterface.InitMessage(_("Activating best chain...")); // scan for better chains in the block chain database, that are not yet connected in the active best chain CValidationState state; - if (!ActivateBestChain(state)) + if (!ActivateBestChain(state, chainparams)) strErrors << "Failed to connect best block"; std::vector vImportFiles; diff --git a/src/main.cpp b/src/main.cpp index c8e01725bb7..ff8e2047726 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2869,6 +2869,7 @@ enum FlushStateMode { * or always and in all cases if we're in prune mode and are deleting files. */ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) { + const CChainParams& chainparams = Params(); LOCK2(cs_main, cs_LastBlockFile); static int64_t nLastWrite = 0; static int64_t nLastFlush = 0; @@ -2877,7 +2878,7 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) { bool fFlushForPrune = false; try { if (fPruneMode && fCheckForPruning && !fReindex) { - FindFilesToPrune(setFilesToPrune); + FindFilesToPrune(setFilesToPrune, chainparams.PruneAfterHeight()); fCheckForPruning = false; if (!setFilesToPrune.empty()) { fFlushForPrune = true; @@ -3093,8 +3094,8 @@ static int64_t nTimePostConnect = 0; * corresponding to pindexNew, to bypass loading it again from disk. * You probably want to call mempool.removeWithoutBranchId after this, with cs_main held. */ -bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, const CBlock *pblock) { - const CChainParams& chainparams = Params(); +bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const CBlock* pblock) +{ assert(pindexNew->pprev == chainActive.Tip()); // Read block from disk. int64_t nTime1 = GetTimeMicros(); @@ -3237,8 +3238,8 @@ static void PruneBlockIndexCandidates() { * Try to make some progress towards making pindexMostWork the active block. * pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork. */ -static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork, const CBlock *pblock) { - const CChainParams& chainparams = Params(); +static bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const CBlock* pblock) +{ AssertLockHeld(cs_main); bool fInvalidFound = false; const CBlockIndex *pindexOldTip = chainActive.Tip(); @@ -3296,7 +3297,7 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo // Connect new blocks. BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) { - if (!ConnectTip(state, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL)) { + if (!ConnectTip(state, chainparams, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL)) { if (state.IsInvalid()) { // The block violates a consensus rule. if (!state.CorruptionPossible()) @@ -3341,10 +3342,10 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo * or an activated best chain. pblock is either NULL or a pointer to a block * that is already loaded (to avoid loading it again from disk). */ -bool ActivateBestChain(CValidationState &state, const CBlock *pblock) { +bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, const CBlock* pblock) +{ CBlockIndex *pindexNewTip = NULL; CBlockIndex *pindexMostWork = NULL; - const CChainParams& chainparams = Params(); do { boost::this_thread::interruption_point(); @@ -3357,7 +3358,7 @@ bool ActivateBestChain(CValidationState &state, const CBlock *pblock) { if (pindexMostWork == NULL || pindexMostWork == chainActive.Tip()) return true; - if (!ActivateBestChainStep(state, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : NULL)) + if (!ActivateBestChainStep(state, chainparams, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : NULL)) return false; pindexNewTip = chainActive.Tip(); @@ -3940,9 +3941,15 @@ static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state return true; } -bool AcceptBlock(const CBlock& block, CValidationState& state, CBlockIndex** ppindex, bool fRequested, CDiskBlockPos* dbp) +/** + * Store block on disk. + * JoinSplit proofs are never verified, because: + * - AcceptBlock doesn't perform script checks either. + * - The only caller of AcceptBlock verifies JoinSplit proofs elsewhere. + * If dbp is non-NULL, the file is known to already reside on disk + */ +static bool AcceptBlock(const CBlock& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, CDiskBlockPos* dbp) { - const CChainParams& chainparams = Params(); AssertLockHeld(cs_main); CBlockIndex *&pindex = *ppindex; @@ -4035,7 +4042,7 @@ bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, c // Store to disk CBlockIndex *pindex = NULL; - bool ret = AcceptBlock(*pblock, state, &pindex, fRequested, dbp); + bool ret = AcceptBlock(*pblock, state, chainparams, &pindex, fRequested, dbp); if (pindex && pfrom) { mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId(); } @@ -4044,7 +4051,7 @@ bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, c return error("%s: AcceptBlock FAILED", __func__); } - if (!ActivateBestChain(state, pblock)) + if (!ActivateBestChain(state, chainparams, pblock)) return error("%s: ActivateBestChain failed", __func__); return true; @@ -4134,13 +4141,13 @@ void UnlinkPrunedFiles(std::set& setFilesToPrune) } /* Calculate the block/rev files that should be deleted to remain under target*/ -void FindFilesToPrune(std::set& setFilesToPrune) +void FindFilesToPrune(std::set& setFilesToPrune, uint64_t nPruneAfterHeight) { LOCK2(cs_main, cs_LastBlockFile); if (chainActive.Tip() == NULL || nPruneTarget == 0) { return; } - if (chainActive.Tip()->nHeight <= Params().PruneAfterHeight()) { + if (chainActive.Tip()->nHeight <= nPruneAfterHeight) { return; } @@ -4432,9 +4439,8 @@ CVerifyDB::~CVerifyDB() uiInterface.ShowProgress("", 100); } -bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth) +bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, int nCheckLevel, int nCheckDepth) { - const CChainParams& chainparams = Params(); LOCK(cs_main); if (chainActive.Tip() == NULL || chainActive.Tip()->pprev == NULL) return true; @@ -4710,9 +4716,8 @@ bool LoadBlockIndex() return true; } - -bool InitBlockIndex() { - const CChainParams& chainparams = Params(); +bool InitBlockIndex(const CChainParams& chainparams) +{ LOCK(cs_main); // Initialize global variables that cannot be constructed at startup. @@ -4738,7 +4743,7 @@ bool InitBlockIndex() { // Only add the genesis block if not reindexing (in which case we reuse the one already on disk) if (!fReindex) { try { - CBlock &block = const_cast(Params().GenesisBlock()); + CBlock &block = const_cast(chainparams.GenesisBlock()); // Start new block file unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); CDiskBlockPos blockPos; @@ -4750,7 +4755,7 @@ bool InitBlockIndex() { CBlockIndex *pindex = AddToBlockIndex(block); if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) return error("LoadBlockIndex(): genesis block not accepted"); - if (!ActivateBestChain(state, &block)) + if (!ActivateBestChain(state, chainparams, &block)) return error("LoadBlockIndex(): genesis block cannot be activated"); // Force a chainstate write so that when we VerifyDB in a moment, it doesn't check stale data return FlushStateToDisk(state, FLUSH_STATE_ALWAYS); @@ -4762,11 +4767,8 @@ bool InitBlockIndex() { return true; } - - -bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) +bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp) { - const CChainParams& chainparams = Params(); // Map of disk positions for blocks with unknown parent (only used for reindex) static std::multimap mapBlocksUnknownParent; int64_t nStart = GetTimeMillis(); @@ -4786,10 +4788,10 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) try { // locate a header unsigned char buf[MESSAGE_START_SIZE]; - blkdat.FindByte(Params().MessageStart()[0]); + blkdat.FindByte(chainparams.MessageStart()[0]); nRewind = blkdat.GetPos()+1; blkdat >> FLATDATA(buf); - if (memcmp(buf, Params().MessageStart(), MESSAGE_START_SIZE)) + if (memcmp(buf, chainparams.MessageStart(), MESSAGE_START_SIZE)) continue; // read size blkdat >> nSize; @@ -5188,7 +5190,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam // best equivalent proof of work) than the best header chain we know about. send = mi->second->IsValid(BLOCK_VALID_SCRIPTS) && (pindexBestHeader != NULL) && (pindexBestHeader->GetBlockTime() - mi->second->GetBlockTime() < nOneMonth) && - (GetBlockProofEquivalentTime(*pindexBestHeader, *mi->second, *pindexBestHeader, Params().GetConsensus()) < nOneMonth); + (GetBlockProofEquivalentTime(*pindexBestHeader, *mi->second, *pindexBestHeader, consensusParams) < nOneMonth); if (!send) { LogPrintf("%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom->GetId()); } @@ -6081,7 +6083,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, uint256 alertHash = alert.GetHash(); if (pfrom->setKnown.count(alertHash) == 0) { - if (alert.ProcessAlert(Params().AlertKey())) + if (alert.ProcessAlert(chainparams.AlertKey())) { // Relay pfrom->setKnown.insert(alertHash); diff --git a/src/main.h b/src/main.h index 1e3a5a4bcab..467f3473ca2 100644 --- a/src/main.h +++ b/src/main.h @@ -215,9 +215,9 @@ FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false); /** Translation to a filesystem path */ boost::filesystem::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix); /** Import blocks from an external file */ -bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp = NULL); +bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp = NULL); /** Initialize a new block tree database + block data on disk */ -bool InitBlockIndex(); +bool InitBlockIndex(const CChainParams& chainparams); /** Load the block tree and coins database from disk */ bool LoadBlockIndex(); /** Unload database information */ @@ -242,7 +242,7 @@ std::string GetWarnings(const std::string& strFor); /** Retrieve a transaction (from memory pool, or from disk, if possible) */ bool GetTransaction(const uint256 &hash, CTransaction &tx, const Consensus::Params& params, uint256 &hashBlock, bool fAllowSlow = false); /** Find the best known block, and make it the tip of the block chain */ -bool ActivateBestChain(CValidationState &state, const CBlock *pblock = NULL); +bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, const CBlock* pblock = NULL); CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams); /** @@ -260,7 +260,7 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams); * * @param[out] setFilesToPrune The set of file indices that can be unlinked will be returned */ -void FindFilesToPrune(std::set& setFilesToPrune); +void FindFilesToPrune(std::set& setFilesToPrune, uint64_t nPruneAfterHeight); /** * Actually unlink the specified files @@ -484,15 +484,6 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn /** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true); -/** - * Store block on disk. - * JoinSplit proofs are never verified, because: - * - AcceptBlock doesn't perform script checks either. - * - The only caller of AcceptBlock verifies JoinSplit proofs elsewhere. - * If dbp is non-NULL, the file is known to already reside on disk - */ -bool AcceptBlock(const CBlock& block, CValidationState& state, CBlockIndex **pindex, bool fRequested, CDiskBlockPos* dbp); - /** * When there are blocks in the active chain with missing data (e.g. if the @@ -563,7 +554,7 @@ class CVerifyDB { public: CVerifyDB(); ~CVerifyDB(); - bool VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth); + bool VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, int nCheckLevel, int nCheckDepth); }; /** Find the last common block between the parameter chain and a locator. */ diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 235b682ce78..4305070e0aa 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -650,7 +650,7 @@ UniValue verifychain(const UniValue& params, bool fHelp) if (params.size() > 1) nCheckDepth = params[1].get_int(); - return CVerifyDB().VerifyDB(pcoinsTip, nCheckLevel, nCheckDepth); + return CVerifyDB().VerifyDB(Params(), pcoinsTip, nCheckLevel, nCheckDepth); } /** Implementation of IsSuperMajority with better feedback */ @@ -980,7 +980,7 @@ UniValue invalidateblock(const UniValue& params, bool fHelp) } if (state.IsValid()) { - ActivateBestChain(state); + ActivateBestChain(state, Params()); } if (!state.IsValid()) { @@ -1019,7 +1019,7 @@ UniValue reconsiderblock(const UniValue& params, bool fHelp) } if (state.IsValid()) { - ActivateBestChain(state); + ActivateBestChain(state, Params()); } if (!state.IsValid()) { diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 3548b9d4bec..f23837da4aa 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -87,6 +87,7 @@ BasicTestingSetup::~BasicTestingSetup() TestingSetup::TestingSetup() { + const CChainParams& chainparams = Params(); // Ideally we'd move all the RPC tests to the functional testing framework // instead of unit tests, but for now we need these here. RegisterAllCoreRPCCommands(tableRPC); @@ -105,7 +106,7 @@ TestingSetup::TestingSetup() pblocktree = new CBlockTreeDB(1 << 20, true); pcoinsdbview = new CCoinsViewDB(1 << 23, true); pcoinsTip = new CCoinsViewCache(pcoinsdbview); - InitBlockIndex(); + InitBlockIndex(chainparams); #ifdef ENABLE_WALLET bool fFirstRun; pwalletMain = new CWallet("wallet.dat"); From 9b0f61af2d90a19603b6d1b46391b6e8b6cb8e30 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Sun, 31 Jan 2016 00:40:23 -0500 Subject: [PATCH 109/395] Improve block validity/ConnectBlock() comments Previously didn't make clear that the ContextualCheckBlock* functions meant the block headers as context - not the UTXO set itself - and that ConnectBlock() also did UTXO-related validity checks (in the future we may split that functionality into a separate UTXO-specific contextual check block function). Also, reordered to put validity checks first for better readability. --- src/main.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main.h b/src/main.h index 467f3473ca2..03ef1866bc2 100644 --- a/src/main.h +++ b/src/main.h @@ -468,19 +468,23 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus /** Functions for validating blocks and updating the block tree */ -/** Apply the effects of this block (with given index) on the UTXO set represented by coins */ -bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false); - /** Context-independent validity checks */ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true); bool CheckBlock(const CBlock& block, CValidationState& state, libzcash::ProofVerifier& verifier, bool fCheckPOW = true, bool fCheckMerkleRoot = true); -/** Context-dependent validity checks */ +/** Context-dependent validity checks. + * By "context", we mean only the previous block headers, but not the UTXO + * set; UTXO-related validity checks are done in ConnectBlock(). */ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex *pindexPrev); bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex *pindexPrev); +/** Apply the effects of this block (with given index) on the UTXO set represented by coins. + * Validity checks that depend on the UTXO set are also done; ConnectBlock() + * can fail if those validity checks fail (among other reasons). */ +bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false); + /** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true); From 98f3010026fc06b398bf4ed3d5fb396afee46ee8 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 3 Apr 2016 11:49:36 +0200 Subject: [PATCH 110/395] [doc] Fix doxygen comments for members --- doc/developer-notes.md | 6 ++++++ src/chainparams.cpp | 4 ++-- src/main.cpp | 8 ++++---- src/main.h | 14 +++++++------- src/policy/fees.h | 4 ++-- src/rpc/client.cpp | 4 ++-- src/script/interpreter.cpp | 12 ++++++------ src/script/standard.h | 2 +- src/txmempool.h | 28 ++++++++++++++-------------- src/utiltime.cpp | 2 +- src/wallet/wallet.h | 8 ++++---- 11 files changed, 49 insertions(+), 43 deletions(-) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 311dbcc46c6..ddbd7df1889 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -71,6 +71,12 @@ To describe a member or variable use: int var; //!< Detailed description after the member ``` +or +```cpp +//! Description before the member +int var; +``` + Also OK: ```c++ /// diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 01b65ddbe45..0980d78121e 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -458,8 +458,8 @@ class CRegTestParams : public CChainParams { assert(consensus.hashGenesisBlock == uint256S("0x029f11d80ef9765602235e1bc9727e3eb6ba20839319f761fee920d63401e327")); assert(genesis.hashMerkleRoot == uint256S("0xc4eaa58879081de3c24a7b117ed2b28300e7ec4c4c1dff1d3f1268b7857a4ddb")); - vFixedSeeds.clear(); //! Regtest mode doesn't have any fixed seeds. - vSeeds.clear(); //! Regtest mode doesn't have any DNS seeds. + vFixedSeeds.clear(); //!< Regtest mode doesn't have any fixed seeds. + vSeeds.clear(); //!< Regtest mode doesn't have any DNS seeds. fMiningRequiresPeers = false; fDefaultConsistencyChecks = true; diff --git a/src/main.cpp b/src/main.cpp index ff8e2047726..9287f994435 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -200,10 +200,10 @@ namespace { /** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */ struct QueuedBlock { uint256 hash; - CBlockIndex *pindex; //! Optional. - int64_t nTime; //! Time of "getdata" request in microseconds. - bool fValidatedHeaders; //! Whether this block has validated headers at the time of request. - int64_t nTimeDisconnect; //! The timeout for this block request (for disconnecting a slow peer) + CBlockIndex* pindex; //!< Optional. + int64_t nTime; //!< Time of "getdata" request in microseconds. + bool fValidatedHeaders; //!< Whether this block has validated headers at the time of request. + int64_t nTimeDisconnect; //!< The timeout for this block request (for disconnecting a slow peer) }; map::iterator> > mapBlocksInFlight; diff --git a/src/main.h b/src/main.h index 03ef1866bc2..c7395dabd33 100644 --- a/src/main.h +++ b/src/main.h @@ -502,13 +502,13 @@ bool RewindBlockIndex(const CChainParams& params, bool& clearWitnessCaches); class CBlockFileInfo { public: - unsigned int nBlocks; //! number of blocks stored in file - unsigned int nSize; //! number of used bytes of block file - unsigned int nUndoSize; //! number of used bytes in the undo file - unsigned int nHeightFirst; //! lowest height of block in file - unsigned int nHeightLast; //! highest height of block in file - uint64_t nTimeFirst; //! earliest time of block in file - uint64_t nTimeLast; //! latest time of block in file + unsigned int nBlocks; //!< number of blocks stored in file + unsigned int nSize; //!< number of used bytes of block file + unsigned int nUndoSize; //!< number of used bytes in the undo file + unsigned int nHeightFirst; //!< lowest height of block in file + unsigned int nHeightLast; //!< highest height of block in file + uint64_t nTimeFirst; //!< earliest time of block in file + uint64_t nTimeLast; //!< latest time of block in file ADD_SERIALIZE_METHODS; diff --git a/src/policy/fees.h b/src/policy/fees.h index ee865c67911..52b0c36cdc7 100644 --- a/src/policy/fees.h +++ b/src/policy/fees.h @@ -259,8 +259,8 @@ class CBlockPolicyEstimator void Read(CAutoFile& filein); private: - CFeeRate minTrackedFee; //! Passed to constructor to avoid dependency on main - double minTrackedPriority; //! Set to AllowFreeThreshold + CFeeRate minTrackedFee; //!< Passed to constructor to avoid dependency on main + double minTrackedPriority; //!< Set to AllowFreeThreshold unsigned int nBestSeenHeight; struct TxStatsInfo { diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 8838bd27390..61c521a7b97 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -17,8 +17,8 @@ using namespace std; class CRPCConvertParam { public: - std::string methodName; //! method whose params want conversion - int paramIdx; //! 0-based idx of param to convert + std::string methodName; //!< method whose params want conversion + int paramIdx; //!< 0-based idx of param to convert }; static const CRPCConvertParam vRPCConvertParams[] = diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index ec1ac52551f..6719443d0b7 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -965,12 +965,12 @@ namespace { */ class CTransactionSignatureSerializer { private: - const CTransaction &txTo; //! reference to the spending transaction (the one being serialized) - const CScript &scriptCode; //! output script being consumed - const unsigned int nIn; //! input index of txTo being signed - const bool fAnyoneCanPay; //! whether the hashtype has the SIGHASH_ANYONECANPAY flag set - const bool fHashSingle; //! whether the hashtype is SIGHASH_SINGLE - const bool fHashNone; //! whether the hashtype is SIGHASH_NONE + const CTransaction& txTo; //!< reference to the spending transaction (the one being serialized) + const CScript& scriptCode; //!< output script being consumed + const unsigned int nIn; //!< input index of txTo being signed + const bool fAnyoneCanPay; //!< whether the hashtype has the SIGHASH_ANYONECANPAY flag set + const bool fHashSingle; //!< whether the hashtype is SIGHASH_SINGLE + const bool fHashNone; //!< whether the hashtype is SIGHASH_NONE public: CTransactionSignatureSerializer(const CTransaction &txToIn, const CScript &scriptCodeIn, unsigned int nInIn, int nHashTypeIn) : diff --git a/src/script/standard.h b/src/script/standard.h index fdb02f7c74f..5dcff1c1a5a 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -25,7 +25,7 @@ class CScriptID : public uint160 CScriptID(const uint160& in) : uint160(in) {} }; -static const unsigned int MAX_OP_RETURN_RELAY = 80; //! bytes +static const unsigned int MAX_OP_RETURN_RELAY = 80; //!< bytes extern unsigned nMaxDatacarrierBytes; /** diff --git a/src/txmempool.h b/src/txmempool.h index ec8a8518aa4..ca8055c90e4 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -41,17 +41,17 @@ class CTxMemPoolEntry { private: CTransaction tx; - CAmount nFee; //! Cached to avoid expensive parent-transaction lookups - size_t nTxSize; //! ... and avoid recomputing tx size - size_t nModSize; //! ... and modified size for priority - size_t nUsageSize; //! ... and total memory usage - CFeeRate feeRate; //! ... and fee per kB - int64_t nTime; //! Local time when entering the mempool - double dPriority; //! Priority when entering the mempool - unsigned int nHeight; //! Chain height when entering the mempool - bool hadNoDependencies; //! Not dependent on any other txs when it entered the mempool - bool spendsCoinbase; //! keep track of transactions that spend a coinbase - uint32_t nBranchId; //! Branch ID this transaction is known to commit to, cached for efficiency + CAmount nFee; //!< Cached to avoid expensive parent-transaction lookups + size_t nTxSize; //!< ... and avoid recomputing tx size + size_t nModSize; //!< ... and modified size for priority + size_t nUsageSize; //!< ... and total memory usage + CFeeRate feeRate; //!< ... and fee per kB + int64_t nTime; //!< Local time when entering the mempool + double dPriority; //!< Priority when entering the mempool + unsigned int nHeight; //!< Chain height when entering the mempool + bool hadNoDependencies; //!< Not dependent on any other txs when it entered the mempool + bool spendsCoinbase; //!< keep track of transactions that spend a coinbase + uint32_t nBranchId; //!< Branch ID this transaction is known to commit to, cached for efficiency public: CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee, @@ -124,12 +124,12 @@ class CInPoint class CTxMemPool { private: - uint32_t nCheckFrequency; //! Value n means that n times in 2^32 we check. + uint32_t nCheckFrequency; //!< Value n means that n times in 2^32 we check. unsigned int nTransactionsUpdated; CBlockPolicyEstimator* minerPolicyEstimator; - uint64_t totalTxSize = 0; //! sum of all mempool tx' byte sizes - uint64_t cachedInnerUsage; //! sum of dynamic memory usage of all the map elements (NOT the maps themselves) + uint64_t totalTxSize = 0; //!< sum of all mempool tx' byte sizes + uint64_t cachedInnerUsage; //!< sum of dynamic memory usage of all the map elements (NOT the maps themselves) std::map mapSproutNullifiers; std::map mapSaplingNullifiers; diff --git a/src/utiltime.cpp b/src/utiltime.cpp index f1a408a31d4..5d0b284fdf8 100644 --- a/src/utiltime.cpp +++ b/src/utiltime.cpp @@ -15,7 +15,7 @@ using namespace std; -static int64_t nMockTime = 0; //! For unit testing +static int64_t nMockTime = 0; //!< For unit testing int64_t GetTime() { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index fa137011199..bfd5c280c4e 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -404,11 +404,11 @@ class CWalletTx : public CMerkleTx mapSaplingNoteData_t mapSaplingNoteData; std::vector > vOrderForm; unsigned int fTimeReceivedIsTxTime; - unsigned int nTimeReceived; //! time received by this node + unsigned int nTimeReceived; //!< time received by this node unsigned int nTimeSmart; char fFromMe; std::string strFromAccount; - int64_t nOrderPos; //! position in ordered transaction list + int64_t nOrderPos; //!< position in ordered transaction list // memory only mutable bool fDebitCached; @@ -502,7 +502,7 @@ class CWalletTx : public CMerkleTx } READWRITE(*(CMerkleTx*)this); - std::vector vUnused; //! Used to be vtxPrev + std::vector vUnused; //!< Used to be vtxPrev READWRITE(vUnused); READWRITE(mapValue); READWRITE(mapSproutNoteData); @@ -648,7 +648,7 @@ class CAccountingEntry std::string strOtherAccount; std::string strComment; mapValue_t mapValue; - int64_t nOrderPos; //! position in ordered transaction list + int64_t nOrderPos; //!< position in ordered transaction list uint64_t nEntryNo; CAccountingEntry() From a68c8114e1e0edd2224a0891bd01d845ac4d0889 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Wed, 6 Apr 2016 16:36:32 +0200 Subject: [PATCH 111/395] Globals: Explicitly pass const CChainParams& to UpdateTip() --- src/main.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 9287f994435..90a3e103fe4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2977,8 +2977,7 @@ void PruneAndFlush() { } /** Update chainActive and related internal data structures. */ -void static UpdateTip(CBlockIndex *pindexNew) { - const CChainParams& chainParams = Params(); +void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { chainActive.SetTip(pindexNew); // New best block @@ -3020,7 +3019,9 @@ void static UpdateTip(CBlockIndex *pindexNew) { * Disconnect chainActive's tip. You probably want to call mempool.removeForReorg and * mempool.removeWithoutBranchId after this, with cs_main held. */ -bool static DisconnectTip(CValidationState &state, const Consensus::Params& consensusParams, bool fBare = false) { +bool static DisconnectTip(CValidationState &state, const Consensus::Params& consensusParams, bool fBare = false) +{ + const CChainParams& chainparams = Params(); // TODO replace consensusParams parameter CBlockIndex *pindexDelete = chainActive.Tip(); assert(pindexDelete); // Read block from disk. @@ -3067,7 +3068,7 @@ bool static DisconnectTip(CValidationState &state, const Consensus::Params& cons } // Update chainActive and related variables. - UpdateTip(pindexDelete->pprev); + UpdateTip(pindexDelete->pprev, chainparams); // Get the current commitment tree SproutMerkleTree newSproutTree; SaplingMerkleTree newSaplingTree; @@ -3143,7 +3144,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, mempool.removeExpired(pindexNew->nHeight); // Update chainActive & related variables. - UpdateTip(pindexNew); + UpdateTip(pindexNew, chainparams); // Tell wallet about transactions that went from mempool // to conflicted: BOOST_FOREACH(const CTransaction &tx, txConflicted) { From f2baeb7cb6a0ac80cc7e40cd747d8a2a449d7bf1 Mon Sep 17 00:00:00 2001 From: face Date: Sun, 17 Apr 2016 10:58:50 +0300 Subject: [PATCH 112/395] Pass CChainParams to DisconnectTip() --- src/main.cpp | 17 ++++++++--------- src/main.h | 2 +- src/rpc/blockchain.cpp | 2 +- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 90a3e103fe4..b46804a99bf 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3019,14 +3019,13 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { * Disconnect chainActive's tip. You probably want to call mempool.removeForReorg and * mempool.removeWithoutBranchId after this, with cs_main held. */ -bool static DisconnectTip(CValidationState &state, const Consensus::Params& consensusParams, bool fBare = false) +bool static DisconnectTip(CValidationState &state, const CChainParams& chainparams, bool fBare = false) { - const CChainParams& chainparams = Params(); // TODO replace consensusParams parameter CBlockIndex *pindexDelete = chainActive.Tip(); assert(pindexDelete); // Read block from disk. CBlock block; - if (!ReadBlockFromDisk(block, pindexDelete, consensusParams)) + if (!ReadBlockFromDisk(block, pindexDelete, chainparams.GetConsensus())) return AbortNode(state, "Failed to read block"); // Apply the block atomically to the chain state. uint256 sproutAnchorBeforeDisconnect = pcoinsTip->GetBestAnchor(SPROUT); @@ -3274,7 +3273,7 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c // Disconnect active blocks which are no longer in the best chain. bool fBlocksDisconnected = false; while (chainActive.Tip() && chainActive.Tip() != pindexFork) { - if (!DisconnectTip(state, chainparams.GetConsensus())) + if (!DisconnectTip(state, chainparams)) return false; fBlocksDisconnected = true; } @@ -3395,7 +3394,7 @@ bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, return true; } -bool InvalidateBlock(CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex *pindex) +bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex) { AssertLockHeld(cs_main); @@ -3411,10 +3410,10 @@ bool InvalidateBlock(CValidationState& state, const Consensus::Params& consensus setBlockIndexCandidates.erase(pindexWalk); // ActivateBestChain considers blocks already in chainActive // unconditionally valid already, so force disconnect away from it. - if (!DisconnectTip(state, consensusParams)) { + if (!DisconnectTip(state, chainparams)) { mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS); mempool.removeWithoutBranchId( - CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, consensusParams)); + CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, chainparams.GetConsensus())); return false; } } @@ -3432,7 +3431,7 @@ bool InvalidateBlock(CValidationState& state, const Consensus::Params& consensus InvalidChainFound(pindex); mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS); mempool.removeWithoutBranchId( - CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, consensusParams)); + CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, chainparams.GetConsensus())); return true; } @@ -4607,7 +4606,7 @@ bool RewindBlockIndex(const CChainParams& params, bool& clearWitnessCaches) // of the blockchain). break; } - if (!DisconnectTip(state, params.GetConsensus(), true)) { + if (!DisconnectTip(state, params, true)) { return error("RewindBlockIndex: unable to disconnect block at height %i", pindex->nHeight); } // Occasionally flush state to disk. diff --git a/src/main.h b/src/main.h index c7395dabd33..24652448791 100644 --- a/src/main.h +++ b/src/main.h @@ -565,7 +565,7 @@ class CVerifyDB { CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator); /** Mark a block as invalid. */ -bool InvalidateBlock(CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex *pindex); +bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex); /** Remove invalidity status from a block and its descendants. */ bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 4305070e0aa..c0ca1f07c43 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -976,7 +976,7 @@ UniValue invalidateblock(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); CBlockIndex* pblockindex = mapBlockIndex[hash]; - InvalidateBlock(state, Params().GetConsensus(), pblockindex); + InvalidateBlock(state, Params(), pblockindex); } if (state.IsValid()) { From e9128c4a1dcbd2f6dc5f31dce46e76eba391e0f6 Mon Sep 17 00:00:00 2001 From: face Date: Tue, 19 Apr 2016 16:16:39 +0300 Subject: [PATCH 113/395] Explicitly pass CChainParams to ConnectBlock --- src/main.cpp | 10 +++++----- src/main.h | 3 ++- src/zcbenchmarks.cpp | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index b46804a99bf..b8fd9082785 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2490,9 +2490,9 @@ static int64_t nTimeIndex = 0; static int64_t nTimeCallbacks = 0; static int64_t nTimeTotal = 0; -bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck) +bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, + CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck) { - const CChainParams& chainparams = Params(); AssertLockHeld(cs_main); bool fExpensiveChecks = true; @@ -3116,7 +3116,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, LogPrint("bench", " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001); { CCoinsViewCache view(pcoinsTip); - bool rv = ConnectBlock(*pblock, state, pindexNew, view); + bool rv = ConnectBlock(*pblock, state, pindexNew, view, chainparams); GetMainSignals().BlockChecked(*pblock, state); if (!rv) { if (state.IsInvalid()) @@ -4076,7 +4076,7 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, return false; if (!ContextualCheckBlock(block, state, pindexPrev)) return false; - if (!ConnectBlock(block, state, &indexDummy, viewNew, true)) + if (!ConnectBlock(block, state, &indexDummy, viewNew, chainparams, true)) return false; assert(state.IsValid()); @@ -4512,7 +4512,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, CBlock block; if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus())) return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); - if (!ConnectBlock(block, state, pindex, coins)) + if (!ConnectBlock(block, state, pindex, coins, chainparams)) return error("VerifyDB(): *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); } } diff --git a/src/main.h b/src/main.h index 24652448791..51db65db4c4 100644 --- a/src/main.h +++ b/src/main.h @@ -483,7 +483,8 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn /** Apply the effects of this block (with given index) on the UTXO set represented by coins. * Validity checks that depend on the UTXO set are also done; ConnectBlock() * can fail if those validity checks fail (among other reasons). */ -bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false); +bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, + const CChainParams& chainparams, bool fJustCheck = false); /** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true); diff --git a/src/zcbenchmarks.cpp b/src/zcbenchmarks.cpp index d257ce8ece9..cb4cc181258 100644 --- a/src/zcbenchmarks.cpp +++ b/src/zcbenchmarks.cpp @@ -556,7 +556,7 @@ double benchmark_connectblock_slow() CValidationState state; struct timeval tv_start; timer_start(tv_start); - assert(ConnectBlock(block, state, &index, view, true)); + assert(ConnectBlock(block, state, &index, view, Params(), true)); auto duration = timer_stop(tv_start); // Undo alterations to global state From 3647f0a7b10fa96da632bda2a083915f741e1b2f Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 5 Apr 2016 15:14:48 +0200 Subject: [PATCH 114/395] =?UTF-8?q?Break=20circular=20dependency=20main=20?= =?UTF-8?q?=E2=86=94=20txdb?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Break the circular dependency between main and txdb by: - Moving `CBlockFileInfo` from `main.h` to `chain.h`. I think this makes sense, as the other block-file stuff is there too. - Moving `CDiskTxPos` from `main.h` to `txdb.h`. This type seems specific to txdb. - Pass a functor `insertBlockIndex` to `LoadBlockIndexGuts`. This leaves it up to the caller how to insert block indices. Zcash: This does not actually break the circular dependency for us yet, as we still need to pull in bitcoin/bitcoin#7756 and bitcoin/bitcoin#7904. --- src/chain.h | 56 +++++++++++++++++++++++++++++++++++-- src/main.cpp | 3 +- src/main.h | 78 ---------------------------------------------------- src/txdb.cpp | 6 ++-- src/txdb.h | 32 +++++++++++++++++++-- 5 files changed, 87 insertions(+), 88 deletions(-) diff --git a/src/chain.h b/src/chain.h index a532c85642f..5a7b3ad9cf4 100644 --- a/src/chain.h +++ b/src/chain.h @@ -14,11 +14,63 @@ #include -#include - static const int SPROUT_VALUE_VERSION = 1001400; static const int SAPLING_VALUE_VERSION = 1010100; +class CBlockFileInfo +{ +public: + unsigned int nBlocks; //!< number of blocks stored in file + unsigned int nSize; //!< number of used bytes of block file + unsigned int nUndoSize; //!< number of used bytes in the undo file + unsigned int nHeightFirst; //!< lowest height of block in file + unsigned int nHeightLast; //!< highest height of block in file + uint64_t nTimeFirst; //!< earliest time of block in file + uint64_t nTimeLast; //!< latest time of block in file + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(VARINT(nBlocks)); + READWRITE(VARINT(nSize)); + READWRITE(VARINT(nUndoSize)); + READWRITE(VARINT(nHeightFirst)); + READWRITE(VARINT(nHeightLast)); + READWRITE(VARINT(nTimeFirst)); + READWRITE(VARINT(nTimeLast)); + } + + void SetNull() { + nBlocks = 0; + nSize = 0; + nUndoSize = 0; + nHeightFirst = 0; + nHeightLast = 0; + nTimeFirst = 0; + nTimeLast = 0; + } + + CBlockFileInfo() { + SetNull(); + } + + std::string ToString() const; + + /** update statistics (does not update nSize) */ + void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) { + if (nBlocks==0 || nHeightFirst > nHeightIn) + nHeightFirst = nHeightIn; + if (nBlocks==0 || nTimeFirst > nTimeIn) + nTimeFirst = nTimeIn; + nBlocks++; + if (nHeightIn > nHeightLast) + nHeightLast = nHeightIn; + if (nTimeIn > nTimeLast) + nTimeLast = nTimeIn; + } +}; + struct CDiskBlockPos { int nFile; diff --git a/src/main.cpp b/src/main.cpp index b8fd9082785..2485ea4503f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4258,8 +4258,7 @@ CBlockIndex * InsertBlockIndex(uint256 hash) bool static LoadBlockIndexDB() { const CChainParams& chainparams = Params(); - - if (!pblocktree->LoadBlockIndexGuts()) + if (!pblocktree->LoadBlockIndexGuts(InsertBlockIndex)) return false; boost::this_thread::interruption_point(); diff --git a/src/main.h b/src/main.h index 51db65db4c4..33e95247a4a 100644 --- a/src/main.h +++ b/src/main.h @@ -290,30 +290,6 @@ struct CNodeStateStats { std::vector vHeightInFlight; }; -struct CDiskTxPos : public CDiskBlockPos -{ - unsigned int nTxOffset; // after header - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(*(CDiskBlockPos*)this); - READWRITE(VARINT(nTxOffset)); - } - - CDiskTxPos(const CDiskBlockPos &blockIn, unsigned int nTxOffsetIn) : CDiskBlockPos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) { - } - - CDiskTxPos() { - SetNull(); - } - - void SetNull() { - CDiskBlockPos::SetNull(); - nTxOffset = 0; - } -}; CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree); @@ -500,60 +476,6 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, */ bool RewindBlockIndex(const CChainParams& params, bool& clearWitnessCaches); -class CBlockFileInfo -{ -public: - unsigned int nBlocks; //!< number of blocks stored in file - unsigned int nSize; //!< number of used bytes of block file - unsigned int nUndoSize; //!< number of used bytes in the undo file - unsigned int nHeightFirst; //!< lowest height of block in file - unsigned int nHeightLast; //!< highest height of block in file - uint64_t nTimeFirst; //!< earliest time of block in file - uint64_t nTimeLast; //!< latest time of block in file - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(VARINT(nBlocks)); - READWRITE(VARINT(nSize)); - READWRITE(VARINT(nUndoSize)); - READWRITE(VARINT(nHeightFirst)); - READWRITE(VARINT(nHeightLast)); - READWRITE(VARINT(nTimeFirst)); - READWRITE(VARINT(nTimeLast)); - } - - void SetNull() { - nBlocks = 0; - nSize = 0; - nUndoSize = 0; - nHeightFirst = 0; - nHeightLast = 0; - nTimeFirst = 0; - nTimeLast = 0; - } - - CBlockFileInfo() { - SetNull(); - } - - std::string ToString() const; - - /** update statistics (does not update nSize) */ - void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) { - if (nBlocks==0 || nHeightFirst > nHeightIn) - nHeightFirst = nHeightIn; - if (nBlocks==0 || nTimeFirst > nTimeIn) - nTimeFirst = nTimeIn; - nBlocks++; - if (nHeightIn > nHeightLast) - nHeightLast = nHeightIn; - if (nTimeIn > nTimeLast) - nTimeLast = nTimeIn; - } -}; - /** RAII wrapper for VerifyDB: Verify consistency of the block and coin databases */ class CVerifyDB { public: diff --git a/src/txdb.cpp b/src/txdb.cpp index 5ed75f3c969..2d421d36934 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -456,7 +456,7 @@ bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) { return true; } -bool CBlockTreeDB::LoadBlockIndexGuts() +bool CBlockTreeDB::LoadBlockIndexGuts(boost::function insertBlockIndex) { boost::scoped_ptr pcursor(NewIterator()); @@ -470,8 +470,8 @@ bool CBlockTreeDB::LoadBlockIndexGuts() CDiskBlockIndex diskindex; if (pcursor->GetValue(diskindex)) { // Construct block index object - CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash()); - pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev); + CBlockIndex* pindexNew = insertBlockIndex(diskindex.GetBlockHash()); + pindexNew->pprev = insertBlockIndex(diskindex.hashPrev); pindexNew->nHeight = diskindex.nHeight; pindexNew->nFile = diskindex.nFile; pindexNew->nDataPos = diskindex.nDataPos; diff --git a/src/txdb.h b/src/txdb.h index c00b2d68a11..e3ef5b57c33 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -8,15 +8,16 @@ #include "coins.h" #include "dbwrapper.h" +#include "chain.h" #include #include #include #include -class CBlockFileInfo; +#include + class CBlockIndex; -struct CDiskTxPos; // START insightexplorer struct CAddressUnspentKey; @@ -45,6 +46,31 @@ static const int64_t nMaxDbCache = sizeof(void*) > 4 ? 16384 : 1024; //! min. -dbcache in (MiB) static const int64_t nMinDbCache = 4; +struct CDiskTxPos : public CDiskBlockPos +{ + unsigned int nTxOffset; // after header + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(*(CDiskBlockPos*)this); + READWRITE(VARINT(nTxOffset)); + } + + CDiskTxPos(const CDiskBlockPos &blockIn, unsigned int nTxOffsetIn) : CDiskBlockPos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) { + } + + CDiskTxPos() { + SetNull(); + } + + void SetNull() { + CDiskBlockPos::SetNull(); + nTxOffset = 0; + } +}; + /** CCoinsView backed by the coin database (chainstate/) */ class CCoinsViewDB : public CCoinsView { @@ -108,7 +134,7 @@ class CBlockTreeDB : public CDBWrapper bool WriteFlag(const std::string &name, bool fValue); bool ReadFlag(const std::string &name, bool &fValue); - bool LoadBlockIndexGuts(); + bool LoadBlockIndexGuts(boost::function insertBlockIndex); }; #endif // BITCOIN_TXDB_H From 9f7f70e0c3c82bf703b376a600adc6b3886f4a68 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 9 Mar 2018 14:07:04 +0000 Subject: [PATCH 115/395] Globals: Remove Zcash-specific Params() calls from main.cpp --- src/main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 2485ea4503f..0c404c9069d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2609,7 +2609,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin assert(view.GetSaplingAnchorAt(view.GetBestAnchor(SAPLING), sapling_tree)); // Grab the consensus branch ID for the block's height - auto consensusBranchId = CurrentEpochBranchId(pindex->nHeight, Params().GetConsensus()); + auto consensusBranchId = CurrentEpochBranchId(pindex->nHeight, chainparams.GetConsensus()); std::vector txdata; txdata.reserve(block.vtx.size()); // Required so that pointers to individual PrecomputedTransactionData don't get invalidated @@ -2787,7 +2787,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // Move this if BLOCK_VALID_CONSENSUS is ever altered. static_assert(BLOCK_VALID_CONSENSUS == BLOCK_VALID_SCRIPTS, "nCachedBranchId must be set after all consensus rules have been validated."); - if (IsActivationHeightForAnyUpgrade(pindex->nHeight, Params().GetConsensus())) { + if (IsActivationHeightForAnyUpgrade(pindex->nHeight, chainparams.GetConsensus())) { pindex->nStatus |= BLOCK_ACTIVATES_UPGRADE; pindex->nCachedBranchId = CurrentEpochBranchId(pindex->nHeight, chainparams.GetConsensus()); } else if (pindex->pprev) { @@ -3325,7 +3325,7 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS); } mempool.removeWithoutBranchId( - CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, Params().GetConsensus())); + CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, chainparams.GetConsensus())); mempool.check(pcoinsTip); // Callbacks/notifications for a new best chain. @@ -5338,7 +5338,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } // Reject incoming connections from nodes that don't know about the current epoch - const Consensus::Params& params = Params().GetConsensus(); + const Consensus::Params& params = chainparams.GetConsensus(); auto currentEpoch = CurrentEpoch(GetHeight(), params); if (pfrom->nVersion < params.vUpgrades[currentEpoch].nProtocolVersion) { From 13cfabb36cd67397fce34c7544f2cef2990c4d5d Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 14 Mar 2019 10:57:14 +0000 Subject: [PATCH 116/395] Globals: Explicitly pass const CChainParams& to IsStandardTx() --- src/main.cpp | 8 ++++---- src/main.h | 2 +- src/test/script_P2SH_tests.cpp | 6 +++--- src/test/transaction_tests.cpp | 34 ++++++++++++++++++---------------- 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 0c404c9069d..0d0a023b195 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -654,10 +654,10 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) EXCLUSIVE_LOCKS_REQUIRE } -bool IsStandardTx(const CTransaction& tx, string& reason, const int nHeight) +bool IsStandardTx(const CTransaction& tx, string& reason, const CChainParams& chainparams, const int nHeight) { - bool overwinterActive = NetworkUpgradeActive(nHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER); - bool saplingActive = NetworkUpgradeActive(nHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING); + bool overwinterActive = NetworkUpgradeActive(nHeight, chainparams.GetConsensus(), Consensus::UPGRADE_OVERWINTER); + bool saplingActive = NetworkUpgradeActive(nHeight, chainparams.GetConsensus(), Consensus::UPGRADE_SAPLING); if (saplingActive) { // Sapling standard rules apply @@ -1400,7 +1400,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Rather not work on nonstandard transactions (unless -testnet/-regtest) string reason; - if (Params().RequireStandard() && !IsStandardTx(tx, reason, nextBlockHeight)) + if (Params().RequireStandard() && !IsStandardTx(tx, reason, Params(), nextBlockHeight)) return state.DoS(0, error("AcceptToMemoryPool: nonstandard transaction: %s", reason), REJECT_NONSTANDARD, reason); diff --git a/src/main.h b/src/main.h index 33e95247a4a..ca631adba95 100644 --- a/src/main.h +++ b/src/main.h @@ -356,7 +356,7 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio /** Check for standard transaction types * @return True if all outputs (scriptPubKeys) use only standard transaction forms */ -bool IsStandardTx(const CTransaction& tx, std::string& reason, int nHeight = 0); +bool IsStandardTx(const CTransaction& tx, std::string& reason, const CChainParams& chainparams, int nHeight = 0); namespace Consensus { diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index fac63dbf564..80e293675a1 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -95,7 +95,7 @@ BOOST_DATA_TEST_CASE(sign, boost::unit_test::data::xrange(static_cast(Conse txFrom.vout[i+4].scriptPubKey = standardScripts[i]; txFrom.vout[i+4].nValue = COIN; } - BOOST_CHECK(IsStandardTx(txFrom, reason)); + BOOST_CHECK(IsStandardTx(txFrom, reason, Params())); CMutableTransaction txTo[8]; // Spending transactions for (int i = 0; i < 8; i++) @@ -198,7 +198,7 @@ BOOST_DATA_TEST_CASE(set, boost::unit_test::data::xrange(static_cast(Consen txFrom.vout[i].scriptPubKey = outer[i]; txFrom.vout[i].nValue = CENT; } - BOOST_CHECK(IsStandardTx(txFrom, reason)); + BOOST_CHECK(IsStandardTx(txFrom, reason, Params())); CMutableTransaction txTo[4]; // Spending transactions for (int i = 0; i < 4; i++) @@ -216,7 +216,7 @@ BOOST_DATA_TEST_CASE(set, boost::unit_test::data::xrange(static_cast(Consen for (int i = 0; i < 4; i++) { BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL, consensusBranchId), strprintf("SignSignature %d", i)); - BOOST_CHECK_MESSAGE(IsStandardTx(txTo[i], reason), strprintf("txTo[%d].IsStandard", i)); + BOOST_CHECK_MESSAGE(IsStandardTx(txTo[i], reason, Params()), strprintf("txTo[%d].IsStandard", i)); } } diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 88f390c1774..3c190aa7f01 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -748,6 +748,7 @@ BOOST_AUTO_TEST_CASE(test_big_overwinter_transaction) { BOOST_AUTO_TEST_CASE(test_IsStandard) { LOCK(cs_main); + auto chainparams = Params(); CBasicKeyStore keystore; CCoinsView coinsDummy; CCoinsViewCache coins(&coinsDummy); @@ -765,48 +766,49 @@ BOOST_AUTO_TEST_CASE(test_IsStandard) t.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID()); string reason; - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(t, reason, chainparams)); t.vout[0].nValue = 53; // dust - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(t, reason, chainparams)); t.vout[0].nValue = 2730; // not dust - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(t, reason, chainparams)); t.vout[0].scriptPubKey = CScript() << OP_1; - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(t, reason, chainparams)); // 80-byte TX_NULL_DATA (standard) t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"); - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(t, reason, chainparams)); // 81-byte TX_NULL_DATA (non-standard) t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3800"); - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(t, reason, chainparams)); // TX_NULL_DATA w/o PUSHDATA t.vout.resize(1); t.vout[0].scriptPubKey = CScript() << OP_RETURN; - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(t, reason, chainparams)); // Only one TX_NULL_DATA permitted in all cases t.vout.resize(2); t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"); t.vout[1].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"); - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(t, reason, chainparams)); t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"); t.vout[1].scriptPubKey = CScript() << OP_RETURN; - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(t, reason, chainparams)); t.vout[0].scriptPubKey = CScript() << OP_RETURN; t.vout[1].scriptPubKey = CScript() << OP_RETURN; - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(t, reason, chainparams)); } BOOST_AUTO_TEST_CASE(test_IsStandardV2) { LOCK(cs_main); + auto chainparams = Params(); CBasicKeyStore keystore; CCoinsView coinsDummy; CCoinsViewCache coins(&coinsDummy); @@ -826,33 +828,33 @@ BOOST_AUTO_TEST_CASE(test_IsStandardV2) string reason; // A v2 transaction with no JoinSplits is still standard. t.nVersion = 2; - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(t, reason, chainparams)); // ... and with one JoinSplit. t.vjoinsplit.push_back(JSDescription()); - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(t, reason, chainparams)); // ... and when that JoinSplit takes from a transparent input. JSDescription *jsdesc = &t.vjoinsplit[0]; jsdesc->vpub_old = 10*CENT; t.vout[0].nValue -= 10*CENT; - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(t, reason, chainparams)); // A v2 transaction with JoinSplits but no transparent inputs is standard. jsdesc->vpub_old = 0; jsdesc->vpub_new = 100*CENT; t.vout[0].nValue = 90*CENT; t.vin.resize(0); - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(t, reason, chainparams)); // v2 transactions can still be non-standard for the same reasons as v1. t.vout[0].nValue = 53; // dust - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(t, reason, chainparams)); // v3 is not standard. t.nVersion = 3; t.vout[0].nValue = 90*CENT; - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(t, reason, chainparams)); } BOOST_AUTO_TEST_SUITE_END() From 7ef947c32bd22e7c3ef367b138a98bafadb328f2 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 14 Mar 2019 11:02:47 +0000 Subject: [PATCH 117/395] Globals: Explicit const CChainParams& arg for main: - CheckBlockHeader - CheckBlock --- src/gtest/test_checkblock.cpp | 4 ++-- src/main.cpp | 25 +++++++++++++++---------- src/main.h | 5 ++++- src/test/checkblock_tests.cpp | 2 +- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/gtest/test_checkblock.cpp b/src/gtest/test_checkblock.cpp index 2919e1314d7..de073565a2d 100644 --- a/src/gtest/test_checkblock.cpp +++ b/src/gtest/test_checkblock.cpp @@ -31,7 +31,7 @@ TEST(CheckBlock, VersionTooLow) { MockCValidationState state; EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "version-too-low", false)).Times(1); - EXPECT_FALSE(CheckBlock(block, state, verifier, false, false)); + EXPECT_FALSE(CheckBlock(block, state, Params(), verifier, false, false)); } @@ -64,7 +64,7 @@ TEST(CheckBlock, BlockSproutRejectsBadVersion) { auto verifier = libzcash::ProofVerifier::Strict(); EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-version-too-low", false)).Times(1); - EXPECT_FALSE(CheckBlock(block, state, verifier, false, false)); + EXPECT_FALSE(CheckBlock(block, state, Params(), verifier, false, false)); } diff --git a/src/main.cpp b/src/main.cpp index 0d0a023b195..2c5f6b65d74 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2508,7 +2508,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin auto disabledVerifier = libzcash::ProofVerifier::Disabled(); // Check it again to verify JoinSplit proofs, and in case a previous version let a bad block in - if (!CheckBlock(block, state, fExpensiveChecks ? verifier : disabledVerifier, !fJustCheck, !fJustCheck)) + if (!CheckBlock(block, state, chainparams, fExpensiveChecks ? verifier : disabledVerifier, !fJustCheck, !fJustCheck)) return false; // verify that the view's current state corresponds to the previous block @@ -3713,7 +3713,11 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne return true; } -bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW) +bool CheckBlockHeader( + const CBlockHeader& block, + CValidationState& state, + const CChainParams& chainparams, + bool fCheckPOW) { // Check block version if (block.nVersion < MIN_BLOCK_VERSION) @@ -3721,12 +3725,12 @@ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool f REJECT_INVALID, "version-too-low"); // Check Equihash solution is valid - if (fCheckPOW && !CheckEquihashSolution(&block, Params().GetConsensus())) + if (fCheckPOW && !CheckEquihashSolution(&block, chainparams.GetConsensus())) return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"), REJECT_INVALID, "invalid-solution"); // Check proof of work matches claimed amount - if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) + if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) return state.DoS(50, error("CheckBlockHeader(): proof of work failed"), REJECT_INVALID, "high-hash"); @@ -3739,6 +3743,7 @@ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool f } bool CheckBlock(const CBlock& block, CValidationState& state, + const CChainParams& chainparams, libzcash::ProofVerifier& verifier, bool fCheckPOW, bool fCheckMerkleRoot) { @@ -3746,7 +3751,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, // Check that the header is valid (particularly PoW). This is mostly // redundant with the call in AcceptBlockHeader. - if (!CheckBlockHeader(block, state, fCheckPOW)) + if (!CheckBlockHeader(block, state, chainparams, fCheckPOW)) return false; // Check the merkle root. @@ -3915,7 +3920,7 @@ static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state return true; } - if (!CheckBlockHeader(block, state)) + if (!CheckBlockHeader(block, state, chainparams)) return false; // Get prev block index @@ -3980,7 +3985,7 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha // See method docstring for why this is always disabled auto verifier = libzcash::ProofVerifier::Disabled(); - if ((!CheckBlock(block, state, verifier)) || !ContextualCheckBlock(block, state, pindex->pprev)) { + if ((!CheckBlock(block, state, chainparams, verifier)) || !ContextualCheckBlock(block, state, pindex->pprev)) { if (state.IsInvalid() && !state.CorruptionPossible()) { pindex->nStatus |= BLOCK_FAILED_VALID; setDirtyBlockIndex.insert(pindex); @@ -4030,7 +4035,7 @@ bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, c { // Preliminary checks auto verifier = libzcash::ProofVerifier::Disabled(); - bool checked = CheckBlock(*pblock, state, verifier); + bool checked = CheckBlock(*pblock, state, chainparams, verifier); { LOCK(cs_main); @@ -4072,7 +4077,7 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, // NOTE: CheckBlockHeader is called by CheckBlock if (!ContextualCheckBlockHeader(block, state, pindexPrev)) return false; - if (!CheckBlock(block, state, verifier, fCheckPOW, fCheckMerkleRoot)) + if (!CheckBlock(block, state, chainparams, verifier, fCheckPOW, fCheckMerkleRoot)) return false; if (!ContextualCheckBlock(block, state, pindexPrev)) return false; @@ -4469,7 +4474,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus())) return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); // check level 1: verify block validity - if (nCheckLevel >= 1 && !CheckBlock(block, state, verifier)) + if (nCheckLevel >= 1 && !CheckBlock(block, state, chainparams, verifier)) return error("VerifyDB(): *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); // check level 2: verify undo validity if (nCheckLevel >= 2 && pindex) { diff --git a/src/main.h b/src/main.h index ca631adba95..7e85094382e 100644 --- a/src/main.h +++ b/src/main.h @@ -445,8 +445,11 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus /** Functions for validating blocks and updating the block tree */ /** Context-independent validity checks */ -bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true); +bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, + const CChainParams& chainparams, + bool fCheckPOW = true); bool CheckBlock(const CBlock& block, CValidationState& state, + const CChainParams& chainparams, libzcash::ProofVerifier& verifier, bool fCheckPOW = true, bool fCheckMerkleRoot = true); diff --git a/src/test/checkblock_tests.cpp b/src/test/checkblock_tests.cpp index c813c9af9ae..dc906282034 100644 --- a/src/test/checkblock_tests.cpp +++ b/src/test/checkblock_tests.cpp @@ -58,7 +58,7 @@ BOOST_AUTO_TEST_CASE(May15) // After May 15'th, big blocks are OK: forkingBlock.nTime = tMay15; // Invalidates PoW auto verifier = libzcash::ProofVerifier::Strict(); - BOOST_CHECK(CheckBlock(forkingBlock, state, verifier, false, false)); + BOOST_CHECK(CheckBlock(forkingBlock, state, Params(), verifier, false, false)); } SetMockTime(0); From be947219530bb4ec2a7c7d028163ce5c92763c0c Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 14 Mar 2019 11:11:10 +0000 Subject: [PATCH 118/395] Globals: Explicitly pass const CChainParams& to ContextualCheckTransaction() --- src/gtest/test_checktransaction.cpp | 25 ++++++++++++++----------- src/gtest/test_transaction_builder.cpp | 8 ++++---- src/main.cpp | 11 ++++++----- src/main.h | 3 ++- src/test/transaction_tests.cpp | 4 ++-- 5 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/gtest/test_checktransaction.cpp b/src/gtest/test_checktransaction.cpp index cf9d7744168..11eba2e9147 100644 --- a/src/gtest/test_checktransaction.cpp +++ b/src/gtest/test_checktransaction.cpp @@ -167,7 +167,7 @@ TEST(checktransaction_tests, BadTxnsOversize) { // ... but fails contextual ones! EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-oversize", false)).Times(1); - EXPECT_FALSE(ContextualCheckTransaction(tx, state, 1, 100)); + EXPECT_FALSE(ContextualCheckTransaction(tx, state, Params(), 1, 100)); } { @@ -188,7 +188,7 @@ TEST(checktransaction_tests, BadTxnsOversize) { MockCValidationState state; EXPECT_TRUE(CheckTransactionWithoutProofVerification(tx, state)); - EXPECT_TRUE(ContextualCheckTransaction(tx, state, 1, 100)); + EXPECT_TRUE(ContextualCheckTransaction(tx, state, Params(), 1, 100)); // Revert to default RegtestDeactivateSapling(); @@ -496,6 +496,7 @@ TEST(checktransaction_tests, bad_txns_prevout_null) { TEST(checktransaction_tests, bad_txns_invalid_joinsplit_signature) { SelectParams(CBaseChainParams::REGTEST); + auto chainparams = Params(); CMutableTransaction mtx = GetValidTransaction(); mtx.joinSplitSig[0] += 1; @@ -504,13 +505,14 @@ TEST(checktransaction_tests, bad_txns_invalid_joinsplit_signature) { MockCValidationState state; // during initial block download, DoS ban score should be zero, else 100 EXPECT_CALL(state, DoS(0, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1); - ContextualCheckTransaction(tx, state, 0, 100, []() { return true; }); + ContextualCheckTransaction(tx, state, chainparams, 0, 100, []() { return true; }); EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1); - ContextualCheckTransaction(tx, state, 0, 100, []() { return false; }); + ContextualCheckTransaction(tx, state, chainparams, 0, 100, []() { return false; }); } TEST(checktransaction_tests, non_canonical_ed25519_signature) { SelectParams(CBaseChainParams::REGTEST); + auto chainparams = Params(); CMutableTransaction mtx = GetValidTransaction(); @@ -518,7 +520,7 @@ TEST(checktransaction_tests, non_canonical_ed25519_signature) { { CTransaction tx(mtx); MockCValidationState state; - EXPECT_TRUE(ContextualCheckTransaction(tx, state, 0, 100)); + EXPECT_TRUE(ContextualCheckTransaction(tx, state, chainparams, 0, 100)); } // Copied from libsodium/crypto_sign/ed25519/ref10/open.c @@ -540,9 +542,9 @@ TEST(checktransaction_tests, non_canonical_ed25519_signature) { MockCValidationState state; // during initial block download, DoS ban score should be zero, else 100 EXPECT_CALL(state, DoS(0, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1); - ContextualCheckTransaction(tx, state, 0, 100, []() { return true; }); + ContextualCheckTransaction(tx, state, chainparams, 0, 100, []() { return true; }); EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1); - ContextualCheckTransaction(tx, state, 0, 100, []() { return false; }); + ContextualCheckTransaction(tx, state, chainparams, 0, 100, []() { return false; }); } TEST(checktransaction_tests, OverwinterConstructors) { @@ -797,7 +799,7 @@ TEST(checktransaction_tests, OverwinterVersionNumberHigh) { UNSAFE_CTransaction tx(mtx); MockCValidationState state; EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-tx-overwinter-version-too-high", false)).Times(1); - ContextualCheckTransaction(tx, state, 1, 100); + ContextualCheckTransaction(tx, state, Params(), 1, 100); // Revert to default UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); @@ -822,6 +824,7 @@ TEST(checktransaction_tests, OverwinterBadVersionGroupId) { // This tests an Overwinter transaction checked against Sprout TEST(checktransaction_tests, OverwinterNotActive) { SelectParams(CBaseChainParams::TESTNET); + auto chainparams = Params(); CMutableTransaction mtx = GetValidTransaction(); mtx.fOverwintered = true; @@ -833,9 +836,9 @@ TEST(checktransaction_tests, OverwinterNotActive) { MockCValidationState state; // during initial block download, DoS ban score should be zero, else 100 EXPECT_CALL(state, DoS(0, false, REJECT_INVALID, "tx-overwinter-not-active", false)).Times(1); - ContextualCheckTransaction(tx, state, 1, 100, []() { return true; }); + ContextualCheckTransaction(tx, state, chainparams, 1, 100, []() { return true; }); EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "tx-overwinter-not-active", false)).Times(1); - ContextualCheckTransaction(tx, state, 1, 100, []() { return false; }); + ContextualCheckTransaction(tx, state, chainparams, 1, 100, []() { return false; }); } // This tests a transaction without the fOverwintered flag set, against the Overwinter consensus rule set. @@ -852,7 +855,7 @@ TEST(checktransaction_tests, OverwinterFlagNotSet) { CTransaction tx(mtx); MockCValidationState state; EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "tx-overwinter-flag-not-set", false)).Times(1); - ContextualCheckTransaction(tx, state, 1, 100); + ContextualCheckTransaction(tx, state, Params(), 1, 100); // Revert to default UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); diff --git a/src/gtest/test_transaction_builder.cpp b/src/gtest/test_transaction_builder.cpp index 3fe71d21b31..5ebf1d737c6 100644 --- a/src/gtest/test_transaction_builder.cpp +++ b/src/gtest/test_transaction_builder.cpp @@ -106,7 +106,7 @@ TEST(TransactionBuilder, TransparentToSapling) EXPECT_EQ(tx.valueBalance, -40000); CValidationState state; - EXPECT_TRUE(ContextualCheckTransaction(tx, state, 2, 0)); + EXPECT_TRUE(ContextualCheckTransaction(tx, state, Params(), 2, 0)); EXPECT_EQ(state.GetRejectReason(), ""); // Revert to default @@ -143,7 +143,7 @@ TEST(TransactionBuilder, SaplingToSapling) { EXPECT_EQ(tx.valueBalance, 10000); CValidationState state; - EXPECT_TRUE(ContextualCheckTransaction(tx, state, 3, 0)); + EXPECT_TRUE(ContextualCheckTransaction(tx, state, Params(), 3, 0)); EXPECT_EQ(state.GetRejectReason(), ""); // Revert to default @@ -181,7 +181,7 @@ TEST(TransactionBuilder, SaplingToSprout) { EXPECT_EQ(tx.valueBalance, 35000); CValidationState state; - EXPECT_TRUE(ContextualCheckTransaction(tx, state, 3, 0)); + EXPECT_TRUE(ContextualCheckTransaction(tx, state, Params(), 3, 0)); EXPECT_EQ(state.GetRejectReason(), ""); // Revert to default @@ -242,7 +242,7 @@ TEST(TransactionBuilder, SproutToSproutAndSapling) { EXPECT_EQ(tx.valueBalance, -5000); CValidationState state; - EXPECT_TRUE(ContextualCheckTransaction(tx, state, 4, 0)); + EXPECT_TRUE(ContextualCheckTransaction(tx, state, Params(), 4, 0)); EXPECT_EQ(state.GetRejectReason(), ""); // Revert to default diff --git a/src/main.cpp b/src/main.cpp index 2c5f6b65d74..90cdb234225 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -891,12 +891,13 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in bool ContextualCheckTransaction( const CTransaction& tx, CValidationState &state, + const CChainParams& chainparams, const int nHeight, const int dosLevel, bool (*isInitBlockDownload)()) { - bool overwinterActive = NetworkUpgradeActive(nHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER); - bool saplingActive = NetworkUpgradeActive(nHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING); + bool overwinterActive = NetworkUpgradeActive(nHeight, chainparams.GetConsensus(), Consensus::UPGRADE_OVERWINTER); + bool saplingActive = NetworkUpgradeActive(nHeight, chainparams.GetConsensus(), Consensus::UPGRADE_SAPLING); bool isSprout = !overwinterActive; // If Sprout rules apply, reject transactions which are intended for Overwinter and beyond @@ -983,7 +984,7 @@ bool ContextualCheckTransaction( !tx.vShieldedSpend.empty() || !tx.vShieldedOutput.empty()) { - auto consensusBranchId = CurrentEpochBranchId(nHeight, Params().GetConsensus()); + auto consensusBranchId = CurrentEpochBranchId(nHeight, chainparams.GetConsensus()); // Empty output script. CScript scriptCode; try { @@ -1382,7 +1383,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // DoS level set to 10 to be more forgiving. // Check transaction contextually against the set of consensus rules which apply in the next block to be mined. - if (!ContextualCheckTransaction(tx, state, nextBlockHeight, 10)) { + if (!ContextualCheckTransaction(tx, state, Params(), nextBlockHeight, 10)) { return error("AcceptToMemoryPool: ContextualCheckTransaction failed"); } @@ -3852,7 +3853,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn BOOST_FOREACH(const CTransaction& tx, block.vtx) { // Check transaction contextually against consensus rules at block height - if (!ContextualCheckTransaction(tx, state, nHeight, 100)) { + if (!ContextualCheckTransaction(tx, state, Params(), nHeight, 100)) { return false; // Failure reason has been set in validation state object } diff --git a/src/main.h b/src/main.h index 7e85094382e..af62a49f289 100644 --- a/src/main.h +++ b/src/main.h @@ -341,7 +341,8 @@ bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, cons std::vector *pvChecks = NULL); /** Check a transaction contextually against a set of consensus rules */ -bool ContextualCheckTransaction(const CTransaction& tx, CValidationState &state, int nHeight, int dosLevel, +bool ContextualCheckTransaction(const CTransaction& tx, CValidationState &state, + const CChainParams& chainparams, int nHeight, int dosLevel, bool (*isInitBlockDownload)() = IsInitialBlockDownload); /** Apply the effects of this transaction on the UTXO set represented by view */ diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 3c190aa7f01..4219e01f4ce 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -491,7 +491,7 @@ void test_simple_joinsplit_invalidity(uint32_t consensusBranchId, CMutableTransa jsdesc->nullifiers[1] = GetRandHash(); BOOST_CHECK(CheckTransactionWithoutProofVerification(newTx, state)); - BOOST_CHECK(!ContextualCheckTransaction(newTx, state, 0, 100)); + BOOST_CHECK(!ContextualCheckTransaction(newTx, state, Params(), 0, 100)); BOOST_CHECK(state.GetRejectReason() == "bad-txns-invalid-joinsplit-signature"); // Empty output script. @@ -505,7 +505,7 @@ void test_simple_joinsplit_invalidity(uint32_t consensusBranchId, CMutableTransa ) == 0); BOOST_CHECK(CheckTransactionWithoutProofVerification(newTx, state)); - BOOST_CHECK(ContextualCheckTransaction(newTx, state, 0, 100)); + BOOST_CHECK(ContextualCheckTransaction(newTx, state, Params(), 0, 100)); } { // Ensure that values within the joinsplit are well-formed. From c6012fe9232011cfde86a0a43556439b919b5484 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 14 Mar 2019 11:18:32 +0000 Subject: [PATCH 119/395] Globals: Explicit const CChainParams& arg for main: - ContextualCheckBlockHeader - ContextualCheckBlock --- src/gtest/test_checkblock.cpp | 12 ++++++------ src/main.cpp | 23 +++++++++++++---------- src/main.h | 6 ++++-- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/gtest/test_checkblock.cpp b/src/gtest/test_checkblock.cpp index de073565a2d..4195647e815 100644 --- a/src/gtest/test_checkblock.cpp +++ b/src/gtest/test_checkblock.cpp @@ -117,7 +117,7 @@ class ContextualCheckBlockTest : public ::testing::Test { // We now expect this to be a valid block. MockCValidationState state; - EXPECT_TRUE(ContextualCheckBlock(block, state, &indexPrev)); + EXPECT_TRUE(ContextualCheckBlock(block, state, Params(), &indexPrev)); } // Expects a height-1 block containing a given transaction to fail @@ -135,7 +135,7 @@ class ContextualCheckBlockTest : public ::testing::Test { // We now expect this to be an invalid block, for the given reason. MockCValidationState state; EXPECT_CALL(state, DoS(level, false, REJECT_INVALID, reason, false)).Times(1); - EXPECT_FALSE(ContextualCheckBlock(block, state, &indexPrev)); + EXPECT_FALSE(ContextualCheckBlock(block, state, Params(), &indexPrev)); } }; @@ -152,7 +152,7 @@ TEST_F(ContextualCheckBlockTest, BadCoinbaseHeight) { // Treating block as genesis should pass MockCValidationState state; - EXPECT_TRUE(ContextualCheckBlock(block, state, NULL)); + EXPECT_TRUE(ContextualCheckBlock(block, state, Params(), NULL)); // Give the transaction a Founder's Reward vout mtx.vout.push_back(CTxOut( @@ -166,20 +166,20 @@ TEST_F(ContextualCheckBlockTest, BadCoinbaseHeight) { CBlockIndex indexPrev {prev}; indexPrev.nHeight = 0; EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-height", false)).Times(1); - EXPECT_FALSE(ContextualCheckBlock(block, state, &indexPrev)); + EXPECT_FALSE(ContextualCheckBlock(block, state, Params(), &indexPrev)); // Setting to an incorrect height should fail mtx.vin[0].scriptSig = CScript() << 2 << OP_0; CTransaction tx3 {mtx}; block.vtx[0] = tx3; EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-height", false)).Times(1); - EXPECT_FALSE(ContextualCheckBlock(block, state, &indexPrev)); + EXPECT_FALSE(ContextualCheckBlock(block, state, Params(), &indexPrev)); // After correcting the scriptSig, should pass mtx.vin[0].scriptSig = CScript() << 1 << OP_0; CTransaction tx4 {mtx}; block.vtx[0] = tx4; - EXPECT_TRUE(ContextualCheckBlock(block, state, &indexPrev)); + EXPECT_TRUE(ContextualCheckBlock(block, state, Params(), &indexPrev)); } // TEST PLAN: first, check that each ruleset accepts its own transaction type. diff --git a/src/main.cpp b/src/main.cpp index 90cdb234225..64887fcdd87 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3806,9 +3806,10 @@ bool CheckBlock(const CBlock& block, CValidationState& state, return true; } -bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex * const pindexPrev) +bool ContextualCheckBlockHeader( + const CBlockHeader& block, CValidationState& state, + const CChainParams& chainParams, CBlockIndex * const pindexPrev) { - const CChainParams& chainParams = Params(); const Consensus::Params& consensusParams = chainParams.GetConsensus(); uint256 hash = block.GetHash(); if (hash == consensusParams.hashGenesisBlock) @@ -3844,16 +3845,18 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta return true; } -bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex * const pindexPrev) +bool ContextualCheckBlock( + const CBlock& block, CValidationState& state, + const CChainParams& chainparams, CBlockIndex * const pindexPrev) { const int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1; - const Consensus::Params& consensusParams = Params().GetConsensus(); + const Consensus::Params& consensusParams = chainparams.GetConsensus(); // Check that all transactions are finalized BOOST_FOREACH(const CTransaction& tx, block.vtx) { // Check transaction contextually against consensus rules at block height - if (!ContextualCheckTransaction(tx, state, Params(), nHeight, 100)) { + if (!ContextualCheckTransaction(tx, state, chainparams, nHeight, 100)) { return false; // Failure reason has been set in validation state object } @@ -3888,7 +3891,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn bool found = false; BOOST_FOREACH(const CTxOut& output, block.vtx[0].vout) { - if (output.scriptPubKey == Params().GetFoundersRewardScriptAtHeight(nHeight)) { + if (output.scriptPubKey == chainparams.GetFoundersRewardScriptAtHeight(nHeight)) { if (output.nValue == (GetBlockSubsidy(nHeight, consensusParams) / 5)) { found = true; break; @@ -3935,7 +3938,7 @@ static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state return state.DoS(100, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk"); } - if (!ContextualCheckBlockHeader(block, state, pindexPrev)) + if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev)) return false; if (pindex == NULL) @@ -3986,7 +3989,7 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha // See method docstring for why this is always disabled auto verifier = libzcash::ProofVerifier::Disabled(); - if ((!CheckBlock(block, state, chainparams, verifier)) || !ContextualCheckBlock(block, state, pindex->pprev)) { + if ((!CheckBlock(block, state, chainparams, verifier)) || !ContextualCheckBlock(block, state, chainparams, pindex->pprev)) { if (state.IsInvalid() && !state.CorruptionPossible()) { pindex->nStatus |= BLOCK_FAILED_VALID; setDirtyBlockIndex.insert(pindex); @@ -4076,11 +4079,11 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, auto verifier = libzcash::ProofVerifier::Disabled(); // NOTE: CheckBlockHeader is called by CheckBlock - if (!ContextualCheckBlockHeader(block, state, pindexPrev)) + if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev)) return false; if (!CheckBlock(block, state, chainparams, verifier, fCheckPOW, fCheckMerkleRoot)) return false; - if (!ContextualCheckBlock(block, state, pindexPrev)) + if (!ContextualCheckBlock(block, state, chainparams, pindexPrev)) return false; if (!ConnectBlock(block, state, &indexDummy, viewNew, chainparams, true)) return false; diff --git a/src/main.h b/src/main.h index af62a49f289..be769b6eb88 100644 --- a/src/main.h +++ b/src/main.h @@ -457,8 +457,10 @@ bool CheckBlock(const CBlock& block, CValidationState& state, /** Context-dependent validity checks. * By "context", we mean only the previous block headers, but not the UTXO * set; UTXO-related validity checks are done in ConnectBlock(). */ -bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex *pindexPrev); -bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex *pindexPrev); +bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, + const CChainParams& chainparams, CBlockIndex *pindexPrev); +bool ContextualCheckBlock(const CBlock& block, CValidationState& state, + const CChainParams& chainparams, CBlockIndex *pindexPrev); /** Apply the effects of this block (with given index) on the UTXO set represented by coins. * Validity checks that depend on the UTXO set are also done; ConnectBlock() From a3b64d8677200dbebdea18d7f1fe85b60c15833e Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 14 Mar 2019 11:24:53 +0000 Subject: [PATCH 120/395] Globals: Explicitly pass const CChainParams& to DisconnectBlock() --- src/main.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 64887fcdd87..dad36f5d0a7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2235,7 +2235,8 @@ enum DisconnectResult * The addressIndex and spentIndex will be updated if requested. */ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& state, - const CBlockIndex* pindex, CCoinsViewCache& view, bool const updateIndices) + const CBlockIndex* pindex, CCoinsViewCache& view, const CChainParams& chainparams, + const bool updateIndices) { assert(pindex->GetBlockHash() == view.GetBestBlock()); @@ -2361,7 +2362,7 @@ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& s // However, this is only reliable if the last block was on or after // the Sapling activation height. Otherwise, the last anchor was the // empty root. - if (NetworkUpgradeActive(pindex->pprev->nHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) { + if (NetworkUpgradeActive(pindex->pprev->nHeight, chainparams.GetConsensus(), Consensus::UPGRADE_SAPLING)) { view.PopAnchor(pindex->pprev->hashFinalSaplingRoot, SAPLING); } else { view.PopAnchor(SaplingMerkleTree::empty_root(), SAPLING); @@ -3035,7 +3036,7 @@ bool static DisconnectTip(CValidationState &state, const CChainParams& chainpara { CCoinsViewCache view(pcoinsTip); // insightexplorer: update indices (true) - if (DisconnectBlock(block, state, pindexDelete, view, true) != DISCONNECT_OK) + if (DisconnectBlock(block, state, pindexDelete, view, chainparams, true) != DISCONNECT_OK) return error("DisconnectTip(): DisconnectBlock %s failed", pindexDelete->GetBlockHash().ToString()); assert(view.Flush()); } @@ -4492,7 +4493,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, // check level 3: check for inconsistencies during memory-only disconnect of tip blocks if (nCheckLevel >= 3 && pindex == pindexState && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) { // insightexplorer: do not update indices (false) - DisconnectResult res = DisconnectBlock(block, state, pindex, coins, false); + DisconnectResult res = DisconnectBlock(block, state, pindex, coins, chainparams, false); if (res == DISCONNECT_FAILED) { return error("VerifyDB(): *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); } From 9e0f75dcbd08302c473fc62c883ef5a658ff49ff Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 2 Apr 2019 02:07:02 +0100 Subject: [PATCH 121/395] Consistently use chainparams and consensusParams --- src/main.cpp | 20 ++++++++++---------- src/main.h | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index dad36f5d0a7..8b4bf1d6f8d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4531,7 +4531,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, return true; } -bool RewindBlockIndex(const CChainParams& params, bool& clearWitnessCaches) +bool RewindBlockIndex(const CChainParams& chainparams, bool& clearWitnessCaches) { LOCK(cs_main); @@ -4544,8 +4544,8 @@ bool RewindBlockIndex(const CChainParams& params, bool& clearWitnessCaches) // // - BLOCK_ACTIVATES_UPGRADE is set only on blocks that activate upgrades. // - nCachedBranchId for each block matches what we expect. - auto sufficientlyValidated = [¶ms](const CBlockIndex* pindex) { - auto consensus = params.GetConsensus(); + auto sufficientlyValidated = [&chainparams](const CBlockIndex* pindex) { + auto consensus = chainparams.GetConsensus(); bool fFlagSet = pindex->nStatus & BLOCK_ACTIVATES_UPGRADE; bool fFlagExpected = IsActivationHeightForAnyUpgrade(pindex->nHeight, consensus); return fFlagSet == fFlagExpected && @@ -4568,7 +4568,7 @@ bool RewindBlockIndex(const CChainParams& params, bool& clearWitnessCaches) if (rewindLength > 0) { LogPrintf("*** First insufficiently validated block at height %d, rewind length %d\n", nHeight, rewindLength); const uint256 *phashFirstInsufValidated = chainActive[nHeight]->phashBlock; - auto networkID = params.NetworkIDString(); + auto networkID = chainparams.NetworkIDString(); // This is true when we intend to do a long rewind. bool intendedRewind = @@ -4615,7 +4615,7 @@ bool RewindBlockIndex(const CChainParams& params, bool& clearWitnessCaches) // of the blockchain). break; } - if (!DisconnectTip(state, params, true)) { + if (!DisconnectTip(state, chainparams, true)) { return error("RewindBlockIndex: unable to disconnect block at height %i", pindex->nHeight); } // Occasionally flush state to disk. @@ -4677,7 +4677,7 @@ bool RewindBlockIndex(const CChainParams& params, bool& clearWitnessCaches) PruneBlockIndexCandidates(); - CheckBlockIndex(params.GetConsensus()); + CheckBlockIndex(chainparams.GetConsensus()); if (!FlushStateToDisk(state, FLUSH_STATE_ALWAYS)) { return false; @@ -5348,14 +5348,14 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } // Reject incoming connections from nodes that don't know about the current epoch - const Consensus::Params& params = chainparams.GetConsensus(); - auto currentEpoch = CurrentEpoch(GetHeight(), params); - if (pfrom->nVersion < params.vUpgrades[currentEpoch].nProtocolVersion) + const Consensus::Params& consensusParams = chainparams.GetConsensus(); + auto currentEpoch = CurrentEpoch(GetHeight(), consensusParams); + if (pfrom->nVersion < consensusParams.vUpgrades[currentEpoch].nProtocolVersion) { LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, pfrom->nVersion); pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", - params.vUpgrades[currentEpoch].nProtocolVersion)); + consensusParams.vUpgrades[currentEpoch].nProtocolVersion)); pfrom->fDisconnect = true; return false; } diff --git a/src/main.h b/src/main.h index be769b6eb88..13b338dddc3 100644 --- a/src/main.h +++ b/src/main.h @@ -480,7 +480,7 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, * clearWitnessCaches is an output parameter that will be set to true iff * witness caches should be cleared in order to handle an intended long rewind. */ -bool RewindBlockIndex(const CChainParams& params, bool& clearWitnessCaches); +bool RewindBlockIndex(const CChainParams& chainparams, bool& clearWitnessCaches); /** RAII wrapper for VerifyDB: Verify consistency of the block and coin databases */ class CVerifyDB { From 3ffc29b88162b93419c28dadd0a4f7a55e57cda6 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 2 Apr 2019 02:30:33 +0100 Subject: [PATCH 122/395] Globals: Explicitly pass const CChainParams& to IsInitialBlockDownload() --- src/gtest/test_checktransaction.cpp | 12 ++--- src/main.cpp | 68 ++++++++++++++--------------- src/main.h | 6 +-- src/metrics.cpp | 4 +- src/miner.cpp | 2 +- src/rpc/mining.cpp | 2 +- src/test/alert_tests.cpp | 2 +- src/wallet/wallet.cpp | 2 +- 8 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/gtest/test_checktransaction.cpp b/src/gtest/test_checktransaction.cpp index 11eba2e9147..6897d42e9a8 100644 --- a/src/gtest/test_checktransaction.cpp +++ b/src/gtest/test_checktransaction.cpp @@ -505,9 +505,9 @@ TEST(checktransaction_tests, bad_txns_invalid_joinsplit_signature) { MockCValidationState state; // during initial block download, DoS ban score should be zero, else 100 EXPECT_CALL(state, DoS(0, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1); - ContextualCheckTransaction(tx, state, chainparams, 0, 100, []() { return true; }); + ContextualCheckTransaction(tx, state, chainparams, 0, 100, [](const CChainParams&) { return true; }); EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1); - ContextualCheckTransaction(tx, state, chainparams, 0, 100, []() { return false; }); + ContextualCheckTransaction(tx, state, chainparams, 0, 100, [](const CChainParams&) { return false; }); } TEST(checktransaction_tests, non_canonical_ed25519_signature) { @@ -542,9 +542,9 @@ TEST(checktransaction_tests, non_canonical_ed25519_signature) { MockCValidationState state; // during initial block download, DoS ban score should be zero, else 100 EXPECT_CALL(state, DoS(0, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1); - ContextualCheckTransaction(tx, state, chainparams, 0, 100, []() { return true; }); + ContextualCheckTransaction(tx, state, chainparams, 0, 100, [](const CChainParams&) { return true; }); EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1); - ContextualCheckTransaction(tx, state, chainparams, 0, 100, []() { return false; }); + ContextualCheckTransaction(tx, state, chainparams, 0, 100, [](const CChainParams&) { return false; }); } TEST(checktransaction_tests, OverwinterConstructors) { @@ -836,9 +836,9 @@ TEST(checktransaction_tests, OverwinterNotActive) { MockCValidationState state; // during initial block download, DoS ban score should be zero, else 100 EXPECT_CALL(state, DoS(0, false, REJECT_INVALID, "tx-overwinter-not-active", false)).Times(1); - ContextualCheckTransaction(tx, state, chainparams, 1, 100, []() { return true; }); + ContextualCheckTransaction(tx, state, chainparams, 1, 100, [](const CChainParams&) { return true; }); EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "tx-overwinter-not-active", false)).Times(1); - ContextualCheckTransaction(tx, state, chainparams, 1, 100, []() { return false; }); + ContextualCheckTransaction(tx, state, chainparams, 1, 100, [](const CChainParams&) { return false; }); } // This tests a transaction without the fOverwintered flag set, against the Overwinter consensus rule set. diff --git a/src/main.cpp b/src/main.cpp index 8b4bf1d6f8d..3065e694fb5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -894,7 +894,7 @@ bool ContextualCheckTransaction( const CChainParams& chainparams, const int nHeight, const int dosLevel, - bool (*isInitBlockDownload)()) + bool (*isInitBlockDownload)(const CChainParams&)) { bool overwinterActive = NetworkUpgradeActive(nHeight, chainparams.GetConsensus(), Consensus::UPGRADE_OVERWINTER); bool saplingActive = NetworkUpgradeActive(nHeight, chainparams.GetConsensus(), Consensus::UPGRADE_SAPLING); @@ -902,7 +902,7 @@ bool ContextualCheckTransaction( // If Sprout rules apply, reject transactions which are intended for Overwinter and beyond if (isSprout && tx.fOverwintered) { - return state.DoS(isInitBlockDownload() ? 0 : dosLevel, + return state.DoS(isInitBlockDownload(chainparams) ? 0 : dosLevel, error("ContextualCheckTransaction(): overwinter is not active yet"), REJECT_INVALID, "tx-overwinter-not-active"); } @@ -916,7 +916,7 @@ bool ContextualCheckTransaction( // Reject transactions with non-Sapling version group ID if (tx.fOverwintered && tx.nVersionGroupId != SAPLING_VERSION_GROUP_ID) { - return state.DoS(isInitBlockDownload() ? 0 : dosLevel, + return state.DoS(isInitBlockDownload(chainparams) ? 0 : dosLevel, error("CheckTransaction(): invalid Sapling tx version"), REJECT_INVALID, "bad-sapling-tx-version-group-id"); } @@ -941,7 +941,7 @@ bool ContextualCheckTransaction( // Reject transactions with non-Overwinter version group ID if (tx.fOverwintered && tx.nVersionGroupId != OVERWINTER_VERSION_GROUP_ID) { - return state.DoS(isInitBlockDownload() ? 0 : dosLevel, + return state.DoS(isInitBlockDownload(chainparams) ? 0 : dosLevel, error("CheckTransaction(): invalid Overwinter tx version"), REJECT_INVALID, "bad-overwinter-tx-version-group-id"); } @@ -1005,7 +1005,7 @@ bool ContextualCheckTransaction( dataToBeSigned.begin(), 32, tx.joinSplitPubKey.begin() ) != 0) { - return state.DoS(isInitBlockDownload() ? 0 : 100, + return state.DoS(isInitBlockDownload(chainparams) ? 0 : 100, error("CheckTransaction(): invalid joinsplit signature"), REJECT_INVALID, "bad-txns-invalid-joinsplit-signature"); } @@ -1599,7 +1599,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } // Store transaction in memory - pool.addUnchecked(hash, entry, !IsInitialBlockDownload()); + pool.addUnchecked(hash, entry, !IsInitialBlockDownload(Params())); } SyncWithWallets(tx, NULL); @@ -1762,10 +1762,8 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) return nSubsidy; } -bool IsInitialBlockDownload() +bool IsInitialBlockDownload(const CChainParams& chainParams) { - const CChainParams& chainParams = Params(); - // Once this function has returned false, it must remain false. static std::atomic latchToFalse{false}; // Optimization: pre-test latch before taking the lock. @@ -1793,12 +1791,12 @@ static bool fLargeWorkInvalidChainFound = false; static CBlockIndex *pindexBestForkTip = NULL; static CBlockIndex *pindexBestForkBase = NULL; -void CheckForkWarningConditions() +void CheckForkWarningConditions(const CChainParams& chainParams) { AssertLockHeld(cs_main); // Before we get past initial download, we cannot reliably alert about forks // (we assume we don't get stuck on a fork before finishing our initial sync) - if (IsInitialBlockDownload()) + if (IsInitialBlockDownload(chainParams)) return; // If our best fork is no longer within 288 blocks (+/- 12 hours if no one mines it) @@ -1836,7 +1834,7 @@ void CheckForkWarningConditions() } } -void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip) +void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip, const CChainParams& chainParams) { AssertLockHeld(cs_main); // If we are on a fork that is sufficiently large, set a warning flag @@ -1866,7 +1864,7 @@ void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip) pindexBestForkBase = pfork; } - CheckForkWarningConditions(); + CheckForkWarningConditions(chainParams); } // Requires cs_main. @@ -1889,7 +1887,7 @@ void Misbehaving(NodeId pnode, int howmuch) LogPrintf("%s: %s (%d -> %d)\n", __func__, state->name, state->nMisbehavior-howmuch, state->nMisbehavior); } -void static InvalidChainFound(CBlockIndex* pindexNew) +void static InvalidChainFound(CBlockIndex* pindexNew, const CChainParams& chainParams) { if (!pindexBestInvalid || pindexNew->nChainWork > pindexBestInvalid->nChainWork) pindexBestInvalid = pindexNew; @@ -1903,10 +1901,10 @@ void static InvalidChainFound(CBlockIndex* pindexNew) LogPrintf("%s: current best=%s height=%d log2_work=%.8g date=%s\n", __func__, tip->GetBlockHash().ToString(), chainActive.Height(), log(tip->nChainWork.getdouble())/log(2.0), DateTimeStrFormat("%Y-%m-%d %H:%M:%S", tip->GetBlockTime())); - CheckForkWarningConditions(); + CheckForkWarningConditions(chainParams); } -void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) { +void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state, const CChainParams& chainParams) { int nDoS = 0; if (state.IsInvalid(nDoS)) { std::map::iterator it = mapBlockSource.find(pindex->GetBlockHash()); @@ -1921,7 +1919,7 @@ void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state pindex->nStatus |= BLOCK_FAILED_VALID; setDirtyBlockIndex.insert(pindex); setBlockIndexCandidates.erase(pindex); - InvalidChainFound(pindex); + InvalidChainFound(pindex, chainParams); } } @@ -2429,10 +2427,11 @@ void ThreadScriptCheck() { // we're being fed a bad chain (blocks being generated much // too slowly or too quickly). // -void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const CBlockIndex *const &bestHeader, +void PartitionCheck(bool (*initialDownloadCheck)(const CChainParams&), + CCriticalSection& cs, const CBlockIndex *const &bestHeader, int64_t nPowTargetSpacing) { - if (bestHeader == NULL || initialDownloadCheck()) return; + if (bestHeader == NULL || initialDownloadCheck(Params())) return; static int64_t lastAlertTime = 0; int64_t now = GetAdjustedTime(); @@ -2995,7 +2994,7 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { // Check the version of the last 100 blocks to see if we need to upgrade: static bool fWarned = false; - if (!IsInitialBlockDownload() && !fWarned) + if (!IsInitialBlockDownload(chainParams) && !fWarned) { int nUpgraded = 0; const CBlockIndex* pindex = chainActive.Tip(); @@ -3122,7 +3121,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, GetMainSignals().BlockChecked(*pblock, state); if (!rv) { if (state.IsInvalid()) - InvalidBlockFound(pindexNew, state); + InvalidBlockFound(pindexNew, state, chainparams); return error("ConnectTip(): ConnectBlock %s failed", pindexNew->GetBlockHash().ToString()); } mapBlockSource.erase(pindexNew->GetBlockHash()); @@ -3139,7 +3138,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, LogPrint("bench", " - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001); // Remove conflicting transactions from the mempool. list txConflicted; - mempool.removeForBlock(pblock->vtx, pindexNew->nHeight, txConflicted, !IsInitialBlockDownload()); + mempool.removeForBlock(pblock->vtx, pindexNew->nHeight, txConflicted, !IsInitialBlockDownload(chainparams)); // Remove transactions that expire at new block height from mempool mempool.removeExpired(pindexNew->nHeight); @@ -3303,7 +3302,7 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c if (state.IsInvalid()) { // The block violates a consensus rule. if (!state.CorruptionPossible()) - InvalidChainFound(vpindexToConnect.back()); + InvalidChainFound(vpindexToConnect.back(), chainparams); state = CValidationState(); fInvalidFound = true; fContinue = false; @@ -3332,9 +3331,9 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c // Callbacks/notifications for a new best chain. if (fInvalidFound) - CheckForkWarningConditionsOnNewFork(vpindexToConnect.back()); + CheckForkWarningConditionsOnNewFork(vpindexToConnect.back(), chainparams); else - CheckForkWarningConditions(); + CheckForkWarningConditions(chainparams); return true; } @@ -3364,7 +3363,7 @@ bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, return false; pindexNewTip = chainActive.Tip(); - fInitialDownload = IsInitialBlockDownload(); + fInitialDownload = IsInitialBlockDownload(chainparams); } // When we reach this point, we switched to a new tip (stored in pindexNewTip). @@ -3430,7 +3429,7 @@ bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, C it++; } - InvalidChainFound(pindex); + InvalidChainFound(pindex, chainparams); mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS); mempool.removeWithoutBranchId( CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, chainparams.GetConsensus())); @@ -5405,7 +5404,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (!pfrom->fInbound) { // Advertise our address - if (fListen && !IsInitialBlockDownload()) + if (fListen && !IsInitialBlockDownload(chainparams)) { CAddress addr = GetLocalAddress(&pfrom->addr); if (addr.IsRoutable()) @@ -5699,7 +5698,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, LOCK(cs_main); - if (IsInitialBlockDownload()) + if (IsInitialBlockDownload(chainparams)) return true; CBlockIndex* pindex = NULL; @@ -5935,7 +5934,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // unless we're still syncing with the network. // Such an unrequested block may still be processed, subject to the // conditions in AcceptBlock(). - bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload(); + bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload(chainparams); ProcessNewBlock(state, chainparams, pfrom, &block, forceProcessing, NULL); int nDoS; if (state.IsInvalid(nDoS)) { @@ -6342,7 +6341,8 @@ bool ProcessMessages(CNode* pfrom) bool SendMessages(CNode* pto, bool fSendTrickle) { - const Consensus::Params& consensusParams = Params().GetConsensus(); + const CChainParams& chainParams = Params(); + const Consensus::Params& consensusParams = chainParams.GetConsensus(); { // Don't send anything until we get its version message if (pto->nVersion == 0) @@ -6383,7 +6383,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) // Address refresh broadcast static int64_t nLastRebroadcast; - if (!IsInitialBlockDownload() && (GetTime() - nLastRebroadcast > 24 * 60 * 60)) + if (!IsInitialBlockDownload(chainParams) && (GetTime() - nLastRebroadcast > 24 * 60 * 60)) { LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) @@ -6463,7 +6463,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) // Resend wallet transactions that haven't gotten in a block yet // Except during reindex, importing and IBD, when old wallet // transactions become unconfirmed and spams other nodes. - if (!fReindex && !fImporting && !IsInitialBlockDownload()) + if (!fReindex && !fImporting && !IsInitialBlockDownload(chainParams)) { GetMainSignals().Broadcast(nTimeBestReceived); } @@ -6552,7 +6552,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) // Message: getdata (blocks) // vector vGetData; - if (!pto->fDisconnect && !pto->fClient && (fFetch || !IsInitialBlockDownload()) && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) { + if (!pto->fDisconnect && !pto->fClient && (fFetch || !IsInitialBlockDownload(chainParams)) && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) { vector vToDownload; NodeId staller = -1; FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller); diff --git a/src/main.h b/src/main.h index 13b338dddc3..2b77875c482 100644 --- a/src/main.h +++ b/src/main.h @@ -234,9 +234,9 @@ bool SendMessages(CNode* pto, bool fSendTrickle); /** Run an instance of the script checking thread */ void ThreadScriptCheck(); /** Try to detect Partition (network isolation) attacks against us */ -void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const CBlockIndex *const &bestHeader, int64_t nPowTargetSpacing); +void PartitionCheck(bool (*initialDownloadCheck)(const CChainParams&), CCriticalSection& cs, const CBlockIndex *const &bestHeader, int64_t nPowTargetSpacing); /** Check whether we are doing an initial block download (synchronizing from disk or network) */ -bool IsInitialBlockDownload(); +bool IsInitialBlockDownload(const CChainParams& chainParams); /** Format a string that describes several potential problems detected by the core */ std::string GetWarnings(const std::string& strFor); /** Retrieve a transaction (from memory pool, or from disk, if possible) */ @@ -343,7 +343,7 @@ bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, cons /** Check a transaction contextually against a set of consensus rules */ bool ContextualCheckTransaction(const CTransaction& tx, CValidationState &state, const CChainParams& chainparams, int nHeight, int dosLevel, - bool (*isInitBlockDownload)() = IsInitialBlockDownload); + bool (*isInitBlockDownload)(const CChainParams&) = IsInitialBlockDownload); /** Apply the effects of this transaction on the UTXO set represented by view */ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight); diff --git a/src/metrics.cpp b/src/metrics.cpp index 680b74bb53e..9eecc22e5d0 100644 --- a/src/metrics.cpp +++ b/src/metrics.cpp @@ -216,7 +216,7 @@ int printStats(bool mining) } auto localsolps = GetLocalSolPS(); - if (IsInitialBlockDownload()) { + if (IsInitialBlockDownload(Params())) { int netheight = EstimateNetHeight(height, tipmediantime, Params()); int downloadPercent = height * 100 / netheight; std::cout << " " << _("Downloading blocks") << " | " << height << " / ~" << netheight << " (" << downloadPercent << "%)" << std::endl; @@ -253,7 +253,7 @@ int printMiningStatus(bool mining) } if (fvNodesEmpty) { std::cout << _("Mining is paused while waiting for connections.") << std::endl; - } else if (IsInitialBlockDownload()) { + } else if (IsInitialBlockDownload(Params())) { std::cout << _("Mining is paused while downloading blocks.") << std::endl; } else { std::cout << _("Mining is paused (a JoinSplit may be in progress).") << std::endl; diff --git a/src/miner.cpp b/src/miner.cpp index ee37c44c7ab..bc8f6888ce8 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -565,7 +565,7 @@ void static BitcoinMiner(const CChainParams& chainparams) LOCK(cs_vNodes); fvNodesEmpty = vNodes.empty(); } - if (!fvNodesEmpty && !IsInitialBlockDownload()) + if (!fvNodesEmpty && !IsInitialBlockDownload(chainparams)) break; MilliSleep(1000); } while (true); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 670d2edd4f3..a75ab5924b1 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -534,7 +534,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) if (vNodes.empty()) throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Zcash is not connected!"); - if (IsInitialBlockDownload()) + if (IsInitialBlockDownload(Params())) throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Zcash is downloading blocks..."); static unsigned int nTransactionsUpdatedLast; diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index a0b49b4ddc2..18acf1f67c5 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -383,7 +383,7 @@ BOOST_AUTO_TEST_CASE(AlertDisablesRPC) mapAlerts.clear(); } -static bool falseFunc() { return false; } +static bool falseFunc(const CChainParams&) { return false; } BOOST_AUTO_TEST_CASE(PartitionAlert) { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 659431f19a2..8eba17c6bda 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -583,7 +583,7 @@ void CWallet::ChainTip(const CBlockIndex *pindex, ChainTipAdded(pindex, pblock, sproutTree, saplingTree); // Prevent migration transactions from being created when node is syncing after launch, // and also when node wakes up from suspension/hibernation and incoming blocks are old. - if (!IsInitialBlockDownload() && + if (!IsInitialBlockDownload(Params()) && pblock->GetBlockTime() > GetAdjustedTime() - 3 * 60 * 60) { RunSaplingMigration(pindex->nHeight); From e12d018464cad3c37689e30dcb8f1f95187261ee Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 29 Apr 2019 16:26:27 +0100 Subject: [PATCH 123/395] Globals: Explicitly pass const CChainParams& to ReceivedBlockTransactions() --- src/gtest/test_validation.cpp | 12 +++++++++--- src/main.cpp | 12 ++++++++---- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/gtest/test_validation.cpp b/src/gtest/test_validation.cpp index 4e937d04266..0f66b8dcfb6 100644 --- a/src/gtest/test_validation.cpp +++ b/src/gtest/test_validation.cpp @@ -7,7 +7,12 @@ extern ZCJoinSplit* params; -extern bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos); +extern bool ReceivedBlockTransactions( + const CBlock &block, + CValidationState& state, + const CChainParams& chainparams, + CBlockIndex *pindexNew, + const CDiskBlockPos& pos); void ExpectOptionalAmount(CAmount expected, boost::optional actual) { EXPECT_TRUE((bool)actual); @@ -87,6 +92,7 @@ TEST(Validation, ContextualCheckInputsPassesWithCoinbase) { } TEST(Validation, ReceivedBlockTransactions) { + auto chainParams = Params(); auto sk = libzcash::SproutSpendingKey::random(); // Create a fake genesis block @@ -122,7 +128,7 @@ TEST(Validation, ReceivedBlockTransactions) { // Mark the second block's transactions as received first CValidationState state; - EXPECT_TRUE(ReceivedBlockTransactions(block2, state, &fakeIndex2, pos2)); + EXPECT_TRUE(ReceivedBlockTransactions(block2, state, chainParams, &fakeIndex2, pos2)); EXPECT_FALSE(fakeIndex1.IsValid(BLOCK_VALID_TRANSACTIONS)); EXPECT_TRUE(fakeIndex2.IsValid(BLOCK_VALID_TRANSACTIONS)); @@ -137,7 +143,7 @@ TEST(Validation, ReceivedBlockTransactions) { EXPECT_FALSE((bool)fakeIndex2.nChainSproutValue); // Now mark the first block's transactions as received - EXPECT_TRUE(ReceivedBlockTransactions(block1, state, &fakeIndex1, pos1)); + EXPECT_TRUE(ReceivedBlockTransactions(block1, state, chainParams, &fakeIndex1, pos1)); EXPECT_TRUE(fakeIndex1.IsValid(BLOCK_VALID_TRANSACTIONS)); EXPECT_TRUE(fakeIndex2.IsValid(BLOCK_VALID_TRANSACTIONS)); diff --git a/src/main.cpp b/src/main.cpp index 3065e694fb5..eb87d2786d3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3543,9 +3543,13 @@ void FallbackSproutValuePoolBalance( } /** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */ -bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos) +bool ReceivedBlockTransactions( + const CBlock &block, + CValidationState& state, + const CChainParams& chainparams, + CBlockIndex *pindexNew, + const CDiskBlockPos& pos) { - const CChainParams& chainparams = Params(); pindexNew->nTx = block.vtx.size(); pindexNew->nChainTx = 0; CAmount sproutValue = 0; @@ -4010,7 +4014,7 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha if (dbp == NULL) if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart())) AbortNode(state, "Failed to write block"); - if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) + if (!ReceivedBlockTransactions(block, state, chainparams, pindex, blockPos)) return error("AcceptBlock(): ReceivedBlockTransactions failed"); } catch (const std::runtime_error& e) { return AbortNode(state, std::string("System error: ") + e.what()); @@ -4761,7 +4765,7 @@ bool InitBlockIndex(const CChainParams& chainparams) if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart())) return error("LoadBlockIndex(): writing genesis block to disk failed"); CBlockIndex *pindex = AddToBlockIndex(block); - if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) + if (!ReceivedBlockTransactions(block, state, chainparams, pindex, blockPos)) return error("LoadBlockIndex(): genesis block not accepted"); if (!ActivateBestChain(state, chainparams, &block)) return error("LoadBlockIndex(): genesis block cannot be activated"); From de410efd54f5b70d810d3d615f2eac0665e04d54 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Tue, 28 May 2019 17:29:40 -0600 Subject: [PATCH 124/395] Do not shadow the return value when testmode is true --- src/wallet/asyncrpcoperation_common.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/wallet/asyncrpcoperation_common.cpp b/src/wallet/asyncrpcoperation_common.cpp index f2deac557af..700c3a24633 100644 --- a/src/wallet/asyncrpcoperation_common.cpp +++ b/src/wallet/asyncrpcoperation_common.cpp @@ -16,7 +16,6 @@ UniValue SendTransaction(CTransaction& tx, bool testmode) { o.push_back(Pair("txid", tx.GetHash().ToString())); } else { // Test mode does not send the transaction to the network. - UniValue o(UniValue::VOBJ); o.push_back(Pair("test", 1)); o.push_back(Pair("txid", tx.GetHash().ToString())); o.push_back(Pair("hex", EncodeHexTx(tx))); @@ -55,4 +54,4 @@ std::pair SignSendRawTransaction(UniValue obj, bool test UniValue sendResult = SendTransaction(tx, testmode); return std::make_pair(tx, sendResult); -} \ No newline at end of file +} From d3d8fb7221322cc4b5747223daf318bb478eeda6 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Tue, 28 May 2019 17:58:49 -0600 Subject: [PATCH 125/395] Inline sign_send_raw_transaction --- src/test/rpc_wallet_tests.cpp | 70 ++++--------------- .../asyncrpcoperation_mergetoaddress.cpp | 23 +++--- src/wallet/asyncrpcoperation_mergetoaddress.h | 7 -- src/wallet/asyncrpcoperation_sendmany.cpp | 22 ++---- src/wallet/asyncrpcoperation_sendmany.h | 6 -- .../asyncrpcoperation_shieldcoinbase.cpp | 21 ++---- src/wallet/asyncrpcoperation_shieldcoinbase.h | 6 -- 7 files changed, 31 insertions(+), 124 deletions(-) diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index f2cc09903d4..521ee9d9475 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -15,6 +15,7 @@ #include "asyncrpcqueue.h" #include "asyncrpcoperation.h" +#include "wallet/asyncrpcoperation_common.h" #include "wallet/asyncrpcoperation_mergetoaddress.h" #include "wallet/asyncrpcoperation_sendmany.h" #include "wallet/asyncrpcoperation_shieldcoinbase.h" @@ -1018,6 +1019,17 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_parameters) } } +BOOST_AUTO_TEST_CASE(asyncrpcoperation_sign_send_raw_transaction) { + // Raw joinsplit is a zaddr->zaddr + std::string raw = "020000000000000000000100000000000000001027000000000000183a0d4c46c369078705e39bcfebee59a978dbd210ce8de3efc9555a03fbabfd3cea16693d730c63850d7e48ccde79854c19adcb7e9dcd7b7d18805ee09083f6b16e1860729d2d4a90e2f2acd009cf78b5eb0f4a6ee4bdb64b1262d7ce9eb910c460b02022991e968d0c50ee44908e4ccccbc591d0053bcca154dd6d6fc400a29fa686af4682339832ccea362a62aeb9df0d5aa74f86a1e75ac0f48a8ccc41e0a940643c6c33e1d09223b0a46eaf47a1bb4407cfc12b1dcf83a29c0cef51e45c7876ca5b9e5bae86d92976eb3ef68f29cd29386a8be8451b50f82bf9da10c04651868655194da8f6ed3d241bb5b5ff93a3e2bbe44644544d88bcde5cc35978032ee92699c7a61fcbb395e7583f47e698c4d53ede54f956629400bf510fb5e22d03158cc10bdcaaf29e418ef18eb6480dd9c8b9e2a377809f9f32a556ef872febd0021d4ad013aa9f0b7255e98e408d302abefd33a71180b720271835b487ab309e160b06dfe51932120fb84a7ede16b20c53599a11071592109e10260f265ee60d48c62bfe24074020e9b586ce9e9356e68f2ad1a9538258234afe4b83a209f178f45202270eaeaeecaf2ce3100b2c5a714f75f35777a9ebff5ebf47059d2bbf6f3726190216468f2b152673b766225b093f3a2f827c86d6b48b42117fec1d0ac38dd7af700308dcfb02eba821612b16a2c164c47715b9b0c93900893b1aba2ea03765c94d87022db5be06ab338d1912e0936dfe87586d0a8ee49144a6cd2e306abdcb652faa3e0222739deb23154d778b50de75069a4a2cce1208cd1ced3cb4744c9888ce1c2fcd2e66dc31e62d3aa9e423d7275882525e9981f92e84ac85975b8660739407efbe1e34c2249420fde7e17db3096d5b22e83d051d01f0e6e7690dca7d168db338aadf0897fedac10de310db2b1bff762d322935dddbb60c2efb8b15d231fa17b84630371cb275c209f0c4c7d0c68b150ea5cd514122215e3f7fcfb351d69514788d67c2f3c8922581946e3a04bdf1f07f15696ca76eb95b10698bf1188fd882945c57657515889d042a6fc45d38cbc943540c4f0f6d1c45a1574c81f3e42d1eb8702328b729909adee8a5cfed7c79d54627d1fd389af941d878376f7927b9830ca659bf9ab18c5ca5192d52d02723008728d03701b8ab3e1c4a3109409ec0b13df334c7deec3523eeef4c97b5603e643de3a647b873f4c1b47fbfc6586ba66724f112e51fc93839648005043620aa3ce458e246d77977b19c53d98e3e812de006afc1a79744df236582943631d04cc02941ac4be500e4ed9fb9e3e7cc187b1c4050fad1d9d09d5fd70d5d01d615b439d8c0015d2eb10398bcdbf8c4b2bd559dbe4c288a186aed3f86f608da4d582e120c4a896e015e2241900d1daeccd05db968852677c71d752bec46de9962174b46f980e8cc603654daf8b98a3ee92dac066033954164a89568b70b1780c2ce2410b2f816dbeddb2cd463e0c8f21a52cf6427d9647a6fd4bafa8fb4cd4d47ac057b0160bee86c6b2fb8adce214c2bcdda277512200adf0eaa5d2114a2c077b009836a68ec254bfe56f51d147b9afe2ddd9cb917c0c2de19d81b7b8fd9f4574f51fa1207630dc13976f4d7587c962f761af267de71f3909a576e6bedaf6311633910d291ac292c467cc8331ef577aef7646a5d949322fa0367a49f20597a13def53136ee31610395e3e48d291fd8f58504374031fe9dcfba5e06086ebcf01a9106f6a4d6e16e19e4c5bb893f7da79419c94eca31a384be6fa1747284dee0fc3bbc8b1b860172c10b29c1594bb8c747d7fe05827358ff2160f49050001625ffe2e880bd7fc26cd0ffd89750745379a8e862816e08a5a2008043921ab6a4976064ac18f7ee37b6628bc0127d8d5ebd3548e41d8881a082d86f20b32e33094f15a0e6ea6074b08c6cd28142de94713451640a55985051f5577eb54572699d838cb34a79c8939e981c0c277d06a6e2ce69ccb74f8a691ff08f81d8b99e6a86223d29a2b7c8e7b041aba44ea678ae654277f7e91cbfa79158b989164a3d549d9f4feb0cc43169699c13e321fe3f4b94258c75d198ff9184269cd6986c55409e07528c93f64942c6c283ce3917b4bf4c3be2fe3173c8c38cccb35f1fbda0ca88b35a599c0678cb22aa8eabea8249dbd2e4f849fffe69803d299e435ebcd7df95854003d8eda17a74d98b4be0e62d45d7fe48c06a6f464a14f8e0570077cc631279092802a89823f031eef5e1028a6d6fdbd502869a731ee7d28b4d6c71b419462a30d31442d3ee444ffbcbd16d558c9000c97e949c2b1f9d6f6d8db7b9131ebd963620d3fc8595278d6f8fdf49084325373196d53e64142fa5a23eccd6ef908c4d80b8b3e6cc334b7f7012103a3682e4678e9b518163d262a39a2c1a69bf88514c52b7ccd7cc8dc80e71f7c2ec0701cff982573eb0c2c4daeb47fa0b586f4451c10d1da2e5d182b03dd067a5e971b3a6138ca6667aaf853d2ac03b80a1d5870905f2cfb6c78ec3c3719c02f973d638a0f973424a2b0f2b0023f136d60092fe15fba4bc180b9176bd0ff576e053f1af6939fe9ca256203ffaeb3e569f09774d2a6cbf91873e56651f4d6ff77e0b5374b0a1a201d7e523604e0247644544cc571d48c458a4f96f45580b"; + UniValue obj(UniValue::VOBJ); + obj.push_back(Pair("rawtxn", raw)); + // Verify test mode is returning output (since no input taddrs, signed and unsigned are the same). + std::pair txAndResult = SignSendRawTransaction(obj, true); + UniValue resultObj = txAndResult.second.get_obj(); + std::string hex = find_value(resultObj, "hex").get_str(); + BOOST_CHECK_EQUAL(hex, raw); +} // TODO: test private methods BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals) @@ -1170,36 +1182,6 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals) BOOST_CHECK_EQUAL(tx.vout[2].nValue, CAmount(7.89)); } - - // Raw joinsplit is a zaddr->zaddr - { - std::string raw = "020000000000000000000100000000000000001027000000000000183a0d4c46c369078705e39bcfebee59a978dbd210ce8de3efc9555a03fbabfd3cea16693d730c63850d7e48ccde79854c19adcb7e9dcd7b7d18805ee09083f6b16e1860729d2d4a90e2f2acd009cf78b5eb0f4a6ee4bdb64b1262d7ce9eb910c460b02022991e968d0c50ee44908e4ccccbc591d0053bcca154dd6d6fc400a29fa686af4682339832ccea362a62aeb9df0d5aa74f86a1e75ac0f48a8ccc41e0a940643c6c33e1d09223b0a46eaf47a1bb4407cfc12b1dcf83a29c0cef51e45c7876ca5b9e5bae86d92976eb3ef68f29cd29386a8be8451b50f82bf9da10c04651868655194da8f6ed3d241bb5b5ff93a3e2bbe44644544d88bcde5cc35978032ee92699c7a61fcbb395e7583f47e698c4d53ede54f956629400bf510fb5e22d03158cc10bdcaaf29e418ef18eb6480dd9c8b9e2a377809f9f32a556ef872febd0021d4ad013aa9f0b7255e98e408d302abefd33a71180b720271835b487ab309e160b06dfe51932120fb84a7ede16b20c53599a11071592109e10260f265ee60d48c62bfe24074020e9b586ce9e9356e68f2ad1a9538258234afe4b83a209f178f45202270eaeaeecaf2ce3100b2c5a714f75f35777a9ebff5ebf47059d2bbf6f3726190216468f2b152673b766225b093f3a2f827c86d6b48b42117fec1d0ac38dd7af700308dcfb02eba821612b16a2c164c47715b9b0c93900893b1aba2ea03765c94d87022db5be06ab338d1912e0936dfe87586d0a8ee49144a6cd2e306abdcb652faa3e0222739deb23154d778b50de75069a4a2cce1208cd1ced3cb4744c9888ce1c2fcd2e66dc31e62d3aa9e423d7275882525e9981f92e84ac85975b8660739407efbe1e34c2249420fde7e17db3096d5b22e83d051d01f0e6e7690dca7d168db338aadf0897fedac10de310db2b1bff762d322935dddbb60c2efb8b15d231fa17b84630371cb275c209f0c4c7d0c68b150ea5cd514122215e3f7fcfb351d69514788d67c2f3c8922581946e3a04bdf1f07f15696ca76eb95b10698bf1188fd882945c57657515889d042a6fc45d38cbc943540c4f0f6d1c45a1574c81f3e42d1eb8702328b729909adee8a5cfed7c79d54627d1fd389af941d878376f7927b9830ca659bf9ab18c5ca5192d52d02723008728d03701b8ab3e1c4a3109409ec0b13df334c7deec3523eeef4c97b5603e643de3a647b873f4c1b47fbfc6586ba66724f112e51fc93839648005043620aa3ce458e246d77977b19c53d98e3e812de006afc1a79744df236582943631d04cc02941ac4be500e4ed9fb9e3e7cc187b1c4050fad1d9d09d5fd70d5d01d615b439d8c0015d2eb10398bcdbf8c4b2bd559dbe4c288a186aed3f86f608da4d582e120c4a896e015e2241900d1daeccd05db968852677c71d752bec46de9962174b46f980e8cc603654daf8b98a3ee92dac066033954164a89568b70b1780c2ce2410b2f816dbeddb2cd463e0c8f21a52cf6427d9647a6fd4bafa8fb4cd4d47ac057b0160bee86c6b2fb8adce214c2bcdda277512200adf0eaa5d2114a2c077b009836a68ec254bfe56f51d147b9afe2ddd9cb917c0c2de19d81b7b8fd9f4574f51fa1207630dc13976f4d7587c962f761af267de71f3909a576e6bedaf6311633910d291ac292c467cc8331ef577aef7646a5d949322fa0367a49f20597a13def53136ee31610395e3e48d291fd8f58504374031fe9dcfba5e06086ebcf01a9106f6a4d6e16e19e4c5bb893f7da79419c94eca31a384be6fa1747284dee0fc3bbc8b1b860172c10b29c1594bb8c747d7fe05827358ff2160f49050001625ffe2e880bd7fc26cd0ffd89750745379a8e862816e08a5a2008043921ab6a4976064ac18f7ee37b6628bc0127d8d5ebd3548e41d8881a082d86f20b32e33094f15a0e6ea6074b08c6cd28142de94713451640a55985051f5577eb54572699d838cb34a79c8939e981c0c277d06a6e2ce69ccb74f8a691ff08f81d8b99e6a86223d29a2b7c8e7b041aba44ea678ae654277f7e91cbfa79158b989164a3d549d9f4feb0cc43169699c13e321fe3f4b94258c75d198ff9184269cd6986c55409e07528c93f64942c6c283ce3917b4bf4c3be2fe3173c8c38cccb35f1fbda0ca88b35a599c0678cb22aa8eabea8249dbd2e4f849fffe69803d299e435ebcd7df95854003d8eda17a74d98b4be0e62d45d7fe48c06a6f464a14f8e0570077cc631279092802a89823f031eef5e1028a6d6fdbd502869a731ee7d28b4d6c71b419462a30d31442d3ee444ffbcbd16d558c9000c97e949c2b1f9d6f6d8db7b9131ebd963620d3fc8595278d6f8fdf49084325373196d53e64142fa5a23eccd6ef908c4d80b8b3e6cc334b7f7012103a3682e4678e9b518163d262a39a2c1a69bf88514c52b7ccd7cc8dc80e71f7c2ec0701cff982573eb0c2c4daeb47fa0b586f4451c10d1da2e5d182b03dd067a5e971b3a6138ca6667aaf853d2ac03b80a1d5870905f2cfb6c78ec3c3719c02f973d638a0f973424a2b0f2b0023f136d60092fe15fba4bc180b9176bd0ff576e053f1af6939fe9ca256203ffaeb3e569f09774d2a6cbf91873e56651f4d6ff77e0b5374b0a1a201d7e523604e0247644544cc571d48c458a4f96f45580b"; - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("rawtxn", raw)); - - // we have the spending key for the dummy recipient zaddr1 - std::vector recipients = { SendManyRecipient(zaddr1, 0.0005, "ABCD") }; - - std::shared_ptr operation( new AsyncRPCOperation_sendmany(boost::none, mtx, zaddr1, {}, recipients, 1) ); - std::shared_ptr ptr = std::dynamic_pointer_cast (operation); - TEST_FRIEND_AsyncRPCOperation_sendmany proxy(ptr); - - // Enable test mode so tx is not sent - static_cast(operation.get())->testmode = true; - - // Pretend that the operation completed successfully - proxy.set_state(OperationStatus::SUCCESS); - - // Verify test mode is returning output (since no input taddrs, signed and unsigned are the same). - BOOST_CHECK_NO_THROW( proxy.sign_send_raw_transaction(obj) ); - UniValue result = operation->getResult(); - BOOST_CHECK(!result.isNull()); - UniValue resultObj = result.get_obj(); - std::string hex = find_value(resultObj, "hex").get_str(); - BOOST_CHECK_EQUAL(hex, raw); - } - - // Test the perform_joinsplit methods. { // Dummy input so the operation object can be instantiated. @@ -1252,7 +1234,6 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals) BOOST_CHECK( string(e.what()).find("error verifying joinsplit")!= string::npos); } } - } @@ -1997,33 +1978,6 @@ BOOST_AUTO_TEST_CASE(rpc_z_mergetoaddress_internals) BOOST_CHECK( string(e.what()).find("error verifying joinsplit")!= string::npos); } } - - // Raw joinsplit is a zaddr->zaddr - { - std::string raw = "020000000000000000000100000000000000001027000000000000183a0d4c46c369078705e39bcfebee59a978dbd210ce8de3efc9555a03fbabfd3cea16693d730c63850d7e48ccde79854c19adcb7e9dcd7b7d18805ee09083f6b16e1860729d2d4a90e2f2acd009cf78b5eb0f4a6ee4bdb64b1262d7ce9eb910c460b02022991e968d0c50ee44908e4ccccbc591d0053bcca154dd6d6fc400a29fa686af4682339832ccea362a62aeb9df0d5aa74f86a1e75ac0f48a8ccc41e0a940643c6c33e1d09223b0a46eaf47a1bb4407cfc12b1dcf83a29c0cef51e45c7876ca5b9e5bae86d92976eb3ef68f29cd29386a8be8451b50f82bf9da10c04651868655194da8f6ed3d241bb5b5ff93a3e2bbe44644544d88bcde5cc35978032ee92699c7a61fcbb395e7583f47e698c4d53ede54f956629400bf510fb5e22d03158cc10bdcaaf29e418ef18eb6480dd9c8b9e2a377809f9f32a556ef872febd0021d4ad013aa9f0b7255e98e408d302abefd33a71180b720271835b487ab309e160b06dfe51932120fb84a7ede16b20c53599a11071592109e10260f265ee60d48c62bfe24074020e9b586ce9e9356e68f2ad1a9538258234afe4b83a209f178f45202270eaeaeecaf2ce3100b2c5a714f75f35777a9ebff5ebf47059d2bbf6f3726190216468f2b152673b766225b093f3a2f827c86d6b48b42117fec1d0ac38dd7af700308dcfb02eba821612b16a2c164c47715b9b0c93900893b1aba2ea03765c94d87022db5be06ab338d1912e0936dfe87586d0a8ee49144a6cd2e306abdcb652faa3e0222739deb23154d778b50de75069a4a2cce1208cd1ced3cb4744c9888ce1c2fcd2e66dc31e62d3aa9e423d7275882525e9981f92e84ac85975b8660739407efbe1e34c2249420fde7e17db3096d5b22e83d051d01f0e6e7690dca7d168db338aadf0897fedac10de310db2b1bff762d322935dddbb60c2efb8b15d231fa17b84630371cb275c209f0c4c7d0c68b150ea5cd514122215e3f7fcfb351d69514788d67c2f3c8922581946e3a04bdf1f07f15696ca76eb95b10698bf1188fd882945c57657515889d042a6fc45d38cbc943540c4f0f6d1c45a1574c81f3e42d1eb8702328b729909adee8a5cfed7c79d54627d1fd389af941d878376f7927b9830ca659bf9ab18c5ca5192d52d02723008728d03701b8ab3e1c4a3109409ec0b13df334c7deec3523eeef4c97b5603e643de3a647b873f4c1b47fbfc6586ba66724f112e51fc93839648005043620aa3ce458e246d77977b19c53d98e3e812de006afc1a79744df236582943631d04cc02941ac4be500e4ed9fb9e3e7cc187b1c4050fad1d9d09d5fd70d5d01d615b439d8c0015d2eb10398bcdbf8c4b2bd559dbe4c288a186aed3f86f608da4d582e120c4a896e015e2241900d1daeccd05db968852677c71d752bec46de9962174b46f980e8cc603654daf8b98a3ee92dac066033954164a89568b70b1780c2ce2410b2f816dbeddb2cd463e0c8f21a52cf6427d9647a6fd4bafa8fb4cd4d47ac057b0160bee86c6b2fb8adce214c2bcdda277512200adf0eaa5d2114a2c077b009836a68ec254bfe56f51d147b9afe2ddd9cb917c0c2de19d81b7b8fd9f4574f51fa1207630dc13976f4d7587c962f761af267de71f3909a576e6bedaf6311633910d291ac292c467cc8331ef577aef7646a5d949322fa0367a49f20597a13def53136ee31610395e3e48d291fd8f58504374031fe9dcfba5e06086ebcf01a9106f6a4d6e16e19e4c5bb893f7da79419c94eca31a384be6fa1747284dee0fc3bbc8b1b860172c10b29c1594bb8c747d7fe05827358ff2160f49050001625ffe2e880bd7fc26cd0ffd89750745379a8e862816e08a5a2008043921ab6a4976064ac18f7ee37b6628bc0127d8d5ebd3548e41d8881a082d86f20b32e33094f15a0e6ea6074b08c6cd28142de94713451640a55985051f5577eb54572699d838cb34a79c8939e981c0c277d06a6e2ce69ccb74f8a691ff08f81d8b99e6a86223d29a2b7c8e7b041aba44ea678ae654277f7e91cbfa79158b989164a3d549d9f4feb0cc43169699c13e321fe3f4b94258c75d198ff9184269cd6986c55409e07528c93f64942c6c283ce3917b4bf4c3be2fe3173c8c38cccb35f1fbda0ca88b35a599c0678cb22aa8eabea8249dbd2e4f849fffe69803d299e435ebcd7df95854003d8eda17a74d98b4be0e62d45d7fe48c06a6f464a14f8e0570077cc631279092802a89823f031eef5e1028a6d6fdbd502869a731ee7d28b4d6c71b419462a30d31442d3ee444ffbcbd16d558c9000c97e949c2b1f9d6f6d8db7b9131ebd963620d3fc8595278d6f8fdf49084325373196d53e64142fa5a23eccd6ef908c4d80b8b3e6cc334b7f7012103a3682e4678e9b518163d262a39a2c1a69bf88514c52b7ccd7cc8dc80e71f7c2ec0701cff982573eb0c2c4daeb47fa0b586f4451c10d1da2e5d182b03dd067a5e971b3a6138ca6667aaf853d2ac03b80a1d5870905f2cfb6c78ec3c3719c02f973d638a0f973424a2b0f2b0023f136d60092fe15fba4bc180b9176bd0ff576e053f1af6939fe9ca256203ffaeb3e569f09774d2a6cbf91873e56651f4d6ff77e0b5374b0a1a201d7e523604e0247644544cc571d48c458a4f96f45580b"; - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("rawtxn", raw)); - - // we have the spending key for the dummy recipient zaddr1 - std::vector inputs = { MergeToAddressInputUTXO{COutPoint{uint256(),0},100000, CScript()} }; - std::shared_ptr operation( new AsyncRPCOperation_mergetoaddress(boost::none, mtx, inputs, {}, {}, zaddr1) ); - std::shared_ptr ptr = std::dynamic_pointer_cast (operation); - TEST_FRIEND_AsyncRPCOperation_mergetoaddress proxy(ptr); - - // Enable test mode so tx is not sent - static_cast(operation.get())->testmode = true; - - // Pretend that the operation completed successfully - proxy.set_state(OperationStatus::SUCCESS); - - // Verify test mode is returning output (since no input taddrs, signed and unsigned are the same). - BOOST_CHECK_NO_THROW( proxy.sign_send_raw_transaction(obj) ); - UniValue result = operation->getResult(); - BOOST_CHECK(!result.isNull()); - UniValue resultObj = result.get_obj(); - std::string hex = find_value(resultObj, "hex").get_str(); - BOOST_CHECK_EQUAL(hex, raw); - } } diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index c551fbe0114..31b3f62ba2a 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -379,7 +379,9 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() if (isPureTaddrOnlyTx) { UniValue obj(UniValue::VOBJ); obj.push_back(Pair("rawtxn", EncodeHexTx(tx_))); - sign_send_raw_transaction(obj); + auto txAndResult = SignSendRawTransaction(obj, testmode); + tx_ = txAndResult.first; + set_result(txAndResult.second); return true; } /** @@ -414,9 +416,10 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() } info.vjsout.push_back(jso); - UniValue obj(UniValue::VOBJ); - obj = perform_joinsplit(info); - sign_send_raw_transaction(obj); + UniValue obj = perform_joinsplit(info); + auto txAndResult = SignSendRawTransaction(obj, testmode); + tx_ = txAndResult.first; + set_result(txAndResult.second); return true; } /** @@ -715,20 +718,10 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() assert(zInputsDeque.size() == 0); assert(vpubNewProcessed); - sign_send_raw_transaction(obj); - return true; -} - - -/** - * Sign and send a raw transaction. - * Raw transaction as hex string should be in object field "rawtxn" - */ -void AsyncRPCOperation_mergetoaddress::sign_send_raw_transaction(UniValue obj) -{ auto txAndResult = SignSendRawTransaction(obj, testmode); tx_ = txAndResult.first; set_result(txAndResult.second); + return true; } diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.h b/src/wallet/asyncrpcoperation_mergetoaddress.h index 774695cf26a..3e7a72c20ea 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.h +++ b/src/wallet/asyncrpcoperation_mergetoaddress.h @@ -123,8 +123,6 @@ class AsyncRPCOperation_mergetoaddress : public AsyncRPCOperation std::vector> witnesses, uint256 anchor); - void sign_send_raw_transaction(UniValue obj); // throws exception if there was an error - void lock_utxos(); void unlock_utxos(); @@ -186,11 +184,6 @@ class TEST_FRIEND_AsyncRPCOperation_mergetoaddress return delegate->perform_joinsplit(info, witnesses, anchor); } - void sign_send_raw_transaction(UniValue obj) - { - delegate->sign_send_raw_transaction(obj); - } - void set_state(OperationStatus state) { delegate->state_.store(state); diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index d0b10420302..954f8541a6e 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -36,8 +36,6 @@ using namespace libzcash; -extern UniValue signrawtransaction(const UniValue& params, bool fHelp); - int find_output(UniValue obj, int n) { UniValue outputMapValue = find_value(obj, "outputmap"); if (!outputMapValue.isArray()) { @@ -503,7 +501,9 @@ bool AsyncRPCOperation_sendmany::main_impl() { UniValue obj(UniValue::VOBJ); obj.push_back(Pair("rawtxn", EncodeHexTx(tx_))); - sign_send_raw_transaction(obj); + auto txAndResult = SignSendRawTransaction(obj, testmode); + tx_ = txAndResult.first; + set_result(txAndResult.second); return true; } /** @@ -608,7 +608,9 @@ bool AsyncRPCOperation_sendmany::main_impl() { } obj = perform_joinsplit(info); } - sign_send_raw_transaction(obj); + auto txAndResult = SignSendRawTransaction(obj, testmode); + tx_ = txAndResult.first; + set_result(txAndResult.second); return true; } /** @@ -886,20 +888,10 @@ bool AsyncRPCOperation_sendmany::main_impl() { assert(zOutputsDeque.size() == 0); assert(vpubNewProcessed); - sign_send_raw_transaction(obj); - return true; -} - - -/** - * Sign and send a raw transaction. - * Raw transaction as hex string should be in object field "rawtxn" - */ -void AsyncRPCOperation_sendmany::sign_send_raw_transaction(UniValue obj) -{ auto txAndResult = SignSendRawTransaction(obj, testmode); tx_ = txAndResult.first; set_result(txAndResult.second); + return true; } diff --git a/src/wallet/asyncrpcoperation_sendmany.h b/src/wallet/asyncrpcoperation_sendmany.h index fcb95227a5e..89b5d94b571 100644 --- a/src/wallet/asyncrpcoperation_sendmany.h +++ b/src/wallet/asyncrpcoperation_sendmany.h @@ -127,8 +127,6 @@ class AsyncRPCOperation_sendmany : public AsyncRPCOperation { std::vector> witnesses, uint256 anchor); - void sign_send_raw_transaction(UniValue obj); // throws exception if there was an error - // payment disclosure! std::vector paymentDisclosureData_; }; @@ -191,10 +189,6 @@ class TEST_FRIEND_AsyncRPCOperation_sendmany { return delegate->perform_joinsplit(info, witnesses, anchor); } - void sign_send_raw_transaction(UniValue obj) { - delegate->sign_send_raw_transaction(obj); - } - void set_state(OperationStatus state) { delegate->state_.store(state); } diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp index 14d9d988b11..197c2d4a467 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp @@ -225,21 +225,20 @@ bool ShieldToAddress::operator()(const libzcash::SproutPaymentAddress &zaddr) co m_op->tx_ = CTransaction(mtx); // Create joinsplit - UniValue obj(UniValue::VOBJ); ShieldCoinbaseJSInfo info; info.vpub_old = sendAmount; info.vpub_new = 0; JSOutput jso = JSOutput(zaddr, sendAmount); info.vjsout.push_back(jso); - obj = m_op->perform_joinsplit(info); + UniValue obj = m_op->perform_joinsplit(info); - m_op->sign_send_raw_transaction(obj); + auto txAndResult = SignSendRawTransaction(obj, m_op->testmode); + m_op->tx_ = txAndResult.first; + m_op->set_result(txAndResult.second); return true; } -extern UniValue signrawtransaction(const UniValue& params, bool fHelp); - bool ShieldToAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) const { m_op->builder_.SetFee(m_op->fee_); @@ -272,18 +271,6 @@ bool ShieldToAddress::operator()(const libzcash::InvalidEncoding& no) const { } -/** - * Sign and send a raw transaction. - * Raw transaction as hex string should be in object field "rawtxn" - */ -void AsyncRPCOperation_shieldcoinbase::sign_send_raw_transaction(UniValue obj) -{ - auto txAndResult = SignSendRawTransaction(obj, testmode); - tx_ = txAndResult.first; - set_result(txAndResult.second); -} - - UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInfo & info) { uint32_t consensusBranchId; uint256 anchor; diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.h b/src/wallet/asyncrpcoperation_shieldcoinbase.h index 4311d84b316..7070cc0f9b5 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.h +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.h @@ -87,8 +87,6 @@ class AsyncRPCOperation_shieldcoinbase : public AsyncRPCOperation { // JoinSplit without any input notes to spend UniValue perform_joinsplit(ShieldCoinbaseJSInfo &); - void sign_send_raw_transaction(UniValue obj); // throws exception if there was an error - void lock_utxos(); void unlock_utxos(); @@ -137,10 +135,6 @@ class TEST_FRIEND_AsyncRPCOperation_shieldcoinbase { return delegate->perform_joinsplit(info); } - void sign_send_raw_transaction(UniValue obj) { - delegate->sign_send_raw_transaction(obj); - } - void set_state(OperationStatus state) { delegate->state_.store(state); } From 27f91abf0009caba029e82484399e8abaabab823 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Tue, 28 May 2019 20:10:42 -0600 Subject: [PATCH 126/395] Allow passing optional reserve key as a parameter to SendTransaction --- src/test/rpc_wallet_tests.cpp | 2 +- src/wallet/asyncrpcoperation_common.cpp | 9 ++++----- src/wallet/asyncrpcoperation_common.h | 5 +++-- src/wallet/asyncrpcoperation_mergetoaddress.cpp | 8 ++++---- src/wallet/asyncrpcoperation_sendmany.cpp | 13 ++++++++----- src/wallet/asyncrpcoperation_shieldcoinbase.cpp | 4 ++-- 6 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index 521ee9d9475..5d7cc08d927 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -1025,7 +1025,7 @@ BOOST_AUTO_TEST_CASE(asyncrpcoperation_sign_send_raw_transaction) { UniValue obj(UniValue::VOBJ); obj.push_back(Pair("rawtxn", raw)); // Verify test mode is returning output (since no input taddrs, signed and unsigned are the same). - std::pair txAndResult = SignSendRawTransaction(obj, true); + std::pair txAndResult = SignSendRawTransaction(obj, boost::none, true); UniValue resultObj = txAndResult.second.get_obj(); std::string hex = find_value(resultObj, "hex").get_str(); BOOST_CHECK_EQUAL(hex, raw); diff --git a/src/wallet/asyncrpcoperation_common.cpp b/src/wallet/asyncrpcoperation_common.cpp index 700c3a24633..dec29f8a2c2 100644 --- a/src/wallet/asyncrpcoperation_common.cpp +++ b/src/wallet/asyncrpcoperation_common.cpp @@ -3,16 +3,15 @@ #include "core_io.h" #include "init.h" #include "rpc/protocol.h" -#include "wallet.h" extern UniValue signrawtransaction(const UniValue& params, bool fHelp); -UniValue SendTransaction(CTransaction& tx, bool testmode) { +UniValue SendTransaction(CTransaction& tx, boost::optional reservekey, bool testmode) { UniValue o(UniValue::VOBJ); // Send the transaction if (!testmode) { CWalletTx wtx(pwalletMain, tx); - pwalletMain->CommitTransaction(wtx, boost::none); + pwalletMain->CommitTransaction(wtx, reservekey); o.push_back(Pair("txid", tx.GetHash().ToString())); } else { // Test mode does not send the transaction to the network. @@ -23,7 +22,7 @@ UniValue SendTransaction(CTransaction& tx, bool testmode) { return o; } -std::pair SignSendRawTransaction(UniValue obj, bool testmode) { +std::pair SignSendRawTransaction(UniValue obj, boost::optional reservekey, bool testmode) { // Sign the raw transaction UniValue rawtxnValue = find_value(obj, "rawtxn"); if (rawtxnValue.isNull()) { @@ -51,7 +50,7 @@ std::pair SignSendRawTransaction(UniValue obj, bool test CTransaction tx; stream >> tx; - UniValue sendResult = SendTransaction(tx, testmode); + UniValue sendResult = SendTransaction(tx, reservekey, testmode); return std::make_pair(tx, sendResult); } diff --git a/src/wallet/asyncrpcoperation_common.h b/src/wallet/asyncrpcoperation_common.h index d22e072a86f..0b27d2952c6 100644 --- a/src/wallet/asyncrpcoperation_common.h +++ b/src/wallet/asyncrpcoperation_common.h @@ -7,6 +7,7 @@ #include "primitives/transaction.h" #include "univalue.h" +#include "wallet.h" /** * Sends a given transaction. @@ -17,7 +18,7 @@ * If testmode is true, do not commit the transaction, * return {"test": 1, "txid": tx.GetHash().ToString(), "hex": EncodeHexTx(tx)} */ -UniValue SendTransaction(CTransaction& tx, bool testmode); +UniValue SendTransaction(CTransaction& tx, boost::optional reservekey, bool testmode); /** * Sign and send a raw transaction. @@ -25,6 +26,6 @@ UniValue SendTransaction(CTransaction& tx, bool testmode); * * Returns a pair of (the parsed transaction, and the result of sending) */ -std::pair SignSendRawTransaction(UniValue obj, bool testmode); +std::pair SignSendRawTransaction(UniValue obj, boost::optional reservekey, bool testmode); #endif /* ASYNCRPCOPERATION_COMMON_H */ diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index 31b3f62ba2a..257d68180fa 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -359,7 +359,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() // Build the transaction tx_ = builder_.Build().GetTxOrThrow(); - UniValue sendResult = SendTransaction(tx_, testmode); + UniValue sendResult = SendTransaction(tx_, boost::none, testmode); set_result(sendResult); return true; @@ -379,7 +379,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() if (isPureTaddrOnlyTx) { UniValue obj(UniValue::VOBJ); obj.push_back(Pair("rawtxn", EncodeHexTx(tx_))); - auto txAndResult = SignSendRawTransaction(obj, testmode); + auto txAndResult = SignSendRawTransaction(obj, boost::none, testmode); tx_ = txAndResult.first; set_result(txAndResult.second); return true; @@ -417,7 +417,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() info.vjsout.push_back(jso); UniValue obj = perform_joinsplit(info); - auto txAndResult = SignSendRawTransaction(obj, testmode); + auto txAndResult = SignSendRawTransaction(obj, boost::none, testmode); tx_ = txAndResult.first; set_result(txAndResult.second); return true; @@ -718,7 +718,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() assert(zInputsDeque.size() == 0); assert(vpubNewProcessed); - auto txAndResult = SignSendRawTransaction(obj, testmode); + auto txAndResult = SignSendRawTransaction(obj, boost::none, testmode); tx_ = txAndResult.first; set_result(txAndResult.second); return true; diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index 954f8541a6e..64a40f03c91 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -460,7 +460,8 @@ bool AsyncRPCOperation_sendmany::main_impl() { // Build the transaction tx_ = builder_.Build().GetTxOrThrow(); - UniValue sendResult = SendTransaction(tx_, testmode); + // TODO use CReserveKey keyChange if isfromtaddr_ + UniValue sendResult = SendTransaction(tx_, boost::none, testmode); set_result(sendResult); return true; @@ -501,7 +502,8 @@ bool AsyncRPCOperation_sendmany::main_impl() { UniValue obj(UniValue::VOBJ); obj.push_back(Pair("rawtxn", EncodeHexTx(tx_))); - auto txAndResult = SignSendRawTransaction(obj, testmode); + // TODO: use CReserveKey from add_taddr_change_output_to_tx + auto txAndResult = SignSendRawTransaction(obj, boost::none, testmode); tx_ = txAndResult.first; set_result(txAndResult.second); return true; @@ -565,7 +567,7 @@ bool AsyncRPCOperation_sendmany::main_impl() { CAmount funds = selectedUTXOAmount; CAmount fundsSpent = t_outputs_total + minersFee + z_outputs_total; CAmount change = funds - fundsSpent; - + if (change > 0) { if (selectedUTXOCoinbase) { assert(isSingleZaddrOutput); @@ -608,7 +610,8 @@ bool AsyncRPCOperation_sendmany::main_impl() { } obj = perform_joinsplit(info); } - auto txAndResult = SignSendRawTransaction(obj, testmode); + // TODO: use CReserveKey from add_taddr_change_output_to_tx + auto txAndResult = SignSendRawTransaction(obj, boost::none, testmode); tx_ = txAndResult.first; set_result(txAndResult.second); return true; @@ -888,7 +891,7 @@ bool AsyncRPCOperation_sendmany::main_impl() { assert(zOutputsDeque.size() == 0); assert(vpubNewProcessed); - auto txAndResult = SignSendRawTransaction(obj, testmode); + auto txAndResult = SignSendRawTransaction(obj, boost::none, testmode); tx_ = txAndResult.first; set_result(txAndResult.second); return true; diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp index 197c2d4a467..dcf018a1c46 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp @@ -232,7 +232,7 @@ bool ShieldToAddress::operator()(const libzcash::SproutPaymentAddress &zaddr) co info.vjsout.push_back(jso); UniValue obj = m_op->perform_joinsplit(info); - auto txAndResult = SignSendRawTransaction(obj, m_op->testmode); + auto txAndResult = SignSendRawTransaction(obj, boost::none, m_op->testmode); m_op->tx_ = txAndResult.first; m_op->set_result(txAndResult.second); return true; @@ -260,7 +260,7 @@ bool ShieldToAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) c // Build the transaction m_op->tx_ = m_op->builder_.Build().GetTxOrThrow(); - UniValue sendResult = SendTransaction(m_op->tx_, m_op->testmode); + UniValue sendResult = SendTransaction(m_op->tx_, boost::none, m_op->testmode); m_op->set_result(sendResult); return true; From 4120aff03736e5b991ee58904d005b5c0ed8a39c Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Thu, 30 May 2019 09:56:45 -0600 Subject: [PATCH 127/395] Use reserve key for transparent change when sending to Sapling --- src/wallet/asyncrpcoperation_sendmany.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index 64a40f03c91..9ebd553a751 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -386,11 +386,11 @@ bool AsyncRPCOperation_sendmany::main_impl() { // Set change address if we are using transparent funds // TODO: Should we just use fromtaddr_ as the change address? + CReserveKey keyChange(pwalletMain); if (isfromtaddr_) { LOCK2(cs_main, pwalletMain->cs_wallet); EnsureWalletIsUnlocked(); - CReserveKey keyChange(pwalletMain); CPubKey vchPubKey; bool ret = keyChange.GetReservedKey(vchPubKey); if (!ret) { @@ -460,8 +460,7 @@ bool AsyncRPCOperation_sendmany::main_impl() { // Build the transaction tx_ = builder_.Build().GetTxOrThrow(); - // TODO use CReserveKey keyChange if isfromtaddr_ - UniValue sendResult = SendTransaction(tx_, boost::none, testmode); + UniValue sendResult = SendTransaction(tx_, keyChange, testmode); set_result(sendResult); return true; From 406b8ff509935fcbc30f84901963001ddba37f66 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Thu, 6 Jun 2019 13:49:11 -0600 Subject: [PATCH 128/395] z_getmigrationstatus help message wording change --- src/wallet/rpcwallet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 2e9139c6545..4cac157be4d 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3937,8 +3937,8 @@ UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) { throw runtime_error( "z_getmigrationstatus\n" "Returns information about the status of the Sprout to Sapling migration.\n" - "A transaction is defined as finalized if it has at least ten confirmations.\n" - "Note: It is possible that manually created transactions involving this wallet\n" + "Note: A transaction is defined as finalized if it has at least ten confirmations.\n" + "Also, it is possible that manually created transactions involving this wallet\n" "will be included in the result.\n" "\nResult:\n" "{\n" From a8055cfe10d501248dbdb515a12e51f7fd40ed20 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Thu, 21 Mar 2019 18:12:50 -0600 Subject: [PATCH 129/395] Fix z_mergetoaddress sending from ANY_SPROUT/ANY_SAPLING when the wallet contains both note types --- qa/pull-tester/rpc-tests.sh | 1 + qa/rpc-tests/mergetoaddress_helper.py | 8 ++- qa/rpc-tests/mergetoaddress_mixednotes.py | 82 +++++++++++++++++++++++ src/wallet/rpcwallet.cpp | 9 ++- 4 files changed, 98 insertions(+), 2 deletions(-) create mode 100755 qa/rpc-tests/mergetoaddress_mixednotes.py diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index d072898b26d..520c60837ef 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -31,6 +31,7 @@ testScripts=( 'wallet_listnotes.py' 'mergetoaddress_sprout.py' 'mergetoaddress_sapling.py' + 'mergetoaddress_mixednotes.py' 'listtransactions.py' 'mempool_resurrect_test.py' 'txn_doublespend.py' diff --git a/qa/rpc-tests/mergetoaddress_helper.py b/qa/rpc-tests/mergetoaddress_helper.py index cc829f8b8aa..962c2b7ff49 100755 --- a/qa/rpc-tests/mergetoaddress_helper.py +++ b/qa/rpc-tests/mergetoaddress_helper.py @@ -17,11 +17,12 @@ def assert_mergetoaddress_exception(expected_error_msg, merge_to_address_lambda): try: merge_to_address_lambda() - fail("Expected exception: %s" % expected_error_msg) except JSONRPCException as e: assert_equal(expected_error_msg, e.error['message']) except Exception as e: fail("Expected JSONRPCException. Found %s" % repr(e)) + else: + fail("Expected exception: %s" % expected_error_msg) class MergeToAddressHelper: @@ -152,6 +153,11 @@ def run_test(self, test): "Destination address is also the only source address, and all its funds are already merged.", lambda: test.nodes[0].z_mergetoaddress([mytaddr], mytaddr)) + # Merging will fail for this specific case where it would spend a fee and do nothing + assert_mergetoaddress_exception( + "Cannot send from both Sprout and Sapling addresses using z_mergetoaddress", + lambda: test.nodes[0].z_mergetoaddress(["ANY_SPROUT", "ANY_SAPLING"], mytaddr)) + # Merge UTXOs from node 0 of value 30, standard fee of 0.00010000 result = test.nodes[0].z_mergetoaddress([mytaddr, mytaddr2, mytaddr3], myzaddr) wait_and_assert_operationid_status(test.nodes[0], result['opid']) diff --git a/qa/rpc-tests/mergetoaddress_mixednotes.py b/qa/rpc-tests/mergetoaddress_mixednotes.py new file mode 100755 index 00000000000..b787429aa99 --- /dev/null +++ b/qa/rpc-tests/mergetoaddress_mixednotes.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python +# Copyright (c) 2019 The Zcash developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." + +from decimal import Decimal +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import assert_equal, get_coinbase_address, \ + initialize_chain_clean, start_nodes, wait_and_assert_operationid_status +from mergetoaddress_helper import assert_mergetoaddress_exception + + +class MergeToAddressMixedNotes(BitcoinTestFramework): + def setup_nodes(self): + return start_nodes(4, self.options.tmpdir, [[ + '-nuparams=5ba81b19:100', # Overwinter + '-nuparams=76b809bb:100', # Sapling + '-experimentalfeatures', '-zmergetoaddress' + ]] * 4) + + def setup_chain(self): + print("Initializing test directory " + self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 4) + + def run_test(self): + print "Mining blocks..." + self.nodes[0].generate(102) + self.sync_all() + + # Send some ZEC to Sprout/Sapling addresses + coinbase_addr = get_coinbase_address(self.nodes[0]) + sproutAddr = self.nodes[0].z_getnewaddress('sprout') + saplingAddr = self.nodes[0].z_getnewaddress('sapling') + t_addr = self.nodes[1].getnewaddress() + + opid = self.nodes[0].z_sendmany(coinbase_addr, [{"address": sproutAddr, "amount": Decimal('10')}], 1, 0) + wait_and_assert_operationid_status(self.nodes[0], opid) + self.nodes[0].generate(1) + self.sync_all() + assert_equal(self.nodes[0].z_getbalance(sproutAddr), Decimal('10')) + assert_equal(self.nodes[0].z_getbalance(saplingAddr), Decimal('0')) + assert_equal(Decimal(self.nodes[1].z_gettotalbalance()["transparent"]), Decimal('0')) + # Make sure we cannot use "ANY_SPROUT" and "ANY_SAPLING" even if we only have Sprout Notes + assert_mergetoaddress_exception( + "Cannot send from both Sprout and Sapling addresses using z_mergetoaddress", + lambda: self.nodes[0].z_mergetoaddress(["ANY_SPROUT", "ANY_SAPLING"], t_addr)) + opid = self.nodes[0].z_sendmany(coinbase_addr, [{"address": saplingAddr, "amount": Decimal('10')}], 1, 0) + wait_and_assert_operationid_status(self.nodes[0], opid) + self.nodes[0].generate(1) + self.sync_all() + + assert_equal(Decimal(self.nodes[1].z_gettotalbalance()["transparent"]), Decimal('0')) + + # Merge Sprout -> taddr + result = self.nodes[0].z_mergetoaddress(["ANY_SPROUT"], t_addr, 0) + wait_and_assert_operationid_status(self.nodes[0], result['opid']) + self.nodes[0].generate(1) + self.sync_all() + + assert_equal(self.nodes[0].z_getbalance(sproutAddr), Decimal('0')) + assert_equal(self.nodes[0].z_getbalance(saplingAddr), Decimal('10')) + assert_equal(Decimal(self.nodes[1].z_gettotalbalance()["transparent"]), Decimal('10')) + + # Make sure we cannot use "ANY_SPROUT" and "ANY_SAPLING" even if we only have Sapling Notes + assert_mergetoaddress_exception( + "Cannot send from both Sprout and Sapling addresses using z_mergetoaddress", + lambda: self.nodes[0].z_mergetoaddress(["ANY_SPROUT", "ANY_SAPLING"], t_addr)) + # Merge Sapling -> taddr + result = self.nodes[0].z_mergetoaddress(["ANY_SAPLING"], t_addr, 0) + wait_and_assert_operationid_status(self.nodes[0], result['opid']) + self.nodes[0].generate(1) + self.sync_all() + + assert_equal(self.nodes[0].z_getbalance(sproutAddr), Decimal('0')) + assert_equal(self.nodes[0].z_getbalance(saplingAddr), Decimal('0')) + assert_equal(Decimal(self.nodes[1].z_gettotalbalance()["transparent"]), Decimal('20')) + + +if __name__ == '__main__': + MergeToAddressMixedNotes().main() diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 4cac157be4d..c018c5410a6 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4532,8 +4532,15 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) if (!saplingActive && saplingEntries.size() > 0) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated"); } + // Do not include Sprout/Sapling notes if using "ANY_SAPLING"/"ANY_SPROUT" respectively + if (useAnySprout) { + saplingEntries.clear(); + } + if (useAnySapling) { + sproutEntries.clear(); + } // Sending from both Sprout and Sapling is currently unsupported using z_mergetoaddress - if (sproutEntries.size() > 0 && saplingEntries.size() > 0) { + if ((sproutEntries.size() > 0 && saplingEntries.size() > 0) || (useAnySprout && useAnySapling)) { throw JSONRPCError( RPC_INVALID_PARAMETER, "Cannot send from both Sprout and Sapling addresses using z_mergetoaddress"); From cf30355fc3a29ce75059fd57f158a9f9e5982989 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Thu, 6 Jun 2019 16:46:06 -0600 Subject: [PATCH 130/395] Clarify what combinations of from addresses can be used in z_mergetoaddress --- src/wallet/rpcwallet.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index c018c5410a6..309446dc38d 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4297,7 +4297,9 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) " - \"ANY_TADDR\": Merge UTXOs from any taddrs belonging to the wallet.\n" " - \"ANY_SPROUT\": Merge notes from any Sprout zaddrs belonging to the wallet.\n" " - \"ANY_SAPLING\": Merge notes from any Sapling zaddrs belonging to the wallet.\n" - " If a special string is given, any given addresses of that type will be counted as duplicates and cause an error.\n" + " While it is possible to use a variety of different combinations of addresses and the above values,\n" + " it is not possible to send funds from both sprout and sapling addresses simultaneously. If a special\n" + " string is given, any given addresses of that type will be counted as duplicates and cause an error.\n" " [\n" " \"address\" (string) Can be a taddr or a zaddr\n" " ,...\n" From f0da2af80c9f673e4f26ee3691d0689411c01ad2 Mon Sep 17 00:00:00 2001 From: codetriage-readme-bot Date: Tue, 11 Jun 2019 10:27:52 -0500 Subject: [PATCH 131/395] Link to development guidelines in CONTRIBUTING.md --- CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000000..ba01490e479 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1 @@ +Please read [our Development Guidelines](https://zcash.readthedocs.io/en/latest/rtd_pages/development_guidelines.html). From 346d11d3eb2f8162df0cb00b1d1f49d542495198 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Tue, 11 Jun 2019 17:27:49 +0100 Subject: [PATCH 132/395] Closes #3992. Remove obsolete warning message. Co-authored-by: Simon Signed-off-by: Daira Hopwood --- src/main.cpp | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index eb87d2786d3..4e1ef99d68a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2991,29 +2991,6 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip()), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize()); cvBlockChange.notify_all(); - - // Check the version of the last 100 blocks to see if we need to upgrade: - static bool fWarned = false; - if (!IsInitialBlockDownload(chainParams) && !fWarned) - { - int nUpgraded = 0; - const CBlockIndex* pindex = chainActive.Tip(); - for (int i = 0; i < 100 && pindex != NULL; i++) - { - if (pindex->nVersion > CBlock::CURRENT_VERSION) - ++nUpgraded; - pindex = pindex->pprev; - } - if (nUpgraded > 0) - LogPrintf("%s: %d of last 100 blocks above version %d\n", __func__, nUpgraded, (int)CBlock::CURRENT_VERSION); - if (nUpgraded > 100/2) - { - // strMiscWarning is read by GetWarnings(), called by the JSON-RPC code to warn the user: - strMiscWarning = _("Warning: This version is obsolete; upgrade required!"); - CAlert::Notify(strMiscWarning, true); - fWarned = true; - } - } } /** From f381d4e0856b5f6ebba429119f3fb97f83983c51 Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Tue, 7 May 2019 16:18:06 -0600 Subject: [PATCH 133/395] add spentindex to getrawtransaction RPC results --- qa/pull-tester/rpc-tests.sh | 1 + qa/rpc-tests/getrawtransaction_insight.py | 104 ++++++++++++++++++++++ src/main.cpp | 24 +++-- src/main.h | 1 + src/rpc/rawtransaction.cpp | 36 ++++++-- src/script/script.cpp | 8 +- src/script/script.h | 9 +- src/script/standard.cpp | 13 +++ src/script/standard.h | 3 + 9 files changed, 180 insertions(+), 19 deletions(-) create mode 100755 qa/rpc-tests/getrawtransaction_insight.py diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index 520c60837ef..aeda0da2cbf 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -38,6 +38,7 @@ testScripts=( 'txn_doublespend.py --mineblock' 'getchaintips.py' 'rawtransactions.py' + 'getrawtransaction_insight.py' 'rest.py' 'mempool_spendcoinbase.py' 'mempool_reorg.py' diff --git a/qa/rpc-tests/getrawtransaction_insight.py b/qa/rpc-tests/getrawtransaction_insight.py new file mode 100755 index 00000000000..f18eed5d465 --- /dev/null +++ b/qa/rpc-tests/getrawtransaction_insight.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python2 +# Copyright (c) 2019 The Zcash developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Test the new fields added to the output of getrawtransaction +# RPC for the Insight Explorer by the new spentindex +# + +from test_framework.test_framework import BitcoinTestFramework + +from test_framework.util import assert_equal +from test_framework.util import initialize_chain_clean +from test_framework.util import start_nodes, stop_nodes, connect_nodes +from test_framework.util import wait_bitcoinds + +from test_framework.mininode import COIN + + +class GetrawtransactionTest(BitcoinTestFramework): + + def setup_chain(self): + print("Initializing test directory "+self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 4) + + def setup_network(self): + # -insightexplorer causes spentindex to be enabled (fSpentIndex = true) + + self.nodes = start_nodes(3, self.options.tmpdir, + [['-debug', '-txindex', '-experimentalfeatures', '-insightexplorer']]*3) + connect_nodes(self.nodes[0], 1) + connect_nodes(self.nodes[0], 2) + + self.is_network_split = False + self.sync_all() + + def run_test(self): + self.nodes[0].generate(105) + self.sync_all() + + chain_height = self.nodes[1].getblockcount() + assert_equal(chain_height, 105) + + # Test getrawtransaction changes and the getspentinfo RPC + + # send coinbase to address a + a = self.nodes[1].getnewaddress() + txid_a = self.nodes[0].sendtoaddress(a, 2) + self.sync_all() + self.nodes[0].generate(1) + self.sync_all() + + # send from a to b + # (the only utxo on node 1 is from address a) + b = self.nodes[2].getnewaddress() + txid_b = self.nodes[1].sendtoaddress(b, 1) + self.sync_all() + + # a to b transaction is not confirmed, so it has no height + tx_b = self.nodes[2].getrawtransaction(txid_b, 1) + assert('height' not in tx_b) + + self.sync_all() + tx_a = self.nodes[2].getrawtransaction(txid_a, 1) + + # txid_b is not yet confirmed, so these should not be set + assert('spentTxId' not in tx_a['vout'][0]) + assert('spentIndex' not in tx_a['vout'][0]) + assert('spentHeight' not in tx_a['vout'][0]) + + # confirm txid_b (a to b transaction) + self.nodes[0].generate(1) + self.sync_all() + + # Restart all nodes to ensure index files are saved to disk and recovered + stop_nodes(self.nodes) + wait_bitcoinds() + self.setup_network() + + # Check new fields added to getrawtransaction + tx_a = self.nodes[2].getrawtransaction(txid_a, 1) + assert_equal(tx_a['vin'][0]['value'], 10) # coinbase + assert_equal(tx_a['vin'][0]['valueSat'], 10*COIN) + # we want the non-change (payment) output + vout = filter(lambda o: o['value'] == 2, tx_a['vout']) + assert_equal(vout[0]['spentTxId'], txid_b) + assert_equal(vout[0]['spentIndex'], 0) + assert_equal(vout[0]['spentHeight'], 107) + assert_equal(tx_a['height'], 106) + + tx_b = self.nodes[2].getrawtransaction(txid_b, 1) + assert_equal(tx_b['vin'][0]['address'], a) + assert_equal(tx_b['vin'][0]['value'], 2) + assert_equal(tx_b['vin'][0]['valueSat'], 2*COIN) + # since this transaction's outputs haven't yet been + # spent, these fields should not be present + assert('spentTxId' not in tx_b['vout'][0]) + assert('spentIndex' not in tx_b['vout'][0]) + assert('spentHeight' not in tx_b['vout'][0]) + assert_equal(tx_b['height'], 107) + +if __name__ == '__main__': + GetrawtransactionTest().main() diff --git a/src/main.cpp b/src/main.cpp index eb87d2786d3..43e7f90e7c9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1607,6 +1607,14 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa return true; } +bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value) +{ + AssertLockHeld(cs_main); + if (!fSpentIndex) + return false; + return pblocktree->ReadSpentIndex(key, value); +} + /** Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */ bool GetTransaction(const uint256 &hash, CTransaction &txOut, const Consensus::Params& consensusParams, uint256 &hashBlock, bool fAllowSlow) { @@ -2269,8 +2277,8 @@ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& s if (fAddressIndex && updateIndices) { for (unsigned int k = tx.vout.size(); k-- > 0;) { const CTxOut &out = tx.vout[k]; - int const scriptType = out.scriptPubKey.Type(); - if (scriptType > 0) { + CScript::ScriptType scriptType = out.scriptPubKey.GetType(); + if (scriptType != CScript::UNKNOWN) { uint160 const addrHash = out.scriptPubKey.AddressHash(); // undo receiving activity @@ -2326,8 +2334,8 @@ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& s const CTxIn input = tx.vin[j]; if (fAddressIndex && updateIndices) { const CTxOut &prevout = view.GetOutputFor(input); - int const scriptType = prevout.scriptPubKey.Type(); - if (scriptType > 0) { + CScript::ScriptType scriptType = prevout.scriptPubKey.GetType(); + if (scriptType != CScript::UNKNOWN) { uint160 const addrHash = prevout.scriptPubKey.AddressHash(); // undo spending activity @@ -2643,9 +2651,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin const CTxIn input = tx.vin[j]; const CTxOut &prevout = view.GetOutputFor(tx.vin[j]); - int const scriptType = prevout.scriptPubKey.Type(); + CScript::ScriptType scriptType = prevout.scriptPubKey.GetType(); const uint160 addrHash = prevout.scriptPubKey.AddressHash(); - if (fAddressIndex && scriptType > 0) { + if (fAddressIndex && scriptType != CScript::UNKNOWN) { // record spending activity addressIndex.push_back(make_pair( CAddressIndexKey(scriptType, addrHash, pindex->nHeight, i, hash, j, true), @@ -2695,8 +2703,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (fAddressIndex) { for (unsigned int k = 0; k < tx.vout.size(); k++) { const CTxOut &out = tx.vout[k]; - int const scriptType = out.scriptPubKey.Type(); - if (scriptType > 0) { + CScript::ScriptType scriptType = out.scriptPubKey.GetType(); + if (scriptType != CScript::UNKNOWN) { uint160 const addrHash = out.scriptPubKey.AddressHash(); // record receiving activity diff --git a/src/main.h b/src/main.h index 2b77875c482..cd2e39a0957 100644 --- a/src/main.h +++ b/src/main.h @@ -437,6 +437,7 @@ class CScriptCheck ScriptError GetScriptError() const { return error; } }; +bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value); /** Functions for disk access for blocks */ bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart); diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 49768c24730..80ff66ee7bd 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -147,7 +147,8 @@ UniValue TxShieldedOutputsToJSON(const CTransaction& tx) { void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) { - entry.push_back(Pair("txid", tx.GetHash().GetHex())); + const uint256 txid = tx.GetHash(); + entry.push_back(Pair("txid", txid.GetHex())); entry.push_back(Pair("overwintered", tx.fOverwintered)); entry.push_back(Pair("version", tx.nVersion)); if (tx.fOverwintered) { @@ -169,6 +170,20 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) o.push_back(Pair("asm", ScriptToAsmStr(txin.scriptSig, true))); o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); in.push_back(Pair("scriptSig", o)); + + // Add address and value info if spentindex enabled + CSpentIndexValue spentInfo; + CSpentIndexKey spentKey(txin.prevout.hash, txin.prevout.n); + if (GetSpentIndex(spentKey, spentInfo)) { + in.push_back(Pair("value", ValueFromAmount(spentInfo.satoshis))); + in.push_back(Pair("valueSat", spentInfo.satoshis)); + + boost::optional dest = + DestFromAddressHash(spentInfo.addressType, spentInfo.addressHash); + if (dest) { + in.push_back(Pair("address", EncodeDestination(*dest))); + } + } } in.push_back(Pair("sequence", (int64_t)txin.nSequence)); vin.push_back(in); @@ -184,6 +199,15 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) UniValue o(UniValue::VOBJ); ScriptPubKeyToJSON(txout.scriptPubKey, o, true); out.push_back(Pair("scriptPubKey", o)); + + // Add spent information if spentindex is enabled + CSpentIndexValue spentInfo; + CSpentIndexKey spentKey(txid, i); + if (GetSpentIndex(spentKey, spentInfo)) { + out.push_back(Pair("spentTxId", spentInfo.txid.GetHex())); + out.push_back(Pair("spentIndex", (int)spentInfo.inputIndex)); + out.push_back(Pair("spentHeight", spentInfo.blockHeight)); + } vout.push_back(out); } entry.push_back(Pair("vout", vout)); @@ -208,12 +232,14 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) if (mi != mapBlockIndex.end() && (*mi).second) { CBlockIndex* pindex = (*mi).second; if (chainActive.Contains(pindex)) { + entry.push_back(Pair("height", pindex->nHeight)); entry.push_back(Pair("confirmations", 1 + chainActive.Height() - pindex->nHeight)); entry.push_back(Pair("time", pindex->GetBlockTime())); entry.push_back(Pair("blocktime", pindex->GetBlockTime())); - } - else + } else { + entry.push_back(Pair("height", -1)); entry.push_back(Pair("confirmations", 0)); + } } } } @@ -312,14 +338,14 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp) + HelpExampleRpc("getrawtransaction", "\"mytxid\", 1") ); - LOCK(cs_main); - uint256 hash = ParseHashV(params[0], "parameter 1"); bool fVerbose = false; if (params.size() > 1) fVerbose = (params[1].get_int() != 0); + LOCK(cs_main); + CTransaction tx; uint256 hashBlock; if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true)) diff --git a/src/script/script.cpp b/src/script/script.cpp index 9d13fd040cd..bcd1c6b2d11 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -242,14 +242,14 @@ bool CScript::IsPushOnly() const } // insightexplorer -int CScript::Type() const +CScript::ScriptType CScript::GetType() const { if (this->IsPayToPublicKeyHash()) - return 1; + return CScript::P2PKH; if (this->IsPayToScriptHash()) - return 2; + return CScript::P2SH; // We don't know this script - return 0; + return CScript::UNKNOWN; } // insightexplorer diff --git a/src/script/script.h b/src/script/script.h index 6f88676118c..2a511cd2eb5 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -567,10 +567,15 @@ class CScript : public CScriptBase */ unsigned int GetSigOpCount(const CScript& scriptSig) const; + // insightexplorer, there may be more script types in the future + enum ScriptType : int { + UNKNOWN = 0, + P2PKH = 1, + P2SH = 2, + }; bool IsPayToPublicKeyHash() const; bool IsPayToScriptHash() const; - - int Type() const; + ScriptType GetType() const; uint160 AddressHash() const; /** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */ diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 88cde36988a..12df6d8556a 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -320,3 +320,16 @@ CScript GetScriptForMultisig(int nRequired, const std::vector& keys) bool IsValidDestination(const CTxDestination& dest) { return dest.which() != 0; } + +// insightexplorer +boost::optional DestFromAddressHash(int scriptType, uint160& addressHash) +{ + switch (scriptType) { + case CScript::P2PKH: + return CTxDestination(CKeyID(addressHash)); + case CScript::P2SH: + return CTxDestination(CScriptID(addressHash)); + default: + return boost::none; + } +} diff --git a/src/script/standard.h b/src/script/standard.h index 5dcff1c1a5a..40b3c329d6c 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -96,4 +96,7 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std:: CScript GetScriptForDestination(const CTxDestination& dest); CScript GetScriptForMultisig(int nRequired, const std::vector& keys); +// insightexplorer +boost::optional DestFromAddressHash(int scriptType, uint160& addressHash); + #endif // BITCOIN_SCRIPT_STANDARD_H From c9d14272af31792471da70e6a308e5953b93c9c0 Mon Sep 17 00:00:00 2001 From: Eirik0 Date: Tue, 11 Jun 2019 14:32:57 -0600 Subject: [PATCH 134/395] Fix comment in mergetoaddress RPC test --- qa/rpc-tests/mergetoaddress_helper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qa/rpc-tests/mergetoaddress_helper.py b/qa/rpc-tests/mergetoaddress_helper.py index 962c2b7ff49..cadbc1293d3 100755 --- a/qa/rpc-tests/mergetoaddress_helper.py +++ b/qa/rpc-tests/mergetoaddress_helper.py @@ -153,7 +153,7 @@ def run_test(self, test): "Destination address is also the only source address, and all its funds are already merged.", lambda: test.nodes[0].z_mergetoaddress([mytaddr], mytaddr)) - # Merging will fail for this specific case where it would spend a fee and do nothing + # Merging will fail if we try to specify from Sprout AND Sapling assert_mergetoaddress_exception( "Cannot send from both Sprout and Sapling addresses using z_mergetoaddress", lambda: test.nodes[0].z_mergetoaddress(["ANY_SPROUT", "ANY_SAPLING"], mytaddr)) From f7a4aab352e5c3f1e4bc22cc6c909b3e2aa240c7 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Wed, 12 Jun 2019 16:32:57 +0100 Subject: [PATCH 135/395] make-release.py: Versioning changes for 2.0.6-rc1. --- README.md | 2 +- configure.ac | 4 ++-- contrib/gitian-descriptors/gitian-linux.yml | 2 +- src/clientversion.h | 4 ++-- src/deprecation.h | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 7d02cf0d349..92c99d49848 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Zcash 2.0.5-2 +Zcash 2.0.6-rc1 =========== diff --git a/configure.ac b/configure.ac index a78439eda44..bcbe56f9ec3 100644 --- a/configure.ac +++ b/configure.ac @@ -2,8 +2,8 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 2) define(_CLIENT_VERSION_MINOR, 0) -define(_CLIENT_VERSION_REVISION, 5) -define(_CLIENT_VERSION_BUILD, 52) +define(_CLIENT_VERSION_REVISION, 6) +define(_CLIENT_VERSION_BUILD, 25) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index edc714f1074..fe21b45fb4a 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "zcash-2.0.5-2" +name: "zcash-2.0.6-rc1" enable_cache: true distro: "debian" suites: diff --git a/src/clientversion.h b/src/clientversion.h index 2455c56b48e..5f8b9687026 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -17,8 +17,8 @@ //! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 2 #define CLIENT_VERSION_MINOR 0 -#define CLIENT_VERSION_REVISION 5 -#define CLIENT_VERSION_BUILD 52 +#define CLIENT_VERSION_REVISION 6 +#define CLIENT_VERSION_BUILD 25 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/deprecation.h b/src/deprecation.h index 13c752c426e..f581b07e5e1 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -8,7 +8,7 @@ // Deprecation policy: // * Shut down 16 weeks' worth of blocks after the estimated release block height. // * A warning is shown during the 2 weeks' worth of blocks prior to shut down. -static const int APPROX_RELEASE_HEIGHT = 533500; +static const int APPROX_RELEASE_HEIGHT = 549200; static const int WEEKS_UNTIL_DEPRECATION = 16; static const int DEPRECATION_HEIGHT = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 24); From 372ff78b2c74e70b3dca00996e3e9aa7e0a310f4 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Wed, 12 Jun 2019 16:36:56 +0100 Subject: [PATCH 136/395] make-release.py: Updated manpages for 2.0.6-rc1. --- doc/man/zcash-cli.1 | 8 ++++---- doc/man/zcash-tx.1 | 8 ++++---- doc/man/zcashd.1 | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/doc/man/zcash-cli.1 b/doc/man/zcash-cli.1 index c2f1b3447ff..1abd7712599 100644 --- a/doc/man/zcash-cli.1 +++ b/doc/man/zcash-cli.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-CLI "1" "May 2019" "zcash-cli v2.0.5-2" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4. +.TH ZCASH-CLI "1" "June 2019" "zcash-cli v2.0.6-rc1" "User Commands" .SH NAME -zcash-cli \- manual page for zcash-cli v2.0.5-2 +zcash-cli \- manual page for zcash-cli v2.0.6-rc1 .SH DESCRIPTION -Zcash RPC client version v2.0.5\-2 +Zcash RPC client version v2.0.6\-rc1 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . diff --git a/doc/man/zcash-tx.1 b/doc/man/zcash-tx.1 index effac79bb36..3e3c8b2bd13 100644 --- a/doc/man/zcash-tx.1 +++ b/doc/man/zcash-tx.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-TX "1" "May 2019" "zcash-tx v2.0.5-2" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4. +.TH ZCASH-TX "1" "June 2019" "zcash-tx v2.0.6-rc1" "User Commands" .SH NAME -zcash-tx \- manual page for zcash-tx v2.0.5-2 +zcash-tx \- manual page for zcash-tx v2.0.6-rc1 .SH DESCRIPTION -Zcash zcash\-tx utility version v2.0.5\-2 +Zcash zcash\-tx utility version v2.0.6\-rc1 .SS "Usage:" .TP zcash\-tx [options] [commands] diff --git a/doc/man/zcashd.1 b/doc/man/zcashd.1 index 73d50333e6d..2af9ed904a9 100644 --- a/doc/man/zcashd.1 +++ b/doc/man/zcashd.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASHD "1" "May 2019" "zcashd v2.0.5-2" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4. +.TH ZCASHD "1" "June 2019" "zcashd v2.0.6-rc1" "User Commands" .SH NAME -zcashd \- manual page for zcashd v2.0.5-2 +zcashd \- manual page for zcashd v2.0.6-rc1 .SH DESCRIPTION -Zcash Daemon version v2.0.5\-2 +Zcash Daemon version v2.0.6\-rc1 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . @@ -75,7 +75,7 @@ limit applied) .HP \fB\-par=\fR .IP -Set the number of script verification threads (\fB\-4\fR to 16, 0 = auto, <0 = +Set the number of script verification threads (\fB\-6\fR to 16, 0 = auto, <0 = leave that many cores free, default: 0) .HP \fB\-pid=\fR From c3afc3fde0138b2b990012c894e3653dcc1eb36e Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Wed, 12 Jun 2019 16:36:57 +0100 Subject: [PATCH 137/395] make-release.py: Updated release notes and changelog for 2.0.6-rc1. --- contrib/debian/changelog | 6 ++ doc/authors.md | 9 ++- doc/release-notes/release-notes-2.0.6-rc1.md | 62 ++++++++++++++++++++ 3 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 doc/release-notes/release-notes-2.0.6-rc1.md diff --git a/contrib/debian/changelog b/contrib/debian/changelog index f48b6e7b6df..af3c93a95d4 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,9 @@ +zcash (2.0.6~rc1) stable; urgency=medium + + * 2.0.6-rc1 release. + + -- Electric Coin Company Wed, 12 Jun 2019 16:36:57 +0100 + zcash (2.0.5+2) stable; urgency=medium * 2.0.5-2 release. diff --git a/doc/authors.md b/doc/authors.md index 72d50f96b7e..9bcdb5ef140 100644 --- a/doc/authors.md +++ b/doc/authors.md @@ -4,18 +4,17 @@ Zcash Contributors Jack Grigg (863) Simon Liu (450) Sean Bowe (278) +Eirik Ogilvie-Wigley (145) Daira Hopwood (115) -Eirik Ogilvie-Wigley (102) Jay Graber (89) Wladimir J. van der Laan (81) Taylor Hornby (73) Jonas Schnelli (62) Nathan Wilcox (56) Pieter Wuille (54) -Eirik0 (43) Kevin Gallagher (38) Cory Fields (35) -mdr0id (22) +Marshall Gaucher (22) Larry Ruane (22) Jonathan "Duke" Leto (17) syd (15) @@ -46,7 +45,6 @@ João Barbosa (4) Jorge Timón (4) George Tankersley (4) Gareth Davies (4) -zebambam (3) lpescher (3) ca333 (3) Per Grön (3) @@ -55,9 +53,9 @@ Jason Davies (3) James O'Beirne (3) Dimitris Apostolou (3) Daniel Kraft (3) +Benjamin Winston (3) Alfie John (3) rofl0r (2) -paveljanik (2) mruddy (2) kpcyrd (2) aniemerg (2) @@ -67,6 +65,7 @@ Robert C. Seacord (2) Pejvan (2) Pavol Rusnak (2) Pavel Vasin (2) +Pavel Janik (2) Matthew King (2) Kaz Wesley (2) Joe Turgeon (2) diff --git a/doc/release-notes/release-notes-2.0.6-rc1.md b/doc/release-notes/release-notes-2.0.6-rc1.md new file mode 100644 index 00000000000..ce40147200a --- /dev/null +++ b/doc/release-notes/release-notes-2.0.6-rc1.md @@ -0,0 +1,62 @@ +Changelog +========= + +Daira Hopwood (3): + Closes #3992. Remove obsolete warning message. + make-release.py: Versioning changes for 2.0.6-rc1. + make-release.py: Updated manpages for 2.0.6-rc1. + +Daniel Kraft (1): + Add some const declarations where they are appropriate. + +Eirik Ogilvie-Wigley (7): + Fix tree depth in comment + Update author aliases + Remove old mergetoaddress RPC test + Replace CSproutNotePlaintextEntry with SproutNoteEntry to match Sapling + z_getmigrationstatus help message wording change + Fix z_mergetoaddress sending from ANY_SPROUT/ANY_SAPLING when the wallet contains both note types + Clarify what combinations of from addresses can be used in z_mergetoaddress + +Jack Grigg (10): + Move Equihash parameters into consensus params + Globals: Remove Zcash-specific Params() calls from main.cpp + Globals: Explicitly pass const CChainParams& to IsStandardTx() + Globals: Explicit const CChainParams& arg for main: + Globals: Explicitly pass const CChainParams& to ContextualCheckTransaction() + Globals: Explicit const CChainParams& arg for main: + Globals: Explicitly pass const CChainParams& to DisconnectBlock() + Consistently use chainparams and consensusParams + Globals: Explicitly pass const CChainParams& to IsInitialBlockDownload() + Globals: Explicitly pass const CChainParams& to ReceivedBlockTransactions() + +Jorge Timón (6): + Globals: Explicit Consensus::Params arg for main: + Globals: Make AcceptBlockHeader static (Fix #6163) + Chainparams: Explicit CChainParams arg for main (pre miner): + Chainparams: Explicit CChainParams arg for miner: + Globals: Remove a bunch of Params() calls from main.cpp: + Globals: Explicitly pass const CChainParams& to UpdateTip() + +Larry Ruane (1): + add spentindex to getrawtransaction RPC results + +MarcoFalke (1): + [doc] Fix doxygen comments for members + +Peter Todd (1): + Improve block validity/ConnectBlock() comments + +Simon Liu (1): + Fix typo and clean up help message for RPC z_getmigrationstatus. + +Wladimir J. van der Laan (1): + Break circular dependency main ↔ txdb + +face (2): + Pass CChainParams to DisconnectTip() + Explicitly pass CChainParams to ConnectBlock + +Benjamin Winston (1): + Fixes #4013, added BitcoinABC as a disclosure partner + From 6a35b68fab53d6d4d7be435e431534d10884c15b Mon Sep 17 00:00:00 2001 From: Charlie O'Keefe Date: Wed, 12 Jun 2019 17:41:38 -0600 Subject: [PATCH 138/395] Add stretch to list of suites in gitian linux descriptors --- contrib/gitian-descriptors/gitian-linux.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index fe21b45fb4a..0e9d9d81f18 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -4,6 +4,7 @@ enable_cache: true distro: "debian" suites: - "jessie" +- "stretch" architectures: - "amd64" packages: From 246f17f6baaabfa9d701d01295f93e3e2fcf90e1 Mon Sep 17 00:00:00 2001 From: Mary Moore-Simmons Date: Fri, 14 Jun 2019 09:02:37 -0600 Subject: [PATCH 139/395] Fixes issue #3504: Changes to --version and adds a couple other useful commands. --- .github/ISSUE_TEMPLATE.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index a025e66aca0..9827e610503 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -31,7 +31,9 @@ Run `zcashd --version` to find out - Disk size: - Disk Type (HD/SDD): - Linux kernel version (uname -a): -- Compiler version (gcc -version): +- Compiler version (gcc --version): +- Linker version (ld --version): +- Assembler version (as --version): ### Any extra information that might be useful in the debugging process. This includes the relevant contents of `~/.zcash/debug.log`. You can paste raw text, attach the file directly in the issue or link to the text via a pastebin type site. From 6177b47d20a8b88d9cc063f298cb14b86c320861 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 14 Jun 2019 23:18:10 +0100 Subject: [PATCH 140/395] ld --version doesn't work on macOS. Signed-off-by: Daira Hopwood --- .github/ISSUE_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 9827e610503..a1592004001 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -32,7 +32,7 @@ Run `zcashd --version` to find out - Disk Type (HD/SDD): - Linux kernel version (uname -a): - Compiler version (gcc --version): -- Linker version (ld --version): +- Linker version (ld -v): - Assembler version (as --version): ### Any extra information that might be useful in the debugging process. From f57f76d78960f719497a3267fd287efb86d22703 Mon Sep 17 00:00:00 2001 From: Dimitris Apostolou Date: Sun, 16 Jun 2019 14:39:05 +0300 Subject: [PATCH 141/395] Rename vjoinsplit to vJoinSplit --- qa/rpc-tests/test_framework/mininode.py | 16 ++-- src/coins.cpp | 6 +- src/gtest/test_checktransaction.cpp | 74 +++++++++---------- src/gtest/test_mempool.cpp | 10 +-- src/gtest/test_transaction_builder.cpp | 36 ++++----- src/main.cpp | 32 ++++---- src/miner.cpp | 2 +- src/primitives/transaction.cpp | 16 ++-- src/primitives/transaction.h | 12 +-- src/rpc/rawtransaction.cpp | 10 +-- src/script/interpreter.cpp | 12 +-- src/test/coins_tests.cpp | 26 +++---- src/test/sighash_tests.cpp | 4 +- src/test/transaction_tests.cpp | 30 ++++---- src/transaction_builder.cpp | 10 +-- src/txmempool.cpp | 10 +-- src/utiltest.cpp | 14 ++-- .../asyncrpcoperation_mergetoaddress.cpp | 14 ++-- .../asyncrpcoperation_saplingmigration.cpp | 2 +- src/wallet/asyncrpcoperation_sendmany.cpp | 16 ++-- .../asyncrpcoperation_shieldcoinbase.cpp | 8 +- src/wallet/gtest/test_wallet.cpp | 16 ++-- src/wallet/paymentdisclosure.h | 2 +- src/wallet/rpcdisclosure.cpp | 10 +-- src/wallet/rpcwallet.cpp | 14 ++-- src/wallet/wallet.cpp | 44 +++++------ src/wallet/wallet.h | 2 +- 27 files changed, 224 insertions(+), 224 deletions(-) diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 4e868c68aff..5f500f0c096 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -575,7 +575,7 @@ def __init__(self, tx=None): self.vout = [] self.nLockTime = 0 self.nExpiryHeight = 0 - self.vjoinsplit = [] + self.vJoinSplit = [] self.joinSplitPubKey = None self.joinSplitSig = None self.sha256 = None @@ -588,7 +588,7 @@ def __init__(self, tx=None): self.vout = copy.deepcopy(tx.vout) self.nLockTime = tx.nLockTime self.nExpiryHeight = tx.nExpiryHeight - self.vjoinsplit = copy.deepcopy(tx.vjoinsplit) + self.vJoinSplit = copy.deepcopy(tx.vJoinSplit) self.joinSplitPubKey = tx.joinSplitPubKey self.joinSplitSig = tx.joinSplitSig self.sha256 = None @@ -612,8 +612,8 @@ def deserialize(self, f): self.nExpiryHeight = struct.unpack("= 2: - self.vjoinsplit = deser_vector(f, JSDescription) - if len(self.vjoinsplit) > 0: + self.vJoinSplit = deser_vector(f, JSDescription) + if len(self.vJoinSplit) > 0: self.joinSplitPubKey = deser_uint256(f) self.joinSplitSig = f.read(64) @@ -636,8 +636,8 @@ def serialize(self): if isOverwinterV3: r += struct.pack("= 2: - r += ser_vector(self.vjoinsplit) - if len(self.vjoinsplit) > 0: + r += ser_vector(self.vJoinSplit) + if len(self.vJoinSplit) > 0: r += ser_uint256(self.joinSplitPubKey) r += self.joinSplitSig return r @@ -664,8 +664,8 @@ def __repr__(self): % (self.fOverwintered, self.nVersion, self.nVersionGroupId, repr(self.vin), repr(self.vout), self.nLockTime, self.nExpiryHeight)) if self.nVersion >= 2: - r += " vjoinsplit=%s" % repr(self.vjoinsplit) - if len(self.vjoinsplit) > 0: + r += " vJoinSplit=%s" % repr(self.vJoinSplit) + if len(self.vJoinSplit) > 0: r += " joinSplitPubKey=%064x joinSplitSig=%064x" \ (self.joinSplitPubKey, self.joinSplitSig) r += ")" diff --git a/src/coins.cpp b/src/coins.cpp index 962fa4405a2..4312fac012f 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -316,7 +316,7 @@ void CCoinsViewCache::PopAnchor(const uint256 &newrt, ShieldedType type) { } void CCoinsViewCache::SetNullifiers(const CTransaction& tx, bool spent) { - for (const JSDescription &joinsplit : tx.vjoinsplit) { + for (const JSDescription &joinsplit : tx.vJoinSplit) { for (const uint256 &nullifier : joinsplit.nullifiers) { std::pair ret = cacheSproutNullifiers.insert(std::make_pair(nullifier, CNullifiersCacheEntry())); ret.first->second.entered = spent; @@ -566,7 +566,7 @@ bool CCoinsViewCache::HaveShieldedRequirements(const CTransaction& tx) const { boost::unordered_map intermediates; - BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) + BOOST_FOREACH(const JSDescription &joinsplit, tx.vJoinSplit) { BOOST_FOREACH(const uint256& nullifier, joinsplit.nullifiers) { @@ -630,7 +630,7 @@ double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight) const // use the maximum priority for all (partially or fully) shielded transactions. // (Note that coinbase transactions cannot contain JoinSplits, or Sapling shielded Spends or Outputs.) - if (tx.vjoinsplit.size() > 0 || tx.vShieldedSpend.size() > 0 || tx.vShieldedOutput.size() > 0) { + if (tx.vJoinSplit.size() > 0 || tx.vShieldedSpend.size() > 0 || tx.vShieldedOutput.size() > 0) { return MAX_PRIORITY; } diff --git a/src/gtest/test_checktransaction.cpp b/src/gtest/test_checktransaction.cpp index 6897d42e9a8..45580a0824c 100644 --- a/src/gtest/test_checktransaction.cpp +++ b/src/gtest/test_checktransaction.cpp @@ -18,9 +18,9 @@ TEST(checktransaction_tests, check_vpub_not_both_nonzero) { CMutableTransaction newTx(tx); CValidationState state; - newTx.vjoinsplit.push_back(JSDescription()); + newTx.vJoinSplit.push_back(JSDescription()); - JSDescription *jsdesc = &newTx.vjoinsplit[0]; + JSDescription *jsdesc = &newTx.vJoinSplit[0]; jsdesc->vpub_old = 1; jsdesc->vpub_new = 1; @@ -61,11 +61,11 @@ CMutableTransaction GetValidTransaction() { // mtx.vout[0].scriptPubKey = mtx.vout[0].nValue = 0; mtx.vout[1].nValue = 0; - mtx.vjoinsplit.resize(2); - mtx.vjoinsplit[0].nullifiers.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000000"); - mtx.vjoinsplit[0].nullifiers.at(1) = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); - mtx.vjoinsplit[1].nullifiers.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000002"); - mtx.vjoinsplit[1].nullifiers.at(1) = uint256S("0000000000000000000000000000000000000000000000000000000000000003"); + mtx.vJoinSplit.resize(2); + mtx.vJoinSplit[0].nullifiers.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000000"); + mtx.vJoinSplit[0].nullifiers.at(1) = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); + mtx.vJoinSplit[1].nullifiers.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000002"); + mtx.vJoinSplit[1].nullifiers.at(1) = uint256S("0000000000000000000000000000000000000000000000000000000000000003"); CreateJoinSplitSignature(mtx, consensusBranchId); return mtx; @@ -115,7 +115,7 @@ TEST(checktransaction_tests, BadVersionTooLow) { TEST(checktransaction_tests, bad_txns_vin_empty) { CMutableTransaction mtx = GetValidTransaction(); - mtx.vjoinsplit.resize(0); + mtx.vJoinSplit.resize(0); mtx.vin.resize(0); CTransaction tx(mtx); @@ -126,7 +126,7 @@ TEST(checktransaction_tests, bad_txns_vin_empty) { TEST(checktransaction_tests, bad_txns_vout_empty) { CMutableTransaction mtx = GetValidTransaction(); - mtx.vjoinsplit.resize(0); + mtx.vJoinSplit.resize(0); mtx.vout.resize(0); CTransaction tx(mtx); @@ -179,8 +179,8 @@ TEST(checktransaction_tests, BadTxnsOversize) { mtx.nVersion = SAPLING_TX_VERSION; // Change the proof types (which requires re-signing the JoinSplit data) - mtx.vjoinsplit[0].proof = libzcash::GrothProof(); - mtx.vjoinsplit[1].proof = libzcash::GrothProof(); + mtx.vJoinSplit[0].proof = libzcash::GrothProof(); + mtx.vJoinSplit[1].proof = libzcash::GrothProof(); CreateJoinSplitSignature(mtx, NetworkUpgradeInfo[Consensus::UPGRADE_SAPLING].nBranchId); CTransaction tx(mtx); @@ -204,8 +204,8 @@ TEST(checktransaction_tests, OversizeSaplingTxns) { mtx.nVersion = SAPLING_TX_VERSION; // Change the proof types (which requires re-signing the JoinSplit data) - mtx.vjoinsplit[0].proof = libzcash::GrothProof(); - mtx.vjoinsplit[1].proof = libzcash::GrothProof(); + mtx.vJoinSplit[0].proof = libzcash::GrothProof(); + mtx.vJoinSplit[1].proof = libzcash::GrothProof(); CreateJoinSplitSignature(mtx, NetworkUpgradeInfo[Consensus::UPGRADE_SAPLING].nBranchId); // Transaction just under the limit @@ -337,7 +337,7 @@ TEST(checktransaction_tests, ValueBalanceOverflowsTotal) { TEST(checktransaction_tests, bad_txns_txouttotal_toolarge_joinsplit) { CMutableTransaction mtx = GetValidTransaction(); mtx.vout[0].nValue = 1; - mtx.vjoinsplit[0].vpub_old = MAX_MONEY; + mtx.vJoinSplit[0].vpub_old = MAX_MONEY; CTransaction tx(mtx); @@ -348,8 +348,8 @@ TEST(checktransaction_tests, bad_txns_txouttotal_toolarge_joinsplit) { TEST(checktransaction_tests, bad_txns_txintotal_toolarge_joinsplit) { CMutableTransaction mtx = GetValidTransaction(); - mtx.vjoinsplit[0].vpub_new = MAX_MONEY - 1; - mtx.vjoinsplit[1].vpub_new = MAX_MONEY - 1; + mtx.vJoinSplit[0].vpub_new = MAX_MONEY - 1; + mtx.vJoinSplit[1].vpub_new = MAX_MONEY - 1; CTransaction tx(mtx); @@ -360,7 +360,7 @@ TEST(checktransaction_tests, bad_txns_txintotal_toolarge_joinsplit) { TEST(checktransaction_tests, bad_txns_vpub_old_negative) { CMutableTransaction mtx = GetValidTransaction(); - mtx.vjoinsplit[0].vpub_old = -1; + mtx.vJoinSplit[0].vpub_old = -1; CTransaction tx(mtx); @@ -371,7 +371,7 @@ TEST(checktransaction_tests, bad_txns_vpub_old_negative) { TEST(checktransaction_tests, bad_txns_vpub_new_negative) { CMutableTransaction mtx = GetValidTransaction(); - mtx.vjoinsplit[0].vpub_new = -1; + mtx.vJoinSplit[0].vpub_new = -1; CTransaction tx(mtx); @@ -382,7 +382,7 @@ TEST(checktransaction_tests, bad_txns_vpub_new_negative) { TEST(checktransaction_tests, bad_txns_vpub_old_toolarge) { CMutableTransaction mtx = GetValidTransaction(); - mtx.vjoinsplit[0].vpub_old = MAX_MONEY + 1; + mtx.vJoinSplit[0].vpub_old = MAX_MONEY + 1; CTransaction tx(mtx); @@ -393,7 +393,7 @@ TEST(checktransaction_tests, bad_txns_vpub_old_toolarge) { TEST(checktransaction_tests, bad_txns_vpub_new_toolarge) { CMutableTransaction mtx = GetValidTransaction(); - mtx.vjoinsplit[0].vpub_new = MAX_MONEY + 1; + mtx.vJoinSplit[0].vpub_new = MAX_MONEY + 1; CTransaction tx(mtx); @@ -404,8 +404,8 @@ TEST(checktransaction_tests, bad_txns_vpub_new_toolarge) { TEST(checktransaction_tests, bad_txns_vpubs_both_nonzero) { CMutableTransaction mtx = GetValidTransaction(); - mtx.vjoinsplit[0].vpub_old = 1; - mtx.vjoinsplit[0].vpub_new = 1; + mtx.vJoinSplit[0].vpub_old = 1; + mtx.vJoinSplit[0].vpub_new = 1; CTransaction tx(mtx); @@ -428,8 +428,8 @@ TEST(checktransaction_tests, bad_txns_inputs_duplicate) { TEST(checktransaction_tests, bad_joinsplits_nullifiers_duplicate_same_joinsplit) { CMutableTransaction mtx = GetValidTransaction(); - mtx.vjoinsplit[0].nullifiers.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000000"); - mtx.vjoinsplit[0].nullifiers.at(1) = uint256S("0000000000000000000000000000000000000000000000000000000000000000"); + mtx.vJoinSplit[0].nullifiers.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000000"); + mtx.vJoinSplit[0].nullifiers.at(1) = uint256S("0000000000000000000000000000000000000000000000000000000000000000"); CTransaction tx(mtx); @@ -440,8 +440,8 @@ TEST(checktransaction_tests, bad_joinsplits_nullifiers_duplicate_same_joinsplit) TEST(checktransaction_tests, bad_joinsplits_nullifiers_duplicate_different_joinsplit) { CMutableTransaction mtx = GetValidTransaction(); - mtx.vjoinsplit[0].nullifiers.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000000"); - mtx.vjoinsplit[1].nullifiers.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000000"); + mtx.vJoinSplit[0].nullifiers.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000000"); + mtx.vJoinSplit[1].nullifiers.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000000"); CTransaction tx(mtx); @@ -456,7 +456,7 @@ TEST(checktransaction_tests, bad_cb_has_joinsplits) { mtx.vin.resize(1); mtx.vin[0].prevout.SetNull(); - mtx.vjoinsplit.resize(1); + mtx.vJoinSplit.resize(1); CTransaction tx(mtx); EXPECT_TRUE(tx.IsCoinBase()); @@ -472,7 +472,7 @@ TEST(checktransaction_tests, bad_cb_empty_scriptsig) { mtx.vin.resize(1); mtx.vin[0].prevout.SetNull(); - mtx.vjoinsplit.resize(0); + mtx.vJoinSplit.resize(0); CTransaction tx(mtx); EXPECT_TRUE(tx.IsCoinBase()); @@ -643,7 +643,7 @@ TEST(checktransaction_tests, OverwinterDefaultValues) { // A valid v3 transaction with no joinsplits TEST(checktransaction_tests, OverwinterValidTx) { CMutableTransaction mtx = GetValidTransaction(); - mtx.vjoinsplit.resize(0); + mtx.vJoinSplit.resize(0); mtx.fOverwintered = true; mtx.nVersion = OVERWINTER_TX_VERSION; mtx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID; @@ -655,7 +655,7 @@ TEST(checktransaction_tests, OverwinterValidTx) { TEST(checktransaction_tests, OverwinterExpiryHeight) { CMutableTransaction mtx = GetValidTransaction(); - mtx.vjoinsplit.resize(0); + mtx.vJoinSplit.resize(0); mtx.fOverwintered = true; mtx.nVersion = OVERWINTER_TX_VERSION; mtx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID; @@ -696,7 +696,7 @@ TEST(checktransaction_tests, OverwinterExpiryHeight) { // given the new Overwinter logic TEST(checktransaction_tests, SproutTxVersionTooLow) { CMutableTransaction mtx = GetValidTransaction(); - mtx.vjoinsplit.resize(0); + mtx.vJoinSplit.resize(0); mtx.fOverwintered = false; mtx.nVersion = -1; @@ -718,7 +718,7 @@ class UNSAFE_CTransaction : public CTransaction { TEST(checktransaction_tests, SaplingSproutInputSumsTooLarge) { CMutableTransaction mtx = GetValidTransaction(); - mtx.vjoinsplit.resize(0); + mtx.vJoinSplit.resize(0); mtx.fOverwintered = true; mtx.nVersion = SAPLING_TX_VERSION; mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID; @@ -746,12 +746,12 @@ TEST(checktransaction_tests, SaplingSproutInputSumsTooLarge) { inputMap, outputMap, 0, 0, false); - mtx.vjoinsplit.push_back(jsdesc); + mtx.vJoinSplit.push_back(jsdesc); } mtx.vShieldedSpend.push_back(SpendDescription()); - mtx.vjoinsplit[0].vpub_new = (MAX_MONEY / 2) + 10; + mtx.vJoinSplit[0].vpub_new = (MAX_MONEY / 2) + 10; { UNSAFE_CTransaction tx(mtx); @@ -772,7 +772,7 @@ TEST(checktransaction_tests, SaplingSproutInputSumsTooLarge) { // Test bad Overwinter version number in CheckTransactionWithoutProofVerification TEST(checktransaction_tests, OverwinterVersionNumberLow) { CMutableTransaction mtx = GetValidTransaction(); - mtx.vjoinsplit.resize(0); + mtx.vJoinSplit.resize(0); mtx.fOverwintered = true; mtx.nVersion = OVERWINTER_MIN_TX_VERSION - 1; mtx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID; @@ -790,7 +790,7 @@ TEST(checktransaction_tests, OverwinterVersionNumberHigh) { UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); CMutableTransaction mtx = GetValidTransaction(); - mtx.vjoinsplit.resize(0); + mtx.vJoinSplit.resize(0); mtx.fOverwintered = true; mtx.nVersion = OVERWINTER_MAX_TX_VERSION + 1; mtx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID; @@ -809,7 +809,7 @@ TEST(checktransaction_tests, OverwinterVersionNumberHigh) { // Test bad Overwinter version group id TEST(checktransaction_tests, OverwinterBadVersionGroupId) { CMutableTransaction mtx = GetValidTransaction(); - mtx.vjoinsplit.resize(0); + mtx.vJoinSplit.resize(0); mtx.fOverwintered = true; mtx.nVersion = OVERWINTER_TX_VERSION; mtx.nExpiryHeight = 0; diff --git a/src/gtest/test_mempool.cpp b/src/gtest/test_mempool.cpp index 97d6ae80c6c..834e29f6486 100644 --- a/src/gtest/test_mempool.cpp +++ b/src/gtest/test_mempool.cpp @@ -174,7 +174,7 @@ TEST(Mempool, OverwinterNotActiveYet) { CTxMemPool pool(::minRelayTxFee); bool missingInputs; CMutableTransaction mtx = GetValidTransaction(); - mtx.vjoinsplit.resize(0); // no joinsplits + mtx.vJoinSplit.resize(0); // no joinsplits mtx.fOverwintered = true; mtx.nVersion = OVERWINTER_TX_VERSION; mtx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID; @@ -200,7 +200,7 @@ TEST(Mempool, SproutV3TxFailsAsExpected) { CTxMemPool pool(::minRelayTxFee); bool missingInputs; CMutableTransaction mtx = GetValidTransaction(); - mtx.vjoinsplit.resize(0); // no joinsplits + mtx.vJoinSplit.resize(0); // no joinsplits mtx.fOverwintered = false; mtx.nVersion = 3; CValidationState state1; @@ -221,7 +221,7 @@ TEST(Mempool, SproutV3TxWhenOverwinterActive) { CTxMemPool pool(::minRelayTxFee); bool missingInputs; CMutableTransaction mtx = GetValidTransaction(); - mtx.vjoinsplit.resize(0); // no joinsplits + mtx.vJoinSplit.resize(0); // no joinsplits mtx.fOverwintered = false; mtx.nVersion = 3; CValidationState state1; @@ -245,7 +245,7 @@ TEST(Mempool, SproutNegativeVersionTxWhenOverwinterActive) { CTxMemPool pool(::minRelayTxFee); bool missingInputs; CMutableTransaction mtx = GetValidTransaction(); - mtx.vjoinsplit.resize(0); // no joinsplits + mtx.vJoinSplit.resize(0); // no joinsplits mtx.fOverwintered = false; // A Sprout transaction with version -3 is created using Sprout code (as found in zcashd <= 1.0.14). @@ -294,7 +294,7 @@ TEST(Mempool, ExpiringSoonTxRejection) { CTxMemPool pool(::minRelayTxFee); bool missingInputs; CMutableTransaction mtx = GetValidTransaction(); - mtx.vjoinsplit.resize(0); // no joinsplits + mtx.vJoinSplit.resize(0); // no joinsplits mtx.fOverwintered = true; mtx.nVersion = OVERWINTER_TX_VERSION; mtx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID; diff --git a/src/gtest/test_transaction_builder.cpp b/src/gtest/test_transaction_builder.cpp index 5ebf1d737c6..d8c44ba1f88 100644 --- a/src/gtest/test_transaction_builder.cpp +++ b/src/gtest/test_transaction_builder.cpp @@ -100,7 +100,7 @@ TEST(TransactionBuilder, TransparentToSapling) EXPECT_EQ(tx.vin.size(), 1); EXPECT_EQ(tx.vout.size(), 0); - EXPECT_EQ(tx.vjoinsplit.size(), 0); + EXPECT_EQ(tx.vJoinSplit.size(), 0); EXPECT_EQ(tx.vShieldedSpend.size(), 0); EXPECT_EQ(tx.vShieldedOutput.size(), 1); EXPECT_EQ(tx.valueBalance, -40000); @@ -137,7 +137,7 @@ TEST(TransactionBuilder, SaplingToSapling) { EXPECT_EQ(tx.vin.size(), 0); EXPECT_EQ(tx.vout.size(), 0); - EXPECT_EQ(tx.vjoinsplit.size(), 0); + EXPECT_EQ(tx.vJoinSplit.size(), 0); EXPECT_EQ(tx.vShieldedSpend.size(), 1); EXPECT_EQ(tx.vShieldedOutput.size(), 2); EXPECT_EQ(tx.valueBalance, 10000); @@ -173,9 +173,9 @@ TEST(TransactionBuilder, SaplingToSprout) { EXPECT_EQ(tx.vin.size(), 0); EXPECT_EQ(tx.vout.size(), 0); - EXPECT_EQ(tx.vjoinsplit.size(), 1); - EXPECT_EQ(tx.vjoinsplit[0].vpub_old, 25000); - EXPECT_EQ(tx.vjoinsplit[0].vpub_new, 0); + EXPECT_EQ(tx.vJoinSplit.size(), 1); + EXPECT_EQ(tx.vJoinSplit[0].vpub_old, 25000); + EXPECT_EQ(tx.vJoinSplit[0].vpub_new, 0); EXPECT_EQ(tx.vShieldedSpend.size(), 1); EXPECT_EQ(tx.vShieldedOutput.size(), 1); EXPECT_EQ(tx.valueBalance, 35000); @@ -203,7 +203,7 @@ TEST(TransactionBuilder, SproutToSproutAndSapling) { SproutMerkleTree sproutTree; for (int i = 0; i < ZC_NUM_JS_OUTPUTS; i++) { - sproutTree.append(wtx.vjoinsplit[0].commitments[i]); + sproutTree.append(wtx.vJoinSplit[0].commitments[i]); } SproutWitness sproutWitness = sproutTree.witness(); // Fake a view with the Sprout note in it @@ -230,13 +230,13 @@ TEST(TransactionBuilder, SproutToSproutAndSapling) { EXPECT_EQ(tx.vout.size(), 0); // TODO: This should be doable in two JoinSplits. // There's an inefficiency in the implementation. - EXPECT_EQ(tx.vjoinsplit.size(), 3); - EXPECT_EQ(tx.vjoinsplit[0].vpub_old, 0); - EXPECT_EQ(tx.vjoinsplit[0].vpub_new, 0); - EXPECT_EQ(tx.vjoinsplit[1].vpub_old, 0); - EXPECT_EQ(tx.vjoinsplit[1].vpub_new, 0); - EXPECT_EQ(tx.vjoinsplit[2].vpub_old, 0); - EXPECT_EQ(tx.vjoinsplit[2].vpub_new, 10000); + EXPECT_EQ(tx.vJoinSplit.size(), 3); + EXPECT_EQ(tx.vJoinSplit[0].vpub_old, 0); + EXPECT_EQ(tx.vJoinSplit[0].vpub_new, 0); + EXPECT_EQ(tx.vJoinSplit[1].vpub_old, 0); + EXPECT_EQ(tx.vJoinSplit[1].vpub_new, 0); + EXPECT_EQ(tx.vJoinSplit[2].vpub_old, 0); + EXPECT_EQ(tx.vJoinSplit[2].vpub_new, 10000); EXPECT_EQ(tx.vShieldedSpend.size(), 0); EXPECT_EQ(tx.vShieldedOutput.size(), 1); EXPECT_EQ(tx.valueBalance, -5000); @@ -373,7 +373,7 @@ TEST(TransactionBuilder, ChangeOutput) EXPECT_EQ(tx.vin.size(), 1); EXPECT_EQ(tx.vout.size(), 0); - EXPECT_EQ(tx.vjoinsplit.size(), 0); + EXPECT_EQ(tx.vJoinSplit.size(), 0); EXPECT_EQ(tx.vShieldedSpend.size(), 1); EXPECT_EQ(tx.vShieldedOutput.size(), 1); EXPECT_EQ(tx.valueBalance, -15000); @@ -388,7 +388,7 @@ TEST(TransactionBuilder, ChangeOutput) EXPECT_EQ(tx.vin.size(), 1); EXPECT_EQ(tx.vout.size(), 0); - EXPECT_EQ(tx.vjoinsplit.size(), 0); + EXPECT_EQ(tx.vJoinSplit.size(), 0); EXPECT_EQ(tx.vShieldedSpend.size(), 0); EXPECT_EQ(tx.vShieldedOutput.size(), 1); EXPECT_EQ(tx.valueBalance, -15000); @@ -403,7 +403,7 @@ TEST(TransactionBuilder, ChangeOutput) EXPECT_EQ(tx.vin.size(), 1); EXPECT_EQ(tx.vout.size(), 1); - EXPECT_EQ(tx.vjoinsplit.size(), 0); + EXPECT_EQ(tx.vJoinSplit.size(), 0); EXPECT_EQ(tx.vShieldedSpend.size(), 0); EXPECT_EQ(tx.vShieldedOutput.size(), 0); EXPECT_EQ(tx.valueBalance, 0); @@ -435,7 +435,7 @@ TEST(TransactionBuilder, SetFee) EXPECT_EQ(tx.vin.size(), 0); EXPECT_EQ(tx.vout.size(), 0); - EXPECT_EQ(tx.vjoinsplit.size(), 0); + EXPECT_EQ(tx.vJoinSplit.size(), 0); EXPECT_EQ(tx.vShieldedSpend.size(), 1); EXPECT_EQ(tx.vShieldedOutput.size(), 2); EXPECT_EQ(tx.valueBalance, 10000); @@ -451,7 +451,7 @@ TEST(TransactionBuilder, SetFee) EXPECT_EQ(tx.vin.size(), 0); EXPECT_EQ(tx.vout.size(), 0); - EXPECT_EQ(tx.vjoinsplit.size(), 0); + EXPECT_EQ(tx.vJoinSplit.size(), 0); EXPECT_EQ(tx.vShieldedSpend.size(), 1); EXPECT_EQ(tx.vShieldedOutput.size(), 2); EXPECT_EQ(tx.valueBalance, 20000); diff --git a/src/main.cpp b/src/main.cpp index f407d81a4ee..b17d621e496 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -980,7 +980,7 @@ bool ContextualCheckTransaction( uint256 dataToBeSigned; - if (!tx.vjoinsplit.empty() || + if (!tx.vJoinSplit.empty() || !tx.vShieldedSpend.empty() || !tx.vShieldedOutput.empty()) { @@ -995,7 +995,7 @@ bool ContextualCheckTransaction( } } - if (!tx.vjoinsplit.empty()) + if (!tx.vJoinSplit.empty()) { BOOST_STATIC_ASSERT(crypto_sign_PUBLICKEYBYTES == 32); @@ -1079,7 +1079,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state, return false; } else { // Ensure that zk-SNARKs verify - BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) { + BOOST_FOREACH(const JSDescription &joinsplit, tx.vJoinSplit) { if (!joinsplit.Verify(*pzcashParams, verifier, tx.joinSplitPubKey)) { return state.DoS(100, error("CheckTransaction(): joinsplit does not verify"), REJECT_INVALID, "bad-txns-joinsplit-verification-failed"); @@ -1136,13 +1136,13 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio } // Transactions containing empty `vin` must have either non-empty - // `vjoinsplit` or non-empty `vShieldedSpend`. - if (tx.vin.empty() && tx.vjoinsplit.empty() && tx.vShieldedSpend.empty()) + // `vJoinSplit` or non-empty `vShieldedSpend`. + if (tx.vin.empty() && tx.vJoinSplit.empty() && tx.vShieldedSpend.empty()) return state.DoS(10, error("CheckTransaction(): vin empty"), REJECT_INVALID, "bad-txns-vin-empty"); // Transactions containing empty `vout` must have either non-empty - // `vjoinsplit` or non-empty `vShieldedOutput`. - if (tx.vout.empty() && tx.vjoinsplit.empty() && tx.vShieldedOutput.empty()) + // `vJoinSplit` or non-empty `vShieldedOutput`. + if (tx.vout.empty() && tx.vJoinSplit.empty() && tx.vShieldedOutput.empty()) return state.DoS(10, error("CheckTransaction(): vout empty"), REJECT_INVALID, "bad-txns-vout-empty"); @@ -1192,7 +1192,7 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio } // Ensure that joinsplit values are well-formed - BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit) + BOOST_FOREACH(const JSDescription& joinsplit, tx.vJoinSplit) { if (joinsplit.vpub_old < 0) { return state.DoS(100, error("CheckTransaction(): joinsplit.vpub_old negative"), @@ -1232,7 +1232,7 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio // to the value pool. { CAmount nValueIn = 0; - for (std::vector::const_iterator it(tx.vjoinsplit.begin()); it != tx.vjoinsplit.end(); ++it) + for (std::vector::const_iterator it(tx.vJoinSplit.begin()); it != tx.vJoinSplit.end(); ++it) { nValueIn += it->vpub_new; @@ -1267,7 +1267,7 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio // Check for duplicate joinsplit nullifiers in this transaction { set vJoinSplitNullifiers; - BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit) + BOOST_FOREACH(const JSDescription& joinsplit, tx.vJoinSplit) { BOOST_FOREACH(const uint256& nf, joinsplit.nullifiers) { @@ -1296,7 +1296,7 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio if (tx.IsCoinBase()) { // There should be no joinsplits in a coinbase transaction - if (tx.vjoinsplit.size() > 0) + if (tx.vJoinSplit.size() > 0) return state.DoS(100, error("CheckTransaction(): coinbase has joinsplits"), REJECT_INVALID, "bad-cb-has-joinsplits"); @@ -1429,7 +1429,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa return false; } } - BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) { + BOOST_FOREACH(const JSDescription &joinsplit, tx.vJoinSplit) { BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) { if (pool.nullifierExists(nf, SPROUT)) { return false; @@ -1528,7 +1528,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa unsigned int nSize = entry.GetTxSize(); // Accept a tx if it contains joinsplits and has at least the default fee specified by z_sendmany. - if (tx.vjoinsplit.size() > 0 && nFees >= ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE) { + if (tx.vJoinSplit.size() > 0 && nFees >= ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE) { // In future we will we have more accurate and dynamic computation of fees for tx with joinsplits. } else { // Don't accept it if it can't get into a block @@ -2726,7 +2726,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin } UpdateCoins(tx, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight); - BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) { + BOOST_FOREACH(const JSDescription &joinsplit, tx.vJoinSplit) { BOOST_FOREACH(const uint256 ¬e_commitment, joinsplit.commitments) { // Insert the note commitments into our temporary tree. @@ -3546,7 +3546,7 @@ bool ReceivedBlockTransactions( // pool. So we invert the sign here. saplingValue += -tx.valueBalance; - for (auto js : tx.vjoinsplit) { + for (auto js : tx.vJoinSplit) { sproutValue += js.vpub_old; sproutValue -= js.vpub_new; } @@ -5806,7 +5806,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } // TODO: currently, prohibit joinsplits and shielded spends/outputs from entering mapOrphans else if (fMissingInputs && - tx.vjoinsplit.empty() && + tx.vJoinSplit.empty() && tx.vShieldedSpend.empty() && tx.vShieldedOutput.empty()) { diff --git a/src/miner.cpp b/src/miner.cpp index bc8f6888ce8..aa3306524ad 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -334,7 +334,7 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s saplingValueDummy += -tx.valueBalance; - for (auto js : tx.vjoinsplit) { + for (auto js : tx.vJoinSplit) { sproutValueDummy += js.vpub_old; sproutValueDummy -= js.vpub_new; } diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index 79adf290eef..b54981b4808 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -203,7 +203,7 @@ CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::SPROUT_MIN_C CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), fOverwintered(tx.fOverwintered), nVersionGroupId(tx.nVersionGroupId), nExpiryHeight(tx.nExpiryHeight), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime), valueBalance(tx.valueBalance), vShieldedSpend(tx.vShieldedSpend), vShieldedOutput(tx.vShieldedOutput), - vjoinsplit(tx.vjoinsplit), joinSplitPubKey(tx.joinSplitPubKey), joinSplitSig(tx.joinSplitSig), + vJoinSplit(tx.vJoinSplit), joinSplitPubKey(tx.joinSplitPubKey), joinSplitSig(tx.joinSplitSig), bindingSig(tx.bindingSig) { @@ -219,12 +219,12 @@ void CTransaction::UpdateHash() const *const_cast(&hash) = SerializeHash(*this); } -CTransaction::CTransaction() : nVersion(CTransaction::SPROUT_MIN_CURRENT_VERSION), fOverwintered(false), nVersionGroupId(0), nExpiryHeight(0), vin(), vout(), nLockTime(0), valueBalance(0), vShieldedSpend(), vShieldedOutput(), vjoinsplit(), joinSplitPubKey(), joinSplitSig(), bindingSig() { } +CTransaction::CTransaction() : nVersion(CTransaction::SPROUT_MIN_CURRENT_VERSION), fOverwintered(false), nVersionGroupId(0), nExpiryHeight(0), vin(), vout(), nLockTime(0), valueBalance(0), vShieldedSpend(), vShieldedOutput(), vJoinSplit(), joinSplitPubKey(), joinSplitSig(), bindingSig() { } CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), fOverwintered(tx.fOverwintered), nVersionGroupId(tx.nVersionGroupId), nExpiryHeight(tx.nExpiryHeight), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime), valueBalance(tx.valueBalance), vShieldedSpend(tx.vShieldedSpend), vShieldedOutput(tx.vShieldedOutput), - vjoinsplit(tx.vjoinsplit), joinSplitPubKey(tx.joinSplitPubKey), joinSplitSig(tx.joinSplitSig), + vJoinSplit(tx.vJoinSplit), joinSplitPubKey(tx.joinSplitPubKey), joinSplitSig(tx.joinSplitSig), bindingSig(tx.bindingSig) { UpdateHash(); @@ -237,7 +237,7 @@ CTransaction::CTransaction( bool evilDeveloperFlag) : nVersion(tx.nVersion), fOverwintered(tx.fOverwintered), nVersionGroupId(tx.nVersionGroupId), nExpiryHeight(tx.nExpiryHeight), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime), valueBalance(tx.valueBalance), vShieldedSpend(tx.vShieldedSpend), vShieldedOutput(tx.vShieldedOutput), - vjoinsplit(tx.vjoinsplit), joinSplitPubKey(tx.joinSplitPubKey), joinSplitSig(tx.joinSplitSig), + vJoinSplit(tx.vJoinSplit), joinSplitPubKey(tx.joinSplitPubKey), joinSplitSig(tx.joinSplitSig), bindingSig(tx.bindingSig) { assert(evilDeveloperFlag); @@ -247,7 +247,7 @@ CTransaction::CTransaction(CMutableTransaction &&tx) : nVersion(tx.nVersion), fO vin(std::move(tx.vin)), vout(std::move(tx.vout)), nLockTime(tx.nLockTime), nExpiryHeight(tx.nExpiryHeight), valueBalance(tx.valueBalance), vShieldedSpend(std::move(tx.vShieldedSpend)), vShieldedOutput(std::move(tx.vShieldedOutput)), - vjoinsplit(std::move(tx.vjoinsplit)), + vJoinSplit(std::move(tx.vJoinSplit)), joinSplitPubKey(std::move(tx.joinSplitPubKey)), joinSplitSig(std::move(tx.joinSplitSig)) { UpdateHash(); @@ -264,7 +264,7 @@ CTransaction& CTransaction::operator=(const CTransaction &tx) { *const_cast(&valueBalance) = tx.valueBalance; *const_cast*>(&vShieldedSpend) = tx.vShieldedSpend; *const_cast*>(&vShieldedOutput) = tx.vShieldedOutput; - *const_cast*>(&vjoinsplit) = tx.vjoinsplit; + *const_cast*>(&vJoinSplit) = tx.vJoinSplit; *const_cast(&joinSplitPubKey) = tx.joinSplitPubKey; *const_cast(&joinSplitSig) = tx.joinSplitSig; *const_cast(&bindingSig) = tx.bindingSig; @@ -291,7 +291,7 @@ CAmount CTransaction::GetValueOut() const } } - for (std::vector::const_iterator it(vjoinsplit.begin()); it != vjoinsplit.end(); ++it) + for (std::vector::const_iterator it(vJoinSplit.begin()); it != vJoinSplit.end(); ++it) { // NB: vpub_old "takes" money from the transparent value pool just as outputs do nValueOut += it->vpub_old; @@ -315,7 +315,7 @@ CAmount CTransaction::GetShieldedValueIn() const } } - for (std::vector::const_iterator it(vjoinsplit.begin()); it != vjoinsplit.end(); ++it) + for (std::vector::const_iterator it(vJoinSplit.begin()); it != vJoinSplit.end(); ++it) { // NB: vpub_new "gives" money to the transparent value pool just as inputs do nValue += it->vpub_new; diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 6ce15a94bd5..394a087c464 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -555,7 +555,7 @@ class CTransaction const CAmount valueBalance; const std::vector vShieldedSpend; const std::vector vShieldedOutput; - const std::vector vjoinsplit; + const std::vector vJoinSplit; const uint256 joinSplitPubKey; const joinsplit_sig_t joinSplitSig = {{0}}; const binding_sig_t bindingSig = {{0}}; @@ -612,8 +612,8 @@ class CTransaction } if (nVersion >= 2) { auto os = WithVersion(&s, static_cast(header)); - ::SerReadWrite(os, *const_cast*>(&vjoinsplit), ser_action); - if (vjoinsplit.size() > 0) { + ::SerReadWrite(os, *const_cast*>(&vJoinSplit), ser_action); + if (vJoinSplit.size() > 0) { READWRITE(*const_cast(&joinSplitPubKey)); READWRITE(*const_cast(&joinSplitSig)); } @@ -702,7 +702,7 @@ struct CMutableTransaction CAmount valueBalance; std::vector vShieldedSpend; std::vector vShieldedOutput; - std::vector vjoinsplit; + std::vector vJoinSplit; uint256 joinSplitPubKey; CTransaction::joinsplit_sig_t joinSplitSig = {{0}}; CTransaction::binding_sig_t bindingSig = {{0}}; @@ -758,8 +758,8 @@ struct CMutableTransaction } if (nVersion >= 2) { auto os = WithVersion(&s, static_cast(header)); - ::SerReadWrite(os, vjoinsplit, ser_action); - if (vjoinsplit.size() > 0) { + ::SerReadWrite(os, vJoinSplit, ser_action); + if (vJoinSplit.size() > 0) { READWRITE(joinSplitPubKey); READWRITE(joinSplitSig); } diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 80ff66ee7bd..612323abc46 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -60,9 +60,9 @@ void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fInclud UniValue TxJoinSplitToJSON(const CTransaction& tx) { bool useGroth = tx.fOverwintered && tx.nVersion >= SAPLING_TX_VERSION; - UniValue vjoinsplit(UniValue::VARR); - for (unsigned int i = 0; i < tx.vjoinsplit.size(); i++) { - const JSDescription& jsdescription = tx.vjoinsplit[i]; + UniValue vJoinSplit(UniValue::VARR); + for (unsigned int i = 0; i < tx.vJoinSplit.size(); i++) { + const JSDescription& jsdescription = tx.vJoinSplit[i]; UniValue joinsplit(UniValue::VOBJ); joinsplit.push_back(Pair("vpub_old", ValueFromAmount(jsdescription.vpub_old))); @@ -110,9 +110,9 @@ UniValue TxJoinSplitToJSON(const CTransaction& tx) { joinsplit.push_back(Pair("ciphertexts", ciphertexts)); } - vjoinsplit.push_back(joinsplit); + vJoinSplit.push_back(joinsplit); } - return vjoinsplit; + return vJoinSplit; } UniValue TxShieldedSpendsToJSON(const CTransaction& tx) { diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 6719443d0b7..bec6cff7664 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1038,7 +1038,7 @@ class CTransactionSignatureSerializer { // Serialize nLockTime ::Serialize(s, txTo.nLockTime); - // Serialize vjoinsplit + // Serialize vJoinSplit if (txTo.nVersion >= 2) { // // SIGHASH_* functions will hash portions of @@ -1046,8 +1046,8 @@ class CTransactionSignatureSerializer { // keeps the JoinSplit cryptographically bound // to the transaction. // - ::Serialize(s, txTo.vjoinsplit); - if (txTo.vjoinsplit.size() > 0) { + ::Serialize(s, txTo.vJoinSplit); + if (txTo.vJoinSplit.size() > 0) { ::Serialize(s, txTo.joinSplitPubKey); CTransaction::joinsplit_sig_t nullSig = {}; @@ -1096,8 +1096,8 @@ uint256 GetOutputsHash(const CTransaction& txTo) { uint256 GetJoinSplitsHash(const CTransaction& txTo) { CBLAKE2bWriter ss(SER_GETHASH, static_cast(txTo.GetHeader()), ZCASH_JOINSPLITS_HASH_PERSONALIZATION); - for (unsigned int n = 0; n < txTo.vjoinsplit.size(); n++) { - ss << txTo.vjoinsplit[n]; + for (unsigned int n = 0; n < txTo.vJoinSplit.size(); n++) { + ss << txTo.vJoinSplit[n]; } ss << txTo.joinSplitPubKey; return ss.GetHash(); @@ -1188,7 +1188,7 @@ uint256 SignatureHash( hashOutputs = ss.GetHash(); } - if (!txTo.vjoinsplit.empty()) { + if (!txTo.vJoinSplit.empty()) { hashJoinSplits = cache ? cache->hashJoinSplits : GetJoinSplitsHash(txTo); } diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 1612ab449c7..35023c47e9b 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -237,7 +237,7 @@ class TxWithNullifiers sproutNullifier = GetRandHash(); JSDescription jsd; jsd.nullifiers[0] = sproutNullifier; - mutableTx.vjoinsplit.emplace_back(jsd); + mutableTx.vJoinSplit.emplace_back(jsd); saplingNullifier = GetRandHash(); SpendDescription sd; @@ -640,7 +640,7 @@ BOOST_AUTO_TEST_CASE(chained_joinsplits) { CMutableTransaction mtx; - mtx.vjoinsplit.push_back(js2); + mtx.vJoinSplit.push_back(js2); BOOST_CHECK(!cache.HaveShieldedRequirements(mtx)); } @@ -649,35 +649,35 @@ BOOST_AUTO_TEST_CASE(chained_joinsplits) // js2 is trying to anchor to js1 but js1 // appears afterwards -- not a permitted ordering CMutableTransaction mtx; - mtx.vjoinsplit.push_back(js2); - mtx.vjoinsplit.push_back(js1); + mtx.vJoinSplit.push_back(js2); + mtx.vJoinSplit.push_back(js1); BOOST_CHECK(!cache.HaveShieldedRequirements(mtx)); } { CMutableTransaction mtx; - mtx.vjoinsplit.push_back(js1); - mtx.vjoinsplit.push_back(js2); + mtx.vJoinSplit.push_back(js1); + mtx.vJoinSplit.push_back(js2); BOOST_CHECK(cache.HaveShieldedRequirements(mtx)); } { CMutableTransaction mtx; - mtx.vjoinsplit.push_back(js1); - mtx.vjoinsplit.push_back(js2); - mtx.vjoinsplit.push_back(js3); + mtx.vJoinSplit.push_back(js1); + mtx.vJoinSplit.push_back(js2); + mtx.vJoinSplit.push_back(js3); BOOST_CHECK(cache.HaveShieldedRequirements(mtx)); } { CMutableTransaction mtx; - mtx.vjoinsplit.push_back(js1); - mtx.vjoinsplit.push_back(js1b); - mtx.vjoinsplit.push_back(js2); - mtx.vjoinsplit.push_back(js3); + mtx.vJoinSplit.push_back(js1); + mtx.vJoinSplit.push_back(js1b); + mtx.vJoinSplit.push_back(js2); + mtx.vJoinSplit.push_back(js3); BOOST_CHECK(cache.HaveShieldedRequirements(mtx)); } diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index f7ecfe5c8f8..69ed32df5ce 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -124,7 +124,7 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle, uint32_t co tx.vout.clear(); tx.vShieldedSpend.clear(); tx.vShieldedOutput.clear(); - tx.vjoinsplit.clear(); + tx.vJoinSplit.clear(); tx.nLockTime = (insecure_rand() % 2) ? insecure_rand() : 0; int ins = (insecure_rand() % 4) + 1; int outs = fSingle ? ins : (insecure_rand() % 4) + 1; @@ -193,7 +193,7 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle, uint32_t co jsdesc.macs[0] = GetRandHash(); jsdesc.macs[1] = GetRandHash(); - tx.vjoinsplit.push_back(jsdesc); + tx.vJoinSplit.push_back(jsdesc); } unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES]; diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 4219e01f4ce..f4314e17521 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -484,8 +484,8 @@ void test_simple_joinsplit_invalidity(uint32_t consensusBranchId, CMutableTransa BOOST_CHECK(!CheckTransactionWithoutProofVerification(newTx, state)); BOOST_CHECK(state.GetRejectReason() == "bad-txns-vout-empty"); - newTx.vjoinsplit.push_back(JSDescription()); - JSDescription *jsdesc = &newTx.vjoinsplit[0]; + newTx.vJoinSplit.push_back(JSDescription()); + JSDescription *jsdesc = &newTx.vJoinSplit[0]; jsdesc->nullifiers[0] = GetRandHash(); jsdesc->nullifiers[1] = GetRandHash(); @@ -512,9 +512,9 @@ void test_simple_joinsplit_invalidity(uint32_t consensusBranchId, CMutableTransa CMutableTransaction newTx(tx); CValidationState state; - newTx.vjoinsplit.push_back(JSDescription()); + newTx.vJoinSplit.push_back(JSDescription()); - JSDescription *jsdesc = &newTx.vjoinsplit[0]; + JSDescription *jsdesc = &newTx.vJoinSplit[0]; jsdesc->vpub_old = -1; BOOST_CHECK(!CheckTransaction(newTx, state, verifier)); @@ -538,9 +538,9 @@ void test_simple_joinsplit_invalidity(uint32_t consensusBranchId, CMutableTransa jsdesc->vpub_new = (MAX_MONEY / 2) + 10; - newTx.vjoinsplit.push_back(JSDescription()); + newTx.vJoinSplit.push_back(JSDescription()); - JSDescription *jsdesc2 = &newTx.vjoinsplit[1]; + JSDescription *jsdesc2 = &newTx.vJoinSplit[1]; jsdesc2->vpub_new = (MAX_MONEY / 2) + 10; BOOST_CHECK(!CheckTransaction(newTx, state, verifier)); @@ -551,8 +551,8 @@ void test_simple_joinsplit_invalidity(uint32_t consensusBranchId, CMutableTransa CMutableTransaction newTx(tx); CValidationState state; - newTx.vjoinsplit.push_back(JSDescription()); - JSDescription *jsdesc = &newTx.vjoinsplit[0]; + newTx.vJoinSplit.push_back(JSDescription()); + JSDescription *jsdesc = &newTx.vJoinSplit[0]; jsdesc->nullifiers[0] = GetRandHash(); jsdesc->nullifiers[1] = jsdesc->nullifiers[0]; @@ -562,9 +562,9 @@ void test_simple_joinsplit_invalidity(uint32_t consensusBranchId, CMutableTransa jsdesc->nullifiers[1] = GetRandHash(); - newTx.vjoinsplit.push_back(JSDescription()); - jsdesc = &newTx.vjoinsplit[0]; // Fixes #2026. Related PR #2078. - JSDescription *jsdesc2 = &newTx.vjoinsplit[1]; + newTx.vJoinSplit.push_back(JSDescription()); + jsdesc = &newTx.vJoinSplit[0]; // Fixes #2026. Related PR #2078. + JSDescription *jsdesc2 = &newTx.vJoinSplit[1]; jsdesc2->nullifiers[0] = GetRandHash(); jsdesc2->nullifiers[1] = jsdesc->nullifiers[0]; @@ -577,8 +577,8 @@ void test_simple_joinsplit_invalidity(uint32_t consensusBranchId, CMutableTransa CMutableTransaction newTx(tx); CValidationState state; - newTx.vjoinsplit.push_back(JSDescription()); - JSDescription *jsdesc = &newTx.vjoinsplit[0]; + newTx.vJoinSplit.push_back(JSDescription()); + JSDescription *jsdesc = &newTx.vJoinSplit[0]; jsdesc->nullifiers[0] = GetRandHash(); jsdesc->nullifiers[1] = GetRandHash(); @@ -831,11 +831,11 @@ BOOST_AUTO_TEST_CASE(test_IsStandardV2) BOOST_CHECK(IsStandardTx(t, reason, chainparams)); // ... and with one JoinSplit. - t.vjoinsplit.push_back(JSDescription()); + t.vJoinSplit.push_back(JSDescription()); BOOST_CHECK(IsStandardTx(t, reason, chainparams)); // ... and when that JoinSplit takes from a transparent input. - JSDescription *jsdesc = &t.vjoinsplit[0]; + JSDescription *jsdesc = &t.vJoinSplit[0]; jsdesc->vpub_old = 10*CENT; t.vout[0].nValue -= 10*CENT; BOOST_CHECK(IsStandardTx(t, reason, chainparams)); diff --git a/src/transaction_builder.cpp b/src/transaction_builder.cpp index 687c1a42024..aa34ffb15e5 100644 --- a/src/transaction_builder.cpp +++ b/src/transaction_builder.cpp @@ -508,12 +508,12 @@ void TransactionBuilder::CreateJSDescriptions() JSDescription prevJoinSplit; // Keep track of previous JoinSplit and its commitments - if (mtx.vjoinsplit.size() > 0) { - prevJoinSplit = mtx.vjoinsplit.back(); + if (mtx.vJoinSplit.size() > 0) { + prevJoinSplit = mtx.vJoinSplit.back(); } // If there is no change, the chain has terminated so we can reset the tracked treestate. - if (jsChange == 0 && mtx.vjoinsplit.size() > 0) { + if (jsChange == 0 && mtx.vJoinSplit.size() > 0) { intermediates.clear(); previousCommitments.clear(); } @@ -679,7 +679,7 @@ void TransactionBuilder::CreateJSDescription( std::array& outputMap) { LogPrint("zrpcunsafe", "CreateJSDescription: creating joinsplit at index %d (vpub_old=%s, vpub_new=%s, in[0]=%s, in[1]=%s, out[0]=%s, out[1]=%s)\n", - mtx.vjoinsplit.size(), + mtx.vJoinSplit.size(), FormatMoney(vpub_old), FormatMoney(vpub_new), FormatMoney(vjsin[0].note.value()), FormatMoney(vjsin[1].note.value()), FormatMoney(vjsout[0].value), FormatMoney(vjsout[1].value)); @@ -708,7 +708,7 @@ void TransactionBuilder::CreateJSDescription( } } - mtx.vjoinsplit.push_back(jsdesc); + mtx.vJoinSplit.push_back(jsdesc); // TODO: Sprout payment disclosure } diff --git a/src/txmempool.cpp b/src/txmempool.cpp index cf04ad57775..af76b355832 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -105,7 +105,7 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, const CTransaction& tx = mapTx.find(hash)->GetTx(); for (unsigned int i = 0; i < tx.vin.size(); i++) mapNextTx[tx.vin[i].prevout] = CInPoint(&tx, i); - BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) { + BOOST_FOREACH(const JSDescription &joinsplit, tx.vJoinSplit) { BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) { mapSproutNullifiers[nf] = &tx; } @@ -158,7 +158,7 @@ void CTxMemPool::remove(const CTransaction &origTx, std::list& rem } BOOST_FOREACH(const CTxIn& txin, tx.vin) mapNextTx.erase(txin.prevout); - BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit) { + BOOST_FOREACH(const JSDescription& joinsplit, tx.vJoinSplit) { BOOST_FOREACH(const uint256& nf, joinsplit.nullifiers) { mapSproutNullifiers.erase(nf); } @@ -219,7 +219,7 @@ void CTxMemPool::removeWithAnchor(const uint256 &invalidRoot, ShieldedType type) const CTransaction& tx = it->GetTx(); switch (type) { case SPROUT: - BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit) { + BOOST_FOREACH(const JSDescription& joinsplit, tx.vJoinSplit) { if (joinsplit.anchor == invalidRoot) { transactionsToRemove.push_back(tx); break; @@ -262,7 +262,7 @@ void CTxMemPool::removeConflicts(const CTransaction &tx, std::list } } - BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) { + BOOST_FOREACH(const JSDescription &joinsplit, tx.vJoinSplit) { BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) { std::map::iterator it = mapSproutNullifiers.find(nf); if (it != mapSproutNullifiers.end()) { @@ -407,7 +407,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const boost::unordered_map intermediates; - BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) { + BOOST_FOREACH(const JSDescription &joinsplit, tx.vJoinSplit) { BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) { assert(!pcoins->GetNullifier(nf, SPROUT)); } diff --git a/src/utiltest.cpp b/src/utiltest.cpp index e62c5611be3..997137b1a78 100644 --- a/src/utiltest.cpp +++ b/src/utiltest.cpp @@ -48,7 +48,7 @@ CMutableTransaction GetValidSproutReceiveTransaction(ZCJoinSplit& params, uint256 rt; JSDescription jsdesc {false, params, mtx.joinSplitPubKey, rt, inputs, outputs, 2*value, 0, false}; - mtx.vjoinsplit.push_back(jsdesc); + mtx.vJoinSplit.push_back(jsdesc); // Consider: The following is a bit misleading (given the name of this function) // and should perhaps be changed, but currently a few tests in test_wallet.cpp @@ -97,8 +97,8 @@ CWalletTx GetInvalidCommitmentSproutReceive(ZCJoinSplit& params, CMutableTransaction mtx = GetValidSproutReceiveTransaction( params, sk, value, randomInputs, version ); - mtx.vjoinsplit[0].commitments[0] = uint256(); - mtx.vjoinsplit[0].commitments[1] = uint256(); + mtx.vJoinSplit[0].commitments[0] = uint256(); + mtx.vJoinSplit[0].commitments[1] = uint256(); CTransaction tx {mtx}; CWalletTx wtx {NULL, tx}; return wtx; @@ -108,11 +108,11 @@ libzcash::SproutNote GetSproutNote(ZCJoinSplit& params, const libzcash::SproutSpendingKey& sk, const CTransaction& tx, size_t js, size_t n) { ZCNoteDecryption decryptor {sk.receiving_key()}; - auto hSig = tx.vjoinsplit[js].h_sig(params, tx.joinSplitPubKey); + auto hSig = tx.vJoinSplit[js].h_sig(params, tx.joinSplitPubKey); auto note_pt = libzcash::SproutNotePlaintext::decrypt( decryptor, - tx.vjoinsplit[js].ciphertexts[n], - tx.vjoinsplit[js].ephemeralKey, + tx.vJoinSplit[js].ciphertexts[n], + tx.vJoinSplit[js].ephemeralKey, hSig, (unsigned char) n); return note_pt.note(sk.address()); @@ -169,7 +169,7 @@ CWalletTx GetValidSproutSpend(ZCJoinSplit& params, uint256 rt = tree.root(); JSDescription jsdesc {false, params, mtx.joinSplitPubKey, rt, inputs, outputs, 0, value, false}; - mtx.vjoinsplit.push_back(jsdesc); + mtx.vJoinSplit.push_back(jsdesc); // Empty output script. uint32_t consensusBranchId = SPROUT_BRANCH_ID; diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index 0e5dd34096e..fda81aa6dc6 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -532,12 +532,12 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() JSDescription prevJoinSplit; // Keep track of previous JoinSplit and its commitments - if (tx_.vjoinsplit.size() > 0) { - prevJoinSplit = tx_.vjoinsplit.back(); + if (tx_.vJoinSplit.size() > 0) { + prevJoinSplit = tx_.vJoinSplit.back(); } // If there is no change, the chain has terminated so we can reset the tracked treestate. - if (jsChange == 0 && tx_.vjoinsplit.size() > 0) { + if (jsChange == 0 && tx_.vJoinSplit.size() > 0) { intermediates.clear(); previousCommitments.clear(); } @@ -645,7 +645,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() wtxHeight = mapBlockIndex[wtx.hashBlock]->nHeight; wtxDepth = wtx.GetDepthInMainChain(); } - LogPrint("zrpcunsafe", "%s: spending note (txid=%s, vjoinsplit=%d, jsoutindex=%d, amount=%s, height=%d, confirmations=%d)\n", + LogPrint("zrpcunsafe", "%s: spending note (txid=%s, vJoinSplit=%d, jsoutindex=%d, amount=%s, height=%d, confirmations=%d)\n", getId(), jso.hash.ToString().substr(0, 10), jso.js, @@ -877,7 +877,7 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit( LogPrint("zrpcunsafe", "%s: creating joinsplit at index %d (vpub_old=%s, vpub_new=%s, in[0]=%s, in[1]=%s, out[0]=%s, out[1]=%s)\n", getId(), - tx_.vjoinsplit.size(), + tx_.vJoinSplit.size(), FormatMoney(info.vpub_old), FormatMoney(info.vpub_new), FormatMoney(info.vjsin[0].note.value()), FormatMoney(info.vjsin[1].note.value()), FormatMoney(info.vjsout[0].value), FormatMoney(info.vjsout[1].value)); @@ -910,7 +910,7 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit( } } - mtx.vjoinsplit.push_back(jsdesc); + mtx.vJoinSplit.push_back(jsdesc); // Empty output script. CScript scriptCode; @@ -973,7 +973,7 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit( memcpy(&buffer[0], &joinSplitPrivKey_[0], 32); // private key in first half of 64 byte buffer std::vector vch(&buffer[0], &buffer[0] + 32); uint256 joinSplitPrivKey = uint256(vch); - size_t js_index = tx_.vjoinsplit.size() - 1; + size_t js_index = tx_.vJoinSplit.size() - 1; uint256 placeholder; for (int i = 0; i < ZC_NUM_JS_OUTPUTS; i++) { uint8_t mapped_index = outputMap[i]; diff --git a/src/wallet/asyncrpcoperation_saplingmigration.cpp b/src/wallet/asyncrpcoperation_saplingmigration.cpp index d99bc539fe0..7b28295bd9e 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.cpp +++ b/src/wallet/asyncrpcoperation_saplingmigration.cpp @@ -116,7 +116,7 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { availableFunds -= fromNoteAmount; for (const SproutNoteEntry& sproutEntry : fromNotes) { std::string data(sproutEntry.memo.begin(), sproutEntry.memo.end()); - LogPrint("zrpcunsafe", "%s: Adding Sprout note input (txid=%s, vjoinsplit=%d, jsoutindex=%d, amount=%s, memo=%s)\n", + LogPrint("zrpcunsafe", "%s: Adding Sprout note input (txid=%s, vJoinSplit=%d, jsoutindex=%d, amount=%s, memo=%s)\n", getId(), sproutEntry.jsop.hash.ToString().substr(0, 10), sproutEntry.jsop.js, diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index 9538a2736e6..7e0a9dd50ce 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -674,12 +674,12 @@ bool AsyncRPCOperation_sendmany::main_impl() { JSDescription prevJoinSplit; // Keep track of previous JoinSplit and its commitments - if (tx_.vjoinsplit.size() > 0) { - prevJoinSplit = tx_.vjoinsplit.back(); + if (tx_.vJoinSplit.size() > 0) { + prevJoinSplit = tx_.vJoinSplit.back(); } // If there is no change, the chain has terminated so we can reset the tracked treestate. - if (jsChange==0 && tx_.vjoinsplit.size() > 0) { + if (jsChange==0 && tx_.vJoinSplit.size() > 0) { intermediates.clear(); previousCommitments.clear(); } @@ -784,7 +784,7 @@ bool AsyncRPCOperation_sendmany::main_impl() { wtxHeight = mapBlockIndex[wtx.hashBlock]->nHeight; wtxDepth = wtx.GetDepthInMainChain(); } - LogPrint("zrpcunsafe", "%s: spending note (txid=%s, vjoinsplit=%d, jsoutindex=%d, amount=%s, height=%d, confirmations=%d)\n", + LogPrint("zrpcunsafe", "%s: spending note (txid=%s, vJoinSplit=%d, jsoutindex=%d, amount=%s, height=%d, confirmations=%d)\n", getId(), jso.hash.ToString().substr(0, 10), jso.js, @@ -1048,7 +1048,7 @@ bool AsyncRPCOperation_sendmany::find_unspent_notes() { for (SproutNoteEntry & entry : sproutEntries) { z_sprout_inputs_.push_back(SendManyInputJSOP(entry.jsop, entry.note, CAmount(entry.note.value()))); std::string data(entry.memo.begin(), entry.memo.end()); - LogPrint("zrpcunsafe", "%s: found unspent Sprout note (txid=%s, vjoinsplit=%d, jsoutindex=%d, amount=%s, memo=%s)\n", + LogPrint("zrpcunsafe", "%s: found unspent Sprout note (txid=%s, vJoinSplit=%d, jsoutindex=%d, amount=%s, memo=%s)\n", getId(), entry.jsop.hash.ToString().substr(0, 10), entry.jsop.js, @@ -1144,7 +1144,7 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit( LogPrint("zrpcunsafe", "%s: creating joinsplit at index %d (vpub_old=%s, vpub_new=%s, in[0]=%s, in[1]=%s, out[0]=%s, out[1]=%s)\n", getId(), - tx_.vjoinsplit.size(), + tx_.vJoinSplit.size(), FormatMoney(info.vpub_old), FormatMoney(info.vpub_new), FormatMoney(info.vjsin[0].note.value()), FormatMoney(info.vjsin[1].note.value()), FormatMoney(info.vjsout[0].value), FormatMoney(info.vjsout[1].value) @@ -1180,7 +1180,7 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit( } } - mtx.vjoinsplit.push_back(jsdesc); + mtx.vJoinSplit.push_back(jsdesc); // Empty output script. CScript scriptCode; @@ -1247,7 +1247,7 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit( memcpy(&buffer[0], &joinSplitPrivKey_[0], 32); // private key in first half of 64 byte buffer std::vector vch(&buffer[0], &buffer[0] + 32); uint256 joinSplitPrivKey = uint256(vch); - size_t js_index = tx_.vjoinsplit.size() - 1; + size_t js_index = tx_.vJoinSplit.size() - 1; uint256 placeholder; for (int i = 0; i < ZC_NUM_JS_OUTPUTS; i++) { uint8_t mapped_index = outputMap[i]; diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp index 84811c6868e..0b2f0174b12 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp @@ -61,7 +61,7 @@ AsyncRPCOperation_shieldcoinbase::AsyncRPCOperation_shieldcoinbase( UniValue contextInfo) : builder_(builder), tx_(contextualTx), inputs_(inputs), fee_(fee), contextinfo_(contextInfo) { - assert(contextualTx.nVersion >= 2); // transaction format version must support vjoinsplit + assert(contextualTx.nVersion >= 2); // transaction format version must support vJoinSplit if (fee < 0 || fee > MAX_MONEY) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Fee is out of range"); @@ -392,7 +392,7 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf LogPrint("zrpcunsafe", "%s: creating joinsplit at index %d (vpub_old=%s, vpub_new=%s, in[0]=%s, in[1]=%s, out[0]=%s, out[1]=%s)\n", getId(), - tx_.vjoinsplit.size(), + tx_.vJoinSplit.size(), FormatMoney(info.vpub_old), FormatMoney(info.vpub_new), FormatMoney(info.vjsin[0].note.value()), FormatMoney(info.vjsin[1].note.value()), FormatMoney(info.vjsout[0].value), FormatMoney(info.vjsout[1].value) @@ -428,7 +428,7 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf } } - mtx.vjoinsplit.push_back(jsdesc); + mtx.vJoinSplit.push_back(jsdesc); // Empty output script. CScript scriptCode; @@ -494,7 +494,7 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf memcpy(&buffer[0], &joinSplitPrivKey_[0], 32); // private key in first half of 64 byte buffer std::vector vch(&buffer[0], &buffer[0] + 32); uint256 joinSplitPrivKey = uint256(vch); - size_t js_index = tx_.vjoinsplit.size() - 1; + size_t js_index = tx_.vJoinSplit.size() - 1; uint256 placeholder; for (int i = 0; i < ZC_NUM_JS_OUTPUTS; i++) { uint8_t mapped_index = outputMap[i]; diff --git a/src/wallet/gtest/test_wallet.cpp b/src/wallet/gtest/test_wallet.cpp index 029753a9483..df95a676c75 100644 --- a/src/wallet/gtest/test_wallet.cpp +++ b/src/wallet/gtest/test_wallet.cpp @@ -451,11 +451,11 @@ TEST(WalletTests, CheckSproutNoteCommitmentAgainstNotePlaintext) { auto note = GetSproutNote(sk, wtx, 0, 1); auto nullifier = note.nullifier(sk); - auto hSig = wtx.vjoinsplit[0].h_sig( + auto hSig = wtx.vJoinSplit[0].h_sig( *params, wtx.joinSplitPubKey); ASSERT_THROW(wallet.GetSproutNoteNullifier( - wtx.vjoinsplit[0], + wtx.vJoinSplit[0], address, dec, hSig, 1), libzcash::note_decryption_failed); @@ -472,11 +472,11 @@ TEST(WalletTests, GetSproutNoteNullifier) { auto note = GetSproutNote(sk, wtx, 0, 1); auto nullifier = note.nullifier(sk); - auto hSig = wtx.vjoinsplit[0].h_sig( + auto hSig = wtx.vJoinSplit[0].h_sig( *params, wtx.joinSplitPubKey); auto ret = wallet.GetSproutNoteNullifier( - wtx.vjoinsplit[0], + wtx.vJoinSplit[0], address, dec, hSig, 1); @@ -485,7 +485,7 @@ TEST(WalletTests, GetSproutNoteNullifier) { wallet.AddSproutSpendingKey(sk); ret = wallet.GetSproutNoteNullifier( - wtx.vjoinsplit[0], + wtx.vJoinSplit[0], address, dec, hSig, 1); @@ -1072,7 +1072,7 @@ TEST(WalletTests, SpentSaplingNoteIsFromMe) { auto tx2 = builder2.Build().GetTxOrThrow(); EXPECT_EQ(tx2.vin.size(), 0); EXPECT_EQ(tx2.vout.size(), 0); - EXPECT_EQ(tx2.vjoinsplit.size(), 0); + EXPECT_EQ(tx2.vJoinSplit.size(), 0); EXPECT_EQ(tx2.vShieldedSpend.size(), 1); EXPECT_EQ(tx2.vShieldedOutput.size(), 2); EXPECT_EQ(tx2.valueBalance, 10000); @@ -1919,7 +1919,7 @@ TEST(WalletTests, MarkAffectedSaplingTransactionsDirty) { EXPECT_EQ(tx1.vin.size(), 1); EXPECT_EQ(tx1.vout.size(), 0); - EXPECT_EQ(tx1.vjoinsplit.size(), 0); + EXPECT_EQ(tx1.vJoinSplit.size(), 0); EXPECT_EQ(tx1.vShieldedSpend.size(), 0); EXPECT_EQ(tx1.vShieldedOutput.size(), 1); EXPECT_EQ(tx1.valueBalance, -40000); @@ -1974,7 +1974,7 @@ TEST(WalletTests, MarkAffectedSaplingTransactionsDirty) { EXPECT_EQ(tx2.vin.size(), 0); EXPECT_EQ(tx2.vout.size(), 0); - EXPECT_EQ(tx2.vjoinsplit.size(), 0); + EXPECT_EQ(tx2.vJoinSplit.size(), 0); EXPECT_EQ(tx2.vShieldedSpend.size(), 1); EXPECT_EQ(tx2.vShieldedOutput.size(), 2); EXPECT_EQ(tx2.valueBalance, 10000); diff --git a/src/wallet/paymentdisclosure.h b/src/wallet/paymentdisclosure.h index 28a1d4cdc87..0014240d240 100644 --- a/src/wallet/paymentdisclosure.h +++ b/src/wallet/paymentdisclosure.h @@ -74,7 +74,7 @@ struct PaymentDisclosurePayload { uint8_t version; // 0 = experimental, 1 = first production version, etc. uint256 esk; // zcash/NoteEncryption.cpp uint256 txid; // primitives/transaction.h - uint64_t js; // Index into CTransaction.vjoinsplit + uint64_t js; // Index into CTransaction.vJoinSplit uint8_t n; // Index into JSDescription fields of length ZC_NUM_JS_OUTPUTS libzcash::SproutPaymentAddress zaddr; // zcash/Address.hpp std::string message; // parameter to RPC call diff --git a/src/wallet/rpcdisclosure.cpp b/src/wallet/rpcdisclosure.cpp index 82d20b76ce2..b57f4a0ddd8 100644 --- a/src/wallet/rpcdisclosure.cpp +++ b/src/wallet/rpcdisclosure.cpp @@ -98,13 +98,13 @@ UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp) const CWalletTx& wtx = pwalletMain->mapWallet[hash]; // Check if shielded tx - if (wtx.vjoinsplit.empty()) { + if (wtx.vJoinSplit.empty()) { throw JSONRPCError(RPC_MISC_ERROR, "Transaction is not a shielded transaction"); } // Check js_index int js_index = params[1].get_int(); - if (js_index < 0 || js_index >= wtx.vjoinsplit.size()) { + if (js_index < 0 || js_index >= wtx.vJoinSplit.size()) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid js_index"); } @@ -220,7 +220,7 @@ UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp) } // Check if shielded tx - if (tx.vjoinsplit.empty()) { + if (tx.vJoinSplit.empty()) { throw JSONRPCError(RPC_MISC_ERROR, "Transaction is not a shielded transaction"); } @@ -229,7 +229,7 @@ UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp) o.push_back(Pair("txid", pd.payload.txid.ToString())); // Check js_index - if (pd.payload.js >= tx.vjoinsplit.size()) { + if (pd.payload.js >= tx.vJoinSplit.size()) { errs.push_back("Payment disclosure refers to an invalid joinsplit index"); } o.push_back(Pair("jsIndex", pd.payload.js)); @@ -260,7 +260,7 @@ UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp) try { // Decrypt the note to get value and memo field - JSDescription jsdesc = tx.vjoinsplit[pd.payload.js]; + JSDescription jsdesc = tx.vJoinSplit[pd.payload.js]; uint256 h_sig = jsdesc.h_sig(*pzcashParams, tx.joinSplitPubKey); ZCPaymentDisclosureNoteDecryption decrypter; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 309446dc38d..5e07e85882d 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3063,7 +3063,7 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp) assert(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey)); } - mtx.vjoinsplit.push_back(jsdesc); + mtx.vJoinSplit.push_back(jsdesc); // Empty output script. CScript scriptCode; @@ -3828,7 +3828,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) if (mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION)) { jsdesc.proof = GrothProof(); } - mtx.vjoinsplit.push_back(jsdesc); + mtx.vJoinSplit.push_back(jsdesc); } } CTransaction tx(mtx); @@ -3896,7 +3896,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextBlockHeight); bool isShielded = !fromTaddr || zaddrRecipients.size() > 0; if (contextualTx.nVersion == 1 && isShielded) { - contextualTx.nVersion = 2; // Tx format should support vjoinsplits + contextualTx.nVersion = 2; // Tx format should support vJoinSplits } // Create operation and add to global queue @@ -3990,9 +3990,9 @@ UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) { // * one or more Sprout JoinSplits with nonzero vpub_new field; and // * no Sapling Spends, and; // * one or more Sapling Outputs. - if (tx.vjoinsplit.size() > 0 && tx.vShieldedSpend.empty() && tx.vShieldedOutput.size() > 0) { + if (tx.vJoinSplit.size() > 0 && tx.vShieldedSpend.empty() && tx.vShieldedOutput.size() > 0) { bool nonZeroVPubNew = false; - for (const auto& js : tx.vjoinsplit) { + for (const auto& js : tx.vJoinSplit) { if (js.vpub_new > 0) { nonZeroVPubNew = true; break; @@ -4235,7 +4235,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp) CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction( Params().GetConsensus(), nextBlockHeight); if (contextualTx.nVersion == 1) { - contextualTx.nVersion = 2; // Tx format should support vjoinsplits + contextualTx.nVersion = 2; // Tx format should support vJoinSplit } // Create operation and add to global queue @@ -4648,7 +4648,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) nextBlockHeight); bool isSproutShielded = sproutNoteInputs.size() > 0 || isToSproutZaddr; if (contextualTx.nVersion == 1 && isSproutShielded) { - contextualTx.nVersion = 2; // Tx format should support vjoinsplit + contextualTx.nVersion = 2; // Tx format should support vJoinSplit } // Builder (used if Sapling addresses are involved) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 7fc5f8f1f37..480547d9577 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -705,7 +705,7 @@ bool CWallet::IsNoteSproutChange( // - Notes created by consolidation transactions (e.g. using // z_mergetoaddress). // - Notes sent from one address to itself. - for (const JSDescription & jsd : mapWallet[jsop.hash].vjoinsplit) { + for (const JSDescription & jsd : mapWallet[jsop.hash].vJoinSplit) { for (const uint256 & nullifier : jsd.nullifiers) { if (nullifierSet.count(std::make_pair(address, nullifier))) { return true; @@ -797,7 +797,7 @@ set CWallet::GetConflicts(const uint256& txid) const std::pair range_n; - for (const JSDescription& jsdesc : wtx.vjoinsplit) { + for (const JSDescription& jsdesc : wtx.vJoinSplit) { for (const uint256& nullifier : jsdesc.nullifiers) { if (mapTxSproutNullifiers.count(nullifier) <= 1) { continue; // No conflict if zero or one spends @@ -1004,7 +1004,7 @@ void CWallet::AddToSpends(const uint256& wtxid) for (const CTxIn& txin : thisTx.vin) { AddToTransparentSpends(txin.prevout, wtxid); } - for (const JSDescription& jsdesc : thisTx.vjoinsplit) { + for (const JSDescription& jsdesc : thisTx.vJoinSplit) { for (const uint256& nullifier : jsdesc.nullifiers) { AddToSproutSpends(nullifier, wtxid); } @@ -1142,8 +1142,8 @@ void CWallet::IncrementNoteWitnesses(const CBlockIndex* pindex, auto hash = tx.GetHash(); bool txIsOurs = mapWallet.count(hash); // Sprout - for (size_t i = 0; i < tx.vjoinsplit.size(); i++) { - const JSDescription& jsdesc = tx.vjoinsplit[i]; + for (size_t i = 0; i < tx.vJoinSplit.size(); i++) { + const JSDescription& jsdesc = tx.vJoinSplit[i]; for (uint8_t j = 0; j < jsdesc.commitments.size(); j++) { const uint256& note_commitment = jsdesc.commitments[j]; sproutTree.append(note_commitment); @@ -1400,10 +1400,10 @@ bool CWallet::UpdateNullifierNoteMap() if (!item.second.nullifier) { if (GetNoteDecryptor(item.second.address, dec)) { auto i = item.first.js; - auto hSig = wtxItem.second.vjoinsplit[i].h_sig( + auto hSig = wtxItem.second.vJoinSplit[i].h_sig( *pzcashParams, wtxItem.second.joinSplitPubKey); item.second.nullifier = GetSproutNoteNullifier( - wtxItem.second.vjoinsplit[i], + wtxItem.second.vJoinSplit[i], item.second.address, dec, hSig, @@ -1729,7 +1729,7 @@ void CWallet::MarkAffectedTransactionsDirty(const CTransaction& tx) if (mapWallet.count(txin.prevout.hash)) mapWallet[txin.prevout.hash].MarkDirty(); } - for (const JSDescription& jsdesc : tx.vjoinsplit) { + for (const JSDescription& jsdesc : tx.vJoinSplit) { for (const uint256& nullifier : jsdesc.nullifiers) { if (mapSproutNullifiersToNotes.count(nullifier) && mapWallet.count(mapSproutNullifiersToNotes[nullifier].hash)) { @@ -1808,15 +1808,15 @@ mapSproutNoteData_t CWallet::FindMySproutNotes(const CTransaction &tx) const uint256 hash = tx.GetHash(); mapSproutNoteData_t noteData; - for (size_t i = 0; i < tx.vjoinsplit.size(); i++) { - auto hSig = tx.vjoinsplit[i].h_sig(*pzcashParams, tx.joinSplitPubKey); - for (uint8_t j = 0; j < tx.vjoinsplit[i].ciphertexts.size(); j++) { + for (size_t i = 0; i < tx.vJoinSplit.size(); i++) { + auto hSig = tx.vJoinSplit[i].h_sig(*pzcashParams, tx.joinSplitPubKey); + for (uint8_t j = 0; j < tx.vJoinSplit[i].ciphertexts.size(); j++) { for (const NoteDecryptorMap::value_type& item : mapNoteDecryptors) { try { auto address = item.first; JSOutPoint jsoutpt {hash, i, j}; auto nullifier = GetSproutNoteNullifier( - tx.vjoinsplit[i], + tx.vJoinSplit[i], address, item.second, hSig, j); @@ -2047,7 +2047,7 @@ bool CWallet::IsFromMe(const CTransaction& tx) const if (GetDebit(tx, ISMINE_ALL) > 0) { return true; } - for (const JSDescription& jsdesc : tx.vjoinsplit) { + for (const JSDescription& jsdesc : tx.vJoinSplit) { for (const uint256& nullifier : jsdesc.nullifiers) { if (IsSproutNullifierFromMe(nullifier)) { return true; @@ -2196,8 +2196,8 @@ void CWalletTx::SetSproutNoteData(mapSproutNoteData_t ¬eData) { mapSproutNoteData.clear(); for (const std::pair nd : noteData) { - if (nd.first.js < vjoinsplit.size() && - nd.first.n < vjoinsplit[nd.first.js].ciphertexts.size()) { + if (nd.first.js < vJoinSplit.size() && + nd.first.n < vJoinSplit[nd.first.js].ciphertexts.size()) { // Store the address and nullifier for the Note mapSproutNoteData[nd.first] = nd.second; } else { @@ -2289,7 +2289,7 @@ void CWalletTx::GetAmounts(list& listReceived, if (isFromMyTaddr) { CAmount myVpubOld = 0; CAmount myVpubNew = 0; - for (const JSDescription& js : vjoinsplit) { + for (const JSDescription& js : vJoinSplit) { bool fMyJSDesc = false; // Check input side @@ -2303,7 +2303,7 @@ void CWalletTx::GetAmounts(list& listReceived, // Check output side if (!fMyJSDesc) { for (const std::pair nd : this->mapSproutNoteData) { - if (nd.first.js < vjoinsplit.size() && nd.first.n < vjoinsplit[nd.first.js].ciphertexts.size()) { + if (nd.first.js < vJoinSplit.size() && nd.first.n < vJoinSplit[nd.first.js].ciphertexts.size()) { fMyJSDesc = true; break; } @@ -2436,7 +2436,7 @@ void CWallet::WitnessNoteCommitment(std::vector commitments, BOOST_FOREACH(const CTransaction& tx, block.vtx) { - BOOST_FOREACH(const JSDescription& jsdesc, tx.vjoinsplit) + BOOST_FOREACH(const JSDescription& jsdesc, tx.vJoinSplit) { BOOST_FOREACH(const uint256 ¬e_commitment, jsdesc.commitments) { @@ -4552,7 +4552,7 @@ void CWallet::GetFilteredNotes( continue; } - int i = jsop.js; // Index into CTransaction.vjoinsplit + int i = jsop.js; // Index into CTransaction.vJoinSplit int j = jsop.n; // Index into JSDescription.ciphertexts // Get cached decryptor @@ -4563,12 +4563,12 @@ void CWallet::GetFilteredNotes( } // determine amount of funds in the note - auto hSig = wtx.vjoinsplit[i].h_sig(*pzcashParams, wtx.joinSplitPubKey); + auto hSig = wtx.vJoinSplit[i].h_sig(*pzcashParams, wtx.joinSplitPubKey); try { SproutNotePlaintext plaintext = SproutNotePlaintext::decrypt( decryptor, - wtx.vjoinsplit[i].ciphertexts[j], - wtx.vjoinsplit[i].ephemeralKey, + wtx.vJoinSplit[i].ciphertexts[j], + wtx.vJoinSplit[i].ephemeralKey, hSig, (unsigned char) j); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 39c473a2f46..e5533dc108e 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -167,7 +167,7 @@ class JSOutPoint public: // Transaction hash uint256 hash; - // Index into CTransaction.vjoinsplit + // Index into CTransaction.vJoinSplit uint64_t js; // Index into JSDescription fields of length ZC_NUM_JS_OUTPUTS uint8_t n; From ff1840f68a474e2f70cf99e6e1862f2ce3174817 Mon Sep 17 00:00:00 2001 From: Dimitris Apostolou Date: Sun, 16 Jun 2019 22:37:23 +0300 Subject: [PATCH 142/395] Fix naming inconsistency --- src/wallet/rpcwallet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 309446dc38d..3f7f35ccb53 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3475,8 +3475,8 @@ UniValue z_gettotalbalance(const UniValue& params, bool fHelp) "\nResult:\n" "{\n" " \"transparent\": xxxxx, (numeric) the total balance of transparent funds\n" - " \"private\": xxxxx, (numeric) the total balance of private funds (in both Sprout and Sapling addresses)\n" - " \"total\": xxxxx, (numeric) the total balance of both transparent and private funds\n" + " \"private\": xxxxx, (numeric) the total balance of shielded funds (in both Sprout and Sapling addresses)\n" + " \"total\": xxxxx, (numeric) the total balance of both transparent and shielded funds\n" "}\n" "\nExamples:\n" "\nThe total amount in the wallet\n" From 8bcb96999ea21bdbbdb815998117baa73cf175c0 Mon Sep 17 00:00:00 2001 From: Dimitris Apostolou Date: Sun, 16 Jun 2019 22:50:58 +0300 Subject: [PATCH 143/395] Rename joinsplit to shielded --- src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index f407d81a4ee..90009d0d3b6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1475,8 +1475,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // are the joinsplits' and sapling spends' requirements met in tx(valid anchors/nullifiers)? if (!view.HaveShieldedRequirements(tx)) - return state.Invalid(error("AcceptToMemoryPool: joinsplit requirements not met"), - REJECT_DUPLICATE, "bad-txns-joinsplit-requirements-not-met"); + return state.Invalid(error("AcceptToMemoryPool: shielded requirements not met"), + REJECT_DUPLICATE, "bad-txns-shielded-requirements-not-met"); // Bring the best block into scope view.GetBestBlock(); From 8b1a8e8b9324b7427cdf2fd93ebbe410d216ecbe Mon Sep 17 00:00:00 2001 From: Dimitris Apostolou Date: Sun, 16 Jun 2019 23:06:45 +0300 Subject: [PATCH 144/395] Rename FindWalletTx to FindWalletTxToZap --- src/wallet/walletdb.cpp | 4 ++-- src/wallet/walletdb.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 1081e9d09f8..e34285f18ec 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -971,7 +971,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) return result; } -DBErrors CWalletDB::FindWalletTx(CWallet* pwallet, vector& vTxHash, vector& vWtx) +DBErrors CWalletDB::FindWalletTxToZap(CWallet* pwallet, vector& vTxHash, vector& vWtx) { pwallet->vchDefaultKey = CPubKey(); bool fNoncriticalErrors = false; @@ -1050,7 +1050,7 @@ DBErrors CWalletDB::ZapWalletTx(CWallet* pwallet, vector& vWtx) { // build list of wallet TXs vector vTxHash; - DBErrors err = FindWalletTx(pwallet, vTxHash, vWtx); + DBErrors err = FindWalletTxToZap(pwallet, vTxHash, vWtx); if (err != DB_LOAD_OK) return err; diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index b3210bbc0ca..7f84366a098 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -172,7 +172,7 @@ class CWalletDB : public CDB DBErrors ReorderTransactions(CWallet* pwallet); DBErrors LoadWallet(CWallet* pwallet); - DBErrors FindWalletTx(CWallet* pwallet, std::vector& vTxHash, std::vector& vWtx); + DBErrors FindWalletTxToZap(CWallet* pwallet, std::vector& vTxHash, std::vector& vWtx); DBErrors ZapWalletTx(CWallet* pwallet, std::vector& vWtx); static bool Recover(CDBEnv& dbenv, const std::string& filename, bool fOnlyKeys); static bool Recover(CDBEnv& dbenv, const std::string& filename); From 3b4bc96bac59aa74aaa9cbde892812b41d319865 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 17 Jun 2019 13:12:11 -0600 Subject: [PATCH 145/395] Notable changes for 2.0.6 Co-authored-by: Daira Hopwood --- doc/release-notes.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index a29094b5174..ff7355d93dd 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,3 +4,24 @@ release-notes at release time) Notable changes =============== +Debian Stretch is now a Supported Platform +------------------------------------------ + +We now provide reproducible builds for Stretch as well as for Jessie. + + +Fixed a bug in ``z_mergetoaddress`` +----------------------------------- + +We fixed a bug which prevented users sending from ``ANY_SPROUT`` or ``ANY_SAPLING`` +with ``z_mergetoaddress`` when a wallet contained both Sprout and Sapling notes. + + +Insight Explorer +---------------- + +We have been incorporating changes to support the Insight explorer directly from +``zcashd``. v2.0.6 includes the first change to an RPC method. If ``zcashd`` is +run with the flag ``--insightexplorer``` (this requires an index rebuild), the +RPC method ``getrawtransaction`` will now return additional information about +spend indices. From dbe49614c152801358f6208b90e0a524ca374ee1 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Tue, 18 Jun 2019 14:00:56 +0100 Subject: [PATCH 146/395] Tweak author aliases. Signed-off-by: Daira Hopwood --- zcutil/release-notes.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zcutil/release-notes.py b/zcutil/release-notes.py index 4446e988f2d..0f9974e8ff3 100755 --- a/zcutil/release-notes.py +++ b/zcutil/release-notes.py @@ -27,8 +27,9 @@ 'Duke Leto': 'Jonathan \"Duke\" Leto', 'Eirik0': 'Eirik Ogilvie-Wigley', 'EthanHeilman': 'Ethan Heilman', + 'MarcoFalke': 'Marco Falke', 'mdr0id': 'Marshall Gaucher', - 'paveljanik': 'Pavel Janik', + 'paveljanik': 'Pavel Janík', 'Simon': 'Simon Liu', 'str4d': 'Jack Grigg', 'zebambam': 'Benjamin Winston' From f6e1e1577362fec98ed8745cb6511c917403abba Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Wed, 19 Jun 2019 00:19:54 +0100 Subject: [PATCH 147/395] Add coding declaration to zcutil/release-notes.py Signed-off-by: Daira Hopwood --- zcutil/release-notes.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zcutil/release-notes.py b/zcutil/release-notes.py index 0f9974e8ff3..b1a262232e1 100755 --- a/zcutil/release-notes.py +++ b/zcutil/release-notes.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + import re, os, os.path import subprocess import argparse From ef2dcbf1d48faa57ffa238ae544c9848082f7733 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Wed, 19 Jun 2019 00:27:11 +0100 Subject: [PATCH 148/395] make-release.py: Versioning changes for 2.0.6. --- README.md | 2 +- configure.ac | 2 +- contrib/gitian-descriptors/gitian-linux.yml | 2 +- src/clientversion.h | 2 +- src/deprecation.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 92c99d49848..4f7931cd958 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Zcash 2.0.6-rc1 +Zcash 2.0.6 =========== diff --git a/configure.ac b/configure.ac index bcbe56f9ec3..05b4667e822 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 2) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_REVISION, 6) -define(_CLIENT_VERSION_BUILD, 25) +define(_CLIENT_VERSION_BUILD, 50) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 0e9d9d81f18..d770c29fc31 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "zcash-2.0.6-rc1" +name: "zcash-2.0.6" enable_cache: true distro: "debian" suites: diff --git a/src/clientversion.h b/src/clientversion.h index 5f8b9687026..259d6d4b3e5 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -18,7 +18,7 @@ #define CLIENT_VERSION_MAJOR 2 #define CLIENT_VERSION_MINOR 0 #define CLIENT_VERSION_REVISION 6 -#define CLIENT_VERSION_BUILD 25 +#define CLIENT_VERSION_BUILD 50 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/deprecation.h b/src/deprecation.h index f581b07e5e1..96ccd2ed717 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -8,7 +8,7 @@ // Deprecation policy: // * Shut down 16 weeks' worth of blocks after the estimated release block height. // * A warning is shown during the 2 weeks' worth of blocks prior to shut down. -static const int APPROX_RELEASE_HEIGHT = 549200; +static const int APPROX_RELEASE_HEIGHT = 553000; static const int WEEKS_UNTIL_DEPRECATION = 16; static const int DEPRECATION_HEIGHT = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 24); From a83969f6ce11932a3af483ec9f872f5248119853 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Wed, 19 Jun 2019 00:28:06 +0100 Subject: [PATCH 149/395] make-release.py: Updated manpages for 2.0.6. --- doc/man/zcash-cli.1 | 6 +++--- doc/man/zcash-tx.1 | 6 +++--- doc/man/zcashd.1 | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/man/zcash-cli.1 b/doc/man/zcash-cli.1 index 1abd7712599..741de3dba72 100644 --- a/doc/man/zcash-cli.1 +++ b/doc/man/zcash-cli.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4. -.TH ZCASH-CLI "1" "June 2019" "zcash-cli v2.0.6-rc1" "User Commands" +.TH ZCASH-CLI "1" "June 2019" "zcash-cli v2.0.6" "User Commands" .SH NAME -zcash-cli \- manual page for zcash-cli v2.0.6-rc1 +zcash-cli \- manual page for zcash-cli v2.0.6 .SH DESCRIPTION -Zcash RPC client version v2.0.6\-rc1 +Zcash RPC client version v2.0.6 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . diff --git a/doc/man/zcash-tx.1 b/doc/man/zcash-tx.1 index 3e3c8b2bd13..1353e34a7f4 100644 --- a/doc/man/zcash-tx.1 +++ b/doc/man/zcash-tx.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4. -.TH ZCASH-TX "1" "June 2019" "zcash-tx v2.0.6-rc1" "User Commands" +.TH ZCASH-TX "1" "June 2019" "zcash-tx v2.0.6" "User Commands" .SH NAME -zcash-tx \- manual page for zcash-tx v2.0.6-rc1 +zcash-tx \- manual page for zcash-tx v2.0.6 .SH DESCRIPTION -Zcash zcash\-tx utility version v2.0.6\-rc1 +Zcash zcash\-tx utility version v2.0.6 .SS "Usage:" .TP zcash\-tx [options] [commands] diff --git a/doc/man/zcashd.1 b/doc/man/zcashd.1 index 2af9ed904a9..491550c9768 100644 --- a/doc/man/zcashd.1 +++ b/doc/man/zcashd.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4. -.TH ZCASHD "1" "June 2019" "zcashd v2.0.6-rc1" "User Commands" +.TH ZCASHD "1" "June 2019" "zcashd v2.0.6" "User Commands" .SH NAME -zcashd \- manual page for zcashd v2.0.6-rc1 +zcashd \- manual page for zcashd v2.0.6 .SH DESCRIPTION -Zcash Daemon version v2.0.6\-rc1 +Zcash Daemon version v2.0.6 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . From f2df508591d1d6309975e23eeb0c7fbd57d98543 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Wed, 19 Jun 2019 00:28:06 +0100 Subject: [PATCH 150/395] make-release.py: Updated release notes and changelog for 2.0.6. --- contrib/debian/changelog | 6 ++ doc/authors.md | 30 +++---- doc/release-notes.md | 21 ----- doc/release-notes/release-notes-2.0.6.md | 102 +++++++++++++++++++++++ 4 files changed, 123 insertions(+), 36 deletions(-) create mode 100644 doc/release-notes/release-notes-2.0.6.md diff --git a/contrib/debian/changelog b/contrib/debian/changelog index af3c93a95d4..ed12564cf6c 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,9 @@ +zcash (2.0.6) stable; urgency=medium + + * 2.0.6 release. + + -- Electric Coin Company Wed, 19 Jun 2019 00:28:06 +0100 + zcash (2.0.6~rc1) stable; urgency=medium * 2.0.6-rc1 release. diff --git a/doc/authors.md b/doc/authors.md index 9bcdb5ef140..6afdb557cdf 100644 --- a/doc/authors.md +++ b/doc/authors.md @@ -1,27 +1,28 @@ Zcash Contributors ================== -Jack Grigg (863) -Simon Liu (450) +Jack Grigg (873) +Simon Liu (451) Sean Bowe (278) -Eirik Ogilvie-Wigley (145) -Daira Hopwood (115) +Eirik Ogilvie-Wigley (152) +Daira Hopwood (124) Jay Graber (89) -Wladimir J. van der Laan (81) +Wladimir J. van der Laan (82) Taylor Hornby (73) Jonas Schnelli (62) Nathan Wilcox (56) Pieter Wuille (54) Kevin Gallagher (38) Cory Fields (35) +Larry Ruane (23) Marshall Gaucher (22) -Larry Ruane (22) Jonathan "Duke" Leto (17) syd (15) Matt Corallo (13) Paige Peterson (11) +Marco Falke (11) Ariel Gabizon (11) -MarcoFalke (10) +Jorge Timón (10) nomnombtc (9) kozyilmaz (8) fanquake (8) @@ -31,20 +32,21 @@ Marius Kjærstad (6) Luke Dashjr (6) David Mercer (6) Daniel Cousens (6) +Charlie O'Keefe (6) Suhas Daftuar (5) -Pavel Janík (5) +Peter Todd (5) Karl-Johan Alm (5) Johnathan Corgan (5) -Charlie O'Keefe (5) Alex Morcos (5) WO (4) Philip Kaufmann (4) -Peter Todd (4) +Pavel Janík (4) Patrick Strateman (4) João Barbosa (4) -Jorge Timón (4) George Tankersley (4) Gareth Davies (4) +Daniel Kraft (4) +Benjamin Winston (4) lpescher (3) ca333 (3) Per Grön (3) @@ -52,12 +54,11 @@ Patick Strateman (3) Jason Davies (3) James O'Beirne (3) Dimitris Apostolou (3) -Daniel Kraft (3) -Benjamin Winston (3) Alfie John (3) rofl0r (2) mruddy (2) kpcyrd (2) +face (2) aniemerg (2) UdjinM6 (2) Scott (2) @@ -65,8 +66,8 @@ Robert C. Seacord (2) Pejvan (2) Pavol Rusnak (2) Pavel Vasin (2) -Pavel Janik (2) Matthew King (2) +Mary Moore-Simmons (2) Kaz Wesley (2) Joe Turgeon (2) Jack Gavigan (2) @@ -109,7 +110,6 @@ Nathaniel Mahieu (1) Murilo Santana (1) Maxwell Gubler (1) Matt Quinn (1) -Mary Moore-Simmons (1) Mark Friedenbach (1) Louis Nyffenegger (1) Leo Arias (1) diff --git a/doc/release-notes.md b/doc/release-notes.md index ff7355d93dd..a29094b5174 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,24 +4,3 @@ release-notes at release time) Notable changes =============== -Debian Stretch is now a Supported Platform ------------------------------------------- - -We now provide reproducible builds for Stretch as well as for Jessie. - - -Fixed a bug in ``z_mergetoaddress`` ------------------------------------ - -We fixed a bug which prevented users sending from ``ANY_SPROUT`` or ``ANY_SAPLING`` -with ``z_mergetoaddress`` when a wallet contained both Sprout and Sapling notes. - - -Insight Explorer ----------------- - -We have been incorporating changes to support the Insight explorer directly from -``zcashd``. v2.0.6 includes the first change to an RPC method. If ``zcashd`` is -run with the flag ``--insightexplorer``` (this requires an index rebuild), the -RPC method ``getrawtransaction`` will now return additional information about -spend indices. diff --git a/doc/release-notes/release-notes-2.0.6.md b/doc/release-notes/release-notes-2.0.6.md new file mode 100644 index 00000000000..f1beec5117e --- /dev/null +++ b/doc/release-notes/release-notes-2.0.6.md @@ -0,0 +1,102 @@ +Notable changes +=============== + +Debian Stretch is now a Supported Platform +------------------------------------------ + +We now provide reproducible builds for Stretch as well as for Jessie. + + +Fixed a bug in ``z_mergetoaddress`` +----------------------------------- + +We fixed a bug which prevented users sending from ``ANY_SPROUT`` or ``ANY_SAPLING`` +with ``z_mergetoaddress`` when a wallet contained both Sprout and Sapling notes. + + +Insight Explorer +---------------- + +We have been incorporating changes to support the Insight explorer directly from +``zcashd``. v2.0.6 includes the first change to an RPC method. If ``zcashd`` is +run with the flag ``--insightexplorer``` (this requires an index rebuild), the +RPC method ``getrawtransaction`` will now return additional information about +spend indices. + +Changelog +========= + +Charlie O'Keefe (1): + Add stretch to list of suites in gitian linux descriptors + +Daira Hopwood (9): + Closes #3992. Remove obsolete warning message. + make-release.py: Versioning changes for 2.0.6-rc1. + make-release.py: Updated manpages for 2.0.6-rc1. + make-release.py: Updated release notes and changelog for 2.0.6-rc1. + ld --version doesn't work on macOS. + Tweak author aliases. + Add coding declaration to zcutil/release-notes.py + make-release.py: Versioning changes for 2.0.6. + make-release.py: Updated manpages for 2.0.6. + +Daniel Kraft (1): + Add some const declarations where they are appropriate. + +Eirik Ogilvie-Wigley (1): + Notable changes for 2.0.6 + +Eirik Ogilvie-Wigley (7): + Fix tree depth in comment + Update author aliases + Remove old mergetoaddress RPC test + Replace CSproutNotePlaintextEntry with SproutNoteEntry to match Sapling + z_getmigrationstatus help message wording change + Fix z_mergetoaddress sending from ANY_SPROUT/ANY_SAPLING when the wallet contains both note types + Clarify what combinations of from addresses can be used in z_mergetoaddress + +Jack Grigg (10): + Move Equihash parameters into consensus params + Globals: Remove Zcash-specific Params() calls from main.cpp + Globals: Explicitly pass const CChainParams& to IsStandardTx() + Globals: Explicit const CChainParams& arg for main: + Globals: Explicitly pass const CChainParams& to ContextualCheckTransaction() + Globals: Explicit const CChainParams& arg for main: + Globals: Explicitly pass const CChainParams& to DisconnectBlock() + Consistently use chainparams and consensusParams + Globals: Explicitly pass const CChainParams& to IsInitialBlockDownload() + Globals: Explicitly pass const CChainParams& to ReceivedBlockTransactions() + +Jorge Timón (6): + Globals: Explicit Consensus::Params arg for main: + Globals: Make AcceptBlockHeader static (Fix #6163) + Chainparams: Explicit CChainParams arg for main (pre miner): + Chainparams: Explicit CChainParams arg for miner: + Globals: Remove a bunch of Params() calls from main.cpp: + Globals: Explicitly pass const CChainParams& to UpdateTip() + +Larry Ruane (1): + add spentindex to getrawtransaction RPC results + +Marco Falke (1): + [doc] Fix doxygen comments for members + +Mary Moore-Simmons (1): + Fixes issue #3504: Changes to --version and adds a couple other useful commands. + +Peter Todd (1): + Improve block validity/ConnectBlock() comments + +Simon Liu (1): + Fix typo and clean up help message for RPC z_getmigrationstatus. + +Wladimir J. van der Laan (1): + Break circular dependency main ↔ txdb + +face (2): + Pass CChainParams to DisconnectTip() + Explicitly pass CChainParams to ConnectBlock + +Benjamin Winston (1): + Fixes #4013, added BitcoinABC as a disclosure partner + From 8863d77d658ed6d8b7be09528a0ae4afd0070088 Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 19 May 2019 13:30:24 -0700 Subject: [PATCH 151/395] Redefine PoW functions to accept height parameter. Introduce target spacing constants and redefine struct member variable nPoWTargetSpacing as a member function. The height parameter is used to determine if Blossom has activated yet. --- src/consensus/params.h | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/src/consensus/params.h b/src/consensus/params.h index 9cd3a84617d..ad0b44e4c34 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -10,6 +10,14 @@ #include +// Forward declaration. Enum requires storage type. +namespace Consensus { + struct Params; + enum UpgradeIndex : uint32_t; +} +bool NetworkUpgradeActive(int nHeight, const Consensus::Params& params, Consensus::UpgradeIndex idx); + + namespace Consensus { /** @@ -20,7 +28,7 @@ namespace Consensus { * The order of these indices MUST match the order of the upgrades on-chain, as * several functions depend on the enum being sorted. */ -enum UpgradeIndex { +enum UpgradeIndex : uint32_t { // Sprout must be first BASE_SPROUT, UPGRADE_TESTDUMMY, @@ -61,6 +69,11 @@ struct NetworkUpgrade { static constexpr int NO_ACTIVATION_HEIGHT = -1; }; +/** ZIP208 block target interval in seconds. */ +static const unsigned int PRE_BLOSSOM_POW_TARGET_SPACING = 150; +static const unsigned int POST_BLOSSOM_POW_TARGET_SPACING = 75; +BOOST_STATIC_ASSERT(POST_BLOSSOM_POW_TARGET_SPACING < PRE_BLOSSOM_POW_TARGET_SPACING); + /** * Parameters that influence chain consensus. */ @@ -100,10 +113,26 @@ struct Params { int64_t nPowAveragingWindow; int64_t nPowMaxAdjustDown; int64_t nPowMaxAdjustUp; - int64_t nPowTargetSpacing; - int64_t AveragingWindowTimespan() const { return nPowAveragingWindow * nPowTargetSpacing; } - int64_t MinActualTimespan() const { return (AveragingWindowTimespan() * (100 - nPowMaxAdjustUp )) / 100; } - int64_t MaxActualTimespan() const { return (AveragingWindowTimespan() * (100 + nPowMaxAdjustDown)) / 100; } + int64_t nPreBlossomPowTargetSpacing; + int64_t nPostBlossomPowTargetSpacing; + + int64_t PoWTargetSpacing(int nHeight) const { + bool blossomActive = NetworkUpgradeActive(nHeight, *this, Consensus::UPGRADE_BLOSSOM); + return blossomActive ? nPostBlossomPowTargetSpacing : nPreBlossomPowTargetSpacing; + } + + int64_t AveragingWindowTimespan(int nHeight) const { + return nPowAveragingWindow * PoWTargetSpacing(nHeight); + } + + int64_t MinActualTimespan(int nHeight) const { + return (AveragingWindowTimespan(nHeight) * (100 - nPowMaxAdjustUp )) / 100; + } + + int64_t MaxActualTimespan(int nHeight) const { + return (AveragingWindowTimespan(nHeight) * (100 + nPowMaxAdjustDown)) / 100; + } + uint256 nMinimumChainWork; }; } // namespace Consensus From ac4a606d4a74161155f0f38028bd338ff3787a74 Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 19 May 2019 13:36:17 -0700 Subject: [PATCH 152/395] Remove use of redundant member nPowTargetSpacing. --- src/chainparams.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 0980d78121e..1f5760f2993 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -98,7 +98,8 @@ class CMainParams : public CChainParams { assert(maxUint/UintToArith256(consensus.powLimit) >= consensus.nPowAveragingWindow); consensus.nPowMaxAdjustDown = 32; // 32% adjustment down consensus.nPowMaxAdjustUp = 16; // 16% adjustment up - consensus.nPowTargetSpacing = 2.5 * 60; + consensus.nPreBlossomPowTargetSpacing = Consensus::PRE_BLOSSOM_POW_TARGET_SPACING; + consensus.nPostBlossomPowTargetSpacing = Consensus::POST_BLOSSOM_POW_TARGET_SPACING; consensus.nPowAllowMinDifficultyBlocksAfterHeight = boost::none; consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002; consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight = @@ -289,7 +290,8 @@ class CTestNetParams : public CChainParams { assert(maxUint/UintToArith256(consensus.powLimit) >= consensus.nPowAveragingWindow); consensus.nPowMaxAdjustDown = 32; // 32% adjustment down consensus.nPowMaxAdjustUp = 16; // 16% adjustment up - consensus.nPowTargetSpacing = 2.5 * 60; + consensus.nPreBlossomPowTargetSpacing = Consensus::PRE_BLOSSOM_POW_TARGET_SPACING; + consensus.nPostBlossomPowTargetSpacing = Consensus::POST_BLOSSOM_POW_TARGET_SPACING; consensus.nPowAllowMinDifficultyBlocksAfterHeight = 299187; consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002; consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight = @@ -421,7 +423,8 @@ class CRegTestParams : public CChainParams { assert(maxUint/UintToArith256(consensus.powLimit) >= consensus.nPowAveragingWindow); consensus.nPowMaxAdjustDown = 0; // Turn off adjustment down consensus.nPowMaxAdjustUp = 0; // Turn off adjustment up - consensus.nPowTargetSpacing = 2.5 * 60; + consensus.nPreBlossomPowTargetSpacing = Consensus::PRE_BLOSSOM_POW_TARGET_SPACING; + consensus.nPostBlossomPowTargetSpacing = Consensus::POST_BLOSSOM_POW_TARGET_SPACING; consensus.nPowAllowMinDifficultyBlocksAfterHeight = 0; consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002; consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight = From 35d1fdeba6311027c3e8767f427b07fd6aafdb9b Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 19 May 2019 13:39:42 -0700 Subject: [PATCH 153/395] Replace nPoWTargetSpacing -> PoWTargetSpacing() --- src/metrics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/metrics.cpp b/src/metrics.cpp index 9eecc22e5d0..a47f4538c80 100644 --- a/src/metrics.cpp +++ b/src/metrics.cpp @@ -135,7 +135,7 @@ int EstimateNetHeight(int height, int64_t tipmediantime, CChainParams chainParam Checkpoints::GetTotalBlocksEstimate(checkpointData), checkpointData.nTimeLastCheckpoint, chainParams.GenesisBlock().nTime, - chainParams.GetConsensus().nPowTargetSpacing); + chainParams.GetConsensus().PoWTargetSpacing(height)); } void TriggerRefresh() From b30ff0d36744777b1dd1440798306147bde869df Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 19 May 2019 13:54:43 -0700 Subject: [PATCH 154/395] Update PoW function calls to pass in height. --- src/pow.cpp | 28 ++++++++++++++++------------ src/pow.h | 3 ++- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/pow.cpp b/src/pow.cpp index ec0410acca2..3f0116d63dc 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -31,9 +31,9 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead pindexLast->nHeight >= params.nPowAllowMinDifficultyBlocksAfterHeight.get()) { // Special difficulty rule for testnet: - // If the new block's timestamp is more than 6 * 2.5 minutes + // If the new block's timestamp is more than 6 * block interval minutes // then allow mining of a min-difficulty block. - if (pblock && pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing * 6) + if (pblock && pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.PoWTargetSpacing(pindexLast->nHeight + 1) * 6) return nProofOfWorkLimit; } } @@ -54,29 +54,33 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead arith_uint256 bnAvg {bnTot / params.nPowAveragingWindow}; - return CalculateNextWorkRequired(bnAvg, pindexLast->GetMedianTimePast(), pindexFirst->GetMedianTimePast(), params); + return CalculateNextWorkRequired(bnAvg, + pindexLast->GetMedianTimePast(), pindexFirst->GetMedianTimePast(), + params, + pindexLast->nHeight + 1 ); } unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg, int64_t nLastBlockTime, int64_t nFirstBlockTime, - const Consensus::Params& params) + const Consensus::Params& params, + int nextHeight) { // Limit adjustment step // Use medians to prevent time-warp attacks int64_t nActualTimespan = nLastBlockTime - nFirstBlockTime; LogPrint("pow", " nActualTimespan = %d before dampening\n", nActualTimespan); - nActualTimespan = params.AveragingWindowTimespan() + (nActualTimespan - params.AveragingWindowTimespan())/4; + nActualTimespan = params.AveragingWindowTimespan(nextHeight) + (nActualTimespan - params.AveragingWindowTimespan(nextHeight))/4; LogPrint("pow", " nActualTimespan = %d before bounds\n", nActualTimespan); - if (nActualTimespan < params.MinActualTimespan()) - nActualTimespan = params.MinActualTimespan(); - if (nActualTimespan > params.MaxActualTimespan()) - nActualTimespan = params.MaxActualTimespan(); + if (nActualTimespan < params.MinActualTimespan(nextHeight)) + nActualTimespan = params.MinActualTimespan(nextHeight); + if (nActualTimespan > params.MaxActualTimespan(nextHeight)) + nActualTimespan = params.MaxActualTimespan(nextHeight); // Retarget const arith_uint256 bnPowLimit = UintToArith256(params.powLimit); arith_uint256 bnNew {bnAvg}; - bnNew /= params.AveragingWindowTimespan(); + bnNew /= params.AveragingWindowTimespan(nextHeight); bnNew *= nActualTimespan; if (bnNew > bnPowLimit) @@ -84,7 +88,7 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg, /// debug print LogPrint("pow", "GetNextWorkRequired RETARGET\n"); - LogPrint("pow", "params.AveragingWindowTimespan() = %d nActualTimespan = %d\n", params.AveragingWindowTimespan(), nActualTimespan); + LogPrint("pow", "params.AveragingWindowTimespan() = %d nActualTimespan = %d\n", params.AveragingWindowTimespan(nextHeight), nActualTimespan); LogPrint("pow", "Current average: %08x %s\n", bnAvg.GetCompact(), bnAvg.ToString()); LogPrint("pow", "After: %08x %s\n", bnNew.GetCompact(), bnNew.ToString()); @@ -162,7 +166,7 @@ int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& fr r = from.nChainWork - to.nChainWork; sign = -1; } - r = r * arith_uint256(params.nPowTargetSpacing) / GetBlockProof(tip); + r = r * arith_uint256(params.PoWTargetSpacing(tip.nHeight)) / GetBlockProof(tip); if (r.bits() > 63) { return sign * std::numeric_limits::max(); } diff --git a/src/pow.h b/src/pow.h index e3cf822d8dd..67c41bc7f39 100644 --- a/src/pow.h +++ b/src/pow.h @@ -19,7 +19,8 @@ class arith_uint256; unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params&); unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg, int64_t nLastBlockTime, int64_t nFirstBlockTime, - const Consensus::Params&); + const Consensus::Params&, + int nextHeight = 0); /** Check whether the Equihash solution in a block header is valid */ bool CheckEquihashSolution(const CBlockHeader *pblock, const Consensus::Params&); From 4b985ce99901b2c0808cc2d76f9b51fa750c8f78 Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 19 May 2019 14:30:56 -0700 Subject: [PATCH 155/395] Update GetBlockTimeout() to take height parameter. --- src/main.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 9549610d919..12aae555695 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -311,9 +311,9 @@ void UpdatePreferredDownload(CNode* node, CNodeState* state) } // Returns time at which to timeout block request (nTime in microseconds) -int64_t GetBlockTimeout(int64_t nTime, int nValidatedQueuedBefore, const Consensus::Params &consensusParams) +int64_t GetBlockTimeout(int64_t nTime, int nValidatedQueuedBefore, const Consensus::Params &consensusParams, int nHeight) { - return nTime + 500000 * consensusParams.nPowTargetSpacing * (4 + nValidatedQueuedBefore); + return nTime + 500000 * consensusParams.PoWTargetSpacing(nHeight) * (4 + nValidatedQueuedBefore); } void InitializeNode(NodeId nodeid, const CNode *pnode) { @@ -368,7 +368,8 @@ void MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const Consensus::Pa MarkBlockAsReceived(hash); int64_t nNow = GetTimeMicros(); - QueuedBlock newentry = {hash, pindex, nNow, pindex != NULL, GetBlockTimeout(nNow, nQueuedValidatedHeaders, consensusParams)}; + int nHeight = pindex != NULL ? pindex->nHeight : chainActive.Height(); // Help block timeout computation + QueuedBlock newentry = {hash, pindex, nNow, pindex != NULL, GetBlockTimeout(nNow, nQueuedValidatedHeaders, consensusParams, nHeight)}; nQueuedValidatedHeaders += newentry.fValidatedHeaders; list::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(), newentry); state->nBlocksInFlight++; @@ -6526,7 +6527,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) // more quickly than once every 5 minutes, then we'll shorten the download window for this block). if (!pto->fDisconnect && state.vBlocksInFlight.size() > 0) { QueuedBlock &queuedBlock = state.vBlocksInFlight.front(); - int64_t nTimeoutIfRequestedNow = GetBlockTimeout(nNow, nQueuedValidatedHeaders - state.nBlocksInFlightValidHeaders, consensusParams); + int64_t nTimeoutIfRequestedNow = GetBlockTimeout(nNow, nQueuedValidatedHeaders - state.nBlocksInFlightValidHeaders, consensusParams, pindexBestHeader->nHeight); if (queuedBlock.nTimeDisconnect > nTimeoutIfRequestedNow) { LogPrint("net", "Reducing block download timeout for peer=%d block=%s, orig=%d new=%d\n", pto->id, queuedBlock.hash.ToString(), queuedBlock.nTimeDisconnect, nTimeoutIfRequestedNow); queuedBlock.nTimeDisconnect = nTimeoutIfRequestedNow; From 22e8dc26797004bc13a7132776ac2fa392a75f0e Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 19 May 2019 14:33:03 -0700 Subject: [PATCH 156/395] Replace nPoWTargetSpacing -> PoWTargetSpacing() in ProcessMessage() --- src/main.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 12aae555695..f2d65c30fe6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5590,7 +5590,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // not a direct successor. pfrom->PushMessage("getheaders", chainActive.GetLocator(pindexBestHeader), inv.hash); CNodeState *nodestate = State(pfrom->GetId()); - if (chainActive.Tip()->GetBlockTime() > GetAdjustedTime() - chainparams.GetConsensus().nPowTargetSpacing * 20 && + + if (chainActive.Tip()->GetBlockTime() > GetAdjustedTime() - chainparams.GetConsensus().PoWTargetSpacing(pindexBestHeader->nHeight) * 20 && nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) { vToFetch.push_back(inv); // Mark block as in flight already, even though the actual "getdata" message only goes out @@ -5661,7 +5662,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } // If pruning, don't inv blocks unless we have on disk and are likely to still have // for some reasonable time window (1 hour) that block relay might require. - const int nPrunedBlocksLikelyToHave = MIN_BLOCKS_TO_KEEP - 3600 / chainparams.GetConsensus().nPowTargetSpacing; + const int nPrunedBlocksLikelyToHave = MIN_BLOCKS_TO_KEEP - 3600 / chainparams.GetConsensus().PoWTargetSpacing(pindex->nHeight); if (fPruneMode && (!(pindex->nStatus & BLOCK_HAVE_DATA) || pindex->nHeight <= chainActive.Tip()->nHeight - nPrunedBlocksLikelyToHave)) { LogPrint("net", " getblocks stopping, pruned or too old block at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); From 3a8fd5ea33823f4af12e02d9ecd5a079769a9359 Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 19 May 2019 14:38:13 -0700 Subject: [PATCH 157/395] Replace nPoWTargetSpacing -> PoWTargetSpacing() in tests --- src/gtest/test_pow.cpp | 18 +++++++++--------- src/test/alert_tests.cpp | 2 +- src/test/miner_tests.cpp | 2 +- src/test/pow_tests.cpp | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/gtest/test_pow.cpp b/src/gtest/test_pow.cpp index 4557f6db11d..b0dd5fa41e7 100644 --- a/src/gtest/test_pow.cpp +++ b/src/gtest/test_pow.cpp @@ -16,7 +16,7 @@ TEST(PoW, DifficultyAveraging) { for (int i = 0; i <= lastBlk; i++) { blocks[i].pprev = i ? &blocks[i - 1] : nullptr; blocks[i].nHeight = i; - blocks[i].nTime = 1269211443 + i * params.nPowTargetSpacing; + blocks[i].nTime = 1269211443 + i * params.PoWTargetSpacing(blocks[i].nHeight); blocks[i].nBits = 0x1e7fffff; /* target 0x007fffff000... */ blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + GetBlockProof(blocks[i - 1]) : arith_uint256(0); } @@ -32,12 +32,12 @@ TEST(PoW, DifficultyAveraging) { // Result should be unchanged, modulo integer division precision loss arith_uint256 bnRes; bnRes.SetCompact(0x1e7fffff); - bnRes /= params.AveragingWindowTimespan(); - bnRes *= params.AveragingWindowTimespan(); + bnRes /= params.AveragingWindowTimespan(blocks[lastBlk].nHeight); + bnRes *= params.AveragingWindowTimespan(blocks[lastBlk].nHeight); EXPECT_EQ(bnRes.GetCompact(), GetNextWorkRequired(&blocks[lastBlk], nullptr, params)); // Randomise the final block time (plus 1 to ensure it is always different) - blocks[lastBlk].nTime += GetRand(params.nPowTargetSpacing/2) + 1; + blocks[lastBlk].nTime += GetRand(params.PoWTargetSpacing(blocks[lastBlk].nHeight)/2) + 1; // Result should be the same as if last difficulty was used bnAvg.SetCompact(blocks[lastBlk].nBits); @@ -80,24 +80,24 @@ TEST(PoW, MinDifficultyRules) { for (int i = 0; i <= lastBlk; i++) { blocks[i].pprev = i ? &blocks[i - 1] : nullptr; blocks[i].nHeight = params.nPowAllowMinDifficultyBlocksAfterHeight.get() + i; - blocks[i].nTime = 1269211443 + i * params.nPowTargetSpacing; + blocks[i].nTime = 1269211443 + i * params.PoWTargetSpacing(blocks[i].nHeight); blocks[i].nBits = 0x1e7fffff; /* target 0x007fffff000... */ blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + GetBlockProof(blocks[i - 1]) : arith_uint256(0); } // Create a new block at the target spacing CBlockHeader next; - next.nTime = blocks[lastBlk].nTime + params.nPowTargetSpacing; + next.nTime = blocks[lastBlk].nTime + params.PoWTargetSpacing(blocks[lastBlk].nHeight + 1); // Result should be unchanged, modulo integer division precision loss arith_uint256 bnRes; bnRes.SetCompact(0x1e7fffff); - bnRes /= params.AveragingWindowTimespan(); - bnRes *= params.AveragingWindowTimespan(); + bnRes /= params.AveragingWindowTimespan(blocks[lastBlk].nHeight); + bnRes *= params.AveragingWindowTimespan(blocks[lastBlk].nHeight); EXPECT_EQ(GetNextWorkRequired(&blocks[lastBlk], &next, params), bnRes.GetCompact()); // Delay last block up to the edge of the min-difficulty limit - next.nTime += params.nPowTargetSpacing * 5; + next.nTime += params.PoWTargetSpacing(blocks[lastBlk].nHeight + 1) * 5; // Result should be unchanged, modulo integer division precision loss EXPECT_EQ(GetNextWorkRequired(&blocks[lastBlk], &next, params), bnRes.GetCompact()); diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index 18acf1f67c5..f50f7c49725 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -391,7 +391,7 @@ BOOST_AUTO_TEST_CASE(PartitionAlert) CCriticalSection csDummy; CBlockIndex indexDummy[400]; CChainParams& params = Params(CBaseChainParams::MAIN); - int64_t nPowTargetSpacing = params.GetConsensus().nPowTargetSpacing; + int64_t nPowTargetSpacing = params.GetConsensus().PoWTargetSpacing(0); // First 400 blocks are pre-Blossom // Generate fake blockchain timestamps relative to // an arbitrary time: diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 23e7634abbd..11bcaa0603e 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -168,7 +168,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) // of the next block must be six spacings ahead of that to be at least // one spacing ahead of the tip. Within 11 blocks of genesis, the median // will be closer to the tip, and blocks will appear slower. - pblock->nTime = chainActive.Tip()->GetMedianTimePast()+6*Params().GetConsensus().nPowTargetSpacing; + pblock->nTime = chainActive.Tip()->GetMedianTimePast()+6*Params().GetConsensus().PoWTargetSpacing(i); CMutableTransaction txCoinbase(pblock->vtx[0]); txCoinbase.nVersion = 1; txCoinbase.vin[0].scriptSig = CScript() << (chainActive.Height()+1) << OP_0; diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index 5a11483f274..a83f5914b70 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test) for (int i = 0; i < 10000; i++) { blocks[i].pprev = i ? &blocks[i - 1] : NULL; blocks[i].nHeight = i; - blocks[i].nTime = 1269211443 + i * params.nPowTargetSpacing; + blocks[i].nTime = 1269211443 + i * params.PoWTargetSpacing(blocks[i].nHeight); blocks[i].nBits = 0x207fffff; /* target 0x7fffff000... */ blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + GetBlockProof(blocks[i - 1]) : arith_uint256(0); } From d7ebbeb2aa0ff79e57d86dfe5dbf709f62d2bd0b Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 19 May 2019 15:58:11 -0700 Subject: [PATCH 158/395] Modify PartitionCheck to be aware of pre & post Blossom target spacing. --- src/init.cpp | 7 +++---- src/main.cpp | 27 ++++++++++++++++++++++++++- src/main.h | 2 +- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 2743f473104..6d6fd1f4a5d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1861,11 +1861,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) StartNode(threadGroup, scheduler); - // Monitor the chain, and alert if we get blocks much quicker or slower than expected - int64_t nPowTargetSpacing = Params().GetConsensus().nPowTargetSpacing; + // Monitor the chain every minute, and alert if we get blocks much quicker or slower than expected. CScheduler::Function f = boost::bind(&PartitionCheck, &IsInitialBlockDownload, - boost::ref(cs_main), boost::cref(pindexBestHeader), nPowTargetSpacing); - scheduler.scheduleEvery(f, nPowTargetSpacing); + boost::ref(cs_main), boost::cref(pindexBestHeader), 0); + scheduler.scheduleEvery(f, 60); #ifdef ENABLE_MINING // Generate coins in the background diff --git a/src/main.cpp b/src/main.cpp index f2d65c30fe6..fa28964e300 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2436,6 +2436,9 @@ void ThreadScriptCheck() { // we're being fed a bad chain (blocks being generated much // too slowly or too quickly). // +// When parameter nPowTargetSpacing is not set, the default value of 0 +// means use the block height of the best header to determine target spacing. +// Setting the parameter value is useful for testing. void PartitionCheck(bool (*initialDownloadCheck)(const CChainParams&), CCriticalSection& cs, const CBlockIndex *const &bestHeader, int64_t nPowTargetSpacing) @@ -2448,14 +2451,36 @@ void PartitionCheck(bool (*initialDownloadCheck)(const CChainParams&), const int SPAN_HOURS=4; const int SPAN_SECONDS=SPAN_HOURS*60*60; + + LOCK(cs); + + int bestHeaderHeight = bestHeader->nHeight; + int blossomHeight = Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; + if (nPowTargetSpacing == 0) { + nPowTargetSpacing = Params().GetConsensus().PoWTargetSpacing(bestHeaderHeight); + blossomHeight = Params().GetConsensus().vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; + } + int BLOCKS_EXPECTED = SPAN_SECONDS / nPowTargetSpacing; + // If the span period includes Blossom activation, adjust the number of expected blocks. + if (blossomHeight != Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT && + bestHeaderHeight > blossomHeight) + { + int t = SPAN_SECONDS; + int nBlossomBlocks = bestHeaderHeight - blossomHeight; + t -= nBlossomBlocks * Consensus::POST_BLOSSOM_POW_TARGET_SPACING; + if (t > 0) { + int nPreBlossomBlocks = t / Consensus::PRE_BLOSSOM_POW_TARGET_SPACING; + BLOCKS_EXPECTED = nPreBlossomBlocks + nBlossomBlocks; + } + } + boost::math::poisson_distribution poisson(BLOCKS_EXPECTED); std::string strWarning; int64_t startTime = GetAdjustedTime()-SPAN_SECONDS; - LOCK(cs); const CBlockIndex* i = bestHeader; int nBlocks = 0; while (i->GetBlockTime() >= startTime) { diff --git a/src/main.h b/src/main.h index cd2e39a0957..deda1276c7b 100644 --- a/src/main.h +++ b/src/main.h @@ -234,7 +234,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle); /** Run an instance of the script checking thread */ void ThreadScriptCheck(); /** Try to detect Partition (network isolation) attacks against us */ -void PartitionCheck(bool (*initialDownloadCheck)(const CChainParams&), CCriticalSection& cs, const CBlockIndex *const &bestHeader, int64_t nPowTargetSpacing); +void PartitionCheck(bool (*initialDownloadCheck)(const CChainParams&), CCriticalSection& cs, const CBlockIndex *const &bestHeader, int64_t nPowTargetSpacing = 0); /** Check whether we are doing an initial block download (synchronizing from disk or network) */ bool IsInitialBlockDownload(const CChainParams& chainParams); /** Format a string that describes several potential problems detected by the core */ From 6db54c98619de5a9603fc157e906bc0e50e246f2 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Sun, 7 Apr 2019 19:56:45 +0100 Subject: [PATCH 159/395] Add MIT license to Makefiles Signed-off-by: Daira Hopwood --- Makefile.am | 6 ++++++ src/Makefile.am | 6 ++++++ src/Makefile.test.include | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/Makefile.am b/Makefile.am index a160fe5f4df..357a7e877ef 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,9 @@ +# Copyright (c) 2016-2019 The Zcash developers +# Copyright (c) 2013-2019 The Bitcoin Core developers +# Copyright (c) 2013-2019 Bitcoin Developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php . + ACLOCAL_AMFLAGS = -I build-aux/m4 SUBDIRS = src if ENABLE_MAN diff --git a/src/Makefile.am b/src/Makefile.am index a7c7b12bc5d..75fa1aa3a01 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,3 +1,9 @@ +# Copyright (c) 2016-2019 The Zcash developers +# Copyright (c) 2013-2019 The Bitcoin Core developers +# Copyright (c) 2013-2019 Bitcoin Developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php . + DIST_SUBDIRS = secp256k1 univalue AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(SAN_LDFLAGS) $(HARDENED_LDFLAGS) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 1eb6b262e91..c339fbf64dd 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -1,3 +1,9 @@ +# Copyright (c) 2016-2019 The Zcash developers +# Copyright (c) 2013-2019 The Bitcoin Core developers +# Copyright (c) 2013-2019 Bitcoin Developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php . + TESTS += test/test_bitcoin noinst_PROGRAMS += test/test_bitcoin TEST_SRCDIR = test From 8c07c3559e7508e1b1c1c0937719d7e8961cb7f2 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 21 Sep 2016 22:35:21 +0000 Subject: [PATCH 160/395] Add MIT license to autogen.sh and share/genbuild.sh Signed-off-by: Daira Hopwood --- autogen.sh | 6 ++++++ share/genbuild.sh | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/autogen.sh b/autogen.sh index 3e26a183059..74ccbc62a9b 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,4 +1,10 @@ #!/bin/sh +# Copyright (c) 2016-2019 The Zcash developers +# Copyright (c) 2013-2019 The Bitcoin Core developers +# Copyright (c) 2013-2019 Bitcoin Developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php . + set -e srcdir="$(dirname $0)" cd "$srcdir" diff --git a/share/genbuild.sh b/share/genbuild.sh index a15cb34e47a..3c0a591a3c9 100755 --- a/share/genbuild.sh +++ b/share/genbuild.sh @@ -1,4 +1,10 @@ #!/bin/sh +# Copyright (c) 2016-2019 The Zcash developers +# Copyright (c) 2012-2019 The Bitcoin Core developers +# Copyright (c) 2012-2019 Bitcoin Developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php . + if [ $# -gt 1 ]; then cd "$2" fi From 60c6730709ffa65a9cb66e9d58a50d9b9917fea5 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Sun, 7 Apr 2019 20:07:10 +0100 Subject: [PATCH 161/395] Add MIT license to build-aux/m4/bitcoin_* scripts, and a permissive license to build-aux/m4/l_atomic.m4 . Signed-off-by: Daira Hopwood --- build-aux/m4/bitcoin_find_bdb.m4 | 6 ++++++ build-aux/m4/bitcoin_subdir_to_include.m4 | 6 ++++++ build-aux/m4/l_atomic.m4 | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/build-aux/m4/bitcoin_find_bdb.m4 b/build-aux/m4/bitcoin_find_bdb.m4 index bd5c2af4545..22b1271a1a2 100644 --- a/build-aux/m4/bitcoin_find_bdb.m4 +++ b/build-aux/m4/bitcoin_find_bdb.m4 @@ -1,3 +1,9 @@ +dnl Copyright (c) 2016-2019 The Zcash developers +dnl Copyright (c) 2013-2019 The Bitcoin Core developers +dnl Copyright (c) 2013-2019 Bitcoin Developers +dnl Distributed under the MIT software license, see the accompanying +dnl file COPYING or http://www.opensource.org/licenses/mit-license.php . + AC_DEFUN([BITCOIN_FIND_BDB62],[ AC_MSG_CHECKING([for Berkeley DB C++ headers]) BDB_CPPFLAGS= diff --git a/build-aux/m4/bitcoin_subdir_to_include.m4 b/build-aux/m4/bitcoin_subdir_to_include.m4 index 66f106c7d47..b03640dbb24 100644 --- a/build-aux/m4/bitcoin_subdir_to_include.m4 +++ b/build-aux/m4/bitcoin_subdir_to_include.m4 @@ -1,3 +1,9 @@ +dnl Copyright (c) 2016-2019 The Zcash developers +dnl Copyright (c) 2013-2019 The Bitcoin Core developers +dnl Copyright (c) 2013-2019 Bitcoin Developers +dnl Distributed under the MIT software license, see the accompanying +dnl file COPYING or http://www.opensource.org/licenses/mit-license.php . + dnl BITCOIN_SUBDIR_TO_INCLUDE([CPPFLAGS-VARIABLE-NAME],[SUBDIRECTORY-NAME],[HEADER-FILE]) dnl SUBDIRECTORY-NAME must end with a path separator AC_DEFUN([BITCOIN_SUBDIR_TO_INCLUDE],[ diff --git a/build-aux/m4/l_atomic.m4 b/build-aux/m4/l_atomic.m4 index 906724b6405..3ceea16bbb9 100644 --- a/build-aux/m4/l_atomic.m4 +++ b/build-aux/m4/l_atomic.m4 @@ -1,3 +1,9 @@ +dnl Copyright (c) 2015 Tim Kosse +dnl Copying and distribution of this file, with or without modification, are +dnl permitted in any medium without royalty provided the copyright notice +dnl and this notice are preserved. This file is offered as-is, without any +dnl warranty. + # Some versions of gcc/libstdc++ require linking with -latomic if # using the C++ atomic library. # From 5cf90cbc99a014bbb9910fe57171316df9607eba Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 21 Sep 2016 22:54:49 +0000 Subject: [PATCH 162/395] Trivial: build-aux/m4/l_atomic: Fix typo --- build-aux/m4/l_atomic.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-aux/m4/l_atomic.m4 b/build-aux/m4/l_atomic.m4 index 3ceea16bbb9..75c43f9a92d 100644 --- a/build-aux/m4/l_atomic.m4 +++ b/build-aux/m4/l_atomic.m4 @@ -38,7 +38,7 @@ AC_DEFUN([CHECK_ATOMIC], [ AC_MSG_RESULT([yes]) ],[ AC_MSG_RESULT([no]) - AC_MSG_FAILURE([cannot figure our how to use std::atomic]) + AC_MSG_FAILURE([cannot figure out how to use std::atomic]) ]) ]) From f63731261cf06c3b17b9b6536d163e81e76b0d4f Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Sun, 7 Apr 2019 22:13:03 +0100 Subject: [PATCH 163/395] Update copyright information for Zcash, leveldb, and libsnark. Signed-off-by: Daira Hopwood --- contrib/debian/copyright | 21 ++++++++++++++------- src/snark/LICENSE | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/contrib/debian/copyright b/contrib/debian/copyright index de1fdf97d19..5c7cf10055c 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -8,18 +8,15 @@ Copyright: 2016-2019, The Zcash developers 2009-2019, Bitcoin Core developers 2009-2019, Bitcoin Developers License: Expat -Comment: The Bitcoin Core developers encompasses the current developers listed on bitcoin.org, - as well as the numerous contributors to the project. - The Zcash developers are listed at https://z.cash/team.html. +Comment: The Bitcoin Core developers encompasses the current developers listed on + bitcoin.org, as well as the numerous contributors to the project. + The Zcash developers are listed at https://z.cash/team.html and in doc/authors.md. + This copyright entry excludes files explicitly listed below. Files: depends/sources/libsodium-*.tar.gz Copyright: 2013-2016 Frank Denis License: ISC -Files: depends/sources/libsnark-*.tar.gz -Copyright: 2012-2016 SCIPR Lab and contributors; 2016 The Zcash developers -License: Expat - Files: depends/sources/gmp-*.tar.bz2 Copyright: 1991, 1996, 1999, 2000, 2007 Free Software Foundation, Inc. License: LGPL @@ -68,6 +65,16 @@ Files: src/secp256k1/build-aux/m4/ax_prog_cc_for_build.m4 Copyright: 2008 Paolo Bonzini License: GNU-All-permissive-License +Files src/leveldb/* +Copyright: 2011, The LevelDB Authors +License: BSD-3clause-Google +Comment: The LevelDB Authors are listed in src/leveldb/AUTHORS. + +Files src/snark/* +Copyright: 2012-2019, SCIPR Lab and contributors +License: Expat +Comment: The contributors are listed in src/snark/AUTHORS. + License: Boost-Software-License-1.0 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by diff --git a/src/snark/LICENSE b/src/snark/LICENSE index 81cea11e135..3eb759a5e07 100644 --- a/src/snark/LICENSE +++ b/src/snark/LICENSE @@ -1,7 +1,7 @@ The libsnark library is developed by SCIPR Lab (http://scipr-lab.org) and contributors. -Copyright (c) 2012-2014 SCIPR Lab and contributors (see AUTHORS file). +Copyright (c) 2012-2019 SCIPR Lab and contributors (see AUTHORS file). All files, with the exceptions below, are released under the MIT License: From 9ee7cd2048017100b91a4d3e638d58b9a851d202 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Sun, 7 Apr 2019 22:21:53 +0100 Subject: [PATCH 164/395] Add license information for Autoconf macros. refs #2827 Signed-off-by: Daira Hopwood --- COPYING | 21 ++++++-- contrib/debian/copyright | 112 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+), 3 deletions(-) diff --git a/COPYING b/COPYING index 2970e8efd02..8249d96000f 100644 --- a/COPYING +++ b/COPYING @@ -22,9 +22,11 @@ THE SOFTWARE. The MIT software license (http://www.opensource.org/licenses/mit-license.php) -above applies to the code directly included in this source distribution. -Dependencies downloaded as part of the build process may be covered by other -open-source licenses. For further details see 'contrib/debian/copyright'. +above applies to the code directly included in this source distribution, with +the exception of certain Autoconf macros. Dependencies downloaded as part of +the build process may be covered by other open-source licenses. The MIT-licensed +source code is not considered a derived work of these Autoconf macros or of the +dependencies. For further details see 'contrib/debian/copyright'. This product includes software developed by the OpenSSL Project for use in the @@ -36,3 +38,16 @@ Although almost all of the Zcash code is licensed under "permissive" open source licenses, users and distributors should note that when built using the default build options, Zcash depends on Oracle Berkeley DB 6.2.x, which is licensed under the GNU Affero General Public License. + + +Contributors should understand licensing implications before modifying the +following files in build-aux/m4 (see ticket #2827): + + * ax_check_compile_flag.m4 + * ax_check_link_flag.m4 + * ax_check_preproc_flag.m4 + * ax_compiler_vendor.m4 + * ax_gcc_archflag.m4 + * ax_gcc_x86_cpuid.m4 + * ax_openmp.m4 + * ax_pthread.m4 diff --git a/contrib/debian/copyright b/contrib/debian/copyright index 5c7cf10055c..424a31125dd 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -13,6 +13,89 @@ Comment: The Bitcoin Core developers encompasses the current developers listed o The Zcash developers are listed at https://z.cash/team.html and in doc/authors.md. This copyright entry excludes files explicitly listed below. +Files: build-aux/m4/ax_boost_base.m4 +Copyright: 2008, Thomas Porschberg + 2009, Peter Adolphs +License: GNU-All-permissive-License + +Files: build-aux/m4/ax_boost_chrono.m4 +Copyright: 2012, Xiyue Deng +License: GNU-All-permissive-License + +Files: build-aux/m4/ax_boost_filesystem.m4 +Copyright: 2009, Thomas Porschberg + 2009, Michael Tindal + 2009, Roman Rybalko +License: GNU-All-permissive-License + +Files: build-aux/m4/ax_boost_program_options.m4 +Copyright: 2009, Thomas Porschberg +License: GNU-All-permissive-License + +Files: build-aux/m4/ax_boost_system.m4 +Copyright: 2008, Thomas Porschberg + 2008, Michael Tindal + 2008, Daniel Casimiro +License: GNU-All-permissive-License + +Files: build-aux/m4/ax_boost_unit_test_framework.m4 +Copyright: 2008, Thomas Porschberg +License: GNU-All-permissive-License + +Files: build-aux/m4/ax_cxx_compile_stdcxx.m4 +Copyright: 2008, Benjamin Kosnik + 2012, Zack Weinberg + 2013, Roy Stogner + 2014-2015, Google Inc.; contributed by Alexey Sokolov + 2015, Paul Norman + 2015, Moritz Klammler +License: GNU-All-permissive-License + +Files: build-aux/m4/ax_gcc_func_attribute.m4 +Copyright: 2013, Gabriele Svelto +License: GNU-All-permissive-License + +Files: build-aux/m4/l_atomic.m4 +Copyright: 2015, Tim Kosse +License: GNU-All-permissive-License + +Files: build-aux/m4/ax_check_compile_flag.m4 + build-aux/m4/ax_check_link_flag.m4 + build-aux/m4/ax_check_preproc_flag.m4 +Copyright: 2008, Guido U. Draheim + 2011, Maarten Bosmans +License: GPLv3-or-later-with-Autoconf-exception + +Files: build-aux/m4/ax_compiler_vendor.m4 +Copyright: 2008, Steven G. Johnson + 2008, Matteo Frigo + 2018-19, John Zaitseff +License: GPLv3-or-later-with-Autoconf-exception + +Files: build-aux/m4/ax_gcc_archflag.m4 +Copyright: 2008, Steven G. Johnson + 2008, Matteo Frigo + 2014, Tsukasa Oi + 2017-2018, Alexey Kopytov +License: GPLv3-or-later-with-Autoconf-exception + +Files: build-aux/m4/ax_gcc_x86_cpuid.m4 +Copyright: 2008, Steven G. Johnson + 2008, Matteo Frigo + 2015, Michael Petch +License: GPLv3-or-later-with-Autoconf-exception + +Files: build-aux/m4/ax_openmp.m4 +Copyright: 2008, Steven G. Johnson + 2015, John W. Peterson + 2016, Nick R. Papior +License: GPLv3-or-later-with-Autoconf-exception + +Files: build-aux/m4/ax_pthread.m4 +Copyright: 2008, Steven G. Johnson + 2011, Daniel Richard G. +License: GPLv3-or-later-with-Autoconf-exception + Files: depends/sources/libsodium-*.tar.gz Copyright: 2013-2016 Frank Denis License: ISC @@ -1330,3 +1413,32 @@ License: GNU-All-permissive-License and this notice are preserved. This file is offered as-is, without any warranty. +License: GPLv3-or-later-with-Autoconf-exception + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + . + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + Public License for more details. + . + You should have received a copy of the GNU General Public License along + with this program. If not, see . + . + As a special exception, the respective Autoconf Macro's copyright owner + gives unlimited permission to copy, distribute and modify the configure + scripts that are the output of Autoconf when processing the Macro. You + need not follow the terms of the GNU General Public License when using + or distributing such scripts, even though portions of the text of the + Macro appear in them. The GNU General Public License (GPL) does govern + all other use of the material that constitutes the Autoconf Macro. + . + This special exception to the GPL applies to versions of the Autoconf + Macro released by the Autoconf Archive. When you make and distribute a + modified version of the Autoconf Macro, you may extend this special + exception to the GPL to apply to your modified version as well. +Comment: + The "special exception" is extended to the versions of files covered by + this license that are distributed with this software. From 6e8685742c22e5df3c5912d065c1b9cab329531c Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Thu, 18 Jul 2019 13:57:17 +0100 Subject: [PATCH 165/395] Update contrib/debian/copyright for ax_boost_thread.m4 Co-Authored-By: str4d --- contrib/debian/copyright | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/contrib/debian/copyright b/contrib/debian/copyright index 424a31125dd..abe2db3cbd3 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -38,6 +38,11 @@ Copyright: 2008, Thomas Porschberg 2008, Daniel Casimiro License: GNU-All-permissive-License +Files: build-aux/m4/ax_boost_thread.m4 +Copyright: 2009, Thomas Porschberg + 2009, Michael Tindal +License: GNU-All-permissive-License + Files: build-aux/m4/ax_boost_unit_test_framework.m4 Copyright: 2008, Thomas Porschberg License: GNU-All-permissive-License From bc909a7a7f0553d8ec80fa6c36a4faf8609edcf7 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Thu, 18 Jul 2019 15:16:09 +0100 Subject: [PATCH 166/395] Replace http with https: in links to the MIT license. Also change MIT/X11 to just MIT, since no distinction was intended. Signed-off-by: Daira Hopwood --- COPYING | 2 +- Makefile.am | 2 +- autogen.sh | 2 +- build-aux/m4/bitcoin_find_bdb.m4 | 2 +- build-aux/m4/bitcoin_subdir_to_include.m4 | 2 +- contrib/amqp/amqp_sub.py | 4 ++-- contrib/devtools/symbol-check.py | 3 ++- contrib/linearize/linearize-data.py | 2 +- contrib/linearize/linearize-hashes.py | 2 +- contrib/seeds/generate-seeds.py | 2 +- contrib/zcash-cli.bash-completion | 3 ++- contrib/zcash-tx.bash-completion | 3 ++- contrib/zcashd.bash-completion | 4 ++-- contrib/zmq/zmq_sub.py | 2 +- qa/pull-tester/run-bitcoind-for-test.sh.in | 2 +- qa/pull-tester/tests-config.sh.in | 2 +- qa/rpc-tests/bip65-cltv-p2p.py | 4 ++-- qa/rpc-tests/bipdersig-p2p.py | 4 ++-- qa/rpc-tests/blockchain.py | 2 +- qa/rpc-tests/decodescript.py | 2 +- qa/rpc-tests/disablewallet.py | 2 +- qa/rpc-tests/finalsaplingroot.py | 2 +- qa/rpc-tests/forknotify.py | 2 +- qa/rpc-tests/fundrawtransaction.py | 2 +- qa/rpc-tests/getblocktemplate.py | 2 +- qa/rpc-tests/getblocktemplate_longpoll.py | 2 +- qa/rpc-tests/getblocktemplate_proposals.py | 2 +- qa/rpc-tests/getchaintips.py | 2 +- qa/rpc-tests/getrawtransaction_insight.py | 2 +- qa/rpc-tests/httpbasics.py | 2 +- qa/rpc-tests/invalidateblock.py | 2 +- qa/rpc-tests/invalidblockrequest.py | 4 ++-- qa/rpc-tests/key_import_export.py | 2 +- qa/rpc-tests/keypool.py | 2 +- qa/rpc-tests/listtransactions.py | 2 +- qa/rpc-tests/maxblocksinflight.py | 4 ++-- qa/rpc-tests/mempool_nu_activation.py | 2 +- qa/rpc-tests/mempool_reorg.py | 2 +- qa/rpc-tests/mempool_resurrect_test.py | 2 +- qa/rpc-tests/mempool_spendcoinbase.py | 2 +- qa/rpc-tests/mempool_tx_expiry.py | 2 +- qa/rpc-tests/mempool_tx_input_limit.py | 2 +- qa/rpc-tests/mergetoaddress_helper.py | 2 +- qa/rpc-tests/mergetoaddress_mixednotes.py | 2 +- qa/rpc-tests/mergetoaddress_sapling.py | 2 +- qa/rpc-tests/mergetoaddress_sprout.py | 2 +- qa/rpc-tests/merkle_blocks.py | 2 +- qa/rpc-tests/nodehandling.py | 2 +- qa/rpc-tests/p2p-acceptblock.py | 4 ++-- qa/rpc-tests/p2p_node_bloom.py | 2 +- qa/rpc-tests/p2p_nu_peer_management.py | 2 +- qa/rpc-tests/p2p_txexpiringsoon.py | 2 +- qa/rpc-tests/p2p_txexpiry_dos.py | 2 +- qa/rpc-tests/paymentdisclosure.py | 2 +- qa/rpc-tests/prioritisetransaction.py | 2 +- qa/rpc-tests/proton_test.py | 2 +- qa/rpc-tests/proxy_test.py | 2 +- qa/rpc-tests/pruning.py | 2 +- qa/rpc-tests/rawtransactions.py | 2 +- qa/rpc-tests/receivedby.py | 2 +- qa/rpc-tests/regtest_signrawtransaction.py | 2 +- qa/rpc-tests/reindex.py | 2 +- qa/rpc-tests/reorg_limit.py | 2 +- qa/rpc-tests/rest.py | 2 +- qa/rpc-tests/rewind_index.py | 2 +- qa/rpc-tests/rpcbind_test.py | 2 +- qa/rpc-tests/script_test.py | 4 ++-- qa/rpc-tests/signrawtransactions.py | 2 +- qa/rpc-tests/smartfees.py | 2 +- qa/rpc-tests/sprout_sapling_migration.py | 2 +- qa/rpc-tests/test_framework/bignum.py | 4 ++-- qa/rpc-tests/test_framework/blocktools.py | 4 ++-- qa/rpc-tests/test_framework/comptool.py | 4 ++-- qa/rpc-tests/test_framework/mininode.py | 4 ++-- qa/rpc-tests/test_framework/netutil.py | 2 +- qa/rpc-tests/test_framework/script.py | 4 ++-- qa/rpc-tests/test_framework/socks5.py | 2 +- qa/rpc-tests/test_framework/test_framework.py | 2 +- qa/rpc-tests/test_framework/util.py | 2 +- qa/rpc-tests/turnstile.py | 2 +- qa/rpc-tests/tx_expiry_helper.py | 2 +- qa/rpc-tests/txn_doublespend.py | 2 +- qa/rpc-tests/wallet.py | 2 +- qa/rpc-tests/wallet_1941.py | 2 +- qa/rpc-tests/wallet_addresses.py | 2 +- qa/rpc-tests/wallet_anchorfork.py | 2 +- qa/rpc-tests/wallet_changeindicator.py | 2 +- qa/rpc-tests/wallet_import_export.py | 2 +- qa/rpc-tests/wallet_listnotes.py | 2 +- qa/rpc-tests/wallet_listreceived.py | 2 +- qa/rpc-tests/wallet_nullifiers.py | 2 +- qa/rpc-tests/wallet_overwintertx.py | 2 +- qa/rpc-tests/wallet_persistence.py | 2 +- qa/rpc-tests/wallet_protectcoinbase.py | 2 +- qa/rpc-tests/wallet_sapling.py | 2 +- qa/rpc-tests/wallet_shieldcoinbase.py | 2 +- qa/rpc-tests/wallet_treestate.py | 2 +- qa/rpc-tests/walletbackup.py | 2 +- qa/rpc-tests/zapwallettxes.py | 2 +- qa/rpc-tests/zkey_import_export.py | 2 +- qa/rpc-tests/zmq_test.py | 2 +- qa/zcash/create_wallet_200k_utxos.py | 2 +- share/genbuild.sh | 2 +- src/Makefile.am | 2 +- src/Makefile.test.include | 2 +- src/addressindex.h | 2 +- src/addrman.cpp | 2 +- src/addrman.h | 2 +- src/alert.cpp | 2 +- src/alert.h | 2 +- src/amount.cpp | 2 +- src/amount.h | 2 +- src/amqp/amqpabstractnotifier.cpp | 2 +- src/amqp/amqpabstractnotifier.h | 2 +- src/amqp/amqpconfig.h | 2 +- src/amqp/amqpnotificationinterface.cpp | 2 +- src/amqp/amqpnotificationinterface.h | 2 +- src/amqp/amqppublishnotifier.cpp | 2 +- src/amqp/amqppublishnotifier.h | 2 +- src/amqp/amqpsender.h | 2 +- src/arith_uint256.cpp | 2 +- src/arith_uint256.h | 2 +- src/asyncrpcoperation.cpp | 2 +- src/asyncrpcoperation.h | 2 +- src/asyncrpcqueue.cpp | 2 +- src/asyncrpcqueue.h | 2 +- src/base58.cpp | 2 +- src/base58.h | 2 +- src/bech32.cpp | 2 +- src/bech32.h | 2 +- src/bitcoin-cli-res.rc | 2 +- src/bitcoin-cli.cpp | 2 +- src/bitcoin-tx-res.rc | 2 +- src/bitcoin-tx.cpp | 2 +- src/bitcoind-res.rc | 2 +- src/bitcoind.cpp | 2 +- src/bloom.cpp | 2 +- src/bloom.h | 2 +- src/chain.cpp | 2 +- src/chain.h | 2 +- src/chainparams.cpp | 2 +- src/chainparams.h | 2 +- src/chainparamsbase.cpp | 2 +- src/chainparamsbase.h | 2 +- src/checkpoints.cpp | 2 +- src/checkpoints.h | 2 +- src/checkqueue.h | 2 +- src/clientversion.cpp | 2 +- src/clientversion.h | 2 +- src/coincontrol.h | 2 +- src/coins.cpp | 2 +- src/coins.h | 2 +- src/compat.h | 2 +- src/compat/byteswap.h | 2 +- src/compat/endian.h | 2 +- src/compat/glibc_compat.cpp | 2 +- src/compat/glibc_sanity.cpp | 2 +- src/compat/glibcxx_sanity.cpp | 2 +- src/compat/sanity.h | 2 +- src/compat/strnlen.cpp | 2 +- src/compressor.cpp | 2 +- src/compressor.h | 2 +- src/consensus/consensus.h | 2 +- src/consensus/params.h | 2 +- src/consensus/upgrades.cpp | 2 +- src/consensus/upgrades.h | 2 +- src/consensus/validation.h | 2 +- src/core_io.h | 2 +- src/core_memusage.h | 2 +- src/core_read.cpp | 2 +- src/core_write.cpp | 2 +- src/crypto/common.h | 2 +- src/crypto/equihash.cpp | 2 +- src/crypto/equihash.h | 2 +- src/crypto/equihash.tcc | 2 +- src/crypto/hmac_sha256.cpp | 2 +- src/crypto/hmac_sha256.h | 2 +- src/crypto/hmac_sha512.cpp | 2 +- src/crypto/hmac_sha512.h | 2 +- src/crypto/ripemd160.cpp | 2 +- src/crypto/ripemd160.h | 2 +- src/crypto/sha1.cpp | 2 +- src/crypto/sha1.h | 2 +- src/crypto/sha256.cpp | 2 +- src/crypto/sha256.h | 2 +- src/crypto/sha512.cpp | 2 +- src/crypto/sha512.h | 2 +- src/dbwrapper.cpp | 2 +- src/dbwrapper.h | 2 +- src/deprecation.cpp | 2 +- src/deprecation.h | 2 +- src/hash.cpp | 2 +- src/hash.h | 2 +- src/httprpc.h | 2 +- src/httpserver.cpp | 2 +- src/httpserver.h | 2 +- src/init.cpp | 2 +- src/init.h | 2 +- src/key.cpp | 2 +- src/key.h | 2 +- src/key_io.cpp | 2 +- src/key_io.h | 2 +- src/keystore.cpp | 2 +- src/keystore.h | 2 +- src/limitedmap.h | 2 +- src/main.cpp | 2 +- src/main.h | 2 +- src/memusage.h | 2 +- src/merkleblock.cpp | 2 +- src/merkleblock.h | 2 +- src/metrics.cpp | 2 +- src/metrics.h | 2 +- src/miner.cpp | 2 +- src/miner.h | 2 +- src/mruset.h | 2 +- src/net.cpp | 2 +- src/net.h | 2 +- src/netbase.cpp | 2 +- src/netbase.h | 2 +- src/noui.cpp | 2 +- src/noui.h | 2 +- src/policy/fees.cpp | 2 +- src/policy/fees.h | 2 +- src/pow.cpp | 2 +- src/pow.h | 2 +- src/primitives/block.cpp | 2 +- src/primitives/block.h | 2 +- src/primitives/transaction.cpp | 2 +- src/primitives/transaction.h | 2 +- src/protocol.cpp | 2 +- src/protocol.h | 2 +- src/pubkey.cpp | 2 +- src/pubkey.h | 2 +- src/random.cpp | 2 +- src/random.h | 2 +- src/rest.cpp | 2 +- src/reverselock.h | 2 +- src/rpc/blockchain.cpp | 2 +- src/rpc/client.cpp | 2 +- src/rpc/client.h | 2 +- src/rpc/mining.cpp | 2 +- src/rpc/misc.cpp | 2 +- src/rpc/net.cpp | 2 +- src/rpc/protocol.cpp | 2 +- src/rpc/protocol.h | 2 +- src/rpc/rawtransaction.cpp | 2 +- src/rpc/register.h | 2 +- src/rpc/server.cpp | 2 +- src/rpc/server.h | 2 +- src/scheduler.cpp | 2 +- src/scheduler.h | 2 +- src/script/interpreter.cpp | 2 +- src/script/interpreter.h | 2 +- src/script/script.cpp | 2 +- src/script/script.h | 2 +- src/script/script_error.cpp | 2 +- src/script/script_error.h | 2 +- src/script/sigcache.cpp | 2 +- src/script/sigcache.h | 2 +- src/script/sign.cpp | 2 +- src/script/sign.h | 2 +- src/script/standard.cpp | 2 +- src/script/standard.h | 2 +- src/script/zcashconsensus.cpp | 2 +- src/script/zcashconsensus.h | 2 +- src/secp256k1/contrib/lax_der_parsing.c | 10 +++++----- src/secp256k1/contrib/lax_der_parsing.h | 10 +++++----- src/secp256k1/contrib/lax_der_privatekey_parsing.c | 10 +++++----- src/secp256k1/contrib/lax_der_privatekey_parsing.h | 10 +++++----- src/secp256k1/src/asm/field_10x26_arm.s | 10 +++++----- src/secp256k1/src/basic-config.h | 10 +++++----- src/secp256k1/src/bench.h | 10 +++++----- src/secp256k1/src/bench_ecdh.c | 10 +++++----- src/secp256k1/src/bench_internal.c | 10 +++++----- src/secp256k1/src/bench_recover.c | 10 +++++----- src/secp256k1/src/bench_sign.c | 10 +++++----- src/secp256k1/src/bench_verify.c | 10 +++++----- src/secp256k1/src/ecdsa.h | 10 +++++----- src/secp256k1/src/ecdsa_impl.h | 10 +++++----- src/secp256k1/src/eckey.h | 10 +++++----- src/secp256k1/src/eckey_impl.h | 10 +++++----- src/secp256k1/src/ecmult.h | 10 +++++----- src/secp256k1/src/ecmult_const.h | 10 +++++----- src/secp256k1/src/ecmult_const_impl.h | 10 +++++----- src/secp256k1/src/ecmult_gen.h | 10 +++++----- src/secp256k1/src/ecmult_gen_impl.h | 10 +++++----- src/secp256k1/src/ecmult_impl.h | 10 +++++----- src/secp256k1/src/field.h | 10 +++++----- src/secp256k1/src/field_10x26.h | 10 +++++----- src/secp256k1/src/field_10x26_impl.h | 10 +++++----- src/secp256k1/src/field_5x52.h | 10 +++++----- src/secp256k1/src/field_5x52_asm_impl.h | 10 +++++----- src/secp256k1/src/field_5x52_impl.h | 10 +++++----- src/secp256k1/src/field_5x52_int128_impl.h | 10 +++++----- src/secp256k1/src/field_impl.h | 10 +++++----- src/secp256k1/src/gen_context.c | 10 +++++----- src/secp256k1/src/group.h | 10 +++++----- src/secp256k1/src/group_impl.h | 10 +++++----- src/secp256k1/src/hash.h | 10 +++++----- src/secp256k1/src/hash_impl.h | 10 +++++----- src/secp256k1/src/modules/ecdh/main_impl.h | 10 +++++----- src/secp256k1/src/modules/ecdh/tests_impl.h | 10 +++++----- src/secp256k1/src/modules/recovery/main_impl.h | 10 +++++----- src/secp256k1/src/modules/recovery/tests_impl.h | 10 +++++----- src/secp256k1/src/num.h | 10 +++++----- src/secp256k1/src/num_gmp.h | 10 +++++----- src/secp256k1/src/num_gmp_impl.h | 10 +++++----- src/secp256k1/src/num_impl.h | 10 +++++----- src/secp256k1/src/scalar.h | 10 +++++----- src/secp256k1/src/scalar_4x64.h | 10 +++++----- src/secp256k1/src/scalar_4x64_impl.h | 10 +++++----- src/secp256k1/src/scalar_8x32.h | 10 +++++----- src/secp256k1/src/scalar_8x32_impl.h | 10 +++++----- src/secp256k1/src/scalar_impl.h | 10 +++++----- src/secp256k1/src/scalar_low.h | 10 +++++----- src/secp256k1/src/scalar_low_impl.h | 10 +++++----- src/secp256k1/src/secp256k1.c | 10 +++++----- src/secp256k1/src/testrand.h | 10 +++++----- src/secp256k1/src/testrand_impl.h | 10 +++++----- src/secp256k1/src/tests.c | 10 +++++----- src/secp256k1/src/tests_exhaustive.c | 10 +++++----- src/secp256k1/src/util.h | 10 +++++----- src/serialize.h | 2 +- src/spentindex.h | 2 +- src/streams.h | 2 +- src/support/allocators/secure.h | 2 +- src/support/allocators/zeroafterfree.h | 2 +- src/support/cleanse.cpp | 2 +- src/support/cleanse.h | 2 +- src/support/events.h | 2 +- src/support/pagelocker.cpp | 2 +- src/support/pagelocker.h | 2 +- src/sync.cpp | 2 +- src/sync.h | 2 +- src/test/Checkpoints_tests.cpp | 2 +- src/test/DoS_tests.cpp | 2 +- src/test/accounting_tests.cpp | 2 +- src/test/addrman_tests.cpp | 2 +- src/test/alert_tests.cpp | 2 +- src/test/allocator_tests.cpp | 2 +- src/test/arith_uint256_tests.cpp | 2 +- src/test/base32_tests.cpp | 2 +- src/test/base58_tests.cpp | 2 +- src/test/base64_tests.cpp | 2 +- src/test/bctest.py | 2 +- src/test/bech32_tests.cpp | 2 +- src/test/bignum.h | 2 +- src/test/bip32_tests.cpp | 2 +- src/test/bitcoin-util-test.py | 2 +- src/test/bloom_tests.cpp | 2 +- src/test/checkblock_tests.cpp | 2 +- src/test/coins_tests.cpp | 2 +- src/test/compress_tests.cpp | 2 +- src/test/convertbits_tests.cpp | 2 +- src/test/crypto_tests.cpp | 2 +- src/test/data/README.md | 2 +- src/test/dbwrapper_tests.cpp | 2 +- src/test/equihash_tests.cpp | 2 +- src/test/getarg_tests.cpp | 2 +- src/test/hash_tests.cpp | 2 +- src/test/key_tests.cpp | 2 +- src/test/main_tests.cpp | 2 +- src/test/mempool_tests.cpp | 2 +- src/test/miner_tests.cpp | 2 +- src/test/mruset_tests.cpp | 2 +- src/test/multisig_tests.cpp | 2 +- src/test/netbase_tests.cpp | 2 +- src/test/pmt_tests.cpp | 2 +- src/test/policyestimator_tests.cpp | 2 +- src/test/pow_tests.cpp | 4 ++-- src/test/prevector_tests.cpp | 2 +- src/test/raii_event_tests.cpp | 2 +- src/test/reverselock_tests.cpp | 2 +- src/test/rpc_tests.cpp | 2 +- src/test/rpc_wallet_tests.cpp | 2 +- src/test/sanity_tests.cpp | 2 +- src/test/scheduler_tests.cpp | 2 +- src/test/script_P2PKH_tests.cpp | 2 +- src/test/script_P2SH_tests.cpp | 2 +- src/test/script_tests.cpp | 2 +- src/test/scriptnum_tests.cpp | 2 +- src/test/serialize_tests.cpp | 2 +- src/test/sighash_tests.cpp | 2 +- src/test/sigopcount_tests.cpp | 2 +- src/test/skiplist_tests.cpp | 2 +- src/test/test_bitcoin.cpp | 2 +- src/test/timedata_tests.cpp | 2 +- src/test/torcontrol_tests.cpp | 2 +- src/test/transaction_tests.cpp | 2 +- src/test/uint256_tests.cpp | 2 +- src/test/univalue_tests.cpp | 2 +- src/test/util_tests.cpp | 2 +- src/threadsafety.h | 2 +- src/timedata.cpp | 2 +- src/timedata.h | 2 +- src/timestampindex.h | 2 +- src/torcontrol.cpp | 2 +- src/torcontrol.h | 2 +- src/transaction_builder.cpp | 2 +- src/transaction_builder.h | 2 +- src/txdb.cpp | 2 +- src/txdb.h | 2 +- src/txmempool.cpp | 2 +- src/txmempool.h | 2 +- src/ui_interface.h | 2 +- src/uint256.cpp | 2 +- src/uint256.h | 2 +- src/undo.h | 2 +- src/univalue/gen/gen.cpp | 2 +- src/univalue/include/univalue.h | 2 +- src/univalue/lib/univalue.cpp | 2 +- src/univalue/lib/univalue_read.cpp | 2 +- src/univalue/lib/univalue_utffilter.h | 2 +- src/univalue/lib/univalue_write.cpp | 2 +- src/univalue/test/unitester.cpp | 4 ++-- src/util.cpp | 4 ++-- src/util.h | 2 +- src/utilmoneystr.cpp | 2 +- src/utilmoneystr.h | 2 +- src/utilstrencodings.cpp | 2 +- src/utilstrencodings.h | 2 +- src/utiltest.cpp | 2 +- src/utiltest.h | 2 +- src/utiltime.cpp | 2 +- src/utiltime.h | 2 +- src/validationinterface.cpp | 2 +- src/validationinterface.h | 2 +- src/version.h | 2 +- src/wallet/asyncrpcoperation_mergetoaddress.cpp | 2 +- src/wallet/asyncrpcoperation_mergetoaddress.h | 2 +- src/wallet/asyncrpcoperation_sendmany.cpp | 2 +- src/wallet/asyncrpcoperation_sendmany.h | 2 +- src/wallet/asyncrpcoperation_shieldcoinbase.cpp | 2 +- src/wallet/asyncrpcoperation_shieldcoinbase.h | 2 +- src/wallet/crypter.cpp | 2 +- src/wallet/crypter.h | 2 +- src/wallet/db.cpp | 2 +- src/wallet/db.h | 2 +- src/wallet/paymentdisclosure.cpp | 2 +- src/wallet/paymentdisclosure.h | 2 +- src/wallet/paymentdisclosuredb.cpp | 2 +- src/wallet/paymentdisclosuredb.h | 2 +- src/wallet/rpcdisclosure.cpp | 2 +- src/wallet/rpcdump.cpp | 2 +- src/wallet/rpcwallet.cpp | 2 +- src/wallet/rpcwallet.h | 2 +- src/wallet/test/wallet_tests.cpp | 2 +- src/wallet/wallet.cpp | 2 +- src/wallet/wallet.h | 2 +- src/wallet/wallet_ismine.cpp | 2 +- src/wallet/wallet_ismine.h | 2 +- src/wallet/walletdb.cpp | 2 +- src/wallet/walletdb.h | 2 +- src/zcash/zip32.cpp | 2 +- src/zcash/zip32.h | 2 +- src/zmq/zmqabstractnotifier.cpp | 2 +- src/zmq/zmqabstractnotifier.h | 2 +- src/zmq/zmqconfig.h | 2 +- src/zmq/zmqnotificationinterface.cpp | 2 +- src/zmq/zmqnotificationinterface.h | 2 +- src/zmq/zmqpublishnotifier.cpp | 2 +- src/zmq/zmqpublishnotifier.h | 2 +- 462 files changed, 709 insertions(+), 706 deletions(-) diff --git a/COPYING b/COPYING index 8249d96000f..b1e9debe7b7 100644 --- a/COPYING +++ b/COPYING @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -The MIT software license (http://www.opensource.org/licenses/mit-license.php) +The MIT software license (https://www.opensource.org/licenses/mit-license.php) above applies to the code directly included in this source distribution, with the exception of certain Autoconf macros. Dependencies downloaded as part of the build process may be covered by other open-source licenses. The MIT-licensed diff --git a/Makefile.am b/Makefile.am index 357a7e877ef..e6d6dc9d60a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,7 +2,7 @@ # Copyright (c) 2013-2019 The Bitcoin Core developers # Copyright (c) 2013-2019 Bitcoin Developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php . +# file COPYING or https://www.opensource.org/licenses/mit-license.php . ACLOCAL_AMFLAGS = -I build-aux/m4 SUBDIRS = src diff --git a/autogen.sh b/autogen.sh index 74ccbc62a9b..a7f0547520b 100755 --- a/autogen.sh +++ b/autogen.sh @@ -3,7 +3,7 @@ # Copyright (c) 2013-2019 The Bitcoin Core developers # Copyright (c) 2013-2019 Bitcoin Developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php . +# file COPYING or https://www.opensource.org/licenses/mit-license.php . set -e srcdir="$(dirname $0)" diff --git a/build-aux/m4/bitcoin_find_bdb.m4 b/build-aux/m4/bitcoin_find_bdb.m4 index 22b1271a1a2..e6c365271c2 100644 --- a/build-aux/m4/bitcoin_find_bdb.m4 +++ b/build-aux/m4/bitcoin_find_bdb.m4 @@ -2,7 +2,7 @@ dnl Copyright (c) 2016-2019 The Zcash developers dnl Copyright (c) 2013-2019 The Bitcoin Core developers dnl Copyright (c) 2013-2019 Bitcoin Developers dnl Distributed under the MIT software license, see the accompanying -dnl file COPYING or http://www.opensource.org/licenses/mit-license.php . +dnl file COPYING or https://www.opensource.org/licenses/mit-license.php . AC_DEFUN([BITCOIN_FIND_BDB62],[ AC_MSG_CHECKING([for Berkeley DB C++ headers]) diff --git a/build-aux/m4/bitcoin_subdir_to_include.m4 b/build-aux/m4/bitcoin_subdir_to_include.m4 index b03640dbb24..52da5ef9f9b 100644 --- a/build-aux/m4/bitcoin_subdir_to_include.m4 +++ b/build-aux/m4/bitcoin_subdir_to_include.m4 @@ -2,7 +2,7 @@ dnl Copyright (c) 2016-2019 The Zcash developers dnl Copyright (c) 2013-2019 The Bitcoin Core developers dnl Copyright (c) 2013-2019 Bitcoin Developers dnl Distributed under the MIT software license, see the accompanying -dnl file COPYING or http://www.opensource.org/licenses/mit-license.php . +dnl file COPYING or https://www.opensource.org/licenses/mit-license.php . dnl BITCOIN_SUBDIR_TO_INCLUDE([CPPFLAGS-VARIABLE-NAME],[SUBDIRECTORY-NAME],[HEADER-FILE]) dnl SUBDIRECTORY-NAME must end with a path separator diff --git a/contrib/amqp/amqp_sub.py b/contrib/amqp/amqp_sub.py index bc51e842866..707c5f46688 100644 --- a/contrib/amqp/amqp_sub.py +++ b/contrib/amqp/amqp_sub.py @@ -1,7 +1,7 @@ #!/usr/bin/env python2 -# Copyright (c) 2017 The Zcash developers +# Copyright (c) 2017-2019 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # Requirements: # pip install python-qpid-proton diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py index 52b48ef74a2..5b83ba97b77 100755 --- a/contrib/devtools/symbol-check.py +++ b/contrib/devtools/symbol-check.py @@ -1,7 +1,8 @@ #!/usr/bin/env python # Copyright (c) 2014 Wladimir J. van der Laan +# Copyright (c) 2016-2019 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . ''' A script to check that the (Linux) executables produced by gitian only contain allowed gcc, glibc and libstdc++ version symbols. This makes sure they are diff --git a/contrib/linearize/linearize-data.py b/contrib/linearize/linearize-data.py index 8badb4b318b..7bc7eb023b7 100755 --- a/contrib/linearize/linearize-data.py +++ b/contrib/linearize/linearize-data.py @@ -4,7 +4,7 @@ # # Copyright (c) 2013-2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # from __future__ import print_function, division diff --git a/contrib/linearize/linearize-hashes.py b/contrib/linearize/linearize-hashes.py index 7e9cf889848..68da0618865 100755 --- a/contrib/linearize/linearize-hashes.py +++ b/contrib/linearize/linearize-hashes.py @@ -4,7 +4,7 @@ # # Copyright (c) 2013-2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # from __future__ import print_function diff --git a/contrib/seeds/generate-seeds.py b/contrib/seeds/generate-seeds.py index c6a2ce6369b..5142a1dd719 100755 --- a/contrib/seeds/generate-seeds.py +++ b/contrib/seeds/generate-seeds.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 Wladimir J. van der Laan # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . ''' Script to generate list of seed nodes for chainparams.cpp. diff --git a/contrib/zcash-cli.bash-completion b/contrib/zcash-cli.bash-completion index 37fa1d1160c..264ba86f4f2 100644 --- a/contrib/zcash-cli.bash-completion +++ b/contrib/zcash-cli.bash-completion @@ -1,7 +1,8 @@ # bash programmable completion for zcash-cli(1) # Copyright (c) 2012-2016 The Bitcoin Core developers +# Copyright (c) 2016-2019 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # call $zcash-cli for RPC _zcash_rpc() { diff --git a/contrib/zcash-tx.bash-completion b/contrib/zcash-tx.bash-completion index e808f93cb95..b6a0cf4349a 100644 --- a/contrib/zcash-tx.bash-completion +++ b/contrib/zcash-tx.bash-completion @@ -1,7 +1,8 @@ # bash programmable completion for zcash-tx(1) # Copyright (c) 2016 The Bitcoin Core developers +# Copyright (c) 2016-2019 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . _zcash_tx() { local cur prev words=() cword diff --git a/contrib/zcashd.bash-completion b/contrib/zcashd.bash-completion index 65f07cd803a..d5135350a73 100644 --- a/contrib/zcashd.bash-completion +++ b/contrib/zcashd.bash-completion @@ -1,8 +1,8 @@ # bash programmable completion for zcashd(1) # Copyright (c) 2012-2017 The Bitcoin Core developers -# Copyright (c) 2016-2017 The Zcash developers +# Copyright (c) 2016-2019 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . _zcashd() { local cur prev words=() cword diff --git a/contrib/zmq/zmq_sub.py b/contrib/zmq/zmq_sub.py index 10ff907fb46..6df3e083832 100755 --- a/contrib/zmq/zmq_sub.py +++ b/contrib/zmq/zmq_sub.py @@ -1,7 +1,7 @@ #!/usr/bin/env python2 # Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import array import binascii diff --git a/qa/pull-tester/run-bitcoind-for-test.sh.in b/qa/pull-tester/run-bitcoind-for-test.sh.in index 999b0f5b73c..122c5523be7 100755 --- a/qa/pull-tester/run-bitcoind-for-test.sh.in +++ b/qa/pull-tester/run-bitcoind-for-test.sh.in @@ -1,7 +1,7 @@ #!/bin/bash # Copyright (c) 2013-2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # ZCASH_LOAD_TIMEOUT=500 DATADIR="@abs_top_builddir@/.zcash" diff --git a/qa/pull-tester/tests-config.sh.in b/qa/pull-tester/tests-config.sh.in index cc76e8ad84a..6dc511432db 100755 --- a/qa/pull-tester/tests-config.sh.in +++ b/qa/pull-tester/tests-config.sh.in @@ -1,7 +1,7 @@ #!/bin/bash # Copyright (c) 2013-2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . BUILDDIR="@abs_top_builddir@" EXEEXT="@EXEEXT@" diff --git a/qa/rpc-tests/bip65-cltv-p2p.py b/qa/rpc-tests/bip65-cltv-p2p.py index 3daff0a37f6..1867ce284bb 100755 --- a/qa/rpc-tests/bip65-cltv-p2p.py +++ b/qa/rpc-tests/bip65-cltv-p2p.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -# Distributed under the MIT/X11 software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/bipdersig-p2p.py b/qa/rpc-tests/bipdersig-p2p.py index 163933ab0e9..404e10e3c28 100755 --- a/qa/rpc-tests/bipdersig-p2p.py +++ b/qa/rpc-tests/bipdersig-p2p.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -# Distributed under the MIT/X11 software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/blockchain.py b/qa/rpc-tests/blockchain.py index 22dd299ec0d..acd04d842ff 100755 --- a/qa/rpc-tests/blockchain.py +++ b/qa/rpc-tests/blockchain.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Test RPC calls related to blockchain state. Tests correspond to code in diff --git a/qa/rpc-tests/decodescript.py b/qa/rpc-tests/decodescript.py index ea4916b0655..04259145557 100755 --- a/qa/rpc-tests/decodescript.py +++ b/qa/rpc-tests/decodescript.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2015 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/disablewallet.py b/qa/rpc-tests/disablewallet.py index e43a9519fad..f665902efe9 100755 --- a/qa/rpc-tests/disablewallet.py +++ b/qa/rpc-tests/disablewallet.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Exercise API with -disablewallet. diff --git a/qa/rpc-tests/finalsaplingroot.py b/qa/rpc-tests/finalsaplingroot.py index 4298ec20b2e..6d66cd83a14 100755 --- a/qa/rpc-tests/finalsaplingroot.py +++ b/qa/rpc-tests/finalsaplingroot.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/forknotify.py b/qa/rpc-tests/forknotify.py index 4386f246da4..8bfab5961e5 100755 --- a/qa/rpc-tests/forknotify.py +++ b/qa/rpc-tests/forknotify.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Test -alertnotify diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index 3b2535c7322..b17947dd2ec 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/getblocktemplate.py b/qa/rpc-tests/getblocktemplate.py index 96fd73083e2..1a7205f5ad3 100755 --- a/qa/rpc-tests/getblocktemplate.py +++ b/qa/rpc-tests/getblocktemplate.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2016 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/getblocktemplate_longpoll.py b/qa/rpc-tests/getblocktemplate_longpoll.py index 748c547e511..beccce881c5 100755 --- a/qa/rpc-tests/getblocktemplate_longpoll.py +++ b/qa/rpc-tests/getblocktemplate_longpoll.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/getblocktemplate_proposals.py b/qa/rpc-tests/getblocktemplate_proposals.py index 771e8b0913e..a14e409f744 100755 --- a/qa/rpc-tests/getblocktemplate_proposals.py +++ b/qa/rpc-tests/getblocktemplate_proposals.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/getchaintips.py b/qa/rpc-tests/getchaintips.py index 7bbb921cac3..8215ce0b51e 100755 --- a/qa/rpc-tests/getchaintips.py +++ b/qa/rpc-tests/getchaintips.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # Exercise the getchaintips API. We introduce a network split, work # on chains of different lengths, and join the network together again. diff --git a/qa/rpc-tests/getrawtransaction_insight.py b/qa/rpc-tests/getrawtransaction_insight.py index f18eed5d465..85f39ccd7f4 100755 --- a/qa/rpc-tests/getrawtransaction_insight.py +++ b/qa/rpc-tests/getrawtransaction_insight.py @@ -1,7 +1,7 @@ #!/usr/bin/env python2 # Copyright (c) 2019 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Test the new fields added to the output of getrawtransaction diff --git a/qa/rpc-tests/httpbasics.py b/qa/rpc-tests/httpbasics.py index ca5924c906f..11e2c1385f9 100755 --- a/qa/rpc-tests/httpbasics.py +++ b/qa/rpc-tests/httpbasics.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Test rpc http basics diff --git a/qa/rpc-tests/invalidateblock.py b/qa/rpc-tests/invalidateblock.py index ab0ba4a69be..069f8ace858 100755 --- a/qa/rpc-tests/invalidateblock.py +++ b/qa/rpc-tests/invalidateblock.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Test InvalidateBlock code diff --git a/qa/rpc-tests/invalidblockrequest.py b/qa/rpc-tests/invalidblockrequest.py index 6e8895f1d39..80124fddfa6 100755 --- a/qa/rpc-tests/invalidblockrequest.py +++ b/qa/rpc-tests/invalidblockrequest.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -# Distributed under the MIT/X11 software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/key_import_export.py b/qa/rpc-tests/key_import_export.py index 02638e6a8b4..66fc7ef041d 100755 --- a/qa/rpc-tests/key_import_export.py +++ b/qa/rpc-tests/key_import_export.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2017 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/keypool.py b/qa/rpc-tests/keypool.py index b538742a443..ddebf3a551d 100755 --- a/qa/rpc-tests/keypool.py +++ b/qa/rpc-tests/keypool.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # Exercise the wallet keypool, and interaction with wallet encryption/locking diff --git a/qa/rpc-tests/listtransactions.py b/qa/rpc-tests/listtransactions.py index 3f508c6033c..28764cd28b2 100755 --- a/qa/rpc-tests/listtransactions.py +++ b/qa/rpc-tests/listtransactions.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # Exercise the listtransactions API diff --git a/qa/rpc-tests/maxblocksinflight.py b/qa/rpc-tests/maxblocksinflight.py index 6ba67940e9d..51210defee7 100755 --- a/qa/rpc-tests/maxblocksinflight.py +++ b/qa/rpc-tests/maxblocksinflight.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -# Distributed under the MIT/X11 software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/mempool_nu_activation.py b/qa/rpc-tests/mempool_nu_activation.py index ed55dcfc020..6a862635b48 100755 --- a/qa/rpc-tests/mempool_nu_activation.py +++ b/qa/rpc-tests/mempool_nu_activation.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/mempool_reorg.py b/qa/rpc-tests/mempool_reorg.py index d422b9027e6..e37e39babf9 100755 --- a/qa/rpc-tests/mempool_reorg.py +++ b/qa/rpc-tests/mempool_reorg.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Test re-org scenarios with a mempool that contains transactions diff --git a/qa/rpc-tests/mempool_resurrect_test.py b/qa/rpc-tests/mempool_resurrect_test.py index 2e31ca19855..2d67bbb9a1a 100755 --- a/qa/rpc-tests/mempool_resurrect_test.py +++ b/qa/rpc-tests/mempool_resurrect_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Test resurrection of mined transactions when diff --git a/qa/rpc-tests/mempool_spendcoinbase.py b/qa/rpc-tests/mempool_spendcoinbase.py index 57716411a63..d9c7bbc37dc 100755 --- a/qa/rpc-tests/mempool_spendcoinbase.py +++ b/qa/rpc-tests/mempool_spendcoinbase.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Test spending coinbase transactions. diff --git a/qa/rpc-tests/mempool_tx_expiry.py b/qa/rpc-tests/mempool_tx_expiry.py index af84ff3a7b2..7d66fd0e986 100755 --- a/qa/rpc-tests/mempool_tx_expiry.py +++ b/qa/rpc-tests/mempool_tx_expiry.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Test proper expiry for transactions >= version 3 diff --git a/qa/rpc-tests/mempool_tx_input_limit.py b/qa/rpc-tests/mempool_tx_input_limit.py index dc1ab125e88..66cccff35e4 100755 --- a/qa/rpc-tests/mempool_tx_input_limit.py +++ b/qa/rpc-tests/mempool_tx_input_limit.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2017 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/mergetoaddress_helper.py b/qa/rpc-tests/mergetoaddress_helper.py index 962c2b7ff49..e3df89eada5 100755 --- a/qa/rpc-tests/mergetoaddress_helper.py +++ b/qa/rpc-tests/mergetoaddress_helper.py @@ -1,6 +1,6 @@ # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Common code for testing z_mergetoaddress before and after sapling activation diff --git a/qa/rpc-tests/mergetoaddress_mixednotes.py b/qa/rpc-tests/mergetoaddress_mixednotes.py index b787429aa99..3e06e42e28d 100755 --- a/qa/rpc-tests/mergetoaddress_mixednotes.py +++ b/qa/rpc-tests/mergetoaddress_mixednotes.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2019 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/mergetoaddress_sapling.py b/qa/rpc-tests/mergetoaddress_sapling.py index 1ab8e61e94c..72ca6929aba 100755 --- a/qa/rpc-tests/mergetoaddress_sapling.py +++ b/qa/rpc-tests/mergetoaddress_sapling.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/mergetoaddress_sprout.py b/qa/rpc-tests/mergetoaddress_sprout.py index 88a821ac20a..8d3e2cbec83 100755 --- a/qa/rpc-tests/mergetoaddress_sprout.py +++ b/qa/rpc-tests/mergetoaddress_sprout.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/merkle_blocks.py b/qa/rpc-tests/merkle_blocks.py index dda8fbd0707..d9fec26f207 100755 --- a/qa/rpc-tests/merkle_blocks.py +++ b/qa/rpc-tests/merkle_blocks.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Test merkleblock fetch/validation diff --git a/qa/rpc-tests/nodehandling.py b/qa/rpc-tests/nodehandling.py index fd7d8356bb5..7ab65f66439 100755 --- a/qa/rpc-tests/nodehandling.py +++ b/qa/rpc-tests/nodehandling.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Test node handling diff --git a/qa/rpc-tests/p2p-acceptblock.py b/qa/rpc-tests/p2p-acceptblock.py index 3f89d786fcf..054967b245f 100755 --- a/qa/rpc-tests/p2p-acceptblock.py +++ b/qa/rpc-tests/p2p-acceptblock.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -# Distributed under the MIT/X11 software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/p2p_node_bloom.py b/qa/rpc-tests/p2p_node_bloom.py index 9a520c4ed58..dd8709c046e 100755 --- a/qa/rpc-tests/p2p_node_bloom.py +++ b/qa/rpc-tests/p2p_node_bloom.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/p2p_nu_peer_management.py b/qa/rpc-tests/p2p_nu_peer_management.py index aee5bfe1877..cbb8a30826f 100755 --- a/qa/rpc-tests/p2p_nu_peer_management.py +++ b/qa/rpc-tests/p2p_nu_peer_management.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/p2p_txexpiringsoon.py b/qa/rpc-tests/p2p_txexpiringsoon.py index 37465cddfc2..bd631a5adb7 100755 --- a/qa/rpc-tests/p2p_txexpiringsoon.py +++ b/qa/rpc-tests/p2p_txexpiringsoon.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/p2p_txexpiry_dos.py b/qa/rpc-tests/p2p_txexpiry_dos.py index 7927f918970..e51bf2cb6db 100755 --- a/qa/rpc-tests/p2p_txexpiry_dos.py +++ b/qa/rpc-tests/p2p_txexpiry_dos.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/paymentdisclosure.py b/qa/rpc-tests/paymentdisclosure.py index f483baa6a48..308fbc0cab0 100755 --- a/qa/rpc-tests/paymentdisclosure.py +++ b/qa/rpc-tests/paymentdisclosure.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2017 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/prioritisetransaction.py b/qa/rpc-tests/prioritisetransaction.py index 131644d80bd..cdb5f58589e 100755 --- a/qa/rpc-tests/prioritisetransaction.py +++ b/qa/rpc-tests/prioritisetransaction.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2017 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/proton_test.py b/qa/rpc-tests/proton_test.py index 20c1521999d..820a9d7beed 100755 --- a/qa/rpc-tests/proton_test.py +++ b/qa/rpc-tests/proton_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2017 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Test Proton interface (provides AMQP 1.0 messaging support). diff --git a/qa/rpc-tests/proxy_test.py b/qa/rpc-tests/proxy_test.py index fec14833c88..8db56c5cbf7 100755 --- a/qa/rpc-tests/proxy_test.py +++ b/qa/rpc-tests/proxy_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2015 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/pruning.py b/qa/rpc-tests/pruning.py index d49cc581224..f10011f9f17 100755 --- a/qa/rpc-tests/pruning.py +++ b/qa/rpc-tests/pruning.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Test pruning code diff --git a/qa/rpc-tests/rawtransactions.py b/qa/rpc-tests/rawtransactions.py index d2dcb857c46..43768695784 100755 --- a/qa/rpc-tests/rawtransactions.py +++ b/qa/rpc-tests/rawtransactions.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Test re-org scenarios with a mempool that contains transactions diff --git a/qa/rpc-tests/receivedby.py b/qa/rpc-tests/receivedby.py index 1a52efce950..dcce3831ff5 100755 --- a/qa/rpc-tests/receivedby.py +++ b/qa/rpc-tests/receivedby.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # Exercise the listreceivedbyaddress API diff --git a/qa/rpc-tests/regtest_signrawtransaction.py b/qa/rpc-tests/regtest_signrawtransaction.py index 9854cf96f25..4b2b524bcad 100755 --- a/qa/rpc-tests/regtest_signrawtransaction.py +++ b/qa/rpc-tests/regtest_signrawtransaction.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/reindex.py b/qa/rpc-tests/reindex.py index c11314a9f72..c19d9c1f523 100755 --- a/qa/rpc-tests/reindex.py +++ b/qa/rpc-tests/reindex.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Test -reindex with CheckBlockIndex diff --git a/qa/rpc-tests/reorg_limit.py b/qa/rpc-tests/reorg_limit.py index 5c46e6d6d63..7eec27ee410 100755 --- a/qa/rpc-tests/reorg_limit.py +++ b/qa/rpc-tests/reorg_limit.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2017 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Test reorg limit diff --git a/qa/rpc-tests/rest.py b/qa/rpc-tests/rest.py index 2aa965b5337..3ba9288b946 100755 --- a/qa/rpc-tests/rest.py +++ b/qa/rpc-tests/rest.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Test REST interface diff --git a/qa/rpc-tests/rewind_index.py b/qa/rpc-tests/rewind_index.py index 96072098e68..9a30f393ca9 100755 --- a/qa/rpc-tests/rewind_index.py +++ b/qa/rpc-tests/rewind_index.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/rpcbind_test.py b/qa/rpc-tests/rpcbind_test.py index 4a6d254637a..e192004d6ab 100755 --- a/qa/rpc-tests/rpcbind_test.py +++ b/qa/rpc-tests/rpcbind_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # Test for -rpcbind, as well as -rpcallowip and -rpcconnect diff --git a/qa/rpc-tests/script_test.py b/qa/rpc-tests/script_test.py index 1bbeb2cfc9e..58627b99d79 100755 --- a/qa/rpc-tests/script_test.py +++ b/qa/rpc-tests/script_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -# Distributed under the MIT/X11 software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # ''' diff --git a/qa/rpc-tests/signrawtransactions.py b/qa/rpc-tests/signrawtransactions.py index 51f2eac3ec2..e6eff05edbf 100755 --- a/qa/rpc-tests/signrawtransactions.py +++ b/qa/rpc-tests/signrawtransactions.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2015 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/smartfees.py b/qa/rpc-tests/smartfees.py index 168c1699bd9..073e7e86ea9 100755 --- a/qa/rpc-tests/smartfees.py +++ b/qa/rpc-tests/smartfees.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014-2015 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Test fee estimation code diff --git a/qa/rpc-tests/sprout_sapling_migration.py b/qa/rpc-tests/sprout_sapling_migration.py index 03e1ccde77c..19c53e912ff 100755 --- a/qa/rpc-tests/sprout_sapling_migration.py +++ b/qa/rpc-tests/sprout_sapling_migration.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2019 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/test_framework/bignum.py b/qa/rpc-tests/test_framework/bignum.py index b0c58ccd474..29658d4c629 100644 --- a/qa/rpc-tests/test_framework/bignum.py +++ b/qa/rpc-tests/test_framework/bignum.py @@ -4,8 +4,8 @@ # # This file is copied from python-bitcoinlib. # -# Distributed under the MIT/X11 software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # """Bignum routines""" diff --git a/qa/rpc-tests/test_framework/blocktools.py b/qa/rpc-tests/test_framework/blocktools.py index 1fe2a5ddabb..3a679f14e37 100644 --- a/qa/rpc-tests/test_framework/blocktools.py +++ b/qa/rpc-tests/test_framework/blocktools.py @@ -1,7 +1,7 @@ # blocktools.py - utilities for manipulating blocks and transactions # -# Distributed under the MIT/X11 software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # from mininode import CBlock, CTransaction, CTxIn, CTxOut, COutPoint diff --git a/qa/rpc-tests/test_framework/comptool.py b/qa/rpc-tests/test_framework/comptool.py index 7f9a97d6826..153ded9816f 100755 --- a/qa/rpc-tests/test_framework/comptool.py +++ b/qa/rpc-tests/test_framework/comptool.py @@ -1,7 +1,7 @@ #!/usr/bin/env python2 # -# Distributed under the MIT/X11 software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # from mininode import CBlock, CTransaction, CInv, NodeConn, NodeConnCB, \ diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 5f500f0c096..bbeaaf8f88f 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -1,7 +1,7 @@ # mininode.py - Bitcoin P2P network half-a-node # -# Distributed under the MIT/X11 software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # This python code was modified from ArtForz' public domain half-a-node, as # found in the mini-node branch of http://github.com/jgarzik/pynode. diff --git a/qa/rpc-tests/test_framework/netutil.py b/qa/rpc-tests/test_framework/netutil.py index b30a88a4f78..25ce069e4b8 100644 --- a/qa/rpc-tests/test_framework/netutil.py +++ b/qa/rpc-tests/test_framework/netutil.py @@ -1,7 +1,7 @@ #!/usr/bin/env python2 # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # Linux network utilities import sys diff --git a/qa/rpc-tests/test_framework/script.py b/qa/rpc-tests/test_framework/script.py index 55a7f8e51ae..e7aa12e9344 100644 --- a/qa/rpc-tests/test_framework/script.py +++ b/qa/rpc-tests/test_framework/script.py @@ -3,8 +3,8 @@ # # This file is modified from python-bitcoinlib. # -# Distributed under the MIT/X11 software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # """Scripts diff --git a/qa/rpc-tests/test_framework/socks5.py b/qa/rpc-tests/test_framework/socks5.py index 1dbfb98d5d3..813654e5238 100644 --- a/qa/rpc-tests/test_framework/socks5.py +++ b/qa/rpc-tests/test_framework/socks5.py @@ -1,6 +1,6 @@ # Copyright (c) 2015 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . ''' Dummy Socks5 server for testing. ''' diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py index 56151bb3e38..067b2dce340 100755 --- a/qa/rpc-tests/test_framework/test_framework.py +++ b/qa/rpc-tests/test_framework/test_framework.py @@ -1,7 +1,7 @@ #!/usr/bin/env python2 # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # Base class for RPC testing diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index 590cb2d48a1..ef933f5460c 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -1,6 +1,6 @@ # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # diff --git a/qa/rpc-tests/turnstile.py b/qa/rpc-tests/turnstile.py index 89d680f0b13..129a91ee50b 100755 --- a/qa/rpc-tests/turnstile.py +++ b/qa/rpc-tests/turnstile.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2019 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Test Sprout and Sapling turnstile violations diff --git a/qa/rpc-tests/tx_expiry_helper.py b/qa/rpc-tests/tx_expiry_helper.py index 3831a3a35c2..36d1b2a4f38 100755 --- a/qa/rpc-tests/tx_expiry_helper.py +++ b/qa/rpc-tests/tx_expiry_helper.py @@ -1,6 +1,6 @@ # Copyright (c) 2019 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Common code for testing transaction expiry diff --git a/qa/rpc-tests/txn_doublespend.py b/qa/rpc-tests/txn_doublespend.py index f342a6f8b6b..3d7d4329ddc 100755 --- a/qa/rpc-tests/txn_doublespend.py +++ b/qa/rpc-tests/txn_doublespend.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Test proper accounting with malleable transactions diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index 2b35177402a..8d5e3d62ccb 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/wallet_1941.py b/qa/rpc-tests/wallet_1941.py index 7a0c482a778..5a1c186715f 100755 --- a/qa/rpc-tests/wallet_1941.py +++ b/qa/rpc-tests/wallet_1941.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2016 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # This is a regression test for #1941. diff --git a/qa/rpc-tests/wallet_addresses.py b/qa/rpc-tests/wallet_addresses.py index ef0e0bde71d..c9a6ab7c30a 100755 --- a/qa/rpc-tests/wallet_addresses.py +++ b/qa/rpc-tests/wallet_addresses.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/wallet_anchorfork.py b/qa/rpc-tests/wallet_anchorfork.py index f136498b11e..177f8e49097 100755 --- a/qa/rpc-tests/wallet_anchorfork.py +++ b/qa/rpc-tests/wallet_anchorfork.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/wallet_changeindicator.py b/qa/rpc-tests/wallet_changeindicator.py index 0a8c2bdbd99..940e314262c 100755 --- a/qa/rpc-tests/wallet_changeindicator.py +++ b/qa/rpc-tests/wallet_changeindicator.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/wallet_import_export.py b/qa/rpc-tests/wallet_import_export.py index 57f69aee519..e4a6dd6a9ab 100755 --- a/qa/rpc-tests/wallet_import_export.py +++ b/qa/rpc-tests/wallet_import_export.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/wallet_listnotes.py b/qa/rpc-tests/wallet_listnotes.py index ad2d56e1f2a..9f9b0993727 100755 --- a/qa/rpc-tests/wallet_listnotes.py +++ b/qa/rpc-tests/wallet_listnotes.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/wallet_listreceived.py b/qa/rpc-tests/wallet_listreceived.py index d5faa3d0a1b..16b384ab855 100755 --- a/qa/rpc-tests/wallet_listreceived.py +++ b/qa/rpc-tests/wallet_listreceived.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/wallet_nullifiers.py b/qa/rpc-tests/wallet_nullifiers.py index a02a7591b31..e32275dd0e4 100755 --- a/qa/rpc-tests/wallet_nullifiers.py +++ b/qa/rpc-tests/wallet_nullifiers.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2016 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/wallet_overwintertx.py b/qa/rpc-tests/wallet_overwintertx.py index c24145ababe..8915789bba4 100755 --- a/qa/rpc-tests/wallet_overwintertx.py +++ b/qa/rpc-tests/wallet_overwintertx.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/wallet_persistence.py b/qa/rpc-tests/wallet_persistence.py index 72db7c48b87..ed34f416b0c 100755 --- a/qa/rpc-tests/wallet_persistence.py +++ b/qa/rpc-tests/wallet_persistence.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/wallet_protectcoinbase.py b/qa/rpc-tests/wallet_protectcoinbase.py index e7a3b9e5a1c..465ce1500b8 100755 --- a/qa/rpc-tests/wallet_protectcoinbase.py +++ b/qa/rpc-tests/wallet_protectcoinbase.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2016 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/wallet_sapling.py b/qa/rpc-tests/wallet_sapling.py index 6fe11e5ec00..fed4fe25648 100755 --- a/qa/rpc-tests/wallet_sapling.py +++ b/qa/rpc-tests/wallet_sapling.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/wallet_shieldcoinbase.py b/qa/rpc-tests/wallet_shieldcoinbase.py index 6aa08b32ae3..804915f681f 100755 --- a/qa/rpc-tests/wallet_shieldcoinbase.py +++ b/qa/rpc-tests/wallet_shieldcoinbase.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2017 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/wallet_treestate.py b/qa/rpc-tests/wallet_treestate.py index 7f782a87dfc..6c88f0d2c19 100755 --- a/qa/rpc-tests/wallet_treestate.py +++ b/qa/rpc-tests/wallet_treestate.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2016 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/walletbackup.py b/qa/rpc-tests/walletbackup.py index f8bc54cdd9c..82030864645 100755 --- a/qa/rpc-tests/walletbackup.py +++ b/qa/rpc-tests/walletbackup.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . """ Exercise the wallet backup code. Ported from walletbackup.sh. diff --git a/qa/rpc-tests/zapwallettxes.py b/qa/rpc-tests/zapwallettxes.py index 1298ff05c8e..1a8a9c5d179 100755 --- a/qa/rpc-tests/zapwallettxes.py +++ b/qa/rpc-tests/zapwallettxes.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/zkey_import_export.py b/qa/rpc-tests/zkey_import_export.py index 4a22082210a..b0311e16b24 100755 --- a/qa/rpc-tests/zkey_import_export.py +++ b/qa/rpc-tests/zkey_import_export.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2017 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/qa/rpc-tests/zmq_test.py b/qa/rpc-tests/zmq_test.py index 38ed8e9b257..69b7542400b 100755 --- a/qa/rpc-tests/zmq_test.py +++ b/qa/rpc-tests/zmq_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2015 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Test ZMQ interface diff --git a/qa/zcash/create_wallet_200k_utxos.py b/qa/zcash/create_wallet_200k_utxos.py index d7f2d10eb06..da54e7a3c40 100755 --- a/qa/zcash/create_wallet_200k_utxos.py +++ b/qa/zcash/create_wallet_200k_utxos.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2017 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Create a large wallet diff --git a/share/genbuild.sh b/share/genbuild.sh index 3c0a591a3c9..c18d6f4fff2 100755 --- a/share/genbuild.sh +++ b/share/genbuild.sh @@ -3,7 +3,7 @@ # Copyright (c) 2012-2019 The Bitcoin Core developers # Copyright (c) 2012-2019 Bitcoin Developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php . +# file COPYING or https://www.opensource.org/licenses/mit-license.php . if [ $# -gt 1 ]; then cd "$2" diff --git a/src/Makefile.am b/src/Makefile.am index 75fa1aa3a01..c1c69dd5514 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,7 +2,7 @@ # Copyright (c) 2013-2019 The Bitcoin Core developers # Copyright (c) 2013-2019 Bitcoin Developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php . +# file COPYING or https://www.opensource.org/licenses/mit-license.php . DIST_SUBDIRS = secp256k1 univalue diff --git a/src/Makefile.test.include b/src/Makefile.test.include index c339fbf64dd..eb30cab4a8b 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -2,7 +2,7 @@ # Copyright (c) 2013-2019 The Bitcoin Core developers # Copyright (c) 2013-2019 Bitcoin Developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php . +# file COPYING or https://www.opensource.org/licenses/mit-license.php . TESTS += test/test_bitcoin noinst_PROGRAMS += test/test_bitcoin diff --git a/src/addressindex.h b/src/addressindex.h index e83c9fc2fdc..0d1f3af59f7 100644 --- a/src/addressindex.h +++ b/src/addressindex.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_ADDRESSINDEX_H #define BITCOIN_ADDRESSINDEX_H diff --git a/src/addrman.cpp b/src/addrman.cpp index c4a2e6e8069..5ae0f173404 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012 Pieter Wuille // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "addrman.h" diff --git a/src/addrman.h b/src/addrman.h index 5c77a4fdb95..bee1bd9f5f2 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -1,6 +1,6 @@ // Copyright (c) 2012 Pieter Wuille // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_ADDRMAN_H #define BITCOIN_ADDRMAN_H diff --git a/src/alert.cpp b/src/alert.cpp index ea9cbad2117..d7668453db9 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "alert.h" diff --git a/src/alert.h b/src/alert.h index 4e3b8877513..bca2f8de169 100644 --- a/src/alert.h +++ b/src/alert.h @@ -1,7 +1,7 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_ALERT_H #define BITCOIN_ALERT_H diff --git a/src/amount.cpp b/src/amount.cpp index f658c4a281d..3572e59c851 100644 --- a/src/amount.cpp +++ b/src/amount.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "amount.h" diff --git a/src/amount.h b/src/amount.h index 3d7eefc589c..9913e565e32 100644 --- a/src/amount.h +++ b/src/amount.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_AMOUNT_H #define BITCOIN_AMOUNT_H diff --git a/src/amqp/amqpabstractnotifier.cpp b/src/amqp/amqpabstractnotifier.cpp index 57686ef1d9b..30481b89d52 100644 --- a/src/amqp/amqpabstractnotifier.cpp +++ b/src/amqp/amqpabstractnotifier.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "amqpabstractnotifier.h" #include "util.h" diff --git a/src/amqp/amqpabstractnotifier.h b/src/amqp/amqpabstractnotifier.h index c993a2b3ecb..f6810961269 100644 --- a/src/amqp/amqpabstractnotifier.h +++ b/src/amqp/amqpabstractnotifier.h @@ -1,6 +1,6 @@ // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef ZCASH_AMQP_AMQPABSTRACTNOTIFIER_H #define ZCASH_AMQP_AMQPABSTRACTNOTIFIER_H diff --git a/src/amqp/amqpconfig.h b/src/amqp/amqpconfig.h index dcc5f7709ba..8b2fd6a881f 100644 --- a/src/amqp/amqpconfig.h +++ b/src/amqp/amqpconfig.h @@ -1,6 +1,6 @@ // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef ZCASH_AMQP_AMQPCONFIG_H #define ZCASH_AMQP_AMQPCONFIG_H diff --git a/src/amqp/amqpnotificationinterface.cpp b/src/amqp/amqpnotificationinterface.cpp index 66f5398ca45..0dfae00b954 100644 --- a/src/amqp/amqpnotificationinterface.cpp +++ b/src/amqp/amqpnotificationinterface.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "amqpnotificationinterface.h" #include "amqppublishnotifier.h" diff --git a/src/amqp/amqpnotificationinterface.h b/src/amqp/amqpnotificationinterface.h index 0c07ce235ea..77495a85c9f 100644 --- a/src/amqp/amqpnotificationinterface.h +++ b/src/amqp/amqpnotificationinterface.h @@ -1,6 +1,6 @@ // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef ZCASH_AMQP_AMQPNOTIFICATIONINTERFACE_H #define ZCASH_AMQP_AMQPNOTIFICATIONINTERFACE_H diff --git a/src/amqp/amqppublishnotifier.cpp b/src/amqp/amqppublishnotifier.cpp index 2704d94c2c5..2dc780273a7 100644 --- a/src/amqp/amqppublishnotifier.cpp +++ b/src/amqp/amqppublishnotifier.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "amqppublishnotifier.h" #include "chainparams.h" diff --git a/src/amqp/amqppublishnotifier.h b/src/amqp/amqppublishnotifier.h index 08b3aba08c5..2eca74444a4 100644 --- a/src/amqp/amqppublishnotifier.h +++ b/src/amqp/amqppublishnotifier.h @@ -1,6 +1,6 @@ // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef ZCASH_AMQP_AMQPPUBLISHNOTIFIER_H #define ZCASH_AMQP_AMQPPUBLISHNOTIFIER_H diff --git a/src/amqp/amqpsender.h b/src/amqp/amqpsender.h index 7fa85d89c03..eb365d3ec6f 100644 --- a/src/amqp/amqpsender.h +++ b/src/amqp/amqpsender.h @@ -1,6 +1,6 @@ // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef ZCASH_AMQP_AMQPSENDER_H #define ZCASH_AMQP_AMQPSENDER_H diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp index 2e613635761..58234d0423e 100644 --- a/src/arith_uint256.cpp +++ b/src/arith_uint256.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "arith_uint256.h" diff --git a/src/arith_uint256.h b/src/arith_uint256.h index 103c78bb8e3..833d41ef21c 100644 --- a/src/arith_uint256.h +++ b/src/arith_uint256.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_ARITH_UINT256_H #define BITCOIN_ARITH_UINT256_H diff --git a/src/asyncrpcoperation.cpp b/src/asyncrpcoperation.cpp index ff5c4cb9f1b..20186b63e39 100644 --- a/src/asyncrpcoperation.cpp +++ b/src/asyncrpcoperation.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2016 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "asyncrpcoperation.h" diff --git a/src/asyncrpcoperation.h b/src/asyncrpcoperation.h index 2b821e25688..a3bc5bf0b63 100644 --- a/src/asyncrpcoperation.h +++ b/src/asyncrpcoperation.h @@ -1,6 +1,6 @@ // Copyright (c) 2016 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef ASYNCRPCOPERATION_H diff --git a/src/asyncrpcqueue.cpp b/src/asyncrpcqueue.cpp index afe6d4bef02..e032449452f 100644 --- a/src/asyncrpcqueue.cpp +++ b/src/asyncrpcqueue.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2016 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "asyncrpcqueue.h" diff --git a/src/asyncrpcqueue.h b/src/asyncrpcqueue.h index 1a099a26365..9956405ed83 100644 --- a/src/asyncrpcqueue.h +++ b/src/asyncrpcqueue.h @@ -1,6 +1,6 @@ // Copyright (c) 2016 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef ASYNCRPCQUEUE_H #define ASYNCRPCQUEUE_H diff --git a/src/base58.cpp b/src/base58.cpp index 137ce2c9e8c..3e2f18b40f2 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "base58.h" diff --git a/src/base58.h b/src/base58.h index 3c926fca0a4..f29c3755653 100644 --- a/src/base58.h +++ b/src/base58.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . /** * Why base-58 instead of standard base-64 encoding? diff --git a/src/bech32.cpp b/src/bech32.cpp index 78c35b976a5..8910d034515 100644 --- a/src/bech32.cpp +++ b/src/bech32.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2017 Pieter Wuille // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "bech32.h" diff --git a/src/bech32.h b/src/bech32.h index 2e2823e974e..eecc6e29f5d 100644 --- a/src/bech32.h +++ b/src/bech32.h @@ -1,6 +1,6 @@ // Copyright (c) 2017 Pieter Wuille // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . // Bech32 is a string encoding format used in newer address types. // The output consists of a human-readable part (alphanumeric), a diff --git a/src/bitcoin-cli-res.rc b/src/bitcoin-cli-res.rc index d365e0b49b1..607c44420cf 100644 --- a/src/bitcoin-cli-res.rc +++ b/src/bitcoin-cli-res.rc @@ -21,7 +21,7 @@ BEGIN VALUE "FileVersion", VER_FILEVERSION_STR VALUE "InternalName", "zcash-cli" VALUE "LegalCopyright", COPYRIGHT_STR - VALUE "LegalTrademarks1", "Distributed under the MIT software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php." + VALUE "LegalTrademarks1", "Distributed under the MIT software license, see the accompanying file COPYING or https://www.opensource.org/licenses/mit-license.php ." VALUE "OriginalFilename", "zcash-cli.exe" VALUE "ProductName", "zcash-cli" VALUE "ProductVersion", VER_PRODUCTVERSION_STR diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 1de5ee43ff5..3cbf296626e 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "chainparamsbase.h" #include "clientversion.h" diff --git a/src/bitcoin-tx-res.rc b/src/bitcoin-tx-res.rc index bc8d5713475..028394e3612 100644 --- a/src/bitcoin-tx-res.rc +++ b/src/bitcoin-tx-res.rc @@ -21,7 +21,7 @@ BEGIN VALUE "FileVersion", VER_FILEVERSION_STR VALUE "InternalName", "zcash-tx" VALUE "LegalCopyright", COPYRIGHT_STR - VALUE "LegalTrademarks1", "Distributed under the MIT software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php." + VALUE "LegalTrademarks1", "Distributed under the MIT software license, see the accompanying file COPYING or https://www.opensource.org/licenses/mit-license.php ." VALUE "OriginalFilename", "zcash-tx.exe" VALUE "ProductName", "zcash-tx" VALUE "ProductVersion", VER_PRODUCTVERSION_STR diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 3ee3c01697c..60c802c78b1 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "clientversion.h" #include "coins.h" diff --git a/src/bitcoind-res.rc b/src/bitcoind-res.rc index eeb6fde5242..de544f10f19 100644 --- a/src/bitcoind-res.rc +++ b/src/bitcoind-res.rc @@ -21,7 +21,7 @@ BEGIN VALUE "FileVersion", VER_FILEVERSION_STR VALUE "InternalName", "zcashd" VALUE "LegalCopyright", COPYRIGHT_STR - VALUE "LegalTrademarks1", "Distributed under the MIT software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php." + VALUE "LegalTrademarks1", "Distributed under the MIT software license, see the accompanying file COPYING or https://www.opensource.org/licenses/mit-license.php ." VALUE "OriginalFilename", "zcashd.exe" VALUE "ProductName", "zcashd" VALUE "ProductVersion", VER_PRODUCTVERSION_STR diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 7e7f54934be..7790a6ce99c 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "clientversion.h" #include "rpc/server.h" diff --git a/src/bloom.cpp b/src/bloom.cpp index de87206592c..49dc5da695b 100644 --- a/src/bloom.cpp +++ b/src/bloom.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "bloom.h" diff --git a/src/bloom.h b/src/bloom.h index df5c30b1e26..00943610424 100644 --- a/src/bloom.h +++ b/src/bloom.h @@ -1,6 +1,6 @@ // Copyright (c) 2012-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_BLOOM_H #define BITCOIN_BLOOM_H diff --git a/src/chain.cpp b/src/chain.cpp index 39520cc8f99..35013969fef 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "chain.h" diff --git a/src/chain.h b/src/chain.h index 5a7b3ad9cf4..7512b06b448 100644 --- a/src/chain.h +++ b/src/chain.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_CHAIN_H #define BITCOIN_CHAIN_H diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 0980d78121e..e2e6f1f6ca4 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "key_io.h" #include "main.h" diff --git a/src/chainparams.h b/src/chainparams.h index 17ebe9d31a6..06b8939781d 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_CHAINPARAMS_H #define BITCOIN_CHAINPARAMS_H diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index 31f15d15d69..d306580fb16 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "chainparamsbase.h" diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h index 33765f0fc84..d17e98e01ca 100644 --- a/src/chainparamsbase.h +++ b/src/chainparamsbase.h @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_CHAINPARAMSBASE_H #define BITCOIN_CHAINPARAMSBASE_H diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index 87f4ad7f2ec..3cb619db6f1 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "checkpoints.h" diff --git a/src/checkpoints.h b/src/checkpoints.h index 5fce6fa81ef..b6501bc9a1f 100644 --- a/src/checkpoints.h +++ b/src/checkpoints.h @@ -1,6 +1,6 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_CHECKPOINTS_H #define BITCOIN_CHECKPOINTS_H diff --git a/src/checkqueue.h b/src/checkqueue.h index 20ba25bb419..157b72c3a3b 100644 --- a/src/checkqueue.h +++ b/src/checkqueue.h @@ -1,6 +1,6 @@ // Copyright (c) 2012-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_CHECKQUEUE_H #define BITCOIN_CHECKQUEUE_H diff --git a/src/clientversion.cpp b/src/clientversion.cpp index ae67e678f1a..ef8961ea5de 100644 --- a/src/clientversion.cpp +++ b/src/clientversion.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "clientversion.h" diff --git a/src/clientversion.h b/src/clientversion.h index 259d6d4b3e5..edca19ca9e4 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers // Copyright (c) 2016-2019 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_CLIENTVERSION_H #define BITCOIN_CLIENTVERSION_H diff --git a/src/coincontrol.h b/src/coincontrol.h index 3e8de83c395..dc0e8e51a92 100644 --- a/src/coincontrol.h +++ b/src/coincontrol.h @@ -1,6 +1,6 @@ // Copyright (c) 2011-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_COINCONTROL_H #define BITCOIN_COINCONTROL_H diff --git a/src/coins.cpp b/src/coins.cpp index 4312fac012f..09a8ccf98c5 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "coins.h" diff --git a/src/coins.h b/src/coins.h index 4f782ee17a8..c29c1331505 100644 --- a/src/coins.h +++ b/src/coins.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_COINS_H #define BITCOIN_COINS_H diff --git a/src/compat.h b/src/compat.h index feaa544e256..b8c238f22ef 100644 --- a/src/compat.h +++ b/src/compat.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_COMPAT_H #define BITCOIN_COMPAT_H diff --git a/src/compat/byteswap.h b/src/compat/byteswap.h index 899220bdc54..f5cbc9f7eb9 100644 --- a/src/compat/byteswap.h +++ b/src/compat/byteswap.h @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_COMPAT_BYTESWAP_H #define BITCOIN_COMPAT_BYTESWAP_H diff --git a/src/compat/endian.h b/src/compat/endian.h index 9fec2a07fab..ae9846ff370 100644 --- a/src/compat/endian.h +++ b/src/compat/endian.h @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_COMPAT_ENDIAN_H #define BITCOIN_COMPAT_ENDIAN_H diff --git a/src/compat/glibc_compat.cpp b/src/compat/glibc_compat.cpp index 3b9c70df7fe..a80137cd8d4 100644 --- a/src/compat/glibc_compat.cpp +++ b/src/compat/glibc_compat.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #if defined(HAVE_CONFIG_H) #include "config/bitcoin-config.h" diff --git a/src/compat/glibc_sanity.cpp b/src/compat/glibc_sanity.cpp index d62d74d462c..71402559d8b 100644 --- a/src/compat/glibc_sanity.cpp +++ b/src/compat/glibc_sanity.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #if defined(HAVE_CONFIG_H) #include "config/bitcoin-config.h" diff --git a/src/compat/glibcxx_sanity.cpp b/src/compat/glibcxx_sanity.cpp index cee8a98c7f5..bbba438ea08 100644 --- a/src/compat/glibcxx_sanity.cpp +++ b/src/compat/glibcxx_sanity.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include #include diff --git a/src/compat/sanity.h b/src/compat/sanity.h index 909c4f6da82..64dcade7823 100644 --- a/src/compat/sanity.h +++ b/src/compat/sanity.h @@ -1,6 +1,6 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_COMPAT_SANITY_H #define BITCOIN_COMPAT_SANITY_H diff --git a/src/compat/strnlen.cpp b/src/compat/strnlen.cpp index 1ac266c2d1b..1a56310af2a 100644 --- a/src/compat/strnlen.cpp +++ b/src/compat/strnlen.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #if defined(HAVE_CONFIG_H) #include "config/bitcoin-config.h" diff --git a/src/compressor.cpp b/src/compressor.cpp index 20c154fc1e5..e91897149da 100644 --- a/src/compressor.cpp +++ b/src/compressor.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "compressor.h" diff --git a/src/compressor.h b/src/compressor.h index 961365d2618..e9c2cbdbbfc 100644 --- a/src/compressor.h +++ b/src/compressor.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_COMPRESSOR_H #define BITCOIN_COMPRESSOR_H diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index c0a3138aabc..865b280e778 100644 --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_CONSENSUS_CONSENSUS_H #define BITCOIN_CONSENSUS_CONSENSUS_H diff --git a/src/consensus/params.h b/src/consensus/params.h index 9cd3a84617d..496b68cb304 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_CONSENSUS_PARAMS_H #define BITCOIN_CONSENSUS_PARAMS_H diff --git a/src/consensus/upgrades.cpp b/src/consensus/upgrades.cpp index e11aaa260e4..e7142977559 100644 --- a/src/consensus/upgrades.cpp +++ b/src/consensus/upgrades.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2018 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "consensus/upgrades.h" diff --git a/src/consensus/upgrades.h b/src/consensus/upgrades.h index 920ec1ea896..0126399a60e 100644 --- a/src/consensus/upgrades.h +++ b/src/consensus/upgrades.h @@ -1,6 +1,6 @@ // Copyright (c) 2018 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef ZCASH_CONSENSUS_UPGRADES_H #define ZCASH_CONSENSUS_UPGRADES_H diff --git a/src/consensus/validation.h b/src/consensus/validation.h index c62adcd8fc3..0ad7701b16d 100644 --- a/src/consensus/validation.h +++ b/src/consensus/validation.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_CONSENSUS_VALIDATION_H #define BITCOIN_CONSENSUS_VALIDATION_H diff --git a/src/core_io.h b/src/core_io.h index ba5b4e6487c..0abfb4b10fd 100644 --- a/src/core_io.h +++ b/src/core_io.h @@ -1,6 +1,6 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_CORE_IO_H #define BITCOIN_CORE_IO_H diff --git a/src/core_memusage.h b/src/core_memusage.h index b2f4a28ae36..bf955ae4cad 100644 --- a/src/core_memusage.h +++ b/src/core_memusage.h @@ -1,6 +1,6 @@ // Copyright (c) 2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_CORE_MEMUSAGE_H #define BITCOIN_CORE_MEMUSAGE_H diff --git a/src/core_read.cpp b/src/core_read.cpp index 4be24f8e097..23b4a610ca6 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "core_io.h" diff --git a/src/core_write.cpp b/src/core_write.cpp index 43344656b70..89a545a9945 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "core_io.h" diff --git a/src/crypto/common.h b/src/crypto/common.h index 9d2100af98b..fd62087b7f0 100644 --- a/src/crypto/common.h +++ b/src/crypto/common.h @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_CRYPTO_COMMON_H #define BITCOIN_CRYPTO_COMMON_H diff --git a/src/crypto/equihash.cpp b/src/crypto/equihash.cpp index 97eea42e356..c72ce5e85a9 100644 --- a/src/crypto/equihash.cpp +++ b/src/crypto/equihash.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2016 Jack Grigg // Copyright (c) 2016 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . // Implementation of the Equihash Proof-of-Work algorithm. // diff --git a/src/crypto/equihash.h b/src/crypto/equihash.h index 6691844bad4..034ed3592c4 100644 --- a/src/crypto/equihash.h +++ b/src/crypto/equihash.h @@ -1,7 +1,7 @@ // Copyright (c) 2016 Jack Grigg // Copyright (c) 2016 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_EQUIHASH_H #define BITCOIN_EQUIHASH_H diff --git a/src/crypto/equihash.tcc b/src/crypto/equihash.tcc index 625749e4745..8279396d1ac 100644 --- a/src/crypto/equihash.tcc +++ b/src/crypto/equihash.tcc @@ -1,7 +1,7 @@ // Copyright (c) 2016 Jack Grigg // Copyright (c) 2016 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include #include diff --git a/src/crypto/hmac_sha256.cpp b/src/crypto/hmac_sha256.cpp index 3c791625d01..951c569eda5 100644 --- a/src/crypto/hmac_sha256.cpp +++ b/src/crypto/hmac_sha256.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "crypto/hmac_sha256.h" diff --git a/src/crypto/hmac_sha256.h b/src/crypto/hmac_sha256.h index 1519c1457e0..c7627da2e84 100644 --- a/src/crypto/hmac_sha256.h +++ b/src/crypto/hmac_sha256.h @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_CRYPTO_HMAC_SHA256_H #define BITCOIN_CRYPTO_HMAC_SHA256_H diff --git a/src/crypto/hmac_sha512.cpp b/src/crypto/hmac_sha512.cpp index 5939c6ec47f..ca7b00c63f8 100644 --- a/src/crypto/hmac_sha512.cpp +++ b/src/crypto/hmac_sha512.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "crypto/hmac_sha512.h" diff --git a/src/crypto/hmac_sha512.h b/src/crypto/hmac_sha512.h index 17dee61ea8e..61514636bdf 100644 --- a/src/crypto/hmac_sha512.h +++ b/src/crypto/hmac_sha512.h @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_CRYPTO_HMAC_SHA512_H #define BITCOIN_CRYPTO_HMAC_SHA512_H diff --git a/src/crypto/ripemd160.cpp b/src/crypto/ripemd160.cpp index 77c9acfc26e..70dad5e5da1 100644 --- a/src/crypto/ripemd160.cpp +++ b/src/crypto/ripemd160.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "crypto/ripemd160.h" diff --git a/src/crypto/ripemd160.h b/src/crypto/ripemd160.h index 687204fdae8..b56aac900bb 100644 --- a/src/crypto/ripemd160.h +++ b/src/crypto/ripemd160.h @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_CRYPTO_RIPEMD160_H #define BITCOIN_CRYPTO_RIPEMD160_H diff --git a/src/crypto/sha1.cpp b/src/crypto/sha1.cpp index 0b895b33a29..c437f9d1f43 100644 --- a/src/crypto/sha1.cpp +++ b/src/crypto/sha1.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "crypto/sha1.h" diff --git a/src/crypto/sha1.h b/src/crypto/sha1.h index 7b2a21bc6c6..553f4928a53 100644 --- a/src/crypto/sha1.h +++ b/src/crypto/sha1.h @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_CRYPTO_SHA1_H #define BITCOIN_CRYPTO_SHA1_H diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index 39583c26afa..ff1ae2f0592 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "crypto/sha256.h" diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h index 8ecb7348df8..3dff0dd2b56 100644 --- a/src/crypto/sha256.h +++ b/src/crypto/sha256.h @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_CRYPTO_SHA256_H #define BITCOIN_CRYPTO_SHA256_H diff --git a/src/crypto/sha512.cpp b/src/crypto/sha512.cpp index 564127cc319..8f02862fa54 100644 --- a/src/crypto/sha512.cpp +++ b/src/crypto/sha512.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "crypto/sha512.h" diff --git a/src/crypto/sha512.h b/src/crypto/sha512.h index f1f17caf90c..194cc61f9f3 100644 --- a/src/crypto/sha512.h +++ b/src/crypto/sha512.h @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_CRYPTO_SHA512_H #define BITCOIN_CRYPTO_SHA512_H diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp index b34be5af7bc..494ab98ce85 100644 --- a/src/dbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "dbwrapper.h" diff --git a/src/dbwrapper.h b/src/dbwrapper.h index e3f9a265295..0996e9cdae8 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -1,6 +1,6 @@ // Copyright (c) 2012-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_DBWRAPPER_H #define BITCOIN_DBWRAPPER_H diff --git a/src/deprecation.cpp b/src/deprecation.cpp index 5dec87d91b9..79b55f29ae2 100644 --- a/src/deprecation.cpp +++ b/src/deprecation.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "deprecation.h" diff --git a/src/deprecation.h b/src/deprecation.h index 96ccd2ed717..ab7ffb299f3 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -1,6 +1,6 @@ // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef ZCASH_DEPRECATION_H #define ZCASH_DEPRECATION_H diff --git a/src/hash.cpp b/src/hash.cpp index 9711293e386..2070e0918ac 100644 --- a/src/hash.cpp +++ b/src/hash.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2013-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "hash.h" #include "crypto/common.h" diff --git a/src/hash.h b/src/hash.h index 3e56f4a86b5..fe1607277b1 100644 --- a/src/hash.h +++ b/src/hash.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_HASH_H #define BITCOIN_HASH_H diff --git a/src/httprpc.h b/src/httprpc.h index d3544571887..cde795ae669 100644 --- a/src/httprpc.h +++ b/src/httprpc.h @@ -1,6 +1,6 @@ // Copyright (c) 2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_HTTPRPC_H #define BITCOIN_HTTPRPC_H diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 2ee8d178ff7..9227e26bbd1 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "httpserver.h" diff --git a/src/httpserver.h b/src/httpserver.h index 93fb5d8d60d..68d26ce2e01 100644 --- a/src/httpserver.h +++ b/src/httpserver.h @@ -1,6 +1,6 @@ // Copyright (c) 2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_HTTPSERVER_H #define BITCOIN_HTTPSERVER_H diff --git a/src/init.cpp b/src/init.cpp index 2743f473104..2f44f84c598 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #if defined(HAVE_CONFIG_H) #include "config/bitcoin-config.h" diff --git a/src/init.h b/src/init.h index 710e43c690e..13462051904 100644 --- a/src/init.h +++ b/src/init.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_INIT_H #define BITCOIN_INIT_H diff --git a/src/key.cpp b/src/key.cpp index 5688b130218..2406dcd7c7f 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "key.h" diff --git a/src/key.h b/src/key.h index 8d64151e38a..762fd1ecbb9 100644 --- a/src/key.h +++ b/src/key.h @@ -2,7 +2,7 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_KEY_H #define BITCOIN_KEY_H diff --git a/src/key_io.cpp b/src/key_io.cpp index 7ffb619746f..f118e3625b7 100644 --- a/src/key_io.cpp +++ b/src/key_io.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2014-2016 The Bitcoin Core developers // Copyright (c) 2016-2018 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include diff --git a/src/key_io.h b/src/key_io.h index 47ca84fb8d5..53795d0ffc1 100644 --- a/src/key_io.h +++ b/src/key_io.h @@ -2,7 +2,7 @@ // Copyright (c) 2009-2015 The Bitcoin Core developers // Copyright (c) 2016-2018 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_KEYIO_H #define BITCOIN_KEYIO_H diff --git a/src/keystore.cpp b/src/keystore.cpp index e1e3ae89b01..6c94bf05afd 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "keystore.h" diff --git a/src/keystore.h b/src/keystore.h index 6ff34b20de4..7c78895dca7 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_KEYSTORE_H #define BITCOIN_KEYSTORE_H diff --git a/src/limitedmap.h b/src/limitedmap.h index e8ea549653b..0e88c056ebb 100644 --- a/src/limitedmap.h +++ b/src/limitedmap.h @@ -1,6 +1,6 @@ // Copyright (c) 2012-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_LIMITEDMAP_H #define BITCOIN_LIMITEDMAP_H diff --git a/src/main.cpp b/src/main.cpp index 9549610d919..8f22e3e83aa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "main.h" diff --git a/src/main.h b/src/main.h index cd2e39a0957..c414f13d504 100644 --- a/src/main.h +++ b/src/main.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_MAIN_H #define BITCOIN_MAIN_H diff --git a/src/memusage.h b/src/memusage.h index 0b232d88bca..87e6525578c 100644 --- a/src/memusage.h +++ b/src/memusage.h @@ -1,6 +1,6 @@ // Copyright (c) 2015 The Bitcoin developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_MEMUSAGE_H #define BITCOIN_MEMUSAGE_H diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp index a368b31add7..25d3dc69784 100644 --- a/src/merkleblock.cpp +++ b/src/merkleblock.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "merkleblock.h" diff --git a/src/merkleblock.h b/src/merkleblock.h index 97223ed926a..5f9c02f5078 100644 --- a/src/merkleblock.h +++ b/src/merkleblock.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_MERKLEBLOCK_H #define BITCOIN_MERKLEBLOCK_H diff --git a/src/metrics.cpp b/src/metrics.cpp index 9eecc22e5d0..e7875a1292c 100644 --- a/src/metrics.cpp +++ b/src/metrics.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2016 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "metrics.h" diff --git a/src/metrics.h b/src/metrics.h index 2d60d30ca6a..33bd45f6762 100644 --- a/src/metrics.h +++ b/src/metrics.h @@ -1,6 +1,6 @@ // Copyright (c) 2016 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "uint256.h" diff --git a/src/miner.cpp b/src/miner.cpp index aa3306524ad..33a07c5a305 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "miner.h" #ifdef ENABLE_MINING diff --git a/src/miner.h b/src/miner.h index 9059be633e5..e71685898c8 100644 --- a/src/miner.h +++ b/src/miner.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_MINER_H #define BITCOIN_MINER_H diff --git a/src/mruset.h b/src/mruset.h index 398aa173bf1..40dee4c4b0f 100644 --- a/src/mruset.h +++ b/src/mruset.h @@ -1,6 +1,6 @@ // Copyright (c) 2012-2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_MRUSET_H #define BITCOIN_MRUSET_H diff --git a/src/net.cpp b/src/net.cpp index 475643199f9..fa2e83710a1 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #if defined(HAVE_CONFIG_H) #include "config/bitcoin-config.h" diff --git a/src/net.h b/src/net.h index 16df97a1964..63b21f2ca49 100644 --- a/src/net.h +++ b/src/net.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_NET_H #define BITCOIN_NET_H diff --git a/src/netbase.cpp b/src/netbase.cpp index 289b623618d..c2e779846b9 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifdef HAVE_CONFIG_H #include "config/bitcoin-config.h" diff --git a/src/netbase.h b/src/netbase.h index a50efc42889..1f43391c907 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -1,6 +1,6 @@ // Copyright (c) 2009-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_NETBASE_H #define BITCOIN_NETBASE_H diff --git a/src/noui.cpp b/src/noui.cpp index 0d9207c11a3..a5ecd9f276a 100644 --- a/src/noui.cpp +++ b/src/noui.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "noui.h" diff --git a/src/noui.h b/src/noui.h index 15cd30a639d..935a1c5dc52 100644 --- a/src/noui.h +++ b/src/noui.h @@ -1,6 +1,6 @@ // Copyright (c) 2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_NOUI_H #define BITCOIN_NOUI_H diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index f08cec3119f..da182b08ef6 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2015 The Bitcoin developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "policy/fees.h" diff --git a/src/policy/fees.h b/src/policy/fees.h index 52b0c36cdc7..ae494a9a24b 100644 --- a/src/policy/fees.h +++ b/src/policy/fees.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2015 The Bitcoin developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_POLICYESTIMATOR_H #define BITCOIN_POLICYESTIMATOR_H diff --git a/src/pow.cpp b/src/pow.cpp index ec0410acca2..1f678ce6993 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "pow.h" diff --git a/src/pow.h b/src/pow.h index e3cf822d8dd..94752fb1c87 100644 --- a/src/pow.h +++ b/src/pow.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_POW_H #define BITCOIN_POW_H diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index 430ac872186..ab80e3255de 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "primitives/block.h" diff --git a/src/primitives/block.h b/src/primitives/block.h index 489d54711ef..d8f65970335 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_PRIMITIVES_BLOCK_H #define BITCOIN_PRIMITIVES_BLOCK_H diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index b54981b4808..49ee45dfcfd 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "primitives/transaction.h" diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 394a087c464..20011e9b5fb 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_PRIMITIVES_TRANSACTION_H #define BITCOIN_PRIMITIVES_TRANSACTION_H diff --git a/src/protocol.cpp b/src/protocol.cpp index dd855aa33aa..ec2fbbfca93 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "protocol.h" diff --git a/src/protocol.h b/src/protocol.h index d908191ccbc..6d9e928b195 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef __cplusplus #error This header can only be compiled as C++. diff --git a/src/pubkey.cpp b/src/pubkey.cpp index 53e94fbdb54..adabd11d127 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "pubkey.h" diff --git a/src/pubkey.h b/src/pubkey.h index 12f11c2491d..871f511796e 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -2,7 +2,7 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_PUBKEY_H #define BITCOIN_PUBKEY_H diff --git a/src/random.cpp b/src/random.cpp index 29faa32a77b..6c4d1bf1349 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "random.h" diff --git a/src/random.h b/src/random.h index 8cec678ef99..38b66bf0fb5 100644 --- a/src/random.h +++ b/src/random.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_RANDOM_H #define BITCOIN_RANDOM_H diff --git a/src/rest.cpp b/src/rest.cpp index e70ce517aac..08f21781552 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "chainparams.h" #include "primitives/block.h" diff --git a/src/reverselock.h b/src/reverselock.h index fac1ccb7931..85d2d964f6a 100644 --- a/src/reverselock.h +++ b/src/reverselock.h @@ -1,6 +1,6 @@ // Copyright (c) 2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_REVERSELOCK_H #define BITCOIN_REVERSELOCK_H diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index c0ca1f07c43..580ba8b11c7 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "amount.h" #include "chain.h" diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 61c521a7b97..05c419068cb 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "rpc/client.h" #include "rpc/protocol.h" diff --git a/src/rpc/client.h b/src/rpc/client.h index 8937a56f035..7c3ee3cc0ab 100644 --- a/src/rpc/client.h +++ b/src/rpc/client.h @@ -1,7 +1,7 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_RPCCLIENT_H #define BITCOIN_RPCCLIENT_H diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index a75ab5924b1..d53ba0645c2 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "amount.h" #include "chainparams.h" diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 589fbf5c6f3..f732f1b9267 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "clientversion.h" #include "init.h" diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 8f738e16a4e..8b38cb89c41 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "rpc/server.h" diff --git a/src/rpc/protocol.cpp b/src/rpc/protocol.cpp index 7713a54b394..1361fe6f8ea 100644 --- a/src/rpc/protocol.cpp +++ b/src/rpc/protocol.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "rpc/protocol.h" diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h index 816ce9ec5ca..5e12d0a4fa2 100644 --- a/src/rpc/protocol.h +++ b/src/rpc/protocol.h @@ -1,7 +1,7 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_RPCPROTOCOL_H #define BITCOIN_RPCPROTOCOL_H diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 612323abc46..26de01a9501 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "consensus/upgrades.h" #include "consensus/validation.h" diff --git a/src/rpc/register.h b/src/rpc/register.h index 01aa58a25d8..4e0e05a04c3 100644 --- a/src/rpc/register.h +++ b/src/rpc/register.h @@ -1,6 +1,6 @@ // Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_RPCREGISTER_H #define BITCOIN_RPCREGISTER_H diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 4e18cfcb79f..1a80577fb38 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "rpc/server.h" diff --git a/src/rpc/server.h b/src/rpc/server.h index 6ae4279287a..63758f9dd93 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -1,7 +1,7 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_RPCSERVER_H #define BITCOIN_RPCSERVER_H diff --git a/src/scheduler.cpp b/src/scheduler.cpp index 8729f2a5a51..ecd904cdec3 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "scheduler.h" diff --git a/src/scheduler.h b/src/scheduler.h index 436659e58bb..a7978260313 100644 --- a/src/scheduler.h +++ b/src/scheduler.h @@ -1,6 +1,6 @@ // Copyright (c) 2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_SCHEDULER_H #define BITCOIN_SCHEDULER_H diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index bec6cff7664..b3cad00a8fc 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "interpreter.h" diff --git a/src/script/interpreter.h b/src/script/interpreter.h index 8315c825229..e88528cf5be 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_SCRIPT_INTERPRETER_H #define BITCOIN_SCRIPT_INTERPRETER_H diff --git a/src/script/script.cpp b/src/script/script.cpp index bcd1c6b2d11..bbbc7cdb3c1 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "script.h" diff --git a/src/script/script.h b/src/script/script.h index 2a511cd2eb5..3b886e58141 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_SCRIPT_SCRIPT_H #define BITCOIN_SCRIPT_SCRIPT_H diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp index f1aa1fb408a..fa0cd18585d 100644 --- a/src/script/script_error.cpp +++ b/src/script/script_error.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "script_error.h" diff --git a/src/script/script_error.h b/src/script/script_error.h index bb10b8a2932..cae125c13eb 100644 --- a/src/script/script_error.h +++ b/src/script/script_error.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_SCRIPT_SCRIPT_ERROR_H #define BITCOIN_SCRIPT_SCRIPT_ERROR_H diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp index eee96e7c2d1..50e475558ce 100644 --- a/src/script/sigcache.cpp +++ b/src/script/sigcache.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "sigcache.h" diff --git a/src/script/sigcache.h b/src/script/sigcache.h index 3583bd45232..28de2675139 100644 --- a/src/script/sigcache.h +++ b/src/script/sigcache.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_SCRIPT_SIGCACHE_H #define BITCOIN_SCRIPT_SIGCACHE_H diff --git a/src/script/sign.cpp b/src/script/sign.cpp index a4f642f9721..a6434e80c19 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "script/sign.h" diff --git a/src/script/sign.h b/src/script/sign.h index f531ad0d822..ee457423a5a 100644 --- a/src/script/sign.h +++ b/src/script/sign.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_SCRIPT_SIGN_H #define BITCOIN_SCRIPT_SIGN_H diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 12df6d8556a..209e8879d93 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "script/standard.h" diff --git a/src/script/standard.h b/src/script/standard.h index 40b3c329d6c..94cd119bf19 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_SCRIPT_STANDARD_H #define BITCOIN_SCRIPT_STANDARD_H diff --git a/src/script/zcashconsensus.cpp b/src/script/zcashconsensus.cpp index 50d732fffe5..ec609155102 100644 --- a/src/script/zcashconsensus.cpp +++ b/src/script/zcashconsensus.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "zcashconsensus.h" diff --git a/src/script/zcashconsensus.h b/src/script/zcashconsensus.h index ff13471c681..a9176dbecf1 100644 --- a/src/script/zcashconsensus.h +++ b/src/script/zcashconsensus.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_ZCASHCONSENSUS_H #define BITCOIN_ZCASHCONSENSUS_H diff --git a/src/secp256k1/contrib/lax_der_parsing.c b/src/secp256k1/contrib/lax_der_parsing.c index 5b141a99481..200dcff751c 100644 --- a/src/secp256k1/contrib/lax_der_parsing.c +++ b/src/secp256k1/contrib/lax_der_parsing.c @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/contrib/lax_der_parsing.h b/src/secp256k1/contrib/lax_der_parsing.h index 7eaf63bf6a0..4287bc6af7c 100644 --- a/src/secp256k1/contrib/lax_der_parsing.h +++ b/src/secp256k1/contrib/lax_der_parsing.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/contrib/lax_der_privatekey_parsing.c b/src/secp256k1/contrib/lax_der_privatekey_parsing.c index c2e63b4b8d7..f7f4fdca777 100644 --- a/src/secp256k1/contrib/lax_der_privatekey_parsing.c +++ b/src/secp256k1/contrib/lax_der_privatekey_parsing.c @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2014, 2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/contrib/lax_der_privatekey_parsing.h b/src/secp256k1/contrib/lax_der_privatekey_parsing.h index fece261fb9e..6a652b0d181 100644 --- a/src/secp256k1/contrib/lax_der_privatekey_parsing.h +++ b/src/secp256k1/contrib/lax_der_privatekey_parsing.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2014, 2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/asm/field_10x26_arm.s b/src/secp256k1/src/asm/field_10x26_arm.s index 5a9cc3ffcfd..04f5b07a16e 100644 --- a/src/secp256k1/src/asm/field_10x26_arm.s +++ b/src/secp256k1/src/asm/field_10x26_arm.s @@ -1,9 +1,9 @@ @ 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 http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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. diff --git a/src/secp256k1/src/basic-config.h b/src/secp256k1/src/basic-config.h index fc588061ca4..5af52c2c255 100644 --- a/src/secp256k1/src/basic-config.h +++ b/src/secp256k1/src/basic-config.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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_BASIC_CONFIG_H #define SECP256K1_BASIC_CONFIG_H diff --git a/src/secp256k1/src/bench.h b/src/secp256k1/src/bench.h index d5ebe01301b..24511e01ce5 100644 --- a/src/secp256k1/src/bench.h +++ b/src/secp256k1/src/bench.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/bench_ecdh.c b/src/secp256k1/src/bench_ecdh.c index 2de5126d634..74cc66a39f9 100644 --- a/src/secp256k1/src/bench_ecdh.c +++ b/src/secp256k1/src/bench_ecdh.c @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2015 Pieter Wuille, Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 .* + ************************************************************************/ #include diff --git a/src/secp256k1/src/bench_internal.c b/src/secp256k1/src/bench_internal.c index 9b30c50d0be..b630482de7b 100644 --- a/src/secp256k1/src/bench_internal.c +++ b/src/secp256k1/src/bench_internal.c @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2014-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 "include/secp256k1.h" diff --git a/src/secp256k1/src/bench_recover.c b/src/secp256k1/src/bench_recover.c index 506fc1880e6..531c0216555 100644 --- a/src/secp256k1/src/bench_recover.c +++ b/src/secp256k1/src/bench_recover.c @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2014-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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.h" #include "include/secp256k1_recovery.h" diff --git a/src/secp256k1/src/bench_sign.c b/src/secp256k1/src/bench_sign.c index 544b43963c8..4f4611d0200 100644 --- a/src/secp256k1/src/bench_sign.c +++ b/src/secp256k1/src/bench_sign.c @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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/secp256k1.h" #include "util.h" diff --git a/src/secp256k1/src/bench_verify.c b/src/secp256k1/src/bench_verify.c index 418defa0aa2..fec74efe6e9 100644 --- a/src/secp256k1/src/bench_verify.c +++ b/src/secp256k1/src/bench_verify.c @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/ecdsa.h b/src/secp256k1/src/ecdsa.h index 80590c7cc86..20a068970bd 100644 --- a/src/secp256k1/src/ecdsa.h +++ b/src/secp256k1/src/ecdsa.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/ecdsa_impl.h b/src/secp256k1/src/ecdsa_impl.h index c3400042d83..d7ce5feb922 100644 --- a/src/secp256k1/src/ecdsa_impl.h +++ b/src/secp256k1/src/ecdsa_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/eckey.h b/src/secp256k1/src/eckey.h index b621f1e6c39..85cbbdc0344 100644 --- a/src/secp256k1/src/eckey.h +++ b/src/secp256k1/src/eckey.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/eckey_impl.h b/src/secp256k1/src/eckey_impl.h index 1ab9a68ec04..9fb910e4cea 100644 --- a/src/secp256k1/src/eckey_impl.h +++ b/src/secp256k1/src/eckey_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/ecmult.h b/src/secp256k1/src/ecmult.h index 6d44aba60b5..ac3e344b20e 100644 --- a/src/secp256k1/src/ecmult.h +++ b/src/secp256k1/src/ecmult.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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_ECMULT_H #define SECP256K1_ECMULT_H diff --git a/src/secp256k1/src/ecmult_const.h b/src/secp256k1/src/ecmult_const.h index 72bf7d7582f..9e4e8a07ab2 100644 --- a/src/secp256k1/src/ecmult_const.h +++ b/src/secp256k1/src/ecmult_const.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/ecmult_const_impl.h b/src/secp256k1/src/ecmult_const_impl.h index 7d7a172b7b3..fd71d6b242f 100644 --- a/src/secp256k1/src/ecmult_const_impl.h +++ b/src/secp256k1/src/ecmult_const_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2015 Pieter Wuille, Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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_ECMULT_CONST_IMPL_H #define SECP256K1_ECMULT_CONST_IMPL_H diff --git a/src/secp256k1/src/ecmult_gen.h b/src/secp256k1/src/ecmult_gen.h index 7564b7015f0..8045394b7d8 100644 --- a/src/secp256k1/src/ecmult_gen.h +++ b/src/secp256k1/src/ecmult_gen.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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_ECMULT_GEN_H #define SECP256K1_ECMULT_GEN_H diff --git a/src/secp256k1/src/ecmult_gen_impl.h b/src/secp256k1/src/ecmult_gen_impl.h index 714f02e94c9..5c3eedcf1a9 100644 --- a/src/secp256k1/src/ecmult_gen_impl.h +++ b/src/secp256k1/src/ecmult_gen_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 .* + ************************************************************************/ #ifndef SECP256K1_ECMULT_GEN_IMPL_H #define SECP256K1_ECMULT_GEN_IMPL_H diff --git a/src/secp256k1/src/ecmult_impl.h b/src/secp256k1/src/ecmult_impl.h index 93d3794cb43..01339b275d5 100644 --- a/src/secp256k1/src/ecmult_impl.h +++ b/src/secp256k1/src/ecmult_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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_ECMULT_IMPL_H #define SECP256K1_ECMULT_IMPL_H diff --git a/src/secp256k1/src/field.h b/src/secp256k1/src/field.h index bb6692ad578..f0788454533 100644 --- a/src/secp256k1/src/field.h +++ b/src/secp256k1/src/field.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/field_10x26.h b/src/secp256k1/src/field_10x26.h index 727c5267fbb..30699eca815 100644 --- a/src/secp256k1/src/field_10x26.h +++ b/src/secp256k1/src/field_10x26.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/field_10x26_impl.h b/src/secp256k1/src/field_10x26_impl.h index 94f8132fc8e..d7918ac1526 100644 --- a/src/secp256k1/src/field_10x26_impl.h +++ b/src/secp256k1/src/field_10x26_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/field_5x52.h b/src/secp256k1/src/field_5x52.h index bccd8feb4dd..87a0687651b 100644 --- a/src/secp256k1/src/field_5x52.h +++ b/src/secp256k1/src/field_5x52.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/field_5x52_asm_impl.h b/src/secp256k1/src/field_5x52_asm_impl.h index 1fc3171f6b0..3c5ccc6da7d 100644 --- a/src/secp256k1/src/field_5x52_asm_impl.h +++ b/src/secp256k1/src/field_5x52_asm_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013-2014 Diederik Huys, Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * Copyright (c) 2013-2014 Diederik Huys, Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php .* + ************************************************************************/ /** * Changelog: diff --git a/src/secp256k1/src/field_5x52_impl.h b/src/secp256k1/src/field_5x52_impl.h index 957c61b0145..2ad914f16c6 100644 --- a/src/secp256k1/src/field_5x52_impl.h +++ b/src/secp256k1/src/field_5x52_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/field_5x52_int128_impl.h b/src/secp256k1/src/field_5x52_int128_impl.h index 95a0d1791c0..0137481ad94 100644 --- a/src/secp256k1/src/field_5x52_int128_impl.h +++ b/src/secp256k1/src/field_5x52_int128_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/field_impl.h b/src/secp256k1/src/field_impl.h index 20428648af3..bb30b2af231 100644 --- a/src/secp256k1/src/field_impl.h +++ b/src/secp256k1/src/field_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/gen_context.c b/src/secp256k1/src/gen_context.c index 1835fd491d1..8016875bfd8 100644 --- a/src/secp256k1/src/gen_context.c +++ b/src/secp256k1/src/gen_context.c @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014, 2015 Thomas Daede, Cory Fields * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * Copyright (c) 2013, 2014, 2015 Thomas Daede, Cory Fields * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php .* + ************************************************************************/ #define USE_BASIC_CONFIG 1 diff --git a/src/secp256k1/src/group.h b/src/secp256k1/src/group.h index ea1302deb82..6d9d7fa1e03 100644 --- a/src/secp256k1/src/group.h +++ b/src/secp256k1/src/group.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/group_impl.h b/src/secp256k1/src/group_impl.h index b31b6c12efe..80c3122c6b6 100644 --- a/src/secp256k1/src/group_impl.h +++ b/src/secp256k1/src/group_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/hash.h b/src/secp256k1/src/hash.h index de26e4b89f8..7aacc85bf46 100644 --- a/src/secp256k1/src/hash.h +++ b/src/secp256k1/src/hash.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/hash_impl.h b/src/secp256k1/src/hash_impl.h index c06db9e3382..2f3f7922bab 100644 --- a/src/secp256k1/src/hash_impl.h +++ b/src/secp256k1/src/hash_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/modules/ecdh/main_impl.h b/src/secp256k1/src/modules/ecdh/main_impl.h index bd8739eeb1f..1c7a54cd67c 100644 --- a/src/secp256k1/src/modules/ecdh/main_impl.h +++ b/src/secp256k1/src/modules/ecdh/main_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/modules/ecdh/tests_impl.h b/src/secp256k1/src/modules/ecdh/tests_impl.h index 0c53f8ee08b..b7562952c5c 100644 --- a/src/secp256k1/src/modules/ecdh/tests_impl.h +++ b/src/secp256k1/src/modules/ecdh/tests_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/modules/recovery/main_impl.h b/src/secp256k1/src/modules/recovery/main_impl.h index 2f6691c5a13..da2140894b8 100755 --- a/src/secp256k1/src/modules/recovery/main_impl.h +++ b/src/secp256k1/src/modules/recovery/main_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/modules/recovery/tests_impl.h b/src/secp256k1/src/modules/recovery/tests_impl.h index 5c9bbe86101..81a12687830 100644 --- a/src/secp256k1/src/modules/recovery/tests_impl.h +++ b/src/secp256k1/src/modules/recovery/tests_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/num.h b/src/secp256k1/src/num.h index 49f2dd791d5..eee697d57e9 100644 --- a/src/secp256k1/src/num.h +++ b/src/secp256k1/src/num.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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_NUM_H #define SECP256K1_NUM_H diff --git a/src/secp256k1/src/num_gmp.h b/src/secp256k1/src/num_gmp.h index 3619844bd51..1885ab2e23a 100644 --- a/src/secp256k1/src/num_gmp.h +++ b/src/secp256k1/src/num_gmp.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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_NUM_REPR_H #define SECP256K1_NUM_REPR_H diff --git a/src/secp256k1/src/num_gmp_impl.h b/src/secp256k1/src/num_gmp_impl.h index 0ae2a8ba0ec..ed67fb4fae4 100644 --- a/src/secp256k1/src/num_gmp_impl.h +++ b/src/secp256k1/src/num_gmp_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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_NUM_REPR_IMPL_H #define SECP256K1_NUM_REPR_IMPL_H diff --git a/src/secp256k1/src/num_impl.h b/src/secp256k1/src/num_impl.h index c45193b033d..a254f91a304 100644 --- a/src/secp256k1/src/num_impl.h +++ b/src/secp256k1/src/num_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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_NUM_IMPL_H #define SECP256K1_NUM_IMPL_H diff --git a/src/secp256k1/src/scalar.h b/src/secp256k1/src/scalar.h index 59304cb66e9..a8d059c3e48 100644 --- a/src/secp256k1/src/scalar.h +++ b/src/secp256k1/src/scalar.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/scalar_4x64.h b/src/secp256k1/src/scalar_4x64.h index 19c7495d1c8..e46df1f3384 100644 --- a/src/secp256k1/src/scalar_4x64.h +++ b/src/secp256k1/src/scalar_4x64.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/scalar_4x64_impl.h b/src/secp256k1/src/scalar_4x64_impl.h index db1ebf94bee..5c72512e711 100644 --- a/src/secp256k1/src/scalar_4x64_impl.h +++ b/src/secp256k1/src/scalar_4x64_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/scalar_8x32.h b/src/secp256k1/src/scalar_8x32.h index 2c9a348e247..9c1d8b25acd 100644 --- a/src/secp256k1/src/scalar_8x32.h +++ b/src/secp256k1/src/scalar_8x32.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/scalar_8x32_impl.h b/src/secp256k1/src/scalar_8x32_impl.h index 4f9ed61feae..b19b058f9c0 100644 --- a/src/secp256k1/src/scalar_8x32_impl.h +++ b/src/secp256k1/src/scalar_8x32_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/scalar_impl.h b/src/secp256k1/src/scalar_impl.h index fa790570ff8..ee26b206d09 100644 --- a/src/secp256k1/src/scalar_impl.h +++ b/src/secp256k1/src/scalar_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/scalar_low.h b/src/secp256k1/src/scalar_low.h index 5836febc5b7..7bfd1cf65c8 100644 --- a/src/secp256k1/src/scalar_low.h +++ b/src/secp256k1/src/scalar_low.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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_H #define SECP256K1_SCALAR_REPR_H diff --git a/src/secp256k1/src/scalar_low_impl.h b/src/secp256k1/src/scalar_low_impl.h index c80e70c5a2a..9b338feea9a 100644 --- a/src/secp256k1/src/scalar_low_impl.h +++ b/src/secp256k1/src/scalar_low_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/secp256k1.c b/src/secp256k1/src/secp256k1.c index cecb1550be7..6c89b0c9ba0 100644 --- a/src/secp256k1/src/secp256k1.c +++ b/src/secp256k1/src/secp256k1.c @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 .* + ************************************************************************/ #include "include/secp256k1.h" diff --git a/src/secp256k1/src/testrand.h b/src/secp256k1/src/testrand.h index f1f9be077e3..339cb1c7a19 100644 --- a/src/secp256k1/src/testrand.h +++ b/src/secp256k1/src/testrand.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/testrand_impl.h b/src/secp256k1/src/testrand_impl.h index 30a91e52961..2b70623e2aa 100644 --- a/src/secp256k1/src/testrand_impl.h +++ b/src/secp256k1/src/testrand_impl.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/secp256k1/src/tests.c b/src/secp256k1/src/tests.c index f307b99d5af..743ca6cca58 100644 --- a/src/secp256k1/src/tests.c +++ b/src/secp256k1/src/tests.c @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 .* + ************************************************************************/ #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" diff --git a/src/secp256k1/src/tests_exhaustive.c b/src/secp256k1/src/tests_exhaustive.c index b040bb0733d..d4f09d63c1f 100644 --- a/src/secp256k1/src/tests_exhaustive.c +++ b/src/secp256k1/src/tests_exhaustive.c @@ -1,8 +1,8 @@ -/*********************************************************************** - * Copyright (c) 2016 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************** + * 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 .* + ************************************************************************/ #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" diff --git a/src/secp256k1/src/util.h b/src/secp256k1/src/util.h index b0441d8e305..708807823dc 100644 --- a/src/secp256k1/src/util.h +++ b/src/secp256k1/src/util.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/************************************************************************ + * 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 diff --git a/src/serialize.h b/src/serialize.h index ac2db6eddfb..eb0d4e7859e 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_SERIALIZE_H #define BITCOIN_SERIALIZE_H diff --git a/src/spentindex.h b/src/spentindex.h index 3e11b60809a..9f85c62b0a3 100644 --- a/src/spentindex.h +++ b/src/spentindex.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_SPENTINDEX_H #define BITCOIN_SPENTINDEX_H diff --git a/src/streams.h b/src/streams.h index 9d4a2e39e04..5b2309e843c 100644 --- a/src/streams.h +++ b/src/streams.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_STREAMS_H #define BITCOIN_STREAMS_H diff --git a/src/support/allocators/secure.h b/src/support/allocators/secure.h index 5e7bb66ea21..1de474b3f85 100644 --- a/src/support/allocators/secure.h +++ b/src/support/allocators/secure.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_SUPPORT_ALLOCATORS_SECURE_H #define BITCOIN_SUPPORT_ALLOCATORS_SECURE_H diff --git a/src/support/allocators/zeroafterfree.h b/src/support/allocators/zeroafterfree.h index 41e23392e80..19075f4e614 100644 --- a/src/support/allocators/zeroafterfree.h +++ b/src/support/allocators/zeroafterfree.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_SUPPORT_ALLOCATORS_ZEROAFTERFREE_H #define BITCOIN_SUPPORT_ALLOCATORS_ZEROAFTERFREE_H diff --git a/src/support/cleanse.cpp b/src/support/cleanse.cpp index a2141b24498..7a4da12b490 100644 --- a/src/support/cleanse.cpp +++ b/src/support/cleanse.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "cleanse.h" diff --git a/src/support/cleanse.h b/src/support/cleanse.h index 3e02aa8fd1f..c6fe12912b1 100644 --- a/src/support/cleanse.h +++ b/src/support/cleanse.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_SUPPORT_CLEANSE_H #define BITCOIN_SUPPORT_CLEANSE_H diff --git a/src/support/events.h b/src/support/events.h index 4f2f3cf9ef7..e1496123107 100644 --- a/src/support/events.h +++ b/src/support/events.h @@ -1,6 +1,6 @@ // Copyright (c) 2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_SUPPORT_EVENTS_H #define BITCOIN_SUPPORT_EVENTS_H diff --git a/src/support/pagelocker.cpp b/src/support/pagelocker.cpp index 440e0a5193a..47a98ba5d96 100644 --- a/src/support/pagelocker.cpp +++ b/src/support/pagelocker.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "support/pagelocker.h" diff --git a/src/support/pagelocker.h b/src/support/pagelocker.h index cf42e3dfd6c..4002fd95340 100644 --- a/src/support/pagelocker.h +++ b/src/support/pagelocker.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_SUPPORT_PAGELOCKER_H #define BITCOIN_SUPPORT_PAGELOCKER_H diff --git a/src/sync.cpp b/src/sync.cpp index 1837e8d53dd..91a6745c056 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2011-2012 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "sync.h" diff --git a/src/sync.h b/src/sync.h index 68a9443084a..45a3bd3fdfa 100644 --- a/src/sync.h +++ b/src/sync.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_SYNC_H #define BITCOIN_SYNC_H diff --git a/src/test/Checkpoints_tests.cpp b/src/test/Checkpoints_tests.cpp index 32b14cb93bc..4a985994f16 100644 --- a/src/test/Checkpoints_tests.cpp +++ b/src/test/Checkpoints_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2011-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . // // Unit tests for block-chain checkpoints diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 6044b221f5b..742b87a6159 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2011-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . // // Unit tests for denial-of-service detection/prevention code diff --git a/src/test/accounting_tests.cpp b/src/test/accounting_tests.cpp index 0c2ade48d62..dcf28ed8583 100644 --- a/src/test/accounting_tests.cpp +++ b/src/test/accounting_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "wallet/wallet.h" #include "wallet/walletdb.h" diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index fc0600dfc6d..0aa7f236920 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "addrman.h" #include "test/test_bitcoin.h" #include diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index 18acf1f67c5..82c83ec16c9 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . // // Unit tests for alert system diff --git a/src/test/allocator_tests.cpp b/src/test/allocator_tests.cpp index 2108efece51..63f4bed007a 100644 --- a/src/test/allocator_tests.cpp +++ b/src/test/allocator_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "util.h" diff --git a/src/test/arith_uint256_tests.cpp b/src/test/arith_uint256_tests.cpp index 17d6bed6d2f..ba0b6141c1d 100644 --- a/src/test/arith_uint256_tests.cpp +++ b/src/test/arith_uint256_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2011-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include #include diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp index 0b883fbeff7..7779461aa91 100644 --- a/src/test/base32_tests.cpp +++ b/src/test/base32_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "utilstrencodings.h" #include "test/test_bitcoin.h" diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index 80b2bb1dc00..f7a6c9e3940 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2011-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "base58.h" diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp index b134e49ca4c..1996b38f173 100644 --- a/src/test/base64_tests.cpp +++ b/src/test/base64_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2011-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "utilstrencodings.h" #include "test/test_bitcoin.h" diff --git a/src/test/bctest.py b/src/test/bctest.py index 86724241bba..33e7c8aa3af 100644 --- a/src/test/bctest.py +++ b/src/test/bctest.py @@ -1,6 +1,6 @@ # Copyright 2014 BitPay, Inc. # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import subprocess import json diff --git a/src/test/bech32_tests.cpp b/src/test/bech32_tests.cpp index 02252bcbfa0..ac4779006a7 100644 --- a/src/test/bech32_tests.cpp +++ b/src/test/bech32_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2017 Pieter Wuille // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "bech32.h" #include "test/test_bitcoin.h" diff --git a/src/test/bignum.h b/src/test/bignum.h index a7fb18953b5..13e70133a19 100644 --- a/src/test/bignum.h +++ b/src/test/bignum.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_TEST_BIGNUM_H #define BITCOIN_TEST_BIGNUM_H diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp index 8815d1c54b5..104173b19c8 100644 --- a/src/test/bip32_tests.cpp +++ b/src/test/bip32_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include diff --git a/src/test/bitcoin-util-test.py b/src/test/bitcoin-util-test.py index 6551eb6f23a..c977a1e28b3 100755 --- a/src/test/bitcoin-util-test.py +++ b/src/test/bitcoin-util-test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright 2014 BitPay, Inc. # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import os import bctest diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index 9189e4af8eb..ef9c4cd283f 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "bloom.h" diff --git a/src/test/checkblock_tests.cpp b/src/test/checkblock_tests.cpp index dc906282034..2563076f90c 100644 --- a/src/test/checkblock_tests.cpp +++ b/src/test/checkblock_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2013-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "clientversion.h" #include "consensus/validation.h" diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 35023c47e9b..79609cc025c 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "coins.h" #include "random.h" diff --git a/src/test/compress_tests.cpp b/src/test/compress_tests.cpp index 376ae936810..5227f6cfd9e 100644 --- a/src/test/compress_tests.cpp +++ b/src/test/compress_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "compressor.h" #include "util.h" diff --git a/src/test/convertbits_tests.cpp b/src/test/convertbits_tests.cpp index a8908ebfcb3..1a4786912e2 100644 --- a/src/test/convertbits_tests.cpp +++ b/src/test/convertbits_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2018 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include #include diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index aeb2a5caa32..9e3cf2d597a 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "crypto/ripemd160.h" #include "crypto/sha1.h" diff --git a/src/test/data/README.md b/src/test/data/README.md index 2463daa42a5..bc31cbf3e2e 100644 --- a/src/test/data/README.md +++ b/src/test/data/README.md @@ -8,5 +8,5 @@ License The data files in this directory are distributed under the MIT software license, see the accompanying file COPYING or -http://www.opensource.org/licenses/mit-license.php. +https://www.opensource.org/licenses/mit-license.php . diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index a047938db01..1853cbf1daa 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2018 The Zcash developers // Copyright (c) 2012-2017 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "dbwrapper.h" #include "uint256.h" diff --git a/src/test/equihash_tests.cpp b/src/test/equihash_tests.cpp index 6f2f0b8587f..745afbd998d 100644 --- a/src/test/equihash_tests.cpp +++ b/src/test/equihash_tests.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2016 Jack Grigg // Copyright (c) 2016 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #if defined(HAVE_CONFIG_H) #include "config/bitcoin-config.h" diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp index a0c5592a959..acc1adab7b7 100644 --- a/src/test/getarg_tests.cpp +++ b/src/test/getarg_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "util.h" #include "test/test_bitcoin.h" diff --git a/src/test/hash_tests.cpp b/src/test/hash_tests.cpp index e5d2e5a439e..356fb245b7c 100644 --- a/src/test/hash_tests.cpp +++ b/src/test/hash_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "hash.h" #include "utilstrencodings.h" diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index 64d7ade52d6..6d28cd1b89e 100644 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "key.h" diff --git a/src/test/main_tests.cpp b/src/test/main_tests.cpp index ec02352e8b5..27ead5a2767 100644 --- a/src/test/main_tests.cpp +++ b/src/test/main_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "chainparams.h" #include "main.h" diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp index a82f5bce65d..f448d92e0cd 100644 --- a/src/test/mempool_tests.cpp +++ b/src/test/mempool_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2011-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "consensus/upgrades.h" #include "main.h" diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 23e7634abbd..133cd21d0a4 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2011-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "arith_uint256.h" #include "consensus/validation.h" diff --git a/src/test/mruset_tests.cpp b/src/test/mruset_tests.cpp index 2b68f8899ee..04f2f9b059d 100644 --- a/src/test/mruset_tests.cpp +++ b/src/test/mruset_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "mruset.h" diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index a7e48ee4cba..506575f1a7e 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2011-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "consensus/upgrades.h" #include "key.h" diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index 40b32a7b378..d81a10038e2 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "netbase.h" #include "test/test_bitcoin.h" diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index 3975dff2e66..f5c80b4a788 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "merkleblock.h" #include "serialize.h" diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp index 7b0a632cb35..382f9d61480 100644 --- a/src/test/policyestimator_tests.cpp +++ b/src/test/policyestimator_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2011-2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "policy/fees.h" #include "txmempool.h" diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index 5a11483f274..09430d025e0 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2015 The Bitcoin Core developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "main.h" #include "pow.h" diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index 01a45b540d5..7e93d424879 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include #include "prevector.h" diff --git a/src/test/raii_event_tests.cpp b/src/test/raii_event_tests.cpp index 0f40874f55c..fd4d92fd003 100644 --- a/src/test/raii_event_tests.cpp +++ b/src/test/raii_event_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include diff --git a/src/test/reverselock_tests.cpp b/src/test/reverselock_tests.cpp index 8bdff97000f..3aeba7af1a9 100644 --- a/src/test/reverselock_tests.cpp +++ b/src/test/reverselock_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "reverselock.h" #include "test/test_bitcoin.h" diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 7cb1ef010e9..02d827ad5dd 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "rpc/server.h" #include "rpc/client.h" diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index f04d3f2c216..6e1cb2cb744 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2013-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "rpc/server.h" #include "rpc/client.h" diff --git a/src/test/sanity_tests.cpp b/src/test/sanity_tests.cpp index f5f7f381d31..c29b173fa4d 100644 --- a/src/test/sanity_tests.cpp +++ b/src/test/sanity_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "compat/sanity.h" #include "key.h" diff --git a/src/test/scheduler_tests.cpp b/src/test/scheduler_tests.cpp index d6c93ef3bca..3bc0be7ae7e 100644 --- a/src/test/scheduler_tests.cpp +++ b/src/test/scheduler_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "random.h" #include "scheduler.h" diff --git a/src/test/script_P2PKH_tests.cpp b/src/test/script_P2PKH_tests.cpp index 3a7dc16608a..99d826345eb 100644 --- a/src/test/script_P2PKH_tests.cpp +++ b/src/test/script_P2PKH_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "script/script.h" #include "test/test_bitcoin.h" diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index 80e293675a1..a01e3e8e40e 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "consensus/upgrades.h" #include "core_io.h" diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 4e8388358d0..2b2ec3fbf4c 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2011-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "data/script_invalid.json.h" #include "data/script_valid.json.h" diff --git a/src/test/scriptnum_tests.cpp b/src/test/scriptnum_tests.cpp index d95724dbe17..784ff739939 100644 --- a/src/test/scriptnum_tests.cpp +++ b/src/test/scriptnum_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "bignum.h" #include "script/script.h" diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp index eaf69f175ea..bed9340000c 100644 --- a/src/test/serialize_tests.cpp +++ b/src/test/serialize_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "serialize.h" #include "streams.h" diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index 69ed32df5ce..d56c3a80f02 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "consensus/upgrades.h" #include "consensus/validation.h" diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp index ea2b9b795f0..3fd68f28dab 100644 --- a/src/test/sigopcount_tests.cpp +++ b/src/test/sigopcount_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "pubkey.h" #include "key.h" diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp index 86a4bc67272..023a7cebb03 100644 --- a/src/test/skiplist_tests.cpp +++ b/src/test/skiplist_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "main.h" #include "random.h" diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index f23837da4aa..03f98870c43 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2011-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #define BOOST_TEST_MODULE Bitcoin Test Suite diff --git a/src/test/timedata_tests.cpp b/src/test/timedata_tests.cpp index 887cfb47613..b3420afeadf 100644 --- a/src/test/timedata_tests.cpp +++ b/src/test/timedata_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2011-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . // #include "timedata.h" #include "test/test_bitcoin.h" diff --git a/src/test/torcontrol_tests.cpp b/src/test/torcontrol_tests.cpp index b7affaacde5..0e9ff78de0e 100644 --- a/src/test/torcontrol_tests.cpp +++ b/src/test/torcontrol_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . // #include "test/test_bitcoin.h" #include "torcontrol.cpp" diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index f4314e17521..42f380138d4 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2011-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "data/tx_invalid.json.h" #include "data/tx_valid.json.h" diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp index a6501faa12c..7034ccfeb3c 100644 --- a/src/test/uint256_tests.cpp +++ b/src/test/uint256_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2011-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "arith_uint256.h" #include "uint256.h" #include "version.h" diff --git a/src/test/univalue_tests.cpp b/src/test/univalue_tests.cpp index f3bbfaef173..51db25e8b1f 100644 --- a/src/test/univalue_tests.cpp +++ b/src/test/univalue_tests.cpp @@ -1,6 +1,6 @@ // Copyright 2014 BitPay, Inc. // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include #include diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 0fcdd653067..24a096b1ea9 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2011-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "util.h" diff --git a/src/threadsafety.h b/src/threadsafety.h index d01c50abb6b..42e2168ad8a 100644 --- a/src/threadsafety.h +++ b/src/threadsafety.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2012 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_THREADSAFETY_H #define BITCOIN_THREADSAFETY_H diff --git a/src/timedata.cpp b/src/timedata.cpp index 1dcef2de3f1..40eb4d33ef3 100644 --- a/src/timedata.cpp +++ b/src/timedata.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "timedata.h" diff --git a/src/timedata.h b/src/timedata.h index 2296baf11bb..69a1eb0f6ab 100644 --- a/src/timedata.h +++ b/src/timedata.h @@ -1,6 +1,6 @@ // Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_TIMEDATA_H #define BITCOIN_TIMEDATA_H diff --git a/src/timestampindex.h b/src/timestampindex.h index 3e402872cf4..fe72669d721 100644 --- a/src/timestampindex.h +++ b/src/timestampindex.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_TIMESTAMPINDEX_H #define BITCOIN_TIMESTAMPINDEX_H diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 99c76995b15..4618042a522 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2015-2017 The Bitcoin Core developers // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "torcontrol.h" #include "utilstrencodings.h" diff --git a/src/torcontrol.h b/src/torcontrol.h index 72dc82c5b17..c3edaee059f 100644 --- a/src/torcontrol.h +++ b/src/torcontrol.h @@ -1,6 +1,6 @@ // Copyright (c) 2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . /** * Functionality for communicating with Tor. diff --git a/src/transaction_builder.cpp b/src/transaction_builder.cpp index aa34ffb15e5..e1f5e3a0946 100644 --- a/src/transaction_builder.cpp +++ b/src/transaction_builder.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2018 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "transaction_builder.h" diff --git a/src/transaction_builder.h b/src/transaction_builder.h index 46f38481ecc..456a1c6c3cd 100644 --- a/src/transaction_builder.h +++ b/src/transaction_builder.h @@ -1,6 +1,6 @@ // Copyright (c) 2018 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef TRANSACTION_BUILDER_H #define TRANSACTION_BUILDER_H diff --git a/src/txdb.cpp b/src/txdb.cpp index 2d421d36934..9ccd4378ed8 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "txdb.h" diff --git a/src/txdb.h b/src/txdb.h index e3ef5b57c33..2e35d87bdf2 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_TXDB_H #define BITCOIN_TXDB_H diff --git a/src/txmempool.cpp b/src/txmempool.cpp index af76b355832..bc9e3ba2a91 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "txmempool.h" diff --git a/src/txmempool.h b/src/txmempool.h index ca8055c90e4..396c24e97cf 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_TXMEMPOOL_H #define BITCOIN_TXMEMPOOL_H diff --git a/src/ui_interface.h b/src/ui_interface.h index ee0fd9113d0..3bcd57648f1 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -1,7 +1,7 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2012 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_UI_INTERFACE_H #define BITCOIN_UI_INTERFACE_H diff --git a/src/uint256.cpp b/src/uint256.cpp index 25148808c67..b16b0d9049c 100644 --- a/src/uint256.cpp +++ b/src/uint256.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "uint256.h" diff --git a/src/uint256.h b/src/uint256.h index f22a8bafa57..b07047b04f5 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_UINT256_H #define BITCOIN_UINT256_H diff --git a/src/undo.h b/src/undo.h index fbb350e6015..6bf96a79fbc 100644 --- a/src/undo.h +++ b/src/undo.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_UNDO_H #define BITCOIN_UNDO_H diff --git a/src/univalue/gen/gen.cpp b/src/univalue/gen/gen.cpp index 17f361941d9..a6530481de8 100644 --- a/src/univalue/gen/gen.cpp +++ b/src/univalue/gen/gen.cpp @@ -1,6 +1,6 @@ // Copyright 2014 BitPay Inc. // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . // // To re-create univalue_escapes.h: diff --git a/src/univalue/include/univalue.h b/src/univalue/include/univalue.h index dfc84f92111..f4dea4af9ee 100644 --- a/src/univalue/include/univalue.h +++ b/src/univalue/include/univalue.h @@ -1,7 +1,7 @@ // Copyright 2014 BitPay Inc. // Copyright 2015 Bitcoin Core Developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef UNIVALUE_H__ #define UNIVALUE_H__ diff --git a/src/univalue/lib/univalue.cpp b/src/univalue/lib/univalue.cpp index 14f4c3c4fd3..aaa027546fa 100644 --- a/src/univalue/lib/univalue.cpp +++ b/src/univalue/lib/univalue.cpp @@ -1,7 +1,7 @@ // Copyright 2014 BitPay Inc. // Copyright 2015 Bitcoin Core Developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include #include diff --git a/src/univalue/lib/univalue_read.cpp b/src/univalue/lib/univalue_read.cpp index 7a9acdd75fd..35a9c726d25 100644 --- a/src/univalue/lib/univalue_read.cpp +++ b/src/univalue/lib/univalue_read.cpp @@ -1,6 +1,6 @@ // Copyright 2014 BitPay Inc. // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include #include diff --git a/src/univalue/lib/univalue_utffilter.h b/src/univalue/lib/univalue_utffilter.h index b4a9ddc0a31..41da1b0c493 100644 --- a/src/univalue/lib/univalue_utffilter.h +++ b/src/univalue/lib/univalue_utffilter.h @@ -1,6 +1,6 @@ // Copyright 2016 Wladimir J. van der Laan // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef UNIVALUE_UTFFILTER_H #define UNIVALUE_UTFFILTER_H diff --git a/src/univalue/lib/univalue_write.cpp b/src/univalue/lib/univalue_write.cpp index cf278359911..0337e690d48 100644 --- a/src/univalue/lib/univalue_write.cpp +++ b/src/univalue/lib/univalue_write.cpp @@ -1,6 +1,6 @@ // Copyright 2014 BitPay Inc. // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include #include diff --git a/src/univalue/test/unitester.cpp b/src/univalue/test/unitester.cpp index aa6f91c1b2f..7492e63e8d8 100644 --- a/src/univalue/test/unitester.cpp +++ b/src/univalue/test/unitester.cpp @@ -1,6 +1,6 @@ // Copyright 2014 BitPay Inc. -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include #include diff --git a/src/util.cpp b/src/util.cpp index 947538f01b5..80d46fb3a61 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #if defined(HAVE_CONFIG_H) #include "config/bitcoin-config.h" @@ -918,7 +918,7 @@ std::string LicenseInfo() "\n" + FormatParagraph(_("This is experimental software.")) + "\n" + "\n" + - FormatParagraph(_("Distributed under the MIT software license, see the accompanying file COPYING or .")) + "\n" + + FormatParagraph(_("Distributed under the MIT software license, see the accompanying file COPYING or .")) + "\n" + "\n" + FormatParagraph(_("This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit and cryptographic software written by Eric Young.")) + "\n"; diff --git a/src/util.h b/src/util.h index 22949902dc3..6da498a0ae4 100644 --- a/src/util.h +++ b/src/util.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . /** * Server/client environment: argument handling, config file parsing, diff --git a/src/utilmoneystr.cpp b/src/utilmoneystr.cpp index 0f3203432f6..0a47765ec15 100644 --- a/src/utilmoneystr.cpp +++ b/src/utilmoneystr.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "utilmoneystr.h" diff --git a/src/utilmoneystr.h b/src/utilmoneystr.h index 99c3ba83061..d3bb1bb6298 100644 --- a/src/utilmoneystr.h +++ b/src/utilmoneystr.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . /** * Money parsing/formatting utilities. diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index ece2ec73eb7..c3a25ca62f6 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "utilstrencodings.h" diff --git a/src/utilstrencodings.h b/src/utilstrencodings.h index 37a07ea06bd..ce2ca034e83 100644 --- a/src/utilstrencodings.h +++ b/src/utilstrencodings.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . /** * Utilities for converting data from/to strings. diff --git a/src/utiltest.cpp b/src/utiltest.cpp index 997137b1a78..e964f284de4 100644 --- a/src/utiltest.cpp +++ b/src/utiltest.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2016 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "utiltest.h" diff --git a/src/utiltest.h b/src/utiltest.h index 5480c559eb8..d3d36d3f40d 100644 --- a/src/utiltest.h +++ b/src/utiltest.h @@ -1,6 +1,6 @@ // Copyright (c) 2016 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef ZCASH_UTIL_TEST_H #define ZCASH_UTIL_TEST_H diff --git a/src/utiltime.cpp b/src/utiltime.cpp index 5d0b284fdf8..7f63bff8869 100644 --- a/src/utiltime.cpp +++ b/src/utiltime.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #if defined(HAVE_CONFIG_H) #include "config/bitcoin-config.h" diff --git a/src/utiltime.h b/src/utiltime.h index 900992f8717..b1267112ebb 100644 --- a/src/utiltime.h +++ b/src/utiltime.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_UTILTIME_H #define BITCOIN_UTILTIME_H diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 1dc3351ab27..54da4477344 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "validationinterface.h" diff --git a/src/validationinterface.h b/src/validationinterface.h index 7b02bd9da4a..1b5a426defc 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_VALIDATIONINTERFACE_H #define BITCOIN_VALIDATIONINTERFACE_H diff --git a/src/version.h b/src/version.h index 72ddac446a6..ed0b111b11d 100644 --- a/src/version.h +++ b/src/version.h @@ -1,6 +1,6 @@ // Copyright (c) 2012-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_VERSION_H #define BITCOIN_VERSION_H diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index fda81aa6dc6..69c8e3d53fe 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "asyncrpcoperation_mergetoaddress.h" diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.h b/src/wallet/asyncrpcoperation_mergetoaddress.h index 774695cf26a..1631b1cc599 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.h +++ b/src/wallet/asyncrpcoperation_mergetoaddress.h @@ -1,6 +1,6 @@ // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef ASYNCRPCOPERATION_MERGETOADDRESS_H #define ASYNCRPCOPERATION_MERGETOADDRESS_H diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index 7e0a9dd50ce..e2e722e929d 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2016 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "asyncrpcoperation_sendmany.h" #include "asyncrpcqueue.h" diff --git a/src/wallet/asyncrpcoperation_sendmany.h b/src/wallet/asyncrpcoperation_sendmany.h index fcb95227a5e..ac7d68436bf 100644 --- a/src/wallet/asyncrpcoperation_sendmany.h +++ b/src/wallet/asyncrpcoperation_sendmany.h @@ -1,6 +1,6 @@ // Copyright (c) 2016 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef ASYNCRPCOPERATION_SENDMANY_H #define ASYNCRPCOPERATION_SENDMANY_H diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp index 0b2f0174b12..63113336eb9 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "asyncrpcqueue.h" #include "amount.h" diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.h b/src/wallet/asyncrpcoperation_shieldcoinbase.h index 4311d84b316..f2709208039 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.h +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.h @@ -1,6 +1,6 @@ // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef ASYNCRPCOPERATION_SHIELDCOINBASE_H #define ASYNCRPCOPERATION_SHIELDCOINBASE_H diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index cf87c01d48f..3cd91abe43c 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "crypter.h" diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h index 1cfefe8865d..a5c11a527aa 100644 --- a/src/wallet/crypter.h +++ b/src/wallet/crypter.h @@ -1,6 +1,6 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_WALLET_CRYPTER_H #define BITCOIN_WALLET_CRYPTER_H diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 7fe2c9b8775..e0ef27e7864 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "db.h" diff --git a/src/wallet/db.h b/src/wallet/db.h index 64071caa3a2..1ae5a03b591 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_WALLET_DB_H #define BITCOIN_WALLET_DB_H diff --git a/src/wallet/paymentdisclosure.cpp b/src/wallet/paymentdisclosure.cpp index 5dd1e3d1b26..ddce48cc2b8 100644 --- a/src/wallet/paymentdisclosure.cpp +++ b/src/wallet/paymentdisclosure.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "wallet/paymentdisclosure.h" diff --git a/src/wallet/paymentdisclosure.h b/src/wallet/paymentdisclosure.h index 0014240d240..2233c88200b 100644 --- a/src/wallet/paymentdisclosure.h +++ b/src/wallet/paymentdisclosure.h @@ -1,6 +1,6 @@ // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef ZCASH_PAYMENTDISCLOSURE_H #define ZCASH_PAYMENTDISCLOSURE_H diff --git a/src/wallet/paymentdisclosuredb.cpp b/src/wallet/paymentdisclosuredb.cpp index db7924fbb7d..21b489e3c15 100644 --- a/src/wallet/paymentdisclosuredb.cpp +++ b/src/wallet/paymentdisclosuredb.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "wallet/paymentdisclosuredb.h" diff --git a/src/wallet/paymentdisclosuredb.h b/src/wallet/paymentdisclosuredb.h index 2ec5ad5e4ef..e4a797e45ed 100644 --- a/src/wallet/paymentdisclosuredb.h +++ b/src/wallet/paymentdisclosuredb.h @@ -1,6 +1,6 @@ // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef ZCASH_PAYMENTDISCLOSUREDB_H #define ZCASH_PAYMENTDISCLOSUREDB_H diff --git a/src/wallet/rpcdisclosure.cpp b/src/wallet/rpcdisclosure.cpp index b57f4a0ddd8..6a5e83f6e2f 100644 --- a/src/wallet/rpcdisclosure.cpp +++ b/src/wallet/rpcdisclosure.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "rpc/server.h" #include "init.h" diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 600d0de8bb0..3268cbd800b 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "chain.h" #include "key_io.h" diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 95b7c3b7463..fb6824e36b9 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "amount.h" #include "consensus/upgrades.h" diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h index a5de7e2de14..fda75db1715 100644 --- a/src/wallet/rpcwallet.h +++ b/src/wallet/rpcwallet.h @@ -1,6 +1,6 @@ // Copyright (c) 2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_WALLET_RPCWALLET_H #define BITCOIN_WALLET_RPCWALLET_H diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index a5bc52b8dc9..5807600b398 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2012-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "wallet/wallet.h" diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 480547d9577..76675d90dc7 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "wallet/wallet.h" diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index e5533dc108e..fe1cba06b66 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_WALLET_WALLET_H #define BITCOIN_WALLET_WALLET_H diff --git a/src/wallet/wallet_ismine.cpp b/src/wallet/wallet_ismine.cpp index 5e144eabef9..b9de548e22b 100644 --- a/src/wallet/wallet_ismine.cpp +++ b/src/wallet/wallet_ismine.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "wallet_ismine.h" diff --git a/src/wallet/wallet_ismine.h b/src/wallet/wallet_ismine.h index 5b9b0e08410..b9d97523cb9 100644 --- a/src/wallet/wallet_ismine.h +++ b/src/wallet/wallet_ismine.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_WALLET_WALLET_ISMINE_H #define BITCOIN_WALLET_WALLET_ISMINE_H diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index e34285f18ec..30a14d11ed0 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "wallet/walletdb.h" diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 7f84366a098..94ebc0c7577 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_WALLET_WALLETDB_H #define BITCOIN_WALLET_WALLETDB_H diff --git a/src/zcash/zip32.cpp b/src/zcash/zip32.cpp index 15478843e3f..5733bd35131 100644 --- a/src/zcash/zip32.cpp +++ b/src/zcash/zip32.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2018 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "zip32.h" diff --git a/src/zcash/zip32.h b/src/zcash/zip32.h index 44bc585987c..8a958cb38b5 100644 --- a/src/zcash/zip32.h +++ b/src/zcash/zip32.h @@ -1,6 +1,6 @@ // Copyright (c) 2018 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef ZCASH_ZIP32_H #define ZCASH_ZIP32_H diff --git a/src/zmq/zmqabstractnotifier.cpp b/src/zmq/zmqabstractnotifier.cpp index 3562a8824db..3e9c4867219 100644 --- a/src/zmq/zmqabstractnotifier.cpp +++ b/src/zmq/zmqabstractnotifier.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "zmqabstractnotifier.h" #include "util.h" diff --git a/src/zmq/zmqabstractnotifier.h b/src/zmq/zmqabstractnotifier.h index 8873b71d804..2ef35bd4fcd 100644 --- a/src/zmq/zmqabstractnotifier.h +++ b/src/zmq/zmqabstractnotifier.h @@ -1,6 +1,6 @@ // Copyright (c) 2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_ZMQ_ZMQABSTRACTNOTIFIER_H #define BITCOIN_ZMQ_ZMQABSTRACTNOTIFIER_H diff --git a/src/zmq/zmqconfig.h b/src/zmq/zmqconfig.h index 6057f5d1a0e..b88fcc4f4e6 100644 --- a/src/zmq/zmqconfig.h +++ b/src/zmq/zmqconfig.h @@ -1,6 +1,6 @@ // Copyright (c) 2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_ZMQ_ZMQCONFIG_H #define BITCOIN_ZMQ_ZMQCONFIG_H diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp index 0d8c36ad246..e427e6b977c 100644 --- a/src/zmq/zmqnotificationinterface.cpp +++ b/src/zmq/zmqnotificationinterface.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "zmqnotificationinterface.h" #include "zmqpublishnotifier.h" diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h index e0fe3b570c6..1dc7211d528 100644 --- a/src/zmq/zmqnotificationinterface.h +++ b/src/zmq/zmqnotificationinterface.h @@ -1,6 +1,6 @@ // Copyright (c) 2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_ZMQ_ZMQNOTIFICATIONINTERFACE_H #define BITCOIN_ZMQ_ZMQNOTIFICATIONINTERFACE_H diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp index 28cf2e597dc..a2a6758cab1 100644 --- a/src/zmq/zmqpublishnotifier.cpp +++ b/src/zmq/zmqpublishnotifier.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #include "chainparams.h" #include "zmqpublishnotifier.h" diff --git a/src/zmq/zmqpublishnotifier.h b/src/zmq/zmqpublishnotifier.h index 627c8af96fe..3a5a6986e84 100644 --- a/src/zmq/zmqpublishnotifier.h +++ b/src/zmq/zmqpublishnotifier.h @@ -1,6 +1,6 @@ // Copyright (c) 2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef BITCOIN_ZMQ_ZMQPUBLISHNOTIFIER_H #define BITCOIN_ZMQ_ZMQPUBLISHNOTIFIER_H From 2fe59a568187cd6908c60dee93cc8f31b3df97e0 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Thu, 18 Jul 2019 15:31:39 +0100 Subject: [PATCH 167/395] qa/zcash/checksec.sh is under a BSD license, with a specialized non-endorsement clause. Signed-off-by: Daira Hopwood --- contrib/debian/copyright | 29 +++++++++++++++++++++++++++++ qa/zcash/checksec.sh | 2 +- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/contrib/debian/copyright b/contrib/debian/copyright index abe2db3cbd3..a0442449939 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -101,6 +101,10 @@ Copyright: 2008, Steven G. Johnson 2011, Daniel Richard G. License: GPLv3-or-later-with-Autoconf-exception +Files: qa/zcash/checksec.sh +Copyright: 2009-2011, Tobias Klein +License: BSD-3clause-Tobias-Klein + Files: depends/sources/libsodium-*.tar.gz Copyright: 2013-2016 Frank Denis License: ISC @@ -1138,6 +1142,31 @@ License: BSD-3clause-Google (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +License: BSD-3clause-Tobias-Klein + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + . + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Tobias Klein nor the name of trapkit.de may be used + to endorse or promote products derived from this software without specific + prior written permission. + . + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + License: ISC Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/qa/zcash/checksec.sh b/qa/zcash/checksec.sh index dd1f72e5417..4e5f7aee49f 100755 --- a/qa/zcash/checksec.sh +++ b/qa/zcash/checksec.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# The BSD License (http://www.opensource.org/licenses/bsd-license.php) +# The BSD License (https://www.opensource.org/licenses/bsd-license.php) # specifies the terms and conditions of use for checksec.sh: # # Copyright (c) 2009-2011, Tobias Klein. From 742127271268d666c58e7d1b2abc557494d3996d Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Thu, 18 Jul 2019 14:57:13 -0600 Subject: [PATCH 168/395] Make nextHeight required in CalculateNextWorkRequired --- src/gtest/test_pow.cpp | 12 ++++++++---- src/pow.cpp | 2 +- src/pow.h | 2 +- src/test/pow_tests.cpp | 8 ++++---- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/gtest/test_pow.cpp b/src/gtest/test_pow.cpp index b0dd5fa41e7..b79d91b898f 100644 --- a/src/gtest/test_pow.cpp +++ b/src/gtest/test_pow.cpp @@ -27,7 +27,8 @@ TEST(PoW, DifficultyAveraging) { EXPECT_EQ(CalculateNextWorkRequired(bnAvg, blocks[lastBlk].GetMedianTimePast(), blocks[firstBlk].GetMedianTimePast(), - params), + params, + blocks[lastBlk].nHeight + 1), GetNextWorkRequired(&blocks[lastBlk], nullptr, params)); // Result should be unchanged, modulo integer division precision loss arith_uint256 bnRes; @@ -44,7 +45,8 @@ TEST(PoW, DifficultyAveraging) { EXPECT_EQ(CalculateNextWorkRequired(bnAvg, blocks[lastBlk].GetMedianTimePast(), blocks[firstBlk].GetMedianTimePast(), - params), + params, + blocks[lastBlk].nHeight + 1), GetNextWorkRequired(&blocks[lastBlk], nullptr, params)); // Result should not be unchanged EXPECT_NE(0x1e7fffff, GetNextWorkRequired(&blocks[lastBlk], nullptr, params)); @@ -57,7 +59,8 @@ TEST(PoW, DifficultyAveraging) { EXPECT_NE(CalculateNextWorkRequired(bnAvg, blocks[lastBlk].GetMedianTimePast(), blocks[firstBlk].GetMedianTimePast(), - params), + params, + blocks[lastBlk].nHeight + 1), GetNextWorkRequired(&blocks[lastBlk], nullptr, params)); // Result should be the same as if the average difficulty was used @@ -65,7 +68,8 @@ TEST(PoW, DifficultyAveraging) { EXPECT_EQ(CalculateNextWorkRequired(average, blocks[lastBlk].GetMedianTimePast(), blocks[firstBlk].GetMedianTimePast(), - params), + params, + blocks[lastBlk].nHeight + 1), GetNextWorkRequired(&blocks[lastBlk], nullptr, params)); } diff --git a/src/pow.cpp b/src/pow.cpp index 3f0116d63dc..d4139c48393 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -57,7 +57,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead return CalculateNextWorkRequired(bnAvg, pindexLast->GetMedianTimePast(), pindexFirst->GetMedianTimePast(), params, - pindexLast->nHeight + 1 ); + pindexLast->nHeight + 1); } unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg, diff --git a/src/pow.h b/src/pow.h index 67c41bc7f39..26cde2e022c 100644 --- a/src/pow.h +++ b/src/pow.h @@ -20,7 +20,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg, int64_t nLastBlockTime, int64_t nFirstBlockTime, const Consensus::Params&, - int nextHeight = 0); + int nextHeight); /** Check whether the Equihash solution in a block header is valid */ bool CheckEquihashSolution(const CBlockHeader *pblock, const Consensus::Params&); diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index a83f5914b70..21c043c9a26 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -24,7 +24,7 @@ BOOST_AUTO_TEST_CASE(get_next_work) arith_uint256 bnAvg; bnAvg.SetCompact(0x1d00ffff); BOOST_CHECK_EQUAL(0x1d011998, - CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params)); + CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params, 0)); } /* Test the constraint on the upper bound for next work */ @@ -38,7 +38,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_pow_limit) arith_uint256 bnAvg; bnAvg.SetCompact(0x1f07ffff); BOOST_CHECK_EQUAL(0x1f07ffff, - CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params)); + CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params, 0)); } /* Test the constraint on the lower bound for actual time taken */ @@ -52,7 +52,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual) arith_uint256 bnAvg; bnAvg.SetCompact(0x1c05a3f4); BOOST_CHECK_EQUAL(0x1c04bceb, - CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params)); + CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params, 0)); } /* Test the constraint on the upper bound for actual time taken */ @@ -66,7 +66,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual) arith_uint256 bnAvg; bnAvg.SetCompact(0x1c387f6f); BOOST_CHECK_EQUAL(0x1c4a93bb, - CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params)); + CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params, 0)); } BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test) From ded45b90d7c1b6ed1774ce59f1d9d611c83a40ca Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Sat, 20 Jul 2019 14:36:08 -0600 Subject: [PATCH 169/395] Fix nondeterministic failure in sapling migration test --- qa/rpc-tests/sprout_sapling_migration.py | 61 +++++++++++++++--------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/qa/rpc-tests/sprout_sapling_migration.py b/qa/rpc-tests/sprout_sapling_migration.py index 03e1ccde77c..e4cb36c0fcc 100755 --- a/qa/rpc-tests/sprout_sapling_migration.py +++ b/qa/rpc-tests/sprout_sapling_migration.py @@ -14,25 +14,40 @@ SAPLING_ADDR = 'zregtestsapling1ssqj3f3majnl270985gqcdqedd9t4nlttjqskccwevj2v20sc25deqspv3masufnwcdy67cydyy' SAPLING_KEY = 'secret-extended-key-regtest1qv62zt2fqyqqpqrh2qzc08h7gncf4447jh9kvnnnhjg959fkwt7mhw9j8e9at7attx8z6u3953u86vcnsujdc2ckdlcmztjt44x3uxpah5mxtncxd0mqcnz9eq8rghh5m4j44ep5d9702sdvvwawqassulktfegrcp4twxgqdxx4eww3lau0mywuaeztpla2cmvagr5nj98elt45zh6fjznadl6wz52n2uyhdwcm2wlsu8fnxstrk6s4t55t8dy6jkgx5g0cwpchh5qffp8x5' +DISABLED_NO_FUNDS = 0 +ENABLED_NO_FUNDS = 1 +DISABLED_BEFORE_MIGRATION = 2 +ENABLED_BEFORE_MIGRATION = 3 +DURING_MIGRATION = 4 +AFTER_MIGRATION = 5 +ALL_MIGRATION_STATES = [DISABLED_NO_FUNDS, ENABLED_NO_FUNDS, DISABLED_BEFORE_MIGRATION, ENABLED_BEFORE_MIGRATION, DURING_MIGRATION, AFTER_MIGRATION] -def check_migration_status( - node, - enabled, - destination_address, - non_zero_unmigrated_amount, - non_zero_unfinalized_migrated_amount, - non_zero_finalized_migrated_amount, - finalized_migration_transactions, - len_migration_txids -): + +def check_migration_status(node, destination_address, migration_state): status = node.z_getmigrationstatus() - assert_equal(enabled, status['enabled']) - assert_equal(destination_address, status['destination_address']) - assert_equal(non_zero_unmigrated_amount, Decimal(status['unmigrated_amount']) > Decimal('0.00')) - assert_equal(non_zero_unfinalized_migrated_amount, Decimal(status['unfinalized_migrated_amount']) > Decimal('0')) - assert_equal(non_zero_finalized_migrated_amount, Decimal(status['finalized_migrated_amount']) > Decimal('0')) - assert_equal(finalized_migration_transactions, status['finalized_migration_transactions']) - assert_equal(len_migration_txids, len(status['migration_txids'])) + assert_equal(destination_address, status['destination_address'], "Migration destination address") + assert_true(migration_state in ALL_MIGRATION_STATES, "Unexpected migration state") + + expected_enabled = migration_state != DISABLED_NO_FUNDS and migration_state != DISABLED_BEFORE_MIGRATION + expexted_sprout_funds = migration_state == DISABLED_BEFORE_MIGRATION or migration_state == ENABLED_BEFORE_MIGRATION + positive_unfinalized_amount = migration_state == DURING_MIGRATION + positive_finalized_amount = migration_state == AFTER_MIGRATION + num_migration_txids = 1 if migration_state == DURING_MIGRATION or migration_state == AFTER_MIGRATION else 0 + num_finalized_migration_transactions = 1 if migration_state == AFTER_MIGRATION else 0 + + assert_equal(expected_enabled, status['enabled'], "Expected enabled: %s" % expected_enabled) + # During and after the migration there may be no remaining sprout funds if + # we have randomly picked to migrate them all at once, so we only check + # this field in the one case. + if expexted_sprout_funds: + assert_true(Decimal(status['unmigrated_amount']) > Decimal('0.00'), "Expected sprout funds") + # For the other two amount fields we know whether or not they will positive + unfinalized_msg = "Positive unfinalized amount: %s " % positive_unfinalized_amount + assert_equal(positive_unfinalized_amount, Decimal(status['unfinalized_migrated_amount']) > Decimal('0'), unfinalized_msg) + finalized_msg = "Positive finalized amount: %s " % positive_finalized_amount + assert_equal(positive_finalized_amount, Decimal(status['finalized_migrated_amount']) > Decimal('0'), finalized_msg) + assert_equal(num_finalized_migration_transactions, status['finalized_migration_transactions'], "Num finalized transactions") + assert_equal(num_migration_txids, len(status['migration_txids']), "Num migration txids") class SproutSaplingMigration(BitcoinTestFramework): @@ -61,7 +76,7 @@ def run_migration_test(self, node, sproutAddr, saplingAddr, target_height): assert_equal(102, node.getblockcount() % 500, "Should be at block 102 % 500") assert_equal(node.z_getbalance(sproutAddr), Decimal('10')) assert_equal(node.z_getbalance(saplingAddr), Decimal('0')) - check_migration_status(node, False, saplingAddr, True, False, False, 0, 0) + check_migration_status(node, saplingAddr, DISABLED_BEFORE_MIGRATION) # Migrate node.z_setmigration(True) @@ -71,7 +86,7 @@ def run_migration_test(self, node, sproutAddr, saplingAddr, target_height): # At 494 % 500 we should have no async operations assert_equal(0, len(node.z_getoperationstatus()), "num async operations at 494 % 500") - check_migration_status(node, True, saplingAddr, True, False, False, 0, 0) + check_migration_status(node, saplingAddr, ENABLED_BEFORE_MIGRATION) node.generate(1) self.sync_all() @@ -135,11 +150,11 @@ def run_migration_test(self, node, sproutAddr, saplingAddr, target_height): assert_true(sapling_balance > Decimal('0'), "Should have more Sapling funds") assert_true(sprout_balance + sapling_balance, Decimal('9.9999')) - check_migration_status(node, True, saplingAddr, True, True, False, 0, 1) + check_migration_status(node, saplingAddr, DURING_MIGRATION) # At 10 % 500 the transactions will be considered 'finalized' node.generate(10) self.sync_all() - check_migration_status(node, True, saplingAddr, True, False, True, 1, 1) + check_migration_status(node, saplingAddr, AFTER_MIGRATION) # Check exact migration status amounts to make sure we account for fee status = node.z_getmigrationstatus() assert_equal(sprout_balance, Decimal(status['unmigrated_amount'])) @@ -154,9 +169,9 @@ def send_to_sprout_zaddr(self, tAddr, sproutAddr): def run_test(self): # Check enabling via '-migration' and disabling via rpc - check_migration_status(self.nodes[0], True, SAPLING_ADDR, False, False, False, 0, 0) + check_migration_status(self.nodes[0], SAPLING_ADDR, ENABLED_NO_FUNDS) self.nodes[0].z_setmigration(False) - check_migration_status(self.nodes[0], False, SAPLING_ADDR, False, False, False, 0, 0) + check_migration_status(self.nodes[0], SAPLING_ADDR, DISABLED_NO_FUNDS) # 1. Test using self.nodes[0] which has the parameter print("Running test using '-migrationdestaddress'...") From ff405316077821c119c28b5aaa6d960a19a10d52 Mon Sep 17 00:00:00 2001 From: Dimitris Apostolou Date: Sun, 16 Jun 2019 23:17:42 +0300 Subject: [PATCH 170/395] Fix RPC undefined behavior. Co-Authored-By: Dimitris Apostolou Signed-off-by: Daira Hopwood --- src/arith_uint256.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp index 2e613635761..87a19fc5994 100644 --- a/src/arith_uint256.cpp +++ b/src/arith_uint256.cpp @@ -173,9 +173,10 @@ unsigned int base_uint::bits() const { for (int pos = WIDTH - 1; pos >= 0; pos--) { if (pn[pos]) { - for (int bits = 31; bits > 0; bits--) { - if (pn[pos] & 1 << bits) + for (size_t bits = 31; bits > 0; bits--) { + if (pn[pos] & (1U << bits)) { return 32 * pos + bits + 1; + } } return 32 * pos + 1; } From 0f2a4e44d1eeca57a15c669e7ce75344d9c39ddb Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Tue, 23 Jul 2019 21:40:28 +0100 Subject: [PATCH 171/395] Link to ticket #2827 using URL Co-Authored-By: Eirik Ogilvie-Wigley --- COPYING | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/COPYING b/COPYING index b1e9debe7b7..2f0bae0b25c 100644 --- a/COPYING +++ b/COPYING @@ -41,7 +41,7 @@ under the GNU Affero General Public License. Contributors should understand licensing implications before modifying the -following files in build-aux/m4 (see ticket #2827): +following files in build-aux/m4 (see https://github.com/zcash/zcash/issues/2827): * ax_check_compile_flag.m4 * ax_check_link_flag.m4 From 6a3f9d8260f9fe793b245a2a232772856e5249ec Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 24 Jul 2019 15:43:08 -0600 Subject: [PATCH 172/395] Clean up and fix typo --- qa/rpc-tests/sprout_sapling_migration.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/qa/rpc-tests/sprout_sapling_migration.py b/qa/rpc-tests/sprout_sapling_migration.py index e4cb36c0fcc..51ba2e8204c 100755 --- a/qa/rpc-tests/sprout_sapling_migration.py +++ b/qa/rpc-tests/sprout_sapling_migration.py @@ -28,20 +28,20 @@ def check_migration_status(node, destination_address, migration_state): assert_equal(destination_address, status['destination_address'], "Migration destination address") assert_true(migration_state in ALL_MIGRATION_STATES, "Unexpected migration state") - expected_enabled = migration_state != DISABLED_NO_FUNDS and migration_state != DISABLED_BEFORE_MIGRATION - expexted_sprout_funds = migration_state == DISABLED_BEFORE_MIGRATION or migration_state == ENABLED_BEFORE_MIGRATION + expected_enabled = migration_state not in [DISABLED_NO_FUNDS, DISABLED_BEFORE_MIGRATION] + expected_sprout_funds = migration_state in [DISABLED_BEFORE_MIGRATION, ENABLED_BEFORE_MIGRATION] positive_unfinalized_amount = migration_state == DURING_MIGRATION positive_finalized_amount = migration_state == AFTER_MIGRATION - num_migration_txids = 1 if migration_state == DURING_MIGRATION or migration_state == AFTER_MIGRATION else 0 + num_migration_txids = 1 if migration_state in [DURING_MIGRATION, AFTER_MIGRATION] else 0 num_finalized_migration_transactions = 1 if migration_state == AFTER_MIGRATION else 0 assert_equal(expected_enabled, status['enabled'], "Expected enabled: %s" % expected_enabled) # During and after the migration there may be no remaining sprout funds if # we have randomly picked to migrate them all at once, so we only check # this field in the one case. - if expexted_sprout_funds: + if expected_sprout_funds: assert_true(Decimal(status['unmigrated_amount']) > Decimal('0.00'), "Expected sprout funds") - # For the other two amount fields we know whether or not they will positive + # For the other two amount fields we know whether or not they will be positive unfinalized_msg = "Positive unfinalized amount: %s " % positive_unfinalized_amount assert_equal(positive_unfinalized_amount, Decimal(status['unfinalized_migrated_amount']) > Decimal('0'), unfinalized_msg) finalized_msg = "Positive finalized amount: %s " % positive_finalized_amount From 5fc227c7dd4f3c0319c19f624fac0651c67b3195 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Thu, 25 Jul 2019 12:35:10 -0600 Subject: [PATCH 173/395] Apply suggestions from code review Show migration status in assertion failures Co-Authored-By: Daira Hopwood --- qa/rpc-tests/sprout_sapling_migration.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/qa/rpc-tests/sprout_sapling_migration.py b/qa/rpc-tests/sprout_sapling_migration.py index 51ba2e8204c..36ac396c3b4 100755 --- a/qa/rpc-tests/sprout_sapling_migration.py +++ b/qa/rpc-tests/sprout_sapling_migration.py @@ -25,8 +25,8 @@ def check_migration_status(node, destination_address, migration_state): status = node.z_getmigrationstatus() - assert_equal(destination_address, status['destination_address'], "Migration destination address") - assert_true(migration_state in ALL_MIGRATION_STATES, "Unexpected migration state") + assert_equal(destination_address, status['destination_address'], "Migration destination address; status=%r" % status) + assert_true(migration_state in ALL_MIGRATION_STATES, "Unexpected migration state %r" % migration_state) expected_enabled = migration_state not in [DISABLED_NO_FUNDS, DISABLED_BEFORE_MIGRATION] expected_sprout_funds = migration_state in [DISABLED_BEFORE_MIGRATION, ENABLED_BEFORE_MIGRATION] @@ -40,14 +40,14 @@ def check_migration_status(node, destination_address, migration_state): # we have randomly picked to migrate them all at once, so we only check # this field in the one case. if expected_sprout_funds: - assert_true(Decimal(status['unmigrated_amount']) > Decimal('0.00'), "Expected sprout funds") + assert_true(Decimal(status['unmigrated_amount']) > Decimal('0.00'), "Expected sprout funds; status=%r" % (status,)) # For the other two amount fields we know whether or not they will be positive - unfinalized_msg = "Positive unfinalized amount: %s " % positive_unfinalized_amount + unfinalized_msg = "Positive unfinalized amount: %s; status=%r " % (positive_unfinalized_amount, status) assert_equal(positive_unfinalized_amount, Decimal(status['unfinalized_migrated_amount']) > Decimal('0'), unfinalized_msg) - finalized_msg = "Positive finalized amount: %s " % positive_finalized_amount + finalized_msg = "Positive finalized amount: %s; status=%r " % (positive_finalized_amount, status) assert_equal(positive_finalized_amount, Decimal(status['finalized_migrated_amount']) > Decimal('0'), finalized_msg) - assert_equal(num_finalized_migration_transactions, status['finalized_migration_transactions'], "Num finalized transactions") - assert_equal(num_migration_txids, len(status['migration_txids']), "Num migration txids") + assert_equal(num_finalized_migration_transactions, status['finalized_migration_transactions'], "Num finalized transactions; status=%r" % (status,)) + assert_equal(num_migration_txids, len(status['migration_txids']), "Num migration txids; status=%r" % (status,)) class SproutSaplingMigration(BitcoinTestFramework): From a63ec6e71736cb30cec4433e22a167dba0653f43 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 24 Jul 2019 15:37:33 -0600 Subject: [PATCH 174/395] Shorter block times rpc test --- qa/pull-tester/rpc-tests.sh | 1 + qa/rpc-tests/shorter_block_times.py | 50 +++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100755 qa/rpc-tests/shorter_block_times.py diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index aeda0da2cbf..3b6d411aead 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -73,6 +73,7 @@ testScripts=( 'p2p_node_bloom.py' 'regtest_signrawtransaction.py' 'finalsaplingroot.py' + 'shorter_block_times.py' 'sprout_sapling_migration.py' 'turnstile.py' ); diff --git a/qa/rpc-tests/shorter_block_times.py b/qa/rpc-tests/shorter_block_times.py new file mode 100755 index 00000000000..26599d30c1a --- /dev/null +++ b/qa/rpc-tests/shorter_block_times.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python +# Copyright (c) 2019 The Zcash developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + assert_equal, + initialize_chain_clean, + start_nodes, +) + + +class ShorterBlockTimes(BitcoinTestFramework): + def setup_nodes(self): + return start_nodes(4, self.options.tmpdir, [[ + '-nuparams=5ba81b19:0', # Overwinter + '-nuparams=76b809bb:0', # Sapling + '-nuparams=2bb40e60:101', # Blossom + ]] * 4) + + def setup_chain(self): + print("Initializing test directory " + self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 4) + + def run_test(self): + print "Mining blocks..." + self.nodes[0].generate(100) + self.sync_all() + + # Sanity-check the block height + assert_equal(self.nodes[0].getblockcount(), 100) + + print "Mining last pre-Blossom block" + # Activate blossom + self.nodes[1].generate(1) + self.sync_all() + assert_equal(10, self.nodes[1].getwalletinfo()['immature_balance']) + + # After blossom activation the block reward will be halved + print "Mining first Blossom block" + self.nodes[1].generate(1) + self.sync_all() + assert_equal(15, self.nodes[1].getwalletinfo()['immature_balance']) + + +if __name__ == '__main__': + ShorterBlockTimes().main() From c192e3a75d1db33b2664cdaded85d4a14f4ce177 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 26 Jul 2019 10:34:23 -0600 Subject: [PATCH 175/395] Update pow_tests for shorter block times --- src/chainparams.cpp | 12 +++++ src/chainparams.h | 2 + src/consensus/params.h | 2 +- src/pow.cpp | 22 ++++++--- src/test/pow_tests.cpp | 109 ++++++++++++++++++++++++++++++++++++----- 5 files changed, 127 insertions(+), 20 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 1f5760f2993..476385539e7 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -504,6 +504,14 @@ class CRegTestParams : public CChainParams { consensus.vUpgrades[idx].nActivationHeight = nActivationHeight; } + void UpdateRegtestPow(int64_t nPowMaxAdjustDown, int64_t nPowMaxAdjustUp, uint256 powLimit) + { + assert(strNetworkID == "regtest"); + consensus.nPowMaxAdjustDown = nPowMaxAdjustDown; + consensus.nPowMaxAdjustUp = nPowMaxAdjustUp; + consensus.powLimit = powLimit; + } + void SetRegTestZIP209Enabled() { fZIP209Enabled = true; } @@ -590,3 +598,7 @@ void UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex idx, int nActivation { regTestParams.UpdateNetworkUpgradeParameters(idx, nActivationHeight); } + +void UpdateRegtestPow(int64_t nPowMaxAdjustDown, int64_t nPowMaxAdjustUp, uint256 powLimit) { + regTestParams.UpdateRegtestPow(nPowMaxAdjustDown, nPowMaxAdjustUp, powLimit); +} diff --git a/src/chainparams.h b/src/chainparams.h index 17ebe9d31a6..34396b6d9d6 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -156,4 +156,6 @@ bool SelectParamsFromCommandLine(); */ void UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex idx, int nActivationHeight); +void UpdateRegtestPow(int64_t nPowMaxAdjustDown, int64_t nPowMaxAdjustUp, uint256 powLimit); + #endif // BITCOIN_CHAINPARAMS_H diff --git a/src/consensus/params.h b/src/consensus/params.h index ad0b44e4c34..ea517536fe8 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -126,7 +126,7 @@ struct Params { } int64_t MinActualTimespan(int nHeight) const { - return (AveragingWindowTimespan(nHeight) * (100 - nPowMaxAdjustUp )) / 100; + return (AveragingWindowTimespan(nHeight) * (100 - nPowMaxAdjustUp)) / 100; } int64_t MaxActualTimespan(int nHeight) const { diff --git a/src/pow.cpp b/src/pow.cpp index d4139c48393..899b4620818 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -65,30 +65,36 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg, const Consensus::Params& params, int nextHeight) { + int64_t averagingWindowTimespan = params.AveragingWindowTimespan(nextHeight); + int64_t minActualTimespan = params.MinActualTimespan(nextHeight); + int64_t maxActualTimespan = params.MaxActualTimespan(nextHeight); // Limit adjustment step // Use medians to prevent time-warp attacks int64_t nActualTimespan = nLastBlockTime - nFirstBlockTime; LogPrint("pow", " nActualTimespan = %d before dampening\n", nActualTimespan); - nActualTimespan = params.AveragingWindowTimespan(nextHeight) + (nActualTimespan - params.AveragingWindowTimespan(nextHeight))/4; + nActualTimespan = averagingWindowTimespan + (nActualTimespan - averagingWindowTimespan)/4; LogPrint("pow", " nActualTimespan = %d before bounds\n", nActualTimespan); - if (nActualTimespan < params.MinActualTimespan(nextHeight)) - nActualTimespan = params.MinActualTimespan(nextHeight); - if (nActualTimespan > params.MaxActualTimespan(nextHeight)) - nActualTimespan = params.MaxActualTimespan(nextHeight); + if (nActualTimespan < minActualTimespan) { + nActualTimespan = minActualTimespan; + } + if (nActualTimespan > maxActualTimespan) { + nActualTimespan = maxActualTimespan; + } // Retarget const arith_uint256 bnPowLimit = UintToArith256(params.powLimit); arith_uint256 bnNew {bnAvg}; - bnNew /= params.AveragingWindowTimespan(nextHeight); + bnNew /= averagingWindowTimespan; bnNew *= nActualTimespan; - if (bnNew > bnPowLimit) + if (bnNew > bnPowLimit) { bnNew = bnPowLimit; + } /// debug print LogPrint("pow", "GetNextWorkRequired RETARGET\n"); - LogPrint("pow", "params.AveragingWindowTimespan() = %d nActualTimespan = %d\n", params.AveragingWindowTimespan(nextHeight), nActualTimespan); + LogPrint("pow", "params.AveragingWindowTimespan(%d) = %d nActualTimespan = %d\n", nextHeight, averagingWindowTimespan, nActualTimespan); LogPrint("pow", "Current average: %08x %s\n", bnAvg.GetCompact(), bnAvg.ToString()); LogPrint("pow", "After: %08x %s\n", bnNew.GetCompact(), bnNew.ToString()); diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index 21c043c9a26..1534cf8e8a8 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -11,6 +11,23 @@ using namespace std; +const Consensus::Params& ActivateBlossom() { + SelectParams(CBaseChainParams::REGTEST); + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_BLOSSOM, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); + UpdateRegtestPow(32, 16, uint256S("0007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); + return Params().GetConsensus(); +} + +void DeactivateBlossom() { + UpdateRegtestPow(0, 0, uint256S("0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f")); + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_BLOSSOM, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); + SelectParams(CBaseChainParams::MAIN); +} + BOOST_FIXTURE_TEST_SUITE(pow_tests, BasicTestingSetup) /* Test calculation of next difficulty target with no constraints applying */ @@ -18,62 +35,120 @@ BOOST_AUTO_TEST_CASE(get_next_work) { SelectParams(CBaseChainParams::MAIN); const Consensus::Params& params = Params().GetConsensus(); + BOOST_CHECK_EQUAL(150, params.PoWTargetSpacing(0)); - int64_t nLastRetargetTime = 1262149169; // NOTE: Not an actual block time - int64_t nThisTime = 1262152739; // Block #32255 of Bitcoin + int64_t nLastRetargetTime = 1000000000; // NOTE: Not an actual block time + int64_t nThisTime = 1000003570; arith_uint256 bnAvg; bnAvg.SetCompact(0x1d00ffff); BOOST_CHECK_EQUAL(0x1d011998, CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params, 0)); } + +BOOST_AUTO_TEST_CASE(get_next_work_blossom) +{ + const Consensus::Params& params = ActivateBlossom(); + BOOST_CHECK_EQUAL(75, params.PoWTargetSpacing(0)); + + int64_t nLastRetargetTime = 1000000000; // NOTE: Not an actual block time + int64_t nThisTime = 1000001445; + arith_uint256 bnAvg; + bnAvg.SetCompact(0x1d00ffff); + BOOST_CHECK_GT(0x1d011998, + CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params, 0)); + + DeactivateBlossom(); +} + /* Test the constraint on the upper bound for next work */ BOOST_AUTO_TEST_CASE(get_next_work_pow_limit) { SelectParams(CBaseChainParams::MAIN); const Consensus::Params& params = Params().GetConsensus(); - int64_t nLastRetargetTime = 1231006505; // Block #0 of Bitcoin - int64_t nThisTime = 1233061996; // Block #2015 of Bitcoin + int64_t nLastRetargetTime = 1231006505; + int64_t nThisTime = 1233061996; arith_uint256 bnAvg; bnAvg.SetCompact(0x1f07ffff); BOOST_CHECK_EQUAL(0x1f07ffff, CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params, 0)); } +BOOST_AUTO_TEST_CASE(get_next_work_pow_limit_blossom) +{ + const Consensus::Params& params = ActivateBlossom(); + + int64_t nLastRetargetTime = 1231006505; + int64_t nThisTime = 1233061996; + arith_uint256 bnAvg; + bnAvg.SetCompact(0x1f07ffff); + BOOST_CHECK_EQUAL(0x1f07ffff, + CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params, 0)); + + DeactivateBlossom(); +} + /* Test the constraint on the lower bound for actual time taken */ BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual) { SelectParams(CBaseChainParams::MAIN); const Consensus::Params& params = Params().GetConsensus(); - int64_t nLastRetargetTime = 1279296753; // NOTE: Not an actual block time - int64_t nThisTime = 1279297671; // Block #68543 of Bitcoin + int64_t nLastRetargetTime = 1000000000; // NOTE: Not an actual block time + // 17*150*(1 - PoWMaxAdjustUp*PoWDampingFactor) = 918 + // so we pick 917 to be outside of this window + int64_t nThisTime = 100000917; arith_uint256 bnAvg; bnAvg.SetCompact(0x1c05a3f4); BOOST_CHECK_EQUAL(0x1c04bceb, CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params, 0)); } +BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual_blossom) +{ + const Consensus::Params& params = ActivateBlossom(); + + int64_t nLastRetargetTime = 1000000000; // NOTE: Not an actual block time + int64_t nThisTime = 1000000458; + arith_uint256 bnAvg; + bnAvg.SetCompact(0x1c05a3f4); + BOOST_CHECK_EQUAL(0x1c04bceb, + CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params, 0)); + + DeactivateBlossom(); +} + /* Test the constraint on the upper bound for actual time taken */ BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual) { SelectParams(CBaseChainParams::MAIN); const Consensus::Params& params = Params().GetConsensus(); - int64_t nLastRetargetTime = 1269205629; // NOTE: Not an actual block time - int64_t nThisTime = 1269211443; // Block #46367 of Bitcoin + int64_t nLastRetargetTime = 1000000000; // NOTE: Not an actual block time + // 17*150*(1 + maxAdjustDown*PoWDampingFactor) = 5814 + int64_t nThisTime = 1000005815; arith_uint256 bnAvg; bnAvg.SetCompact(0x1c387f6f); BOOST_CHECK_EQUAL(0x1c4a93bb, CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params, 0)); } -BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test) +BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual_blossom) { - SelectParams(CBaseChainParams::MAIN); - const Consensus::Params& params = Params().GetConsensus(); + const Consensus::Params& params = ActivateBlossom(); + + int64_t nLastRetargetTime = 1000000000; // NOTE: Not an actual block time + int64_t nThisTime = 1000002908; + arith_uint256 bnAvg; + bnAvg.SetCompact(0x1c387f6f); + BOOST_CHECK_EQUAL(0x1c4a93bb, + CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params, 0)); + + DeactivateBlossom(); +} +void GetBlockProofEquivalentTimeImpl(const Consensus::Params& params) { std::vector blocks(10000); for (int i = 0; i < 10000; i++) { blocks[i].pprev = i ? &blocks[i - 1] : NULL; @@ -93,4 +168,16 @@ BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test) } } +BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test) +{ + SelectParams(CBaseChainParams::MAIN); + GetBlockProofEquivalentTimeImpl(Params().GetConsensus()); +} + +BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test_blossom) +{ + GetBlockProofEquivalentTimeImpl(ActivateBlossom()); + DeactivateBlossom(); +} + BOOST_AUTO_TEST_SUITE_END() From ff0820df5ee8dc80016fa56c6574c646a0b9c037 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 26 Jul 2019 10:48:16 -0600 Subject: [PATCH 176/395] Update test_pow for shorter block times --- src/gtest/test_pow.cpp | 16 +++++++++++++--- src/test/pow_tests.cpp | 28 ++++++---------------------- src/utiltest.cpp | 20 ++++++++++++++++++++ src/utiltest.h | 4 ++++ 4 files changed, 43 insertions(+), 25 deletions(-) diff --git a/src/gtest/test_pow.cpp b/src/gtest/test_pow.cpp index b79d91b898f..4a09ac69dd9 100644 --- a/src/gtest/test_pow.cpp +++ b/src/gtest/test_pow.cpp @@ -4,10 +4,10 @@ #include "chainparams.h" #include "pow.h" #include "random.h" +#include "utiltest.h" -TEST(PoW, DifficultyAveraging) { - SelectParams(CBaseChainParams::MAIN); - const Consensus::Params& params = Params().GetConsensus(); +void TestDifficultyAveragigingImpl(const Consensus::Params& params) +{ size_t lastBlk = 2*params.nPowAveragingWindow; size_t firstBlk = lastBlk - params.nPowAveragingWindow; @@ -73,6 +73,16 @@ TEST(PoW, DifficultyAveraging) { GetNextWorkRequired(&blocks[lastBlk], nullptr, params)); } +TEST(PoW, DifficultyAveraging) { + SelectParams(CBaseChainParams::MAIN); + TestDifficultyAveragigingImpl(Params().GetConsensus()); +} + +TEST(PoW, DifficultyAveragingBlossom) { + TestDifficultyAveragigingImpl(ActivateBlossom(true)); + DeactivateBlossom(); +} + TEST(PoW, MinDifficultyRules) { SelectParams(CBaseChainParams::TESTNET); const Consensus::Params& params = Params().GetConsensus(); diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index 1534cf8e8a8..626aaf5955f 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -5,29 +5,13 @@ #include "main.h" #include "pow.h" #include "util.h" +#include "utiltest.h" #include "test/test_bitcoin.h" #include using namespace std; -const Consensus::Params& ActivateBlossom() { - SelectParams(CBaseChainParams::REGTEST); - UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); - UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); - UpdateNetworkUpgradeParameters(Consensus::UPGRADE_BLOSSOM, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); - UpdateRegtestPow(32, 16, uint256S("0007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); - return Params().GetConsensus(); -} - -void DeactivateBlossom() { - UpdateRegtestPow(0, 0, uint256S("0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f")); - UpdateNetworkUpgradeParameters(Consensus::UPGRADE_BLOSSOM, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); - UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); - UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); - SelectParams(CBaseChainParams::MAIN); -} - BOOST_FIXTURE_TEST_SUITE(pow_tests, BasicTestingSetup) /* Test calculation of next difficulty target with no constraints applying */ @@ -48,7 +32,7 @@ BOOST_AUTO_TEST_CASE(get_next_work) BOOST_AUTO_TEST_CASE(get_next_work_blossom) { - const Consensus::Params& params = ActivateBlossom(); + const Consensus::Params& params = ActivateBlossom(true); BOOST_CHECK_EQUAL(75, params.PoWTargetSpacing(0)); int64_t nLastRetargetTime = 1000000000; // NOTE: Not an actual block time @@ -77,7 +61,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_pow_limit) BOOST_AUTO_TEST_CASE(get_next_work_pow_limit_blossom) { - const Consensus::Params& params = ActivateBlossom(); + const Consensus::Params& params = ActivateBlossom(true); int64_t nLastRetargetTime = 1231006505; int64_t nThisTime = 1233061996; @@ -107,7 +91,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual) BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual_blossom) { - const Consensus::Params& params = ActivateBlossom(); + const Consensus::Params& params = ActivateBlossom(true); int64_t nLastRetargetTime = 1000000000; // NOTE: Not an actual block time int64_t nThisTime = 1000000458; @@ -136,7 +120,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual) BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual_blossom) { - const Consensus::Params& params = ActivateBlossom(); + const Consensus::Params& params = ActivateBlossom(true); int64_t nLastRetargetTime = 1000000000; // NOTE: Not an actual block time int64_t nThisTime = 1000002908; @@ -176,7 +160,7 @@ BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test) BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test_blossom) { - GetBlockProofEquivalentTimeImpl(ActivateBlossom()); + GetBlockProofEquivalentTimeImpl(ActivateBlossom(true)); DeactivateBlossom(); } diff --git a/src/utiltest.cpp b/src/utiltest.cpp index 997137b1a78..7c503f388a6 100644 --- a/src/utiltest.cpp +++ b/src/utiltest.cpp @@ -200,6 +200,26 @@ void RegtestDeactivateSapling() { UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); } +const Consensus::Params& ActivateBlossom(bool updatePow) { + SelectParams(CBaseChainParams::REGTEST); + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_BLOSSOM, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); + if (updatePow) { + UpdateRegtestPow(32, 16, uint256S("0007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); + } + return Params().GetConsensus(); +} + +void DeactivateBlossom() { + UpdateRegtestPow(0, 0, uint256S("0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f")); + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_BLOSSOM, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); + SelectParams(CBaseChainParams::MAIN); +} + + libzcash::SaplingExtendedSpendingKey GetTestMasterSaplingSpendingKey() { std::vector> rawSeed(32); HDSeed seed(rawSeed); diff --git a/src/utiltest.h b/src/utiltest.h index 5480c559eb8..9fd3b661361 100644 --- a/src/utiltest.h +++ b/src/utiltest.h @@ -43,6 +43,10 @@ const Consensus::Params& RegtestActivateSapling(); void RegtestDeactivateSapling(); +const Consensus::Params& ActivateBlossom(bool updatePow); + +void DeactivateBlossom(); + libzcash::SaplingExtendedSpendingKey GetTestMasterSaplingSpendingKey(); CKey AddTestCKeyToKeyStore(CBasicKeyStore& keyStore); From 102dafdf89aa6b6ad07ef30695e466c70d7098c1 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 29 Jul 2019 13:44:53 -0600 Subject: [PATCH 177/395] Update block subsidy halving for zip208 --- qa/rpc-tests/shorter_block_times.py | 4 ++-- src/chainparams.cpp | 28 +++++++++++++++------- src/consensus/params.h | 36 +++++++++++++++++++++++++---- src/gtest/test_foundersreward.cpp | 8 +++---- src/main.cpp | 33 ++++++++++++++++++++++---- src/metrics.cpp | 2 +- src/miner.cpp | 2 +- src/rpc/mining.cpp | 2 +- src/test/main_tests.cpp | 12 +++++----- 9 files changed, 95 insertions(+), 32 deletions(-) diff --git a/qa/rpc-tests/shorter_block_times.py b/qa/rpc-tests/shorter_block_times.py index 26599d30c1a..74857740112 100755 --- a/qa/rpc-tests/shorter_block_times.py +++ b/qa/rpc-tests/shorter_block_times.py @@ -27,11 +27,11 @@ def setup_chain(self): def run_test(self): print "Mining blocks..." - self.nodes[0].generate(100) + self.nodes[0].generate(99) self.sync_all() # Sanity-check the block height - assert_equal(self.nodes[0].getblockcount(), 100) + assert_equal(self.nodes[0].getblockcount(), 99) print "Mining last pre-Blossom block" # Activate blossom diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 476385539e7..67ed810786c 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -85,7 +85,8 @@ class CMainParams : public CChainParams { bip44CoinType = 133; // As registered in https://github.com/satoshilabs/slips/blob/master/slip-0044.md consensus.fCoinbaseMustBeProtected = true; consensus.nSubsidySlowStartInterval = 20000; - consensus.nSubsidyHalvingInterval = 840000; + consensus.nPreBlossomSubsidyHalvingInterval = Consensus::PRE_BLOSSOM_HALVING_INTERVAL; + consensus.nPostBlossomSubsidyHalvingInterval = Consensus::POST_BLOSSOM_HALVING_INTERVAL; consensus.nMajorityEnforceBlockUpgrade = 750; consensus.nMajorityRejectBlockOutdated = 950; consensus.nMajorityWindow = 4000; @@ -261,7 +262,7 @@ class CMainParams : public CChainParams { // "t3T4WmAp6nrLkJ24iPpGeCe1fSWTPv47ASG", /* main-index: 53*/ // "t3fP6GrDM4QVwdjFhmCxGNbe7jXXXSDQ5dv", /* main-index: 54*/ }; - assert(vFoundersRewardAddress.size() <= consensus.GetLastFoundersRewardBlockHeight()); + assert(vFoundersRewardAddress.size() <= consensus.GetLastFoundersRewardBlockHeight(0)); } }; static CMainParams mainParams; @@ -277,7 +278,8 @@ class CTestNetParams : public CChainParams { bip44CoinType = 1; consensus.fCoinbaseMustBeProtected = true; consensus.nSubsidySlowStartInterval = 20000; - consensus.nSubsidyHalvingInterval = 840000; + consensus.nPreBlossomSubsidyHalvingInterval = Consensus::PRE_BLOSSOM_HALVING_INTERVAL; + consensus.nPostBlossomSubsidyHalvingInterval = Consensus::POST_BLOSSOM_HALVING_INTERVAL; consensus.nMajorityEnforceBlockUpgrade = 51; consensus.nMajorityRejectBlockOutdated = 75; consensus.nMajorityWindow = 400; @@ -394,7 +396,7 @@ class CTestNetParams : public CChainParams { "t2KXJVVyyrjVxxSeazbY9ksGyft4qsXUNm9", "t2J9YYtH31cveiLZzjaE4AcuwVho6qjTNzp", "t2QgvW4sP9zaGpPMH1GRzy7cpydmuRfB4AZ", "t2NDTJP9MosKpyFPHJmfjc5pGCvAU58XGa4", "t29pHDBWq7qN4EjwSEHg8wEqYe9pkmVrtRP", "t2Ez9KM8VJLuArcxuEkNRAkhNvidKkzXcjJ", "t2D5y7J5fpXajLbGrMBQkFg2mFN8fo3n8cX", "t2UV2wr1PTaUiybpkV3FdSdGxUJeZdZztyt", }; - assert(vFoundersRewardAddress.size() <= consensus.GetLastFoundersRewardBlockHeight()); + assert(vFoundersRewardAddress.size() <= consensus.GetLastFoundersRewardBlockHeight(0)); } }; static CTestNetParams testNetParams; @@ -410,7 +412,8 @@ class CRegTestParams : public CChainParams { bip44CoinType = 1; consensus.fCoinbaseMustBeProtected = false; consensus.nSubsidySlowStartInterval = 0; - consensus.nSubsidyHalvingInterval = 150; + consensus.nPreBlossomSubsidyHalvingInterval = Consensus::PRE_BLOSSOM_REGTEST_HALVING_INTERVAL; + consensus.nPostBlossomSubsidyHalvingInterval = Consensus::POST_BLOSSOM_REGTEST_HALVING_INTERVAL; consensus.nMajorityEnforceBlockUpgrade = 750; consensus.nMajorityRejectBlockOutdated = 950; consensus.nMajorityWindow = 1000; @@ -495,7 +498,7 @@ class CRegTestParams : public CChainParams { // Founders reward script expects a vector of 2-of-3 multisig addresses vFoundersRewardAddress = { "t2FwcEhFdNXuFMv1tcYwaBJtYVtMj8b1uTg" }; - assert(vFoundersRewardAddress.size() <= consensus.GetLastFoundersRewardBlockHeight()); + assert(vFoundersRewardAddress.size() <= consensus.GetLastFoundersRewardBlockHeight(0)); } void UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex idx, int nActivationHeight) @@ -568,7 +571,16 @@ bool SelectParamsFromCommandLine() // Block height must be >0 and <=last founders reward block height // Index variable i ranges from 0 - (vFoundersRewardAddress.size()-1) std::string CChainParams::GetFoundersRewardAddressAtHeight(int nHeight) const { - int maxHeight = consensus.GetLastFoundersRewardBlockHeight(); + int maxHeight = consensus.GetLastFoundersRewardBlockHeight(nHeight); + // zip208 + // FounderAddressAdjustedHeight(height) := + // height, if not IsBlossomActivated(height) + // BlossomActivationHeight + floor((height - BlossomActivationHeight) / BlossomPoWTargetSpacingRatio), otherwise + bool blossomActive = NetworkUpgradeActive(nHeight, consensus, Consensus::UPGRADE_BLOSSOM); + if (blossomActive) { + int blossomActivationHeight = consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; + nHeight = blossomActivationHeight + ((nHeight - blossomActivationHeight) / Consensus::BLOSSOM_POW_TARGET_SPACING_RATIO); + } assert(nHeight > 0 && nHeight <= maxHeight); size_t addressChangeInterval = (maxHeight + vFoundersRewardAddress.size()) / vFoundersRewardAddress.size(); @@ -579,7 +591,7 @@ std::string CChainParams::GetFoundersRewardAddressAtHeight(int nHeight) const { // Block height must be >0 and <=last founders reward block height // The founders reward address is expected to be a multisig (P2SH) address CScript CChainParams::GetFoundersRewardScriptAtHeight(int nHeight) const { - assert(nHeight > 0 && nHeight <= consensus.GetLastFoundersRewardBlockHeight()); + assert(nHeight > 0 && nHeight <= consensus.GetLastFoundersRewardBlockHeight(nHeight)); CTxDestination address = DecodeDestination(GetFoundersRewardAddressAtHeight(nHeight).c_str()); assert(IsValidDestination(address)); diff --git a/src/consensus/params.h b/src/consensus/params.h index ea517536fe8..b5cfe9177b9 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -73,6 +73,11 @@ struct NetworkUpgrade { static const unsigned int PRE_BLOSSOM_POW_TARGET_SPACING = 150; static const unsigned int POST_BLOSSOM_POW_TARGET_SPACING = 75; BOOST_STATIC_ASSERT(POST_BLOSSOM_POW_TARGET_SPACING < PRE_BLOSSOM_POW_TARGET_SPACING); +static const unsigned int PRE_BLOSSOM_HALVING_INTERVAL = 840000; +static const unsigned int PRE_BLOSSOM_REGTEST_HALVING_INTERVAL = 150; +static const unsigned int BLOSSOM_POW_TARGET_SPACING_RATIO = PRE_BLOSSOM_POW_TARGET_SPACING / POST_BLOSSOM_POW_TARGET_SPACING; +static const unsigned int POST_BLOSSOM_HALVING_INTERVAL = PRE_BLOSSOM_HALVING_INTERVAL * BLOSSOM_POW_TARGET_SPACING_RATIO; +static const unsigned int POST_BLOSSOM_REGTEST_HALVING_INTERVAL = PRE_BLOSSOM_REGTEST_HALVING_INTERVAL * BLOSSOM_POW_TARGET_SPACING_RATIO; /** * Parameters that influence chain consensus. @@ -92,14 +97,34 @@ struct Params { * * t_s = nSubsidySlowStartInterval * t_r = number of blocks between end of slow start and first halving - * t_h = nSubsidyHalvingInterval + * t_h = nPreBlossomSubsidyHalvingInterval * t_c = SubsidySlowStartShift() */ int SubsidySlowStartShift() const { return nSubsidySlowStartInterval / 2; } - int nSubsidyHalvingInterval; - int GetLastFoundersRewardBlockHeight() const { - return nSubsidyHalvingInterval + SubsidySlowStartShift() - 1; + int nPreBlossomSubsidyHalvingInterval; + int nPostBlossomSubsidyHalvingInterval; + + int GetLastFoundersRewardBlockHeight(int nHeight) const { + // zip208 + // FoundersRewardLastBlockHeight := max({ height ⦂ N | Halving(height) < 1 }) + // H := blossom activation height; SS := SubsidySlowStartShift(); R := BLOSSOM_POW_TARGET_SPACING_RATIO + // preBlossom: + // 1 = (height - SS) / preInterval + // height = preInterval + SS + // postBlossom: + // 1 = (H - SS) / preInterval + (height - H) / postInterval + // height = H + postInterval + (SS - H) * (postInterval / preInterval) + // height = H + postInterval + (SS - H) / R + bool blossomActive = NetworkUpgradeActive(nHeight, *this, Consensus::UPGRADE_BLOSSOM); + if (blossomActive) { + int blossomActivationHeight = vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; + return blossomActivationHeight + nPostBlossomSubsidyHalvingInterval + - (SubsidySlowStartShift() - blossomActivationHeight) / BLOSSOM_POW_TARGET_SPACING_RATIO - 1; + } else { + return nPreBlossomSubsidyHalvingInterval + SubsidySlowStartShift() - 1; + } } + /** Used to check majorities for block version upgrade */ int nMajorityEnforceBlockUpgrade; int nMajorityRejectBlockOutdated; @@ -117,6 +142,9 @@ struct Params { int64_t nPostBlossomPowTargetSpacing; int64_t PoWTargetSpacing(int nHeight) const { + // PoWTargetSpacing(height) := + // PreBlossomPoWTargetSpacing, if not IsBlossomActivated(height) + // PostBlossomPoWTargetSpacing, otherwise. bool blossomActive = NetworkUpgradeActive(nHeight, *this, Consensus::UPGRADE_BLOSSOM); return blossomActive ? nPostBlossomPowTargetSpacing : nPreBlossomPowTargetSpacing; } diff --git a/src/gtest/test_foundersreward.cpp b/src/gtest/test_foundersreward.cpp index 12c16ad897b..15e2c81b779 100644 --- a/src/gtest/test_foundersreward.cpp +++ b/src/gtest/test_foundersreward.cpp @@ -85,7 +85,7 @@ TEST(founders_reward_test, create_testnet_2of3multisig) { // Utility method to check the number of unique addresses from height 1 to maxHeight void checkNumberOfUniqueAddresses(int nUnique) { - int maxHeight = Params().GetConsensus().GetLastFoundersRewardBlockHeight(); + int maxHeight = Params().GetConsensus().GetLastFoundersRewardBlockHeight(0); std::set addresses; for (int i = 1; i <= maxHeight; i++) { addresses.insert(Params().GetFoundersRewardAddressAtHeight(i)); @@ -110,7 +110,7 @@ TEST(founders_reward_test, general) { EXPECT_EQ(HexStr(params.GetFoundersRewardScriptAtHeight(53127)), "a91455d64928e69829d9376c776550b6cc710d42715387"); EXPECT_EQ(params.GetFoundersRewardAddressAtHeight(53127), "t2ENg7hHVqqs9JwU5cgjvSbxnT2a9USNfhy"); - int maxHeight = params.GetConsensus().GetLastFoundersRewardBlockHeight(); + int maxHeight = params.GetConsensus().GetLastFoundersRewardBlockHeight(0); // If the block height parameter is out of bounds, there is an assert. EXPECT_DEATH(params.GetFoundersRewardScriptAtHeight(0), "nHeight"); @@ -151,7 +151,7 @@ TEST(founders_reward_test, slow_start_subsidy) { SelectParams(CBaseChainParams::MAIN); CChainParams params = Params(); - int maxHeight = params.GetConsensus().GetLastFoundersRewardBlockHeight(); + int maxHeight = params.GetConsensus().GetLastFoundersRewardBlockHeight(0); CAmount totalSubsidy = 0; for (int nHeight = 1; nHeight <= maxHeight; nHeight++) { CAmount nSubsidy = GetBlockSubsidy(nHeight, params.GetConsensus()) / 5; @@ -166,7 +166,7 @@ TEST(founders_reward_test, slow_start_subsidy) { // Verify the number of rewards each individual address receives. void verifyNumberOfRewards() { CChainParams params = Params(); - int maxHeight = params.GetConsensus().GetLastFoundersRewardBlockHeight(); + int maxHeight = params.GetConsensus().GetLastFoundersRewardBlockHeight(0); std::multiset ms; for (int nHeight = 1; nHeight <= maxHeight; nHeight++) { ms.insert(params.GetFoundersRewardAddressAtHeight(nHeight)); diff --git a/src/main.cpp b/src/main.cpp index fa28964e300..fbce29a91a2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1761,14 +1761,37 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) } assert(nHeight > consensusParams.SubsidySlowStartShift()); - int halvings = (nHeight - consensusParams.SubsidySlowStartShift()) / consensusParams.nSubsidyHalvingInterval; + + // zip208 + // Halving(height) := + // floor((height - SlowStartShift) / PreBlossomHalvingInterval), if not IsBlossomActivated(height) + // floor((BlossomActivationHeight - SlowStartShift) / PreBlossomHalvingInterval + (height - BlossomActivationHeight) / PostBlossomHalvingInterval), otherwise + bool blossomActive = NetworkUpgradeActive(nHeight, consensusParams, Consensus::UPGRADE_BLOSSOM); + int halvings; + if (blossomActive) { + int blossomActivationHeight = consensusParams.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; + halvings = (blossomActivationHeight - consensusParams.SubsidySlowStartShift()) / consensusParams.nPreBlossomSubsidyHalvingInterval + + (nHeight - blossomActivationHeight) / consensusParams.nPostBlossomSubsidyHalvingInterval; + } else { + halvings = (nHeight - consensusParams.SubsidySlowStartShift()) / consensusParams.nPreBlossomSubsidyHalvingInterval; + } + // Force block reward to zero when right shift is undefined. if (halvings >= 64) return 0; - // Subsidy is cut in half every 840,000 blocks which will occur approximately every 4 years. - nSubsidy >>= halvings; - return nSubsidy; + // zip208 + // BlockSubsidy(height) := + // SlowStartRate · height, if height < SlowStartInterval / 2 + // SlowStartRate · (height + 1), if SlowStartInterval / 2 ≤ height and height < SlowStartInterval + // floor(MaxBlockSubsidy / 2^Halving(height)), if SlowStartInterval ≤ height and not IsBlossomActivated(height) + // floor(MaxBlockSubsidy / (BlossomPoWTargetSpacingRatio · 2^Halving(height))), otherwise + if (blossomActive) { + return (nSubsidy / Consensus::BLOSSOM_POW_TARGET_SPACING_RATIO) >> halvings; + } else { + // Subsidy is cut in half every 840,000 blocks which will occur approximately every 4 years. + return nSubsidy >> halvings; + } } bool IsInitialBlockDownload(const CChainParams& chainParams) @@ -3902,7 +3925,7 @@ bool ContextualCheckBlock( // reward block is reached, with exception of the genesis block. // The last founders reward block is defined as the block just before the // first subsidy halving block, which occurs at halving_interval + slow_start_shift - if ((nHeight > 0) && (nHeight <= consensusParams.GetLastFoundersRewardBlockHeight())) { + if ((nHeight > 0) && (nHeight <= consensusParams.GetLastFoundersRewardBlockHeight(nHeight))) { bool found = false; BOOST_FOREACH(const CTxOut& output, block.vtx[0].vout) { diff --git a/src/metrics.cpp b/src/metrics.cpp index a47f4538c80..877167de947 100644 --- a/src/metrics.cpp +++ b/src/metrics.cpp @@ -331,7 +331,7 @@ int printMetrics(size_t cols, bool mining) chainActive.Contains(mapBlockIndex[hash])) { int height = mapBlockIndex[hash]->nHeight; CAmount subsidy = GetBlockSubsidy(height, consensusParams); - if ((height > 0) && (height <= consensusParams.GetLastFoundersRewardBlockHeight())) { + if ((height > 0) && (height <= consensusParams.GetLastFoundersRewardBlockHeight(height))) { subsidy -= subsidy/5; } if (std::max(0, COINBASE_MATURITY - (tipHeight - height)) > 0) { diff --git a/src/miner.cpp b/src/miner.cpp index aa3306524ad..e9795ec6d19 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -405,7 +405,7 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s // Set to 0 so expiry height does not apply to coinbase txs txNew.nExpiryHeight = 0; - if ((nHeight > 0) && (nHeight <= chainparams.GetConsensus().GetLastFoundersRewardBlockHeight())) { + if ((nHeight > 0) && (nHeight <= chainparams.GetConsensus().GetLastFoundersRewardBlockHeight(nHeight))) { // Founders reward is 20% of the block subsidy auto vFoundersReward = txNew.vout[0].nValue / 5; // Take some reward away from us diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index a75ab5924b1..6eb2e2f3950 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -884,7 +884,7 @@ UniValue getblocksubsidy(const UniValue& params, bool fHelp) CAmount nReward = GetBlockSubsidy(nHeight, Params().GetConsensus()); CAmount nFoundersReward = 0; - if ((nHeight > 0) && (nHeight <= Params().GetConsensus().GetLastFoundersRewardBlockHeight())) { + if ((nHeight > 0) && (nHeight <= Params().GetConsensus().GetLastFoundersRewardBlockHeight(nHeight))) { nFoundersReward = nReward/5; nReward -= nFoundersReward; } diff --git a/src/test/main_tests.cpp b/src/test/main_tests.cpp index ec02352e8b5..b731e89131e 100644 --- a/src/test/main_tests.cpp +++ b/src/test/main_tests.cpp @@ -22,7 +22,7 @@ static void TestBlockSubsidyHalvings(const Consensus::Params& consensusParams) for (int nHalvings = 0; nHalvings < maxHalvings; nHalvings++) { int nHeight; if (nHalvings > 0) // Check subsidy right at halvings - nHeight = nHalvings * consensusParams.nSubsidyHalvingInterval + consensusParams.SubsidySlowStartShift(); + nHeight = nHalvings * consensusParams.nPreBlossomSubsidyHalvingInterval + consensusParams.SubsidySlowStartShift(); else // Check subsidy just after end of slow start nHeight = consensusParams.nSubsidySlowStartInterval; CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams); @@ -30,14 +30,14 @@ static void TestBlockSubsidyHalvings(const Consensus::Params& consensusParams) BOOST_CHECK_EQUAL(nSubsidy, nPreviousSubsidy / 2); nPreviousSubsidy = nSubsidy; } - BOOST_CHECK_EQUAL(GetBlockSubsidy((maxHalvings * consensusParams.nSubsidyHalvingInterval) + consensusParams.SubsidySlowStartShift(), consensusParams), 0); + BOOST_CHECK_EQUAL(GetBlockSubsidy((maxHalvings * consensusParams.nPreBlossomSubsidyHalvingInterval) + consensusParams.SubsidySlowStartShift(), consensusParams), 0); } -static void TestBlockSubsidyHalvings(int nSubsidySlowStartInterval, int nSubsidyHalvingInterval) +static void TestBlockSubsidyHalvings(int nSubsidySlowStartInterval, int nPreBlossomSubsidyHalvingInterval) { Consensus::Params consensusParams; consensusParams.nSubsidySlowStartInterval = nSubsidySlowStartInterval; - consensusParams.nSubsidyHalvingInterval = nSubsidyHalvingInterval; + consensusParams.nPreBlossomSubsidyHalvingInterval = nPreBlossomSubsidyHalvingInterval; TestBlockSubsidyHalvings(consensusParams); } @@ -61,7 +61,7 @@ BOOST_AUTO_TEST_CASE(subsidy_limit_test) } BOOST_CHECK_EQUAL(nSum, 12500000000000ULL); // Remainder of first period - for (int nHeight = consensusParams.nSubsidySlowStartInterval; nHeight < consensusParams.nSubsidyHalvingInterval + consensusParams.SubsidySlowStartShift(); nHeight ++) { + for (int nHeight = consensusParams.nSubsidySlowStartInterval; nHeight < consensusParams.nPreBlossomSubsidyHalvingInterval + consensusParams.SubsidySlowStartShift(); nHeight ++) { CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams); BOOST_CHECK(nSubsidy <= 12.5 * COIN); nSum += nSubsidy; @@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE(subsidy_limit_test) } BOOST_CHECK_EQUAL(nSum, 1050000000000000ULL); // Regular mining - for (int nHeight = consensusParams.nSubsidyHalvingInterval + consensusParams.SubsidySlowStartShift(); nHeight < 56000000; nHeight += 1000) { + for (int nHeight = consensusParams.nPreBlossomSubsidyHalvingInterval + consensusParams.SubsidySlowStartShift(); nHeight < 56000000; nHeight += 1000) { CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams); BOOST_CHECK(nSubsidy <= 12.5 * COIN); nSum += nSubsidy * 1000; From 2c6c55261de16189a6da376cfc6ebe72bbf65686 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 29 Jul 2019 14:47:06 -0600 Subject: [PATCH 178/395] Make NetworkUpgradeAvailable a method of Params --- src/Makefile.am | 1 + src/chainparams.cpp | 2 +- src/consensus/params.cpp | 50 ++++++++++++++++ src/consensus/params.h | 59 ++++--------------- src/consensus/upgrades.cpp | 10 +--- src/consensus/upgrades.h | 10 ---- src/main.cpp | 20 +++---- src/rpc/rawtransaction.cpp | 4 +- .../asyncrpcoperation_mergetoaddress.cpp | 2 +- src/wallet/asyncrpcoperation_sendmany.cpp | 2 +- .../asyncrpcoperation_shieldcoinbase.cpp | 2 +- src/wallet/rpcwallet.cpp | 22 +++---- src/wallet/wallet.cpp | 10 ++-- 13 files changed, 93 insertions(+), 101 deletions(-) create mode 100644 src/consensus/params.cpp diff --git a/src/Makefile.am b/src/Makefile.am index a7c7b12bc5d..45a6a883455 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -367,6 +367,7 @@ libbitcoin_common_a_SOURCES = \ chainparams.cpp \ coins.cpp \ compressor.cpp \ + consensus/params.cpp \ consensus/upgrades.cpp \ core_read.cpp \ core_write.cpp \ diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 67ed810786c..50af3616baf 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -576,7 +576,7 @@ std::string CChainParams::GetFoundersRewardAddressAtHeight(int nHeight) const { // FounderAddressAdjustedHeight(height) := // height, if not IsBlossomActivated(height) // BlossomActivationHeight + floor((height - BlossomActivationHeight) / BlossomPoWTargetSpacingRatio), otherwise - bool blossomActive = NetworkUpgradeActive(nHeight, consensus, Consensus::UPGRADE_BLOSSOM); + bool blossomActive = consensus.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_BLOSSOM); if (blossomActive) { int blossomActivationHeight = consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; nHeight = blossomActivationHeight + ((nHeight - blossomActivationHeight) / Consensus::BLOSSOM_POW_TARGET_SPACING_RATIO); diff --git a/src/consensus/params.cpp b/src/consensus/params.cpp new file mode 100644 index 00000000000..4703a5549a4 --- /dev/null +++ b/src/consensus/params.cpp @@ -0,0 +1,50 @@ +#include "params.h" +#include "upgrades.h" + +namespace Consensus { + bool Params::NetworkUpgradeActive(int nHeight, Consensus::UpgradeIndex idx) const { + return NetworkUpgradeState(nHeight, *this, idx) == UPGRADE_ACTIVE; + } + + int Params::GetLastFoundersRewardBlockHeight(int nHeight) const { + // zip208 + // FoundersRewardLastBlockHeight := max({ height ⦂ N | Halving(height) < 1 }) + // H := blossom activation height; SS := SubsidySlowStartShift(); R := BLOSSOM_POW_TARGET_SPACING_RATIO + // preBlossom: + // 1 = (height - SS) / preInterval + // height = preInterval + SS + // postBlossom: + // 1 = (H - SS) / preInterval + (height - H) / postInterval + // height = H + postInterval + (SS - H) * (postInterval / preInterval) + // height = H + postInterval + (SS - H) / R + bool blossomActive = NetworkUpgradeActive(nHeight, Consensus::UPGRADE_BLOSSOM); + if (blossomActive) { + int blossomActivationHeight = vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; + return blossomActivationHeight + nPostBlossomSubsidyHalvingInterval + - (SubsidySlowStartShift() - blossomActivationHeight) / BLOSSOM_POW_TARGET_SPACING_RATIO - 1; + } else { + return nPreBlossomSubsidyHalvingInterval + SubsidySlowStartShift() - 1; + } + } + + int64_t Params::PoWTargetSpacing(int nHeight) const { + // zip208 + // PoWTargetSpacing(height) := + // PreBlossomPoWTargetSpacing, if not IsBlossomActivated(height) + // PostBlossomPoWTargetSpacing, otherwise. + bool blossomActive = NetworkUpgradeActive(nHeight, Consensus::UPGRADE_BLOSSOM); + return blossomActive ? nPostBlossomPowTargetSpacing : nPreBlossomPowTargetSpacing; + } + + int64_t Params::AveragingWindowTimespan(int nHeight) const { + return nPowAveragingWindow * PoWTargetSpacing(nHeight); + } + + int64_t Params::MinActualTimespan(int nHeight) const { + return (AveragingWindowTimespan(nHeight) * (100 - nPowMaxAdjustUp)) / 100; + } + + int64_t Params::MaxActualTimespan(int nHeight) const { + return (AveragingWindowTimespan(nHeight) * (100 + nPowMaxAdjustDown)) / 100; + } +} \ No newline at end of file diff --git a/src/consensus/params.h b/src/consensus/params.h index b5cfe9177b9..764b0efd49c 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -10,14 +10,6 @@ #include -// Forward declaration. Enum requires storage type. -namespace Consensus { - struct Params; - enum UpgradeIndex : uint32_t; -} -bool NetworkUpgradeActive(int nHeight, const Consensus::Params& params, Consensus::UpgradeIndex idx); - - namespace Consensus { /** @@ -83,6 +75,13 @@ static const unsigned int POST_BLOSSOM_REGTEST_HALVING_INTERVAL = PRE_BLOSSOM_RE * Parameters that influence chain consensus. */ struct Params { + /** + * Returns true if the given network upgrade is active as of the given block + * height. Caller must check that the height is >= 0 (and handle unknown + * heights). + */ + bool NetworkUpgradeActive(int nHeight, Consensus::UpgradeIndex idx) const; + uint256 hashGenesisBlock; bool fCoinbaseMustBeProtected; @@ -104,26 +103,7 @@ struct Params { int nPreBlossomSubsidyHalvingInterval; int nPostBlossomSubsidyHalvingInterval; - int GetLastFoundersRewardBlockHeight(int nHeight) const { - // zip208 - // FoundersRewardLastBlockHeight := max({ height ⦂ N | Halving(height) < 1 }) - // H := blossom activation height; SS := SubsidySlowStartShift(); R := BLOSSOM_POW_TARGET_SPACING_RATIO - // preBlossom: - // 1 = (height - SS) / preInterval - // height = preInterval + SS - // postBlossom: - // 1 = (H - SS) / preInterval + (height - H) / postInterval - // height = H + postInterval + (SS - H) * (postInterval / preInterval) - // height = H + postInterval + (SS - H) / R - bool blossomActive = NetworkUpgradeActive(nHeight, *this, Consensus::UPGRADE_BLOSSOM); - if (blossomActive) { - int blossomActivationHeight = vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; - return blossomActivationHeight + nPostBlossomSubsidyHalvingInterval - - (SubsidySlowStartShift() - blossomActivationHeight) / BLOSSOM_POW_TARGET_SPACING_RATIO - 1; - } else { - return nPreBlossomSubsidyHalvingInterval + SubsidySlowStartShift() - 1; - } - } + int GetLastFoundersRewardBlockHeight(int nHeight) const; /** Used to check majorities for block version upgrade */ int nMajorityEnforceBlockUpgrade; @@ -141,25 +121,10 @@ struct Params { int64_t nPreBlossomPowTargetSpacing; int64_t nPostBlossomPowTargetSpacing; - int64_t PoWTargetSpacing(int nHeight) const { - // PoWTargetSpacing(height) := - // PreBlossomPoWTargetSpacing, if not IsBlossomActivated(height) - // PostBlossomPoWTargetSpacing, otherwise. - bool blossomActive = NetworkUpgradeActive(nHeight, *this, Consensus::UPGRADE_BLOSSOM); - return blossomActive ? nPostBlossomPowTargetSpacing : nPreBlossomPowTargetSpacing; - } - - int64_t AveragingWindowTimespan(int nHeight) const { - return nPowAveragingWindow * PoWTargetSpacing(nHeight); - } - - int64_t MinActualTimespan(int nHeight) const { - return (AveragingWindowTimespan(nHeight) * (100 - nPowMaxAdjustUp)) / 100; - } - - int64_t MaxActualTimespan(int nHeight) const { - return (AveragingWindowTimespan(nHeight) * (100 + nPowMaxAdjustDown)) / 100; - } + int64_t PoWTargetSpacing(int nHeight) const; + int64_t AveragingWindowTimespan(int nHeight) const; + int64_t MinActualTimespan(int nHeight) const; + int64_t MaxActualTimespan(int nHeight) const; uint256 nMinimumChainWork; }; diff --git a/src/consensus/upgrades.cpp b/src/consensus/upgrades.cpp index e11aaa260e4..b86fbc23bd4 100644 --- a/src/consensus/upgrades.cpp +++ b/src/consensus/upgrades.cpp @@ -65,17 +65,9 @@ UpgradeState NetworkUpgradeState( } } -bool NetworkUpgradeActive( - int nHeight, - const Consensus::Params& params, - Consensus::UpgradeIndex idx) -{ - return NetworkUpgradeState(nHeight, params, idx) == UPGRADE_ACTIVE; -} - int CurrentEpoch(int nHeight, const Consensus::Params& params) { for (auto idxInt = Consensus::MAX_NETWORK_UPGRADES - 1; idxInt >= Consensus::BASE_SPROUT; idxInt--) { - if (NetworkUpgradeActive(nHeight, params, Consensus::UpgradeIndex(idxInt))) { + if (params.NetworkUpgradeActive(nHeight, Consensus::UpgradeIndex(idxInt))) { return idxInt; } } diff --git a/src/consensus/upgrades.h b/src/consensus/upgrades.h index 920ec1ea896..f773ecae4a0 100644 --- a/src/consensus/upgrades.h +++ b/src/consensus/upgrades.h @@ -38,16 +38,6 @@ UpgradeState NetworkUpgradeState( const Consensus::Params& params, Consensus::UpgradeIndex idx); -/** - * Returns true if the given network upgrade is active as of the given block - * height. Caller must check that the height is >= 0 (and handle unknown - * heights). - */ -bool NetworkUpgradeActive( - int nHeight, - const Consensus::Params& params, - Consensus::UpgradeIndex idx); - /** * Returns the index of the most recent upgrade as of the given block height * (corresponding to the current "epoch"). Consensus::BASE_SPROUT is the diff --git a/src/main.cpp b/src/main.cpp index fbce29a91a2..5a8b7983d87 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -657,8 +657,8 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) EXCLUSIVE_LOCKS_REQUIRE bool IsStandardTx(const CTransaction& tx, string& reason, const CChainParams& chainparams, const int nHeight) { - bool overwinterActive = NetworkUpgradeActive(nHeight, chainparams.GetConsensus(), Consensus::UPGRADE_OVERWINTER); - bool saplingActive = NetworkUpgradeActive(nHeight, chainparams.GetConsensus(), Consensus::UPGRADE_SAPLING); + bool overwinterActive = chainparams.GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_OVERWINTER); + bool saplingActive = chainparams.GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_SAPLING); if (saplingActive) { // Sapling standard rules apply @@ -897,8 +897,8 @@ bool ContextualCheckTransaction( const int dosLevel, bool (*isInitBlockDownload)(const CChainParams&)) { - bool overwinterActive = NetworkUpgradeActive(nHeight, chainparams.GetConsensus(), Consensus::UPGRADE_OVERWINTER); - bool saplingActive = NetworkUpgradeActive(nHeight, chainparams.GetConsensus(), Consensus::UPGRADE_SAPLING); + bool overwinterActive = chainparams.GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_OVERWINTER); + bool saplingActive = chainparams.GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_SAPLING); bool isSprout = !overwinterActive; // If Sprout rules apply, reject transactions which are intended for Overwinter and beyond @@ -1367,7 +1367,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Node operator can choose to reject tx by number of transparent inputs static_assert(std::numeric_limits::max() >= std::numeric_limits::max(), "size_t too small"); size_t limit = (size_t) GetArg("-mempooltxinputlimit", 0); - if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) { + if (Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_OVERWINTER)) { limit = 0; } if (limit > 0) { @@ -1766,7 +1766,7 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) // Halving(height) := // floor((height - SlowStartShift) / PreBlossomHalvingInterval), if not IsBlossomActivated(height) // floor((BlossomActivationHeight - SlowStartShift) / PreBlossomHalvingInterval + (height - BlossomActivationHeight) / PostBlossomHalvingInterval), otherwise - bool blossomActive = NetworkUpgradeActive(nHeight, consensusParams, Consensus::UPGRADE_BLOSSOM); + bool blossomActive = consensusParams.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_BLOSSOM); int halvings; if (blossomActive) { int blossomActivationHeight = consensusParams.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; @@ -2392,7 +2392,7 @@ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& s // However, this is only reliable if the last block was on or after // the Sapling activation height. Otherwise, the last anchor was the // empty root. - if (NetworkUpgradeActive(pindex->pprev->nHeight, chainparams.GetConsensus(), Consensus::UPGRADE_SAPLING)) { + if (chainparams.GetConsensus().NetworkUpgradeActive(pindex->pprev->nHeight, Consensus::UPGRADE_SAPLING)) { view.PopAnchor(pindex->pprev->hashFinalSaplingRoot, SAPLING); } else { view.PopAnchor(SaplingMerkleTree::empty_root(), SAPLING); @@ -2800,7 +2800,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // If Sapling is active, block.hashFinalSaplingRoot must be the // same as the root of the Sapling tree - if (NetworkUpgradeActive(pindex->nHeight, chainparams.GetConsensus(), Consensus::UPGRADE_SAPLING)) { + if (chainparams.GetConsensus().NetworkUpgradeActive(pindex->nHeight, Consensus::UPGRADE_SAPLING)) { if (block.hashFinalSaplingRoot != sapling_tree.root()) { return state.DoS(100, error("ConnectBlock(): block's hashFinalSaplingRoot is incorrect"), @@ -6670,7 +6670,7 @@ CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Para CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight, int nExpiryDelta) { CMutableTransaction mtx; - bool isOverwintered = NetworkUpgradeActive(nHeight, consensusParams, Consensus::UPGRADE_OVERWINTER); + bool isOverwintered = consensusParams.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_OVERWINTER); if (isOverwintered) { mtx.fOverwintered = true; mtx.nExpiryHeight = nHeight + nExpiryDelta; @@ -6683,7 +6683,7 @@ CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Para // of the current epoch (see below: Overwinter->Sapling), the transaction will be rejected if it falls within // the expiring soon threshold of 3 blocks (for DoS mitigation) based on the current height. // TODO: Generalise this code so behaviour applies to all post-Overwinter epochs - if (NetworkUpgradeActive(nHeight, consensusParams, Consensus::UPGRADE_SAPLING)) { + if (consensusParams.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_SAPLING)) { mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID; mtx.nVersion = SAPLING_TX_VERSION; } else { diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 612323abc46..d951d91bf95 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -531,7 +531,7 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) } if (params.size() > 3 && !params[3].isNull()) { - if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) { + if (Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_OVERWINTER)) { int64_t nExpiryHeight = params[3].get_int64(); if (nExpiryHeight < 0 || nExpiryHeight >= TX_EXPIRY_HEIGHT_THRESHOLD) { throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, expiryheight must be nonnegative and less than %d.", TX_EXPIRY_HEIGHT_THRESHOLD)); @@ -1046,7 +1046,7 @@ UniValue sendrawtransaction(const UniValue& params, bool fHelp) // DoS mitigation: reject transactions expiring soon if (tx.nExpiryHeight > 0) { int nextBlockHeight = chainActive.Height() + 1; - if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) { + if (Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_OVERWINTER)) { if (nextBlockHeight + TX_EXPIRING_SOON_THRESHOLD > tx.nExpiryHeight) { throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("tx-expiring-soon: expiryheight is %d but should be at least %d to avoid transaction expiring soon", diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index fda81aa6dc6..4152f5be958 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -217,7 +217,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() size_t limit = (size_t)GetArg("-mempooltxinputlimit", 0); { LOCK(cs_main); - if (NetworkUpgradeActive(chainActive.Height() + 1, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) { + if (Params().GetConsensus().NetworkUpgradeActive(chainActive.Height() + 1, Consensus::UPGRADE_OVERWINTER)) { limit = 0; } } diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index 7e0a9dd50ce..e1bf32594c9 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -318,7 +318,7 @@ bool AsyncRPCOperation_sendmany::main_impl() { size_t limit = (size_t)GetArg("-mempooltxinputlimit", 0); { LOCK(cs_main); - if (NetworkUpgradeActive(chainActive.Height() + 1, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) { + if (Params().GetConsensus().NetworkUpgradeActive(chainActive.Height() + 1, Consensus::UPGRADE_OVERWINTER)) { limit = 0; } } diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp index 0b2f0174b12..9b9d8ce20ea 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp @@ -180,7 +180,7 @@ bool AsyncRPCOperation_shieldcoinbase::main_impl() { size_t limit = (size_t)GetArg("-mempooltxinputlimit", 0); { LOCK(cs_main); - if (NetworkUpgradeActive(chainActive.Height() + 1, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) { + if (Params().GetConsensus().NetworkUpgradeActive(chainActive.Height() + 1, Consensus::UPGRADE_OVERWINTER)) { limit = 0; } } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 5e07e85882d..67caf89cc09 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3790,8 +3790,8 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID; mtx.nVersion = SAPLING_TX_VERSION; unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING; - if (!NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) { - if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) { + if (!Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_SAPLING)) { + if (Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_OVERWINTER)) { mtx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID; mtx.nVersion = OVERWINTER_TX_VERSION; } else { @@ -3805,10 +3805,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) if (zaddrRecipients.size() > Z_SENDMANY_MAX_ZADDR_OUTPUTS_BEFORE_SAPLING) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, too many zaddr outputs"); } - } - - // If Sapling is not active, do not allow sending from or sending to Sapling addresses. - if (!NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) { + // If Sapling is not active, do not allow sending from or sending to Sapling addresses. if (fromSapling || containsSaplingOutput) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated"); } @@ -4122,15 +4119,12 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp) } int nextBlockHeight = chainActive.Height() + 1; - bool overwinterActive = NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER); + bool overwinterActive = Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_OVERWINTER); unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING; - if (!NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) { + if (!Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_SAPLING)) { max_tx_size = MAX_TX_SIZE_BEFORE_SAPLING; - } - - // If Sapling is not active, do not allow sending to a Sapling address. - if (!NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) { auto res = DecodePaymentAddress(destaddress); + // If Sapling is not active, do not allow sending to a Sapling address. if (IsValidPaymentAddress(res)) { bool toSapling = boost::get(&res) != nullptr; if (toSapling) { @@ -4388,8 +4382,8 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) } const int nextBlockHeight = chainActive.Height() + 1; - const bool overwinterActive = NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER); - const bool saplingActive = NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING); + const bool overwinterActive = Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_OVERWINTER); + const bool saplingActive = Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_SAPLING); // Validate the destination address auto destaddress = params[1].get_str(); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 480547d9577..6133f56076d 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -595,7 +595,7 @@ void CWallet::ChainTip(const CBlockIndex *pindex, } void CWallet::RunSaplingMigration(int blockHeight) { - if (!NetworkUpgradeActive(blockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) { + if (!Params().GetConsensus().NetworkUpgradeActive(blockHeight, Consensus::UPGRADE_SAPLING)) { return; } LOCK(cs_wallet); @@ -2526,7 +2526,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) // state on the path to the tip of our chain assert(pcoinsTip->GetSproutAnchorAt(pindex->hashSproutAnchor, sproutTree)); if (pindex->pprev) { - if (NetworkUpgradeActive(pindex->pprev->nHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) { + if (Params().GetConsensus().NetworkUpgradeActive(pindex->pprev->nHeight, Consensus::UPGRADE_SAPLING)) { assert(pcoinsTip->GetSaplingAnchorAt(pindex->pprev->hashFinalSaplingRoot, saplingTree)); } } @@ -3303,7 +3303,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt Params().GetConsensus(), nextBlockHeight); // Activates after Overwinter network upgrade - if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) { + if (Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_OVERWINTER)) { if (txNew.nExpiryHeight >= TX_EXPIRY_HEIGHT_THRESHOLD){ strFailReason = _("nExpiryHeight must be less than TX_EXPIRY_HEIGHT_THRESHOLD."); return false; @@ -3311,7 +3311,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt } unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING; - if (!NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) { + if (!Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_SAPLING)) { max_tx_size = MAX_TX_SIZE_BEFORE_SAPLING; } @@ -3502,7 +3502,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt size_t limit = (size_t)GetArg("-mempooltxinputlimit", 0); { LOCK(cs_main); - if (NetworkUpgradeActive(chainActive.Height() + 1, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) { + if (Params().GetConsensus().NetworkUpgradeActive(chainActive.Height() + 1, Consensus::UPGRADE_OVERWINTER)) { limit = 0; } } From 07851670b4d907198b15fca476a16d197f5e90c9 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 29 Jul 2019 15:04:34 -0600 Subject: [PATCH 179/395] Temporarily disable test --- qa/pull-tester/rpc-tests.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index 3b6d411aead..e724c93fa95 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -73,7 +73,8 @@ testScripts=( 'p2p_node_bloom.py' 'regtest_signrawtransaction.py' 'finalsaplingroot.py' - 'shorter_block_times.py' + # TODO: enable the following test when updating PROTOCOL_VERSION in version.h for Blossom + # 'shorter_block_times.py' 'sprout_sapling_migration.py' 'turnstile.py' ); From c0d27cb3f2cee056218a1d51a825d740ddbcbfcb Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 29 Jul 2019 18:29:39 -0600 Subject: [PATCH 180/395] Simplify PartitionCheck --- src/init.cpp | 2 +- src/main.cpp | 37 +++++++++++++------------------------ src/main.h | 2 +- src/test/alert_tests.cpp | 21 ++++++++++++--------- 4 files changed, 27 insertions(+), 35 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 6d6fd1f4a5d..7b6b2ab03b4 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1863,7 +1863,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // Monitor the chain every minute, and alert if we get blocks much quicker or slower than expected. CScheduler::Function f = boost::bind(&PartitionCheck, &IsInitialBlockDownload, - boost::ref(cs_main), boost::cref(pindexBestHeader), 0); + boost::ref(cs_main), boost::cref(pindexBestHeader)); scheduler.scheduleEvery(f, 60); #ifdef ENABLE_MINING diff --git a/src/main.cpp b/src/main.cpp index 5a8b7983d87..04a817c1ce7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2458,13 +2458,8 @@ void ThreadScriptCheck() { // Called periodically asynchronously; alerts if it smells like // we're being fed a bad chain (blocks being generated much // too slowly or too quickly). -// -// When parameter nPowTargetSpacing is not set, the default value of 0 -// means use the block height of the best header to determine target spacing. -// Setting the parameter value is useful for testing. void PartitionCheck(bool (*initialDownloadCheck)(const CChainParams&), - CCriticalSection& cs, const CBlockIndex *const &bestHeader, - int64_t nPowTargetSpacing) + CCriticalSection& cs, const CBlockIndex *const &bestHeader) { if (bestHeader == NULL || initialDownloadCheck(Params())) return; @@ -2477,26 +2472,20 @@ void PartitionCheck(bool (*initialDownloadCheck)(const CChainParams&), LOCK(cs); - int bestHeaderHeight = bestHeader->nHeight; - int blossomHeight = Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; - if (nPowTargetSpacing == 0) { - nPowTargetSpacing = Params().GetConsensus().PoWTargetSpacing(bestHeaderHeight); - blossomHeight = Params().GetConsensus().vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; - } - - int BLOCKS_EXPECTED = SPAN_SECONDS / nPowTargetSpacing; + Consensus::Params consensusParams = Params().GetConsensus(); + int BLOCKS_EXPECTED; + // TODO: This can be simplified when the Blossom activation height is set + int nBlossomBlocks = consensusParams.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight == Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT ? + 0 : std::max(0, bestHeader->nHeight - consensusParams.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight); + int blossomBlockTime = nBlossomBlocks * consensusParams.nPostBlossomPowTargetSpacing; // If the span period includes Blossom activation, adjust the number of expected blocks. - if (blossomHeight != Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT && - bestHeaderHeight > blossomHeight) - { - int t = SPAN_SECONDS; - int nBlossomBlocks = bestHeaderHeight - blossomHeight; - t -= nBlossomBlocks * Consensus::POST_BLOSSOM_POW_TARGET_SPACING; - if (t > 0) { - int nPreBlossomBlocks = t / Consensus::PRE_BLOSSOM_POW_TARGET_SPACING; - BLOCKS_EXPECTED = nPreBlossomBlocks + nBlossomBlocks; - } + if (blossomBlockTime < SPAN_SECONDS) { + // If there are 0 blossomBlocks the following is equivalent to + // BLOCKS_EXPECTED = SPAN_SECONDS / consensusParams.nPreBlossomPowTargetSpacing + BLOCKS_EXPECTED = nBlossomBlocks + (SPAN_SECONDS - blossomBlockTime) / consensusParams.nPreBlossomPowTargetSpacing; + } else { + BLOCKS_EXPECTED = SPAN_SECONDS / consensusParams.nPostBlossomPowTargetSpacing; } boost::math::poisson_distribution poisson(BLOCKS_EXPECTED); diff --git a/src/main.h b/src/main.h index deda1276c7b..ff15180ccdb 100644 --- a/src/main.h +++ b/src/main.h @@ -234,7 +234,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle); /** Run an instance of the script checking thread */ void ThreadScriptCheck(); /** Try to detect Partition (network isolation) attacks against us */ -void PartitionCheck(bool (*initialDownloadCheck)(const CChainParams&), CCriticalSection& cs, const CBlockIndex *const &bestHeader, int64_t nPowTargetSpacing = 0); +void PartitionCheck(bool (*initialDownloadCheck)(const CChainParams&), CCriticalSection& cs, const CBlockIndex *const &bestHeader); /** Check whether we are doing an initial block download (synchronizing from disk or network) */ bool IsInitialBlockDownload(const CChainParams& chainParams); /** Format a string that describes several potential problems detected by the core */ diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index f50f7c49725..9be91645c19 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -410,23 +410,25 @@ BOOST_AUTO_TEST_CASE(PartitionAlert) // Test 1: chain with blocks every nPowTargetSpacing seconds, // as normal, no worries: - PartitionCheck(falseFunc, csDummy, &indexDummy[399], nPowTargetSpacing); - BOOST_CHECK(strMiscWarning.empty()); + strMiscWarning = ""; + PartitionCheck(falseFunc, csDummy, &indexDummy[399]); + BOOST_CHECK_EQUAL("", strMiscWarning); // Test 2: go 3.5 hours without a block, expect a warning: now += 3*60*60+30*60; SetMockTime(now); - PartitionCheck(falseFunc, csDummy, &indexDummy[399], nPowTargetSpacing); - BOOST_CHECK(!strMiscWarning.empty()); - BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); strMiscWarning = ""; + PartitionCheck(falseFunc, csDummy, &indexDummy[399]); + BOOST_CHECK_EQUAL("WARNING: check your network connection, 12 blocks received in the last 4 hours (96 expected)", strMiscWarning); + BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); // Test 3: test the "partition alerts only go off once per day" // code: now += 60*10; SetMockTime(now); - PartitionCheck(falseFunc, csDummy, &indexDummy[399], nPowTargetSpacing); - BOOST_CHECK(strMiscWarning.empty()); + strMiscWarning = ""; + PartitionCheck(falseFunc, csDummy, &indexDummy[399]); + BOOST_CHECK_EQUAL("", strMiscWarning); // Test 4: get 2.5 times as many blocks as expected: now += 60*60*24; // Pretend it is a day later @@ -434,8 +436,9 @@ BOOST_AUTO_TEST_CASE(PartitionAlert) int64_t quickSpacing = nPowTargetSpacing*2/5; for (int i = 0; i < 400; i++) // Tweak chain timestamps: indexDummy[i].nTime = now - (400-i)*quickSpacing; - PartitionCheck(falseFunc, csDummy, &indexDummy[399], nPowTargetSpacing); - BOOST_CHECK(!strMiscWarning.empty()); + strMiscWarning = ""; + PartitionCheck(falseFunc, csDummy, &indexDummy[399]); + BOOST_CHECK_EQUAL("WARNING: abnormally high number of blocks generated, 240 blocks received in the last 4 hours (96 expected)", strMiscWarning); BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); strMiscWarning = ""; From e6b63d1f784ea019568fea0ad6a1ec12d522812c Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 29 Jul 2019 19:05:41 -0600 Subject: [PATCH 181/395] Use static_assert --- src/consensus/params.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/consensus/params.h b/src/consensus/params.h index 764b0efd49c..a3657da6135 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -64,7 +64,7 @@ struct NetworkUpgrade { /** ZIP208 block target interval in seconds. */ static const unsigned int PRE_BLOSSOM_POW_TARGET_SPACING = 150; static const unsigned int POST_BLOSSOM_POW_TARGET_SPACING = 75; -BOOST_STATIC_ASSERT(POST_BLOSSOM_POW_TARGET_SPACING < PRE_BLOSSOM_POW_TARGET_SPACING); +static_assert(POST_BLOSSOM_POW_TARGET_SPACING < PRE_BLOSSOM_POW_TARGET_SPACING); static const unsigned int PRE_BLOSSOM_HALVING_INTERVAL = 840000; static const unsigned int PRE_BLOSSOM_REGTEST_HALVING_INTERVAL = 150; static const unsigned int BLOSSOM_POW_TARGET_SPACING_RATIO = PRE_BLOSSOM_POW_TARGET_SPACING / POST_BLOSSOM_POW_TARGET_SPACING; From 68e9d2164cd46ffe306d41d7923b73f13a4af441 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 29 Jul 2019 19:07:27 -0600 Subject: [PATCH 182/395] Add missing new line at end of file --- src/consensus/params.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/consensus/params.cpp b/src/consensus/params.cpp index 4703a5549a4..1d6003a1a82 100644 --- a/src/consensus/params.cpp +++ b/src/consensus/params.cpp @@ -47,4 +47,4 @@ namespace Consensus { int64_t Params::MaxActualTimespan(int nHeight) const { return (AveragingWindowTimespan(nHeight) * (100 + nPowMaxAdjustDown)) / 100; } -} \ No newline at end of file +} From 0bb79ea1914afba2e51e80162ec0459d1e731075 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 29 Jul 2019 19:07:56 -0600 Subject: [PATCH 183/395] pow test cleanup --- src/gtest/test_pow.cpp | 14 +++++++------- src/test/pow_tests.cpp | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/gtest/test_pow.cpp b/src/gtest/test_pow.cpp index 4a09ac69dd9..281701892e3 100644 --- a/src/gtest/test_pow.cpp +++ b/src/gtest/test_pow.cpp @@ -16,7 +16,7 @@ void TestDifficultyAveragigingImpl(const Consensus::Params& params) for (int i = 0; i <= lastBlk; i++) { blocks[i].pprev = i ? &blocks[i - 1] : nullptr; blocks[i].nHeight = i; - blocks[i].nTime = 1269211443 + i * params.PoWTargetSpacing(blocks[i].nHeight); + blocks[i].nTime = i ? blocks[i - 1].nTime + params.PoWTargetSpacing(i) : 1269211443; blocks[i].nBits = 0x1e7fffff; /* target 0x007fffff000... */ blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + GetBlockProof(blocks[i - 1]) : arith_uint256(0); } @@ -33,12 +33,12 @@ void TestDifficultyAveragigingImpl(const Consensus::Params& params) // Result should be unchanged, modulo integer division precision loss arith_uint256 bnRes; bnRes.SetCompact(0x1e7fffff); - bnRes /= params.AveragingWindowTimespan(blocks[lastBlk].nHeight); - bnRes *= params.AveragingWindowTimespan(blocks[lastBlk].nHeight); + bnRes /= params.AveragingWindowTimespan(blocks[lastBlk].nHeight + 1); + bnRes *= params.AveragingWindowTimespan(blocks[lastBlk].nHeight + 1); EXPECT_EQ(bnRes.GetCompact(), GetNextWorkRequired(&blocks[lastBlk], nullptr, params)); // Randomise the final block time (plus 1 to ensure it is always different) - blocks[lastBlk].nTime += GetRand(params.PoWTargetSpacing(blocks[lastBlk].nHeight)/2) + 1; + blocks[lastBlk].nTime += GetRand(params.PoWTargetSpacing(blocks[lastBlk].nHeight + 1)/2) + 1; // Result should be the same as if last difficulty was used bnAvg.SetCompact(blocks[lastBlk].nBits); @@ -94,7 +94,7 @@ TEST(PoW, MinDifficultyRules) { for (int i = 0; i <= lastBlk; i++) { blocks[i].pprev = i ? &blocks[i - 1] : nullptr; blocks[i].nHeight = params.nPowAllowMinDifficultyBlocksAfterHeight.get() + i; - blocks[i].nTime = 1269211443 + i * params.PoWTargetSpacing(blocks[i].nHeight); + blocks[i].nTime = i ? blocks[i - 1].nTime + params.PoWTargetSpacing(i) : 1269211443; blocks[i].nBits = 0x1e7fffff; /* target 0x007fffff000... */ blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + GetBlockProof(blocks[i - 1]) : arith_uint256(0); } @@ -106,8 +106,8 @@ TEST(PoW, MinDifficultyRules) { // Result should be unchanged, modulo integer division precision loss arith_uint256 bnRes; bnRes.SetCompact(0x1e7fffff); - bnRes /= params.AveragingWindowTimespan(blocks[lastBlk].nHeight); - bnRes *= params.AveragingWindowTimespan(blocks[lastBlk].nHeight); + bnRes /= params.AveragingWindowTimespan(blocks[lastBlk].nHeight + 1); + bnRes *= params.AveragingWindowTimespan(blocks[lastBlk].nHeight + 1); EXPECT_EQ(GetNextWorkRequired(&blocks[lastBlk], &next, params), bnRes.GetCompact()); // Delay last block up to the edge of the min-difficulty limit diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index 626aaf5955f..416b4ac7c17 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -137,7 +137,7 @@ void GetBlockProofEquivalentTimeImpl(const Consensus::Params& params) { for (int i = 0; i < 10000; i++) { blocks[i].pprev = i ? &blocks[i - 1] : NULL; blocks[i].nHeight = i; - blocks[i].nTime = 1269211443 + i * params.PoWTargetSpacing(blocks[i].nHeight); + blocks[i].nTime = i ? blocks[i - 1].nTime + params.PoWTargetSpacing(i) : 1269211443; blocks[i].nBits = 0x207fffff; /* target 0x7fffff000... */ blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + GetBlockProof(blocks[i - 1]) : arith_uint256(0); } From c5ac4321f994fd243834a2bbc273798be889d990 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 29 Jul 2019 23:25:08 -0600 Subject: [PATCH 184/395] Add message to static_assert --- src/consensus/params.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/consensus/params.h b/src/consensus/params.h index a3657da6135..9bb2fe6c740 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -64,7 +64,7 @@ struct NetworkUpgrade { /** ZIP208 block target interval in seconds. */ static const unsigned int PRE_BLOSSOM_POW_TARGET_SPACING = 150; static const unsigned int POST_BLOSSOM_POW_TARGET_SPACING = 75; -static_assert(POST_BLOSSOM_POW_TARGET_SPACING < PRE_BLOSSOM_POW_TARGET_SPACING); +static_assert(POST_BLOSSOM_POW_TARGET_SPACING < PRE_BLOSSOM_POW_TARGET_SPACING, "Blossom target spacing must be less than pre-Blossom target spacing."); static const unsigned int PRE_BLOSSOM_HALVING_INTERVAL = 840000; static const unsigned int PRE_BLOSSOM_REGTEST_HALVING_INTERVAL = 150; static const unsigned int BLOSSOM_POW_TARGET_SPACING_RATIO = PRE_BLOSSOM_POW_TARGET_SPACING / POST_BLOSSOM_POW_TARGET_SPACING; From 8865f4b6f61cc888968ac3e514f16fbee917d1d5 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Tue, 30 Jul 2019 01:16:37 -0600 Subject: [PATCH 185/395] Update expiry height for shorter block times --- src/consensus/params.cpp | 6 ++++ src/consensus/params.h | 2 ++ src/gtest/test_checktransaction.cpp | 12 +++---- src/gtest/test_transaction_builder.cpp | 34 +++++++++---------- src/init.cpp | 13 ++++--- src/main.cpp | 9 ++--- src/main.h | 13 +++---- src/rpc/rawtransaction.cpp | 4 ++- src/test/rpc_wallet_tests.cpp | 2 +- src/transaction_builder.cpp | 9 +++-- src/transaction_builder.h | 3 +- src/utiltest.cpp | 2 +- .../asyncrpcoperation_saplingmigration.cpp | 4 +-- src/wallet/gtest/test_wallet.cpp | 24 ++++++------- src/wallet/rpcwallet.cpp | 6 ++-- 15 files changed, 80 insertions(+), 63 deletions(-) diff --git a/src/consensus/params.cpp b/src/consensus/params.cpp index 1d6003a1a82..2179a30d3d8 100644 --- a/src/consensus/params.cpp +++ b/src/consensus/params.cpp @@ -1,4 +1,6 @@ #include "params.h" + +#include "main.h" #include "upgrades.h" namespace Consensus { @@ -27,6 +29,10 @@ namespace Consensus { } } + unsigned int Params::DefaultExpiryDelta(int nHeight) const { + return NetworkUpgradeActive(nHeight, Consensus::UPGRADE_BLOSSOM) ? DEFAULT_POST_BLOSSOM_TX_EXPIRY_DELTA : DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA; + } + int64_t Params::PoWTargetSpacing(int nHeight) const { // zip208 // PoWTargetSpacing(height) := diff --git a/src/consensus/params.h b/src/consensus/params.h index 9bb2fe6c740..7ececeeb7c0 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -105,6 +105,8 @@ struct Params { int GetLastFoundersRewardBlockHeight(int nHeight) const; + unsigned int DefaultExpiryDelta(int nHeight) const; + /** Used to check majorities for block version upgrade */ int nMajorityEnforceBlockUpgrade; int nMajorityRejectBlockOutdated; diff --git a/src/gtest/test_checktransaction.cpp b/src/gtest/test_checktransaction.cpp index 45580a0824c..e4b3d33617c 100644 --- a/src/gtest/test_checktransaction.cpp +++ b/src/gtest/test_checktransaction.cpp @@ -906,18 +906,18 @@ TEST(checktransaction_tests, OverwinteredContextualCreateTx) { // Overwinter activates { CMutableTransaction mtx = CreateNewContextualCMutableTransaction( - consensusParams, activationHeight ); + consensusParams, activationHeight); EXPECT_EQ(mtx.nVersion, 3); EXPECT_EQ(mtx.fOverwintered, true); EXPECT_EQ(mtx.nVersionGroupId, OVERWINTER_VERSION_GROUP_ID); - EXPECT_EQ(mtx.nExpiryHeight, activationHeight + expiryDelta); + EXPECT_EQ(mtx.nExpiryHeight, activationHeight + DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA); } // Close to Sapling activation { CMutableTransaction mtx = CreateNewContextualCMutableTransaction( - consensusParams, saplingActivationHeight - expiryDelta - 2); + consensusParams, saplingActivationHeight - DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA - 2); EXPECT_EQ(mtx.fOverwintered, true); EXPECT_EQ(mtx.nVersionGroupId, OVERWINTER_VERSION_GROUP_ID); @@ -927,7 +927,7 @@ TEST(checktransaction_tests, OverwinteredContextualCreateTx) { { CMutableTransaction mtx = CreateNewContextualCMutableTransaction( - consensusParams, saplingActivationHeight - expiryDelta - 1); + consensusParams, saplingActivationHeight - DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA - 1); EXPECT_EQ(mtx.fOverwintered, true); EXPECT_EQ(mtx.nVersionGroupId, OVERWINTER_VERSION_GROUP_ID); @@ -937,7 +937,7 @@ TEST(checktransaction_tests, OverwinteredContextualCreateTx) { { CMutableTransaction mtx = CreateNewContextualCMutableTransaction( - consensusParams, saplingActivationHeight - expiryDelta); + consensusParams, saplingActivationHeight - DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA); EXPECT_EQ(mtx.fOverwintered, true); EXPECT_EQ(mtx.nVersionGroupId, OVERWINTER_VERSION_GROUP_ID); @@ -964,7 +964,7 @@ TEST(checktransaction_tests, OverwinteredContextualCreateTx) { EXPECT_EQ(mtx.fOverwintered, true); EXPECT_EQ(mtx.nVersionGroupId, SAPLING_VERSION_GROUP_ID); EXPECT_EQ(mtx.nVersion, SAPLING_TX_VERSION); - EXPECT_EQ(mtx.nExpiryHeight, saplingActivationHeight + expiryDelta); + EXPECT_EQ(mtx.nExpiryHeight, saplingActivationHeight + DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA); } // Revert to default diff --git a/src/gtest/test_transaction_builder.cpp b/src/gtest/test_transaction_builder.cpp index d8c44ba1f88..332c194f85a 100644 --- a/src/gtest/test_transaction_builder.cpp +++ b/src/gtest/test_transaction_builder.cpp @@ -93,7 +93,7 @@ TEST(TransactionBuilder, TransparentToSapling) // Create a shielding transaction from transparent to Sapling // 0.0005 t-ZEC in, 0.0004 z-ZEC out, 0.0001 t-ZEC fee - auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore); + auto builder = TransactionBuilder(consensusParams, 1, &keystore); builder.AddTransparentInput(COutPoint(), scriptPubKey, 50000); builder.AddSaplingOutput(fvk_from.ovk, pk, 40000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -125,7 +125,7 @@ TEST(TransactionBuilder, SaplingToSapling) { // Create a Sapling-only transaction // 0.0004 z-ZEC in, 0.00025 z-ZEC out, 0.0001 t-ZEC fee, 0.00005 z-ZEC change - auto builder = TransactionBuilder(consensusParams, 2, expiryDelta); + auto builder = TransactionBuilder(consensusParams, 2); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); // Check that trying to add a different anchor fails @@ -166,7 +166,7 @@ TEST(TransactionBuilder, SaplingToSprout) { // - 0.0004 Sapling-ZEC in - 0.00025 Sprout-ZEC out // - 0.00005 Sapling-ZEC change // - 0.0001 t-ZEC fee - auto builder = TransactionBuilder(consensusParams, 2, expiryDelta, nullptr, params); + auto builder = TransactionBuilder(consensusParams, 2, nullptr, params); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSproutOutput(sproutAddr, 25000); auto tx = builder.Build().GetTxOrThrow(); @@ -218,7 +218,7 @@ TEST(TransactionBuilder, SproutToSproutAndSapling) { // - 0.00005 Sprout-ZEC change // - 0.00005 Sapling-ZEC out // - 0.00005 t-ZEC fee - auto builder = TransactionBuilder(consensusParams, 2, expiryDelta, nullptr, params, &view); + auto builder = TransactionBuilder(consensusParams, 2, nullptr, params, &view); builder.SetFee(5000); builder.AddSproutInput(sproutSk, sproutNote, sproutWitness); builder.AddSproutOutput(sproutAddr, 6000); @@ -255,7 +255,7 @@ TEST(TransactionBuilder, ThrowsOnSproutOutputWithoutParams) auto sk = libzcash::SproutSpendingKey::random(); auto addr = sk.address(); - auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); + auto builder = TransactionBuilder(consensusParams, 1); ASSERT_THROW(builder.AddSproutOutput(addr, 10), std::runtime_error); } @@ -264,7 +264,7 @@ TEST(TransactionBuilder, ThrowsOnTransparentInputWithoutKeyStore) SelectParams(CBaseChainParams::REGTEST); auto consensusParams = Params().GetConsensus(); - auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); + auto builder = TransactionBuilder(consensusParams, 1); ASSERT_THROW(builder.AddTransparentInput(COutPoint(), CScript(), 1), std::runtime_error); } @@ -275,7 +275,7 @@ TEST(TransactionBuilder, RejectsInvalidTransparentOutput) // Default CTxDestination type is an invalid address CTxDestination taddr; - auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); + auto builder = TransactionBuilder(consensusParams, 1); ASSERT_THROW(builder.AddTransparentOutput(taddr, 50), UniValue); } @@ -286,7 +286,7 @@ TEST(TransactionBuilder, RejectsInvalidTransparentChangeAddress) // Default CTxDestination type is an invalid address CTxDestination taddr; - auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); + auto builder = TransactionBuilder(consensusParams, 1); ASSERT_THROW(builder.SendChangeTo(taddr), UniValue); } @@ -311,13 +311,13 @@ TEST(TransactionBuilder, FailsWithNegativeChange) // Fail if there is only a Sapling output // 0.0005 z-ZEC out, 0.0001 t-ZEC fee - auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); + auto builder = TransactionBuilder(consensusParams, 1); builder.AddSaplingOutput(fvk.ovk, pa, 50000, {}); EXPECT_EQ("Change cannot be negative", builder.Build().GetError()); // Fail if there is only a transparent output // 0.0005 t-ZEC out, 0.0001 t-ZEC fee - builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore); + builder = TransactionBuilder(consensusParams, 1, &keystore); builder.AddTransparentOutput(taddr, 50000); EXPECT_EQ("Change cannot be negative", builder.Build().GetError()); @@ -359,14 +359,14 @@ TEST(TransactionBuilder, ChangeOutput) // No change address and no Sapling spends { - auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore); + auto builder = TransactionBuilder(consensusParams, 1, &keystore); builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000); EXPECT_EQ("Could not determine change address", builder.Build().GetError()); } // Change to the same address as the first Sapling spend { - auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore); + auto builder = TransactionBuilder(consensusParams, 1, &keystore); builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); auto tx = builder.Build().GetTxOrThrow(); @@ -381,7 +381,7 @@ TEST(TransactionBuilder, ChangeOutput) // Change to a Sapling address { - auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore); + auto builder = TransactionBuilder(consensusParams, 1, &keystore); builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000); builder.SendChangeTo(zChangeAddr, fvkOut.ovk); auto tx = builder.Build().GetTxOrThrow(); @@ -396,7 +396,7 @@ TEST(TransactionBuilder, ChangeOutput) // Change to a transparent address { - auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore); + auto builder = TransactionBuilder(consensusParams, 1, &keystore); builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000); builder.SendChangeTo(taddr); auto tx = builder.Build().GetTxOrThrow(); @@ -428,7 +428,7 @@ TEST(TransactionBuilder, SetFee) // Default fee { - auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); + auto builder = TransactionBuilder(consensusParams, 1); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -443,7 +443,7 @@ TEST(TransactionBuilder, SetFee) // Configured fee { - auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); + auto builder = TransactionBuilder(consensusParams, 1); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); builder.SetFee(20000); @@ -472,7 +472,7 @@ TEST(TransactionBuilder, CheckSaplingTxVersion) auto pk = sk.default_address(); // Cannot add Sapling outputs to a non-Sapling transaction - auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); + auto builder = TransactionBuilder(consensusParams, 1); try { builder.AddSaplingOutput(uint256(), pk, 12345, {}); } catch (std::runtime_error const & err) { diff --git a/src/init.cpp b/src/init.cpp index 7b6b2ab03b4..a1f5c30e30d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -418,7 +418,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), 0)); strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), 1)); strUsage += HelpMessageOpt("-txconfirmtarget=", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), DEFAULT_TX_CONFIRM_TARGET)); - strUsage += HelpMessageOpt("-txexpirydelta", strprintf(_("Set the number of blocks after which a transaction that has not been mined will become invalid (min: %u, default: %u)"), TX_EXPIRING_SOON_THRESHOLD + 1, DEFAULT_TX_EXPIRY_DELTA)); + strUsage += HelpMessageOpt("-txexpirydelta", strprintf(_("Set the number of blocks after which a transaction that has not been mined will become invalid (min: %u, default: %u (pre-Blossom) or %u (post-Blossom))"), TX_EXPIRING_SOON_THRESHOLD + 1, DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA, DEFAULT_POST_BLOSSOM_TX_EXPIRY_DELTA)); strUsage += HelpMessageOpt("-maxtxfee=", strprintf(_("Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s)"), CURRENCY_UNIT, FormatMoney(maxTxFee))); strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format") + " " + _("on startup")); @@ -1065,10 +1065,13 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } } nTxConfirmTarget = GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET); - expiryDelta = GetArg("-txexpirydelta", DEFAULT_TX_EXPIRY_DELTA); - uint32_t minExpiryDelta = TX_EXPIRING_SOON_THRESHOLD + 1; - if (expiryDelta < minExpiryDelta) { - return InitError(strprintf(_("Invalid value for -expiryDelta='%u' (must be least %u)"), expiryDelta, minExpiryDelta)); + if (mapArgs.count("-txexpirydelta")) { + int64_t expiryDelta = atoi64(mapArgs["txexpirydelta"]); + uint32_t minExpiryDelta = TX_EXPIRING_SOON_THRESHOLD + 1; + if (expiryDelta < minExpiryDelta) { + return InitError(strprintf(_("Invalid value for -txexpirydelta='%u' (must be least %u)"), expiryDelta, minExpiryDelta)); + } + expiryDeltaArg = expiryDelta; } bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", true); fSendFreeTransactions = GetBoolArg("-sendfreetransactions", false); diff --git a/src/main.cpp b/src/main.cpp index 04a817c1ce7..1537a76b113 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -84,7 +84,7 @@ bool fAlerts = DEFAULT_ALERTS; */ int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; -unsigned int expiryDelta = DEFAULT_TX_EXPIRY_DELTA; +boost::optional expiryDeltaArg = boost::none; /** Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) */ CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE); @@ -6654,16 +6654,13 @@ static class CMainCleanup // Set default values of new CMutableTransaction based on consensus rules at given height. CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight) { - return CreateNewContextualCMutableTransaction(consensusParams, nHeight, expiryDelta); -} - -CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight, int nExpiryDelta) { CMutableTransaction mtx; bool isOverwintered = consensusParams.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_OVERWINTER); if (isOverwintered) { mtx.fOverwintered = true; - mtx.nExpiryHeight = nHeight + nExpiryDelta; + mtx.nExpiryHeight = nHeight + (expiryDeltaArg ? expiryDeltaArg.get() : consensusParams.DefaultExpiryDelta(nHeight)); + // Review: Should the following if() be checking the expiry delta rather than the transaction height? if (mtx.nExpiryHeight <= 0 || mtx.nExpiryHeight >= TX_EXPIRY_HEIGHT_THRESHOLD) { throw new std::runtime_error("CreateNewContextualCMutableTransaction: invalid expiry height"); } diff --git a/src/main.h b/src/main.h index ff15180ccdb..85d1782c673 100644 --- a/src/main.h +++ b/src/main.h @@ -73,7 +73,8 @@ static const unsigned int DEFAULT_MIN_RELAY_TX_FEE = 100; /** Default for -maxorphantx, maximum number of orphan transactions kept in memory */ static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100; /** Default for -txexpirydelta, in number of blocks */ -static const unsigned int DEFAULT_TX_EXPIRY_DELTA = 20; +static const unsigned int DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA = 20; +static const unsigned int DEFAULT_POST_BLOSSOM_TX_EXPIRY_DELTA = DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA * Consensus::BLOSSOM_POW_TARGET_SPACING_RATIO; /** The number of blocks within expiry height when a tx is considered to be expiring soon */ static constexpr uint32_t TX_EXPIRING_SOON_THRESHOLD = 3; /** The maximum size of a blk?????.dat file (since 0.8) */ @@ -119,7 +120,7 @@ struct BlockHasher size_t operator()(const uint256& hash) const { return hash.GetCheapHash(); } }; -extern unsigned int expiryDelta; +extern boost::optional expiryDeltaArg; extern CScript COINBASE_FLAGS; extern CCriticalSection cs_main; extern CTxMemPool mempool; @@ -518,10 +519,10 @@ int GetSpendHeight(const CCoinsViewCache& inputs); uint64_t CalculateCurrentUsage(); -/** Return a CMutableTransaction with contextual default values based on set of consensus rules at nHeight, and the default expiry delta. */ +/** + * Return a CMutableTransaction with contextual default values based on set of consensus rules at nHeight. The expiryDelta will + * either be based on the command-line argument '-txexpirydelta' or derived from consensusParams. + */ CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight); -/** Return a CMutableTransaction with contextual default values based on set of consensus rules at nHeight, and given expiry delta. */ -CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight, int nExpiryDelta); - #endif // BITCOIN_MAIN_H diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index d951d91bf95..065d1498292 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -502,7 +502,9 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) " ,...\n" " }\n" "3. locktime (numeric, optional, default=0) Raw locktime. Non-0 value also locktime-activates inputs\n" - "4. expiryheight (numeric, optional, default=nextblockheight+" + strprintf("%d", DEFAULT_TX_EXPIRY_DELTA) + ") Expiry height of transaction (if Overwinter is active)\n" + "4. expiryheight (numeric, optional, default=nextblockheight+" + + strprintf("%d (pre-Blossom) or %d (post-Blossom)", DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA, DEFAULT_POST_BLOSSOM_TX_EXPIRY_DELTA) + ") " + "Expiry height of transaction (if Overwinter is active)\n" "\nResult:\n" "\"transaction\" (string) hex string of the transaction\n" diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index f04d3f2c216..f2cc09903d4 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -1302,7 +1302,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_taddr_to_sapling) pwalletMain->AddToWallet(wtx, true, NULL); // Context that z_sendmany requires - auto builder = TransactionBuilder(consensusParams, nextBlockHeight, expiryDelta, pwalletMain); + auto builder = TransactionBuilder(consensusParams, nextBlockHeight, pwalletMain); mtx = CreateNewContextualCMutableTransaction(consensusParams, nextBlockHeight); std::vector recipients = { SendManyRecipient(zaddr1, 1 * COIN, "ABCD") }; diff --git a/src/transaction_builder.cpp b/src/transaction_builder.cpp index aa34ffb15e5..f81bcc4debb 100644 --- a/src/transaction_builder.cpp +++ b/src/transaction_builder.cpp @@ -50,7 +50,6 @@ std::string TransactionBuilderResult::GetError() { TransactionBuilder::TransactionBuilder( const Consensus::Params& consensusParams, int nHeight, - int nExpiryDelta, CKeyStore* keystore, ZCJoinSplit* sproutParams, CCoinsViewCache* coinsView, @@ -62,7 +61,7 @@ TransactionBuilder::TransactionBuilder( coinsView(coinsView), cs_coinsView(cs_coinsView) { - mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight, nExpiryDelta); + mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight); } // This exception is thrown in certain scenarios when building JoinSplits fails. @@ -76,6 +75,12 @@ struct JSDescException : public std::exception std::string msg; }; + +void TransactionBuilder::SetExpiryHeight(uint32_t nExpiryHeight) +{ + mtx.nExpiryHeight = nExpiryHeight; +} + void TransactionBuilder::AddSaplingSpend( libzcash::SaplingExpandedSpendingKey expsk, libzcash::SaplingNote note, diff --git a/src/transaction_builder.h b/src/transaction_builder.h index 46f38481ecc..7cd12bee843 100644 --- a/src/transaction_builder.h +++ b/src/transaction_builder.h @@ -95,12 +95,13 @@ class TransactionBuilder TransactionBuilder( const Consensus::Params& consensusParams, int nHeight, - int nExpiryDelta, CKeyStore* keyStore = nullptr, ZCJoinSplit* sproutParams = nullptr, CCoinsViewCache* coinsView = nullptr, CCriticalSection* cs_coinsView = nullptr); + void SetExpiryHeight(uint32_t nExpiryHeight); + void SetFee(CAmount fee); // Throws if the anchor does not match the anchor used by diff --git a/src/utiltest.cpp b/src/utiltest.cpp index 7c503f388a6..9e382d08425 100644 --- a/src/utiltest.cpp +++ b/src/utiltest.cpp @@ -252,7 +252,7 @@ CWalletTx GetValidSaplingReceive(const Consensus::Params& consensusParams, auto fvk = sk.expsk.full_viewing_key(); auto pa = sk.DefaultAddress(); - auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keyStore); + auto builder = TransactionBuilder(consensusParams, 1, &keyStore); builder.SetFee(0); builder.AddTransparentInput(COutPoint(), scriptPubKey, value); builder.AddSaplingOutput(fvk.ovk, pa, value, {}); diff --git a/src/wallet/asyncrpcoperation_saplingmigration.cpp b/src/wallet/asyncrpcoperation_saplingmigration.cpp index 7b28295bd9e..a8ac453ad51 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.cpp +++ b/src/wallet/asyncrpcoperation_saplingmigration.cpp @@ -103,8 +103,8 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { CCoinsViewCache coinsView(pcoinsTip); do { CAmount amountToSend = chooseAmount(availableFunds); - auto builder = TransactionBuilder(consensusParams, targetHeight_, MIGRATION_EXPIRY_DELTA, pwalletMain, pzcashParams, - &coinsView, &cs_main); + auto builder = TransactionBuilder(consensusParams, targetHeight_, pwalletMain, pzcashParams, &coinsView, &cs_main); + builder.SetExpiryHeight(targetHeight_ + MIGRATION_EXPIRY_DELTA); LogPrint("zrpcunsafe", "%s: Beginning creating transaction with Sapling output amount=%s\n", getId(), FormatMoney(amountToSend - FEE)); std::vector fromNotes; CAmount fromNoteAmount = 0; diff --git a/src/wallet/gtest/test_wallet.cpp b/src/wallet/gtest/test_wallet.cpp index df95a676c75..b5b9a237ae0 100644 --- a/src/wallet/gtest/test_wallet.cpp +++ b/src/wallet/gtest/test_wallet.cpp @@ -379,7 +379,7 @@ TEST(WalletTests, SetSaplingNoteAddrsInCWalletTx) { ASSERT_TRUE(nf); uint256 nullifier = nf.get(); - auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); + auto builder = TransactionBuilder(consensusParams, 1); builder.AddSaplingSpend(expsk, note, anchor, witness); builder.AddSaplingOutput(fvk.ovk, pk, 50000, {}); builder.SetFee(0); @@ -506,7 +506,7 @@ TEST(WalletTests, FindMySaplingNotes) { auto testNote = GetTestSaplingNote(pa, 50000); // Generate transaction - auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); + auto builder = TransactionBuilder(consensusParams, 1); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -638,7 +638,7 @@ TEST(WalletTests, GetConflictedSaplingNotes) { auto witness = saplingTree.witness(); // Generate tx to create output note B - auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); + auto builder = TransactionBuilder(consensusParams, 1); builder.AddSaplingSpend(expsk, note, anchor, witness); builder.AddSaplingOutput(fvk.ovk, pk, 35000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -692,13 +692,13 @@ TEST(WalletTests, GetConflictedSaplingNotes) { anchor = saplingTree.root(); // Create transaction to spend note B - auto builder2 = TransactionBuilder(consensusParams, 2, expiryDelta); + auto builder2 = TransactionBuilder(consensusParams, 2); builder2.AddSaplingSpend(expsk, note2, anchor, spend_note_witness); builder2.AddSaplingOutput(fvk.ovk, pk, 20000, {}); auto tx2 = builder2.Build().GetTxOrThrow(); // Create conflicting transaction which also spends note B - auto builder3 = TransactionBuilder(consensusParams, 2, expiryDelta); + auto builder3 = TransactionBuilder(consensusParams, 2); builder3.AddSaplingSpend(expsk, note2, anchor, spend_note_witness); builder3.AddSaplingOutput(fvk.ovk, pk, 19999, {}); auto tx3 = builder3.Build().GetTxOrThrow(); @@ -785,7 +785,7 @@ TEST(WalletTests, SaplingNullifierIsSpent) { auto testNote = GetTestSaplingNote(pa, 50000); // Generate transaction - auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); + auto builder = TransactionBuilder(consensusParams, 1); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -868,7 +868,7 @@ TEST(WalletTests, NavigateFromSaplingNullifierToNote) { auto testNote = GetTestSaplingNote(pa, 50000); // Generate transaction - auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); + auto builder = TransactionBuilder(consensusParams, 1); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -996,7 +996,7 @@ TEST(WalletTests, SpentSaplingNoteIsFromMe) { auto witness = saplingTree.witness(); // Generate transaction, which sends funds to note B - auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); + auto builder = TransactionBuilder(consensusParams, 1); builder.AddSaplingSpend(expsk, note, anchor, witness); builder.AddSaplingOutput(fvk.ovk, pk, 25000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -1066,7 +1066,7 @@ TEST(WalletTests, SpentSaplingNoteIsFromMe) { anchor = saplingTree.root(); // Create transaction to spend note B - auto builder2 = TransactionBuilder(consensusParams, 2, expiryDelta); + auto builder2 = TransactionBuilder(consensusParams, 2); builder2.AddSaplingSpend(expsk, note2, anchor, spend_note_witness); builder2.AddSaplingOutput(fvk.ovk, pk, 12500, {}); auto tx2 = builder2.Build().GetTxOrThrow(); @@ -1771,7 +1771,7 @@ TEST(WalletTests, UpdatedSaplingNoteData) { auto testNote = GetTestSaplingNote(pa, 50000); // Generate transaction - auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); + auto builder = TransactionBuilder(consensusParams, 1); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingOutput(fvk.ovk, pa2, 25000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -1912,7 +1912,7 @@ TEST(WalletTests, MarkAffectedSaplingTransactionsDirty) { // Generate shielding tx from transparent to Sapling // 0.0005 t-ZEC in, 0.0004 z-ZEC out, 0.0001 t-ZEC fee - auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore); + auto builder = TransactionBuilder(consensusParams, 1, &keystore); builder.AddTransparentInput(COutPoint(), scriptPubKey, 50000); builder.AddSaplingOutput(fvk.ovk, pk, 40000, {}); auto tx1 = builder.Build().GetTxOrThrow(); @@ -1967,7 +1967,7 @@ TEST(WalletTests, MarkAffectedSaplingTransactionsDirty) { // Create a Sapling-only transaction // 0.0004 z-ZEC in, 0.00025 z-ZEC out, 0.0001 t-ZEC fee, 0.00005 z-ZEC change - auto builder2 = TransactionBuilder(consensusParams, 2, expiryDelta); + auto builder2 = TransactionBuilder(consensusParams, 2); builder2.AddSaplingSpend(expsk, note, anchor, witness); builder2.AddSaplingOutput(fvk.ovk, pk, 25000, {}); auto tx2 = builder2.Build().GetTxOrThrow(); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 67caf89cc09..973646efc2d 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3885,7 +3885,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) // Builder (used if Sapling addresses are involved) boost::optional builder; if (noSproutAddrs) { - builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, expiryDelta, pwalletMain); + builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, pwalletMain); } // Contextual transaction we will build on @@ -4222,7 +4222,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp) // Builder (used if Sapling addresses are involved) TransactionBuilder builder = TransactionBuilder( - Params().GetConsensus(), nextBlockHeight, expiryDelta, pwalletMain); + Params().GetConsensus(), nextBlockHeight, pwalletMain); // Contextual transaction we will build on // (used if no Sapling addresses are involved) @@ -4648,7 +4648,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) // Builder (used if Sapling addresses are involved) boost::optional builder; if (isToSaplingZaddr || saplingNoteInputs.size() > 0) { - builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, expiryDelta, pwalletMain); + builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, pwalletMain); } // Create operation and add to global queue std::shared_ptr q = getAsyncRPCQueue(); From 1188c9adf7bcbecabe9bd70357d76992872f486b Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Tue, 30 Jul 2019 17:41:33 -0600 Subject: [PATCH 186/395] Fix zip208 founders reward calculation and update test --- src/consensus/params.cpp | 4 ++-- src/consensus/params.h | 2 +- src/gtest/test_foundersreward.cpp | 12 +++++++++++- src/gtest/test_pow.cpp | 4 ++-- src/test/pow_tests.cpp | 20 ++++++++++---------- src/utiltest.cpp | 6 +++--- src/utiltest.h | 4 ++-- 7 files changed, 31 insertions(+), 21 deletions(-) diff --git a/src/consensus/params.cpp b/src/consensus/params.cpp index 2179a30d3d8..35cc6c9d24e 100644 --- a/src/consensus/params.cpp +++ b/src/consensus/params.cpp @@ -18,12 +18,12 @@ namespace Consensus { // postBlossom: // 1 = (H - SS) / preInterval + (height - H) / postInterval // height = H + postInterval + (SS - H) * (postInterval / preInterval) - // height = H + postInterval + (SS - H) / R + // height = H + postInterval + (SS - H) * R bool blossomActive = NetworkUpgradeActive(nHeight, Consensus::UPGRADE_BLOSSOM); if (blossomActive) { int blossomActivationHeight = vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; return blossomActivationHeight + nPostBlossomSubsidyHalvingInterval - - (SubsidySlowStartShift() - blossomActivationHeight) / BLOSSOM_POW_TARGET_SPACING_RATIO - 1; + + (SubsidySlowStartShift() - blossomActivationHeight) * BLOSSOM_POW_TARGET_SPACING_RATIO - 1; } else { return nPreBlossomSubsidyHalvingInterval + SubsidySlowStartShift() - 1; } diff --git a/src/consensus/params.h b/src/consensus/params.h index 7ececeeb7c0..979d294bff6 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -67,7 +67,7 @@ static const unsigned int POST_BLOSSOM_POW_TARGET_SPACING = 75; static_assert(POST_BLOSSOM_POW_TARGET_SPACING < PRE_BLOSSOM_POW_TARGET_SPACING, "Blossom target spacing must be less than pre-Blossom target spacing."); static const unsigned int PRE_BLOSSOM_HALVING_INTERVAL = 840000; static const unsigned int PRE_BLOSSOM_REGTEST_HALVING_INTERVAL = 150; -static const unsigned int BLOSSOM_POW_TARGET_SPACING_RATIO = PRE_BLOSSOM_POW_TARGET_SPACING / POST_BLOSSOM_POW_TARGET_SPACING; +static const int BLOSSOM_POW_TARGET_SPACING_RATIO = PRE_BLOSSOM_POW_TARGET_SPACING / POST_BLOSSOM_POW_TARGET_SPACING; static const unsigned int POST_BLOSSOM_HALVING_INTERVAL = PRE_BLOSSOM_HALVING_INTERVAL * BLOSSOM_POW_TARGET_SPACING_RATIO; static const unsigned int POST_BLOSSOM_REGTEST_HALVING_INTERVAL = PRE_BLOSSOM_REGTEST_HALVING_INTERVAL * BLOSSOM_POW_TARGET_SPACING_RATIO; diff --git a/src/gtest/test_foundersreward.cpp b/src/gtest/test_foundersreward.cpp index 15e2c81b779..1f4f8241125 100644 --- a/src/gtest/test_foundersreward.cpp +++ b/src/gtest/test_foundersreward.cpp @@ -13,6 +13,7 @@ #include #include #include "util.h" +#include "utiltest.h" // To run tests: // ./zcash-gtest --gtest_filter="founders_reward_test.*" @@ -119,6 +120,15 @@ TEST(founders_reward_test, general) { EXPECT_DEATH(params.GetFoundersRewardAddressAtHeight(maxHeight+1), "nHeight"); } +TEST(founders_reward_test, get_last_block_blossom) { + int blossomActivationHeight = /*slowStartShift*/ + Consensus::PRE_BLOSSOM_REGTEST_HALVING_INTERVAL / 2; // = 75 + auto params = RegtestActivateBlossom(false, blossomActivationHeight); + int slowStartShift = params.SubsidySlowStartShift(); // 0 for regtest + EXPECT_EQ(Consensus::PRE_BLOSSOM_REGTEST_HALVING_INTERVAL + slowStartShift - 1, params.GetLastFoundersRewardBlockHeight(0)); + EXPECT_EQ(Consensus::PRE_BLOSSOM_REGTEST_HALVING_INTERVAL + slowStartShift - 1, params.GetLastFoundersRewardBlockHeight(blossomActivationHeight - 1)); + int blossomBlocks = (Consensus::PRE_BLOSSOM_REGTEST_HALVING_INTERVAL- blossomActivationHeight) * Consensus::BLOSSOM_POW_TARGET_SPACING_RATIO; + EXPECT_EQ(blossomActivationHeight + blossomBlocks + slowStartShift - 1, params.GetLastFoundersRewardBlockHeight(blossomActivationHeight)); +} #define NUM_MAINNET_FOUNDER_ADDRESSES 48 @@ -147,7 +157,7 @@ TEST(founders_reward_test, regtest) { // Test that 10% founders reward is fully rewarded after the first halving and slow start shift. // On Mainnet, this would be 2,100,000 ZEC after 850,000 blocks (840,000 + 10,000). -TEST(founders_reward_test, slow_start_subsidy) { +TEST(founders_reward_test, slow_start_subsidy) { // TODO: Update this test when the Blossom activation height is set SelectParams(CBaseChainParams::MAIN); CChainParams params = Params(); diff --git a/src/gtest/test_pow.cpp b/src/gtest/test_pow.cpp index 281701892e3..4e0e8fcdc5c 100644 --- a/src/gtest/test_pow.cpp +++ b/src/gtest/test_pow.cpp @@ -79,8 +79,8 @@ TEST(PoW, DifficultyAveraging) { } TEST(PoW, DifficultyAveragingBlossom) { - TestDifficultyAveragigingImpl(ActivateBlossom(true)); - DeactivateBlossom(); + TestDifficultyAveragigingImpl(RegtestActivateBlossom(true)); + RegtestDeactivateBlossom(); } TEST(PoW, MinDifficultyRules) { diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index 416b4ac7c17..3aebbc00d9a 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -32,7 +32,7 @@ BOOST_AUTO_TEST_CASE(get_next_work) BOOST_AUTO_TEST_CASE(get_next_work_blossom) { - const Consensus::Params& params = ActivateBlossom(true); + const Consensus::Params& params = RegtestActivateBlossom(true); BOOST_CHECK_EQUAL(75, params.PoWTargetSpacing(0)); int64_t nLastRetargetTime = 1000000000; // NOTE: Not an actual block time @@ -42,7 +42,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_blossom) BOOST_CHECK_GT(0x1d011998, CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params, 0)); - DeactivateBlossom(); + RegtestDeactivateBlossom(); } /* Test the constraint on the upper bound for next work */ @@ -61,7 +61,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_pow_limit) BOOST_AUTO_TEST_CASE(get_next_work_pow_limit_blossom) { - const Consensus::Params& params = ActivateBlossom(true); + const Consensus::Params& params = RegtestActivateBlossom(true); int64_t nLastRetargetTime = 1231006505; int64_t nThisTime = 1233061996; @@ -70,7 +70,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_pow_limit_blossom) BOOST_CHECK_EQUAL(0x1f07ffff, CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params, 0)); - DeactivateBlossom(); + RegtestDeactivateBlossom(); } /* Test the constraint on the lower bound for actual time taken */ @@ -91,7 +91,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual) BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual_blossom) { - const Consensus::Params& params = ActivateBlossom(true); + const Consensus::Params& params = RegtestActivateBlossom(true); int64_t nLastRetargetTime = 1000000000; // NOTE: Not an actual block time int64_t nThisTime = 1000000458; @@ -100,7 +100,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual_blossom) BOOST_CHECK_EQUAL(0x1c04bceb, CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params, 0)); - DeactivateBlossom(); + RegtestDeactivateBlossom(); } /* Test the constraint on the upper bound for actual time taken */ @@ -120,7 +120,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual) BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual_blossom) { - const Consensus::Params& params = ActivateBlossom(true); + const Consensus::Params& params = RegtestActivateBlossom(true); int64_t nLastRetargetTime = 1000000000; // NOTE: Not an actual block time int64_t nThisTime = 1000002908; @@ -129,7 +129,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual_blossom) BOOST_CHECK_EQUAL(0x1c4a93bb, CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params, 0)); - DeactivateBlossom(); + RegtestDeactivateBlossom(); } void GetBlockProofEquivalentTimeImpl(const Consensus::Params& params) { @@ -160,8 +160,8 @@ BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test) BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test_blossom) { - GetBlockProofEquivalentTimeImpl(ActivateBlossom(true)); - DeactivateBlossom(); + GetBlockProofEquivalentTimeImpl(RegtestActivateBlossom(true)); + RegtestDeactivateBlossom(); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/utiltest.cpp b/src/utiltest.cpp index 9e382d08425..d8e1e441099 100644 --- a/src/utiltest.cpp +++ b/src/utiltest.cpp @@ -200,18 +200,18 @@ void RegtestDeactivateSapling() { UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); } -const Consensus::Params& ActivateBlossom(bool updatePow) { +const Consensus::Params& RegtestActivateBlossom(bool updatePow, int blossomActivationHeight) { SelectParams(CBaseChainParams::REGTEST); UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); - UpdateNetworkUpgradeParameters(Consensus::UPGRADE_BLOSSOM, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_BLOSSOM, blossomActivationHeight); if (updatePow) { UpdateRegtestPow(32, 16, uint256S("0007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); } return Params().GetConsensus(); } -void DeactivateBlossom() { +void RegtestDeactivateBlossom() { UpdateRegtestPow(0, 0, uint256S("0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f")); UpdateNetworkUpgradeParameters(Consensus::UPGRADE_BLOSSOM, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); diff --git a/src/utiltest.h b/src/utiltest.h index 9fd3b661361..df060362e55 100644 --- a/src/utiltest.h +++ b/src/utiltest.h @@ -43,9 +43,9 @@ const Consensus::Params& RegtestActivateSapling(); void RegtestDeactivateSapling(); -const Consensus::Params& ActivateBlossom(bool updatePow); +const Consensus::Params& RegtestActivateBlossom(bool updatePow, int blossomActivationHeight = Consensus::NetworkUpgrade::ALWAYS_ACTIVE); -void DeactivateBlossom(); +void RegtestDeactivateBlossom(); libzcash::SaplingExtendedSpendingKey GetTestMasterSaplingSpendingKey(); From 6bc69c39cb5aded949f24cc0fe1ebdec36c2cf98 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 31 Jul 2019 11:09:32 +0100 Subject: [PATCH 187/395] test: Check for change t-addr reuse in z_sendmany --- qa/pull-tester/rpc-tests.sh | 1 + qa/rpc-tests/wallet_changeaddresses.py | 99 ++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 qa/rpc-tests/wallet_changeaddresses.py diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index d072898b26d..6465420d664 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -15,6 +15,7 @@ testScripts=( 'prioritisetransaction.py' 'wallet_treestate.py' 'wallet_anchorfork.py' + 'wallet_changeaddresses.py' 'wallet_changeindicator.py' 'wallet_import_export.py' 'wallet_protectcoinbase.py' diff --git a/qa/rpc-tests/wallet_changeaddresses.py b/qa/rpc-tests/wallet_changeaddresses.py new file mode 100644 index 00000000000..f1c2aee7ed4 --- /dev/null +++ b/qa/rpc-tests/wallet_changeaddresses.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python +# Copyright (c) 2019 The Zcash developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.authproxy import JSONRPCException +from test_framework.util import ( + assert_equal, + connect_nodes_bi, + get_coinbase_address, + initialize_chain_clean, + start_node, + wait_and_assert_operationid_status, +) + +from decimal import Decimal + +# Test wallet change address behaviour +class WalletChangeAddressesTest(BitcoinTestFramework): + + def setup_chain(self): + print("Initializing test directory " + self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 2) + + def setup_network(self): + args = [ + '-nuparams=5ba81b19:1', # Overwinter + '-nuparams=76b809bb:1', # Sapling + '-txindex', # Avoid JSONRPC error: No information available about transaction + '-experimentalfeatures', '-zmergetoaddress', + ] + self.nodes = [] + self.nodes.append(start_node(0, self.options.tmpdir, args)) + self.nodes.append(start_node(1, self.options.tmpdir, args)) + connect_nodes_bi(self.nodes,0,1) + self.is_network_split=False + self.sync_all() + + def run_test(self): + self.nodes[0].generate(110) + + # Obtain some transparent funds + midAddr = self.nodes[0].z_getnewaddress('sapling') + myopid = self.nodes[0].z_shieldcoinbase(get_coinbase_address(self.nodes[0]), midAddr, 0)['opid'] + txid1 = wait_and_assert_operationid_status(self.nodes[0], myopid) + self.nodes[1].generate(1) + self.sync_all() + taddrSource = self.nodes[0].getnewaddress() + for _ in range(6): + recipients = [{"address": taddrSource, "amount": Decimal('2')}] + myopid = self.nodes[0].z_sendmany(midAddr, recipients, 1, 0) + txid1 = wait_and_assert_operationid_status(self.nodes[0], myopid) + self.nodes[1].generate(1) + self.sync_all() + + def check_change_taddr_reuse(target): + recipients = [{"address": target, "amount": Decimal('1')}] + + # Send funds to recipient address twice + myopid = self.nodes[0].z_sendmany(taddrSource, recipients, 1, 0) + txid1 = wait_and_assert_operationid_status(self.nodes[0], myopid) + self.nodes[1].generate(1) + self.sync_all() + myopid = self.nodes[0].z_sendmany(taddrSource, recipients, 1, 0) + txid2 = wait_and_assert_operationid_status(self.nodes[0], myopid) + self.nodes[1].generate(1) + self.sync_all() + + # Verify that the two transactions used different change addresses + tx1 = self.nodes[0].getrawtransaction(txid1, 1) + tx2 = self.nodes[0].getrawtransaction(txid2, 1) + for i in range(len(tx1['vout'])): + tx1OutAddrs = tx1['vout'][i]['scriptPubKey']['addresses'] + tx2OutAddrs = tx2['vout'][i]['scriptPubKey']['addresses'] + if tx1OutAddrs != [target]: + print('Source address: %s' % taddrSource) + print('TX1 change address: %s' % tx1OutAddrs[0]) + print('TX2 change address: %s' % tx2OutAddrs[0]) + assert(tx1OutAddrs != tx2OutAddrs) + + taddr = self.nodes[0].getnewaddress() + saplingAddr = self.nodes[0].z_getnewaddress('sapling') + sproutAddr = self.nodes[0].z_getnewaddress('sprout') + + print + print('Checking z_sendmany(taddr->Sapling)') + check_change_taddr_reuse(saplingAddr) + print + print('Checking z_sendmany(taddr->Sprout)') + check_change_taddr_reuse(sproutAddr) + print + print('Checking z_sendmany(taddr->taddr)') + check_change_taddr_reuse(taddr) + +if __name__ == '__main__': + WalletChangeAddressesTest().main() From 19bd2d0e7c44ad28324132588d1a060052c65fcc Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 31 Jul 2019 12:15:09 +0100 Subject: [PATCH 188/395] Use reserve key for transparent change when sending to Sprout --- src/test/rpc_wallet_tests.cpp | 5 +++-- src/wallet/asyncrpcoperation_sendmany.cpp | 18 +++++++++--------- src/wallet/asyncrpcoperation_sendmany.h | 10 +++++----- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index 5d7cc08d927..cf83271d502 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -1147,15 +1147,16 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals) CTransaction tx = proxy.getTx(); BOOST_CHECK(tx.vout.size() == 0); + CReserveKey keyChange(pwalletMain); CAmount amount = AmountFromValue(ValueFromString("123.456")); - proxy.add_taddr_change_output_to_tx(amount); + proxy.add_taddr_change_output_to_tx(keyChange, amount); tx = proxy.getTx(); BOOST_CHECK(tx.vout.size() == 1); CTxOut out = tx.vout[0]; BOOST_CHECK_EQUAL(out.nValue, amount); amount = AmountFromValue(ValueFromString("1.111")); - proxy.add_taddr_change_output_to_tx(amount); + proxy.add_taddr_change_output_to_tx(keyChange, amount); tx = proxy.getTx(); BOOST_CHECK(tx.vout.size() == 2); out = tx.vout[1]; diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index 9ebd553a751..b5e7022379f 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -489,9 +489,10 @@ bool AsyncRPCOperation_sendmany::main_impl() { CAmount funds = selectedUTXOAmount; CAmount fundsSpent = t_outputs_total + minersFee; CAmount change = funds - fundsSpent; - + + CReserveKey keyChange(pwalletMain); if (change > 0) { - add_taddr_change_output_to_tx(change); + add_taddr_change_output_to_tx(keyChange, change); LogPrint("zrpc", "%s: transparent change in transaction output (amount=%s)\n", getId(), @@ -501,8 +502,7 @@ bool AsyncRPCOperation_sendmany::main_impl() { UniValue obj(UniValue::VOBJ); obj.push_back(Pair("rawtxn", EncodeHexTx(tx_))); - // TODO: use CReserveKey from add_taddr_change_output_to_tx - auto txAndResult = SignSendRawTransaction(obj, boost::none, testmode); + auto txAndResult = SignSendRawTransaction(obj, keyChange, testmode); tx_ = txAndResult.first; set_result(txAndResult.second); return true; @@ -567,6 +567,7 @@ bool AsyncRPCOperation_sendmany::main_impl() { CAmount fundsSpent = t_outputs_total + minersFee + z_outputs_total; CAmount change = funds - fundsSpent; + CReserveKey keyChange(pwalletMain); if (change > 0) { if (selectedUTXOCoinbase) { assert(isSingleZaddrOutput); @@ -575,7 +576,7 @@ bool AsyncRPCOperation_sendmany::main_impl() { "allow any change as there is currently no way to specify a change address " "in z_sendmany.", FormatMoney(change))); } else { - add_taddr_change_output_to_tx(change); + add_taddr_change_output_to_tx(keyChange, change); LogPrint("zrpc", "%s: transparent change in transaction output (amount=%s)\n", getId(), FormatMoney(change) @@ -609,8 +610,8 @@ bool AsyncRPCOperation_sendmany::main_impl() { } obj = perform_joinsplit(info); } - // TODO: use CReserveKey from add_taddr_change_output_to_tx - auto txAndResult = SignSendRawTransaction(obj, boost::none, testmode); + + auto txAndResult = SignSendRawTransaction(obj, keyChange, testmode); tx_ = txAndResult.first; set_result(txAndResult.second); return true; @@ -1211,12 +1212,11 @@ void AsyncRPCOperation_sendmany::add_taddr_outputs_to_tx() { tx_ = CTransaction(rawTx); } -void AsyncRPCOperation_sendmany::add_taddr_change_output_to_tx(CAmount amount) { +void AsyncRPCOperation_sendmany::add_taddr_change_output_to_tx(CReserveKey& keyChange, CAmount amount) { LOCK2(cs_main, pwalletMain->cs_wallet); EnsureWalletIsUnlocked(); - CReserveKey keyChange(pwalletMain); CPubKey vchPubKey; bool ret = keyChange.GetReservedKey(vchPubKey); if (!ret) { diff --git a/src/wallet/asyncrpcoperation_sendmany.h b/src/wallet/asyncrpcoperation_sendmany.h index 89b5d94b571..b0bf3f067af 100644 --- a/src/wallet/asyncrpcoperation_sendmany.h +++ b/src/wallet/asyncrpcoperation_sendmany.h @@ -107,8 +107,8 @@ class AsyncRPCOperation_sendmany : public AsyncRPCOperation { TransactionBuilder builder_; CTransaction tx_; - - void add_taddr_change_output_to_tx(CAmount amount); + + void add_taddr_change_output_to_tx(CReserveKey& keyChange, CAmount amount); void add_taddr_outputs_to_tx(); bool find_unspent_notes(); bool find_utxos(bool fAcceptCoinbase); @@ -148,9 +148,9 @@ class TEST_FRIEND_AsyncRPCOperation_sendmany { } // Delegated methods - - void add_taddr_change_output_to_tx(CAmount amount) { - delegate->add_taddr_change_output_to_tx(amount); + + void add_taddr_change_output_to_tx(CReserveKey& keyChange, CAmount amount) { + delegate->add_taddr_change_output_to_tx(keyChange, amount); } void add_taddr_outputs_to_tx() { From d65000ae257f8e2a358f4abaa96746bb93223ab1 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Wed, 31 Jul 2019 16:16:17 +0100 Subject: [PATCH 189/395] Release process doc: add step to set the gpg key id. Signed-off-by: Daira Hopwood --- doc/release-process.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/release-process.md b/doc/release-process.md index eed18ad4730..93eab0ffb91 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -98,6 +98,10 @@ The output should include something like, which is created by Homu: Auto merge of #4242 - nathan-at-least:release-v1.0.9, r=nathan-at-least +If you haven't previously done so, set the gpg key id you intend to use for signing: + + git config --global user.signingkey + Then create the git tag. The `-s` means the release tag will be signed. **CAUTION:** Remember the `v` at the beginning here: From 28765ed39bd8b07246433dfea27d1d5670be9982 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Wed, 31 Jul 2019 16:16:17 +0100 Subject: [PATCH 190/395] Release process doc: mention the commit message. Signed-off-by: Daira Hopwood --- doc/release-process.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/release-process.md b/doc/release-process.md index 93eab0ffb91..44d43364f61 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -102,8 +102,9 @@ If you haven't previously done so, set the gpg key id you intend to use for sign git config --global user.signingkey -Then create the git tag. The `-s` means the release tag will be -signed. **CAUTION:** Remember the `v` at the beginning here: +Then create the git tag. The `-s` means the release tag will be signed. +Enter "Release ." and save when prompted for a commit message. +**CAUTION:** Remember the `v` at the beginning here: $ git tag -s v1.0.9 $ git push origin v1.0.9 From 68e174e22b82476c4d22535f119d99739202a9d0 Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Wed, 31 Jul 2019 10:25:49 -0600 Subject: [PATCH 191/395] add addressindex related RPCs --- qa/pull-tester/rpc-tests.sh | 1 + qa/rpc-tests/addressindex.py | 357 +++++++++++++++++++++ src/addressindex.h | 62 ++++ src/main.cpp | 31 +- src/main.h | 6 + src/rpc/client.cpp | 5 + src/rpc/misc.cpp | 569 ++++++++++++++++++++++++++++++++++ src/rpc/rawtransaction.cpp | 9 +- src/script/script.cpp | 4 +- src/script/standard.cpp | 7 +- src/script/standard.h | 2 +- src/test/rpc_tests.cpp | 75 +++++ src/test/rpc_wallet_tests.cpp | 13 - src/test/test_bitcoin.h | 3 + src/txdb.cpp | 2 +- src/txmempool.cpp | 62 ++++ src/txmempool.h | 13 + 17 files changed, 1198 insertions(+), 23 deletions(-) create mode 100755 qa/rpc-tests/addressindex.py diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index aeda0da2cbf..b1c6758c91f 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -56,6 +56,7 @@ testScripts=( 'key_import_export.py' 'nodehandling.py' 'reindex.py' + 'addressindex.py' 'decodescript.py' 'blockchain.py' 'disablewallet.py' diff --git a/qa/rpc-tests/addressindex.py b/qa/rpc-tests/addressindex.py new file mode 100755 index 00000000000..4e18d95140e --- /dev/null +++ b/qa/rpc-tests/addressindex.py @@ -0,0 +1,357 @@ +#!/usr/bin/env python +# Copyright (c) 2019 The Zcash developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Test addressindex generation and fetching for insightexplorer +# +# RPCs tested here: +# +# getaddresstxids +# getaddressbalance +# getaddressdeltas +# getaddressutxos +# getaddressmempool +# + +import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." + +from test_framework.test_framework import BitcoinTestFramework + + +from test_framework.util import ( + assert_equal, + initialize_chain_clean, + start_nodes, + stop_nodes, + connect_nodes, +) + +from test_framework.util import wait_bitcoinds + +from test_framework.script import ( + CScript, + OP_HASH160, + OP_EQUAL, + OP_DUP, + OP_DROP, +) + +from test_framework.mininode import COIN, CTransaction +from test_framework.mininode import CTxIn, CTxOut, COutPoint + +from binascii import hexlify + + +class AddressIndexTest(BitcoinTestFramework): + + def setup_chain(self): + print("Initializing test directory "+self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 3) + + def setup_network(self): + # -insightexplorer causes addressindex to be enabled (fAddressIndex = true) + args = ('-debug', '-txindex', '-experimentalfeatures', '-insightexplorer') + self.nodes = start_nodes(3, self.options.tmpdir, [args] * 3) + connect_nodes(self.nodes[0], 1) + connect_nodes(self.nodes[0], 2) + + self.is_network_split = False + self.sync_all() + + def run_test(self): + + # helper functions + def getaddresstxids(node_index, addresses, start, end): + return self.nodes[node_index].getaddresstxids({ + 'addresses': addresses, + 'start': start, + 'end': end + }) + + def getaddressdeltas(node_index, addresses, start, end, chainInfo=None): + params = { + 'addresses': addresses, + 'start': start, + 'end': end, + } + if chainInfo is not None: + params.update({'chainInfo': chainInfo}) + return self.nodes[node_index].getaddressdeltas(params) + + # default received value is the balance value + def check_balance(node_index, address, expected_balance, expected_received=None): + if isinstance(address, list): + bal = self.nodes[node_index].getaddressbalance({'addresses': address}) + else: + bal = self.nodes[node_index].getaddressbalance(address) + assert_equal(bal['balance'], expected_balance) + if expected_received is None: + expected_received = expected_balance + assert_equal(bal['received'], expected_received) + + # begin test + + self.nodes[0].generate(105) + self.sync_all() + assert_equal(self.nodes[0].getbalance(), 5 * 10) + assert_equal(self.nodes[1].getblockcount(), 105) + assert_equal(self.nodes[1].getbalance(), 0) + + # only the oldest 5; subsequent are not yet mature + unspent_txids = [ u['txid'] for u in self.nodes[0].listunspent() ] + + # Currently our only unspents are coinbase transactions, choose any one + tx = self.nodes[0].getrawtransaction(unspent_txids[0], 1) + + # It just so happens that the first output is the mining reward, + # which has type pay-to-public-key-hash, and the second output + # is the founders' reward, which has type pay-to-script-hash. + addr_p2pkh = tx['vout'][0]['scriptPubKey']['addresses'][0] + addr_p2sh = tx['vout'][1]['scriptPubKey']['addresses'][0] + + # Check that balances from mining are correct (105 blocks mined); in + # regtest, all mining rewards from a single call to generate() are sent + # to the same pair of addresses. + check_balance(1, addr_p2pkh, 105 * 10 * COIN) + check_balance(1, addr_p2sh, 105 * 2.5 * COIN) + + # Multiple address arguments, results are the sum + check_balance(1, [addr_p2sh, addr_p2pkh], 105 * 12.5 * COIN) + + assert_equal(len(self.nodes[1].getaddresstxids(addr_p2pkh)), 105) + assert_equal(len(self.nodes[1].getaddresstxids(addr_p2sh)), 105) + + # only the oldest 5 transactions are in the unspent list, + # dup addresses are ignored + height_txids = getaddresstxids(1, [addr_p2pkh, addr_p2pkh], 1, 5) + assert_equal(sorted(height_txids), sorted(unspent_txids)) + + height_txids = getaddresstxids(1, [addr_p2sh], 1, 5) + assert_equal(sorted(height_txids), sorted(unspent_txids)) + + # each txid should appear only once + height_txids = getaddresstxids(1, [addr_p2pkh, addr_p2sh], 1, 5) + assert_equal(sorted(height_txids), sorted(unspent_txids)) + + # do some transfers, make sure balances are good + txids_a1 = [] + addr1 = self.nodes[1].getnewaddress() + expected = 0 + expected_deltas = [] # for checking getaddressdeltas (below) + for i in range(5): + # first transaction happens at height 105, mined in block 106 + txid = self.nodes[0].sendtoaddress(addr1, i + 1) + txids_a1.append(txid) + self.nodes[0].generate(1) + self.sync_all() + expected += i + 1 + expected_deltas.append({ + 'height': 106 + i, + 'satoshis': (i + 1) * COIN, + 'txid': txid, + }) + check_balance(1, addr1, expected * COIN) + assert_equal(sorted(self.nodes[0].getaddresstxids(addr1)), sorted(txids_a1)) + assert_equal(sorted(self.nodes[1].getaddresstxids(addr1)), sorted(txids_a1)) + + # Restart all nodes to ensure indices are saved to disk and recovered + stop_nodes(self.nodes) + wait_bitcoinds() + self.setup_network() + + bal = self.nodes[1].getaddressbalance(addr1) + assert_equal(bal['balance'], expected * COIN) + assert_equal(bal['received'], expected * COIN) + assert_equal(sorted(self.nodes[0].getaddresstxids(addr1)), sorted(txids_a1)) + assert_equal(sorted(self.nodes[1].getaddresstxids(addr1)), sorted(txids_a1)) + + # Send 3 from addr1, but -- subtlety alert! -- addr1 at this + # time has 4 UTXOs, with values 1, 2, 3, 4. Sending value 3 requires + # using up the value 4 UTXO, because of the tx fee + # (the 3 UTXO isn't quite large enough). + # + # The txid from sending *from* addr1 is also added to the list of + # txids associated with that address (test will verify below). + + addr2 = self.nodes[2].getnewaddress() + txid = self.nodes[1].sendtoaddress(addr2, 3) + self.sync_all() + + # the one tx in the mempool refers to addresses addr1 and addr2, + # check that duplicate addresses are processed correctly + mempool = self.nodes[0].getaddressmempool({'addresses': [addr2, addr1, addr2]}) + assert_equal(len(mempool), 3) + + # addr2 (first arg) + assert_equal(mempool[0]['address'], addr2) + assert_equal(mempool[0]['satoshis'], 3 * COIN) + assert_equal(mempool[0]['txid'], txid) + + # addr1 (second arg) + assert_equal(mempool[1]['address'], addr1) + assert_equal(mempool[1]['satoshis'], (-4) * COIN) + assert_equal(mempool[1]['txid'], txid) + + # addr2 (third arg) + assert_equal(mempool[2]['address'], addr2) + assert_equal(mempool[2]['satoshis'], 3 * COIN) + assert_equal(mempool[2]['txid'], txid) + + # a single address can be specified as a string (not json object) + assert_equal([mempool[1]], self.nodes[0].getaddressmempool(addr1)) + + txids_a1.append(txid) + expected_deltas.append({ + 'height': 111, + 'satoshis': (-4) * COIN, + 'txid': txid, + }) + self.sync_all() # ensure transaction is included in the next block + self.nodes[0].generate(1) + self.sync_all() + + # the send to addr2 tx is now in a mined block, no longer in the mempool + mempool = self.nodes[0].getaddressmempool({'addresses': [addr2, addr1]}) + assert_equal(len(mempool), 0) + + # Test DisconnectBlock() by invalidating the most recent mined block + tip = self.nodes[1].getchaintips()[0] + for i in range(3): + node = self.nodes[i] + # the value 4 UTXO is no longer in our balance + check_balance(i, addr1, (expected - 4) * COIN, expected * COIN) + check_balance(i, addr2, 3 * COIN) + + assert_equal(node.getblockcount(), 111) + node.invalidateblock(tip['hash']) + assert_equal(node.getblockcount(), 110) + + mempool = node.getaddressmempool({'addresses': [addr2, addr1]}) + assert_equal(len(mempool), 2) + + check_balance(i, addr1, expected * COIN) + check_balance(i, addr2, 0) + + # now re-mine the addr1 to addr2 send + self.nodes[0].generate(1) + self.sync_all() + for node in self.nodes: + assert_equal(node.getblockcount(), 111) + + mempool = self.nodes[0].getaddressmempool({'addresses': [addr2, addr1]}) + assert_equal(len(mempool), 0) + + # the value 4 UTXO is no longer in our balance + check_balance(2, addr1, (expected - 4) * COIN, expected * COIN) + + # Ensure the change from that transaction appears + tx = self.nodes[0].getrawtransaction(txid, 1) + change_vout = filter(lambda v: v['valueZat'] != 3 * COIN, tx['vout']) + change = change_vout[0]['scriptPubKey']['addresses'][0] + bal = self.nodes[2].getaddressbalance(change) + assert(bal['received'] > 0) + # the inequality is due to randomness in the tx fee + assert(bal['received'] < (4 - 3) * COIN) + assert_equal(bal['received'], bal['balance']) + assert_equal(self.nodes[2].getaddresstxids(change), [txid]) + + # Further checks that limiting by height works + + # various ranges + for i in range(5): + height_txids = getaddresstxids(1, [addr1], 106, 106 + i) + assert_equal(height_txids, txids_a1[0:i+1]) + + height_txids = getaddresstxids(1, [addr1], 1, 108) + assert_equal(height_txids, txids_a1[0:3]) + + # Further check specifying multiple addresses + txids_all = list(txids_a1) + txids_all += self.nodes[1].getaddresstxids(addr_p2pkh) + txids_all += self.nodes[1].getaddresstxids(addr_p2sh) + multitxids = self.nodes[1].getaddresstxids({ + 'addresses': [addr1, addr_p2sh, addr_p2pkh] + }) + # No dups in return list from getaddresstxids + assert_equal(len(multitxids), len(set(multitxids))) + + # set(txids_all) removes its (expected) duplicates + assert_equal(set(multitxids), set(txids_all)) + + deltas = self.nodes[1].getaddressdeltas({'addresses': [addr1]}) + assert_equal(len(deltas), len(expected_deltas)) + for i in range(len(deltas)): + assert_equal(deltas[i]['address'], addr1) + assert_equal(deltas[i]['height'], expected_deltas[i]['height']) + assert_equal(deltas[i]['satoshis'], expected_deltas[i]['satoshis']) + assert_equal(deltas[i]['txid'], expected_deltas[i]['txid']) + + # 106-111 is the full range (also the default) + deltas_limited = getaddressdeltas(1, [addr1], 106, 111) + assert_equal(deltas_limited, deltas) + + # only the first element missing + deltas_limited = getaddressdeltas(1, [addr1], 107, 111) + assert_equal(deltas_limited, deltas[1:]) + + deltas_limited = getaddressdeltas(1, [addr1], 109, 109) + assert_equal(deltas_limited, deltas[3:4]) + + # the full range (also the default) + deltas_info = getaddressdeltas(1, [addr1], 106, 111, chainInfo=True) + assert_equal(deltas_info['deltas'], deltas) + + # check the additional items returned by chainInfo + assert_equal(deltas_info['start']['height'], 106) + block_hash = self.nodes[1].getblockhash(106) + assert_equal(deltas_info['start']['hash'], block_hash) + + assert_equal(deltas_info['end']['height'], 111) + block_hash = self.nodes[1].getblockhash(111) + assert_equal(deltas_info['end']['hash'], block_hash) + + # Test getaddressutxos by comparing results with deltas + utxos = self.nodes[1].getaddressutxos(addr1) + + # The value 4 note was spent, so won't show up in the utxo list, + # so for comparison, remove the 4 (and -4 for output) from the + # deltas list + deltas = self.nodes[1].getaddressdeltas({'addresses': [addr1]}) + deltas = filter(lambda d: abs(d['satoshis']) != 4 * COIN, deltas) + assert_equal(len(utxos), len(deltas)) + for i in range(len(utxos)): + assert_equal(utxos[i]['address'], addr1) + assert_equal(utxos[i]['height'], deltas[i]['height']) + assert_equal(utxos[i]['satoshis'], deltas[i]['satoshis']) + assert_equal(utxos[i]['txid'], deltas[i]['txid']) + + # Check that outputs with the same address in the same tx return one txid + # (can't use createrawtransaction() as it combines duplicate addresses) + addr = "t2LMJ6Arw9UWBMWvfUr2QLHM4Xd9w53FftS" + addressHash = "97643ce74b188f4fb6bbbb285e067a969041caf2".decode('hex') + scriptPubKey = CScript([OP_HASH160, addressHash, OP_EQUAL]) + # Add an unrecognized script type to vout[], a legal script that pays, + # but won't modify the addressindex (since the address can't be extracted). + # (This extra output has no effect on the rest of the test.) + scriptUnknown = CScript([OP_HASH160, OP_DUP, OP_DROP, addressHash, OP_EQUAL]) + unspent = filter(lambda u: u['amount'] >= 4, self.nodes[0].listunspent()) + tx = CTransaction() + tx.vin = [CTxIn(COutPoint(int(unspent[0]['txid'], 16), unspent[0]['vout']))] + tx.vout = [ + CTxOut(1 * COIN, scriptPubKey), + CTxOut(2 * COIN, scriptPubKey), + CTxOut(7 * COIN, scriptUnknown), + ] + tx = self.nodes[0].signrawtransaction(hexlify(tx.serialize()).decode('utf-8')) + txid = self.nodes[0].sendrawtransaction(tx['hex'], True) + self.nodes[0].generate(1) + self.sync_all() + + assert_equal(self.nodes[1].getaddresstxids(addr), [txid]) + check_balance(2, addr, 3 * COIN) + + +if __name__ == '__main__': + AddressIndexTest().main() diff --git a/src/addressindex.h b/src/addressindex.h index 0d1f3af59f7..1cbd300015a 100644 --- a/src/addressindex.h +++ b/src/addressindex.h @@ -222,4 +222,66 @@ struct CAddressIndexIteratorHeightKey { } }; +struct CMempoolAddressDelta +{ + int64_t time; + CAmount amount; + uint256 prevhash; + unsigned int prevout; + + CMempoolAddressDelta(int64_t t, CAmount a, uint256 hash, unsigned int out) { + time = t; + amount = a; + prevhash = hash; + prevout = out; + } + + CMempoolAddressDelta(int64_t t, CAmount a) { + time = t; + amount = a; + prevhash.SetNull(); + prevout = 0; + } +}; + +struct CMempoolAddressDeltaKey +{ + int type; + uint160 addressBytes; + uint256 txhash; + unsigned int index; + int spending; + + CMempoolAddressDeltaKey(int addressType, uint160 addressHash, uint256 hash, unsigned int i, int s) { + type = addressType; + addressBytes = addressHash; + txhash = hash; + index = i; + spending = s; + } + + CMempoolAddressDeltaKey(int addressType, uint160 addressHash) { + type = addressType; + addressBytes = addressHash; + txhash.SetNull(); + index = 0; + spending = 0; + } +}; + +struct CMempoolAddressDeltaKeyCompare +{ + bool operator()(const CMempoolAddressDeltaKey& a, const CMempoolAddressDeltaKey& b) const { + if (a.type != b.type) + return a.type < b.type; + if (a.addressBytes != b.addressBytes) + return a.addressBytes < b.addressBytes; + if (a.txhash != b.txhash) + return a.txhash < b.txhash; + if (a.index != b.index) + return a.index < b.index; + return a.spending < b.spending; + } +}; + #endif // BITCOIN_ADDRESSINDEX_H diff --git a/src/main.cpp b/src/main.cpp index 8f22e3e83aa..c0cd9b043ea 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,7 +21,6 @@ #include "metrics.h" #include "net.h" #include "pow.h" -#include "txdb.h" #include "txmempool.h" #include "ui_interface.h" #include "undo.h" @@ -1600,6 +1599,11 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Store transaction in memory pool.addUnchecked(hash, entry, !IsInitialBlockDownload(Params())); + + // Add memory address index + if (fAddressIndex) { + pool.addAddressIndex(entry, view); + } } SyncWithWallets(tx, NULL); @@ -1615,6 +1619,31 @@ bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value) return pblocktree->ReadSpentIndex(key, value); } +bool GetAddressIndex(const uint160& addressHash, int type, + std::vector& addressIndex, + int start, int end) +{ + if (!fAddressIndex) + return error("address index not enabled"); + + if (!pblocktree->ReadAddressIndex(addressHash, type, addressIndex, start, end)) + return error("unable to get txids for address"); + + return true; +} + +bool GetAddressUnspent(const uint160& addressHash, int type, + std::vector& unspentOutputs) +{ + if (!fAddressIndex) + return error("address index not enabled"); + + if (!pblocktree->ReadAddressUnspentIndex(addressHash, type, unspentOutputs)) + return error("unable to get txids for address"); + + return true; +} + /** Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */ bool GetTransaction(const uint256 &hash, CTransaction &txOut, const Consensus::Params& consensusParams, uint256 &hashBlock, bool fAllowSlow) { diff --git a/src/main.h b/src/main.h index c414f13d504..f3b46e3d9d5 100644 --- a/src/main.h +++ b/src/main.h @@ -24,6 +24,7 @@ #include "script/standard.h" #include "sync.h" #include "tinyformat.h" +#include "txdb.h" #include "txmempool.h" #include "uint256.h" #include "addressindex.h" @@ -438,6 +439,11 @@ class CScriptCheck }; bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value); +bool GetAddressIndex(const uint160& addressHash, int type, + std::vector &addressIndex, + int start = 0, int end = 0); +bool GetAddressUnspent(const uint160& addressHash, int type, + std::vector& unspentOutputs); /** Functions for disk access for blocks */ bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart); diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 05c419068cb..137210a2313 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -99,6 +99,11 @@ static const CRPCConvertParam vRPCConvertParams[] = { "prioritisetransaction", 2 }, { "setban", 2 }, { "setban", 3 }, + { "getaddresstxids", 0}, + { "getaddressbalance", 0}, + { "getaddressdeltas", 0}, + { "getaddressutxos", 0}, + { "getaddressmempool", 0}, { "zcrawjoinsplit", 1 }, { "zcrawjoinsplit", 2 }, { "zcrawjoinsplit", 3 }, diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index f732f1b9267..a34d7b2503c 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -11,6 +11,7 @@ #include "netbase.h" #include "rpc/server.h" #include "timedata.h" +#include "txmempool.h" #include "util.h" #ifdef ENABLE_WALLET #include "wallet/wallet.h" @@ -483,6 +484,567 @@ UniValue setmocktime(const UniValue& params, bool fHelp) return NullUniValue; } +static bool getAddressFromIndex( + int type, const uint160 &hash, std::string &address) +{ + if (type == CScript::P2SH) { + address = EncodeDestination(CScriptID(hash)); + } else if (type == CScript::P2PKH) { + address = EncodeDestination(CKeyID(hash)); + } else { + return false; + } + return true; +} + +// This function accepts an address and returns in the output parameters +// the version and raw bytes for the RIPEMD-160 hash. +static bool getIndexKey( + const CTxDestination& dest, uint160& hashBytes, int& type) +{ + if (!IsValidDestination(dest)) { + return false; + } + if (dest.type() == typeid(CKeyID)) { + auto x = boost::get(&dest); + memcpy(&hashBytes, x->begin(), 20); + type = CScript::P2PKH; + return true; + } + if (dest.type() == typeid(CScriptID)) { + auto x = boost::get(&dest); + memcpy(&hashBytes, x->begin(), 20); + type = CScript::P2SH; + return true; + } + return false; +} + +static bool getAddressesFromParams( + const UniValue& params, + std::vector> &addresses) +{ + std::vector param_addresses; + if (params[0].isStr()) { + param_addresses.push_back(params[0].get_str()); + } else if (params[0].isObject()) { + UniValue addressValues = find_value(params[0].get_obj(), "addresses"); + if (!addressValues.isArray()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, + "Addresses is expected to be an array"); + } + for (const auto& it : addressValues.getValues()) { + param_addresses.push_back(it.get_str()); + } + + } else { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); + } + for (const auto& it : param_addresses) { + CTxDestination address = DecodeDestination(it); + uint160 hashBytes; + int type = 0; + if (!getIndexKey(address, hashBytes, type)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); + } + addresses.push_back(std::make_pair(hashBytes, type)); + } + return true; +} + +UniValue getaddressmempool(const UniValue& params, bool fHelp) +{ + std::string enableArg = "insightexplorer"; + bool fEnableGetAddressMempool = fExperimentalMode && fInsightExplorer; + std::string disabledMsg = ""; + if (!fEnableGetAddressMempool) { + disabledMsg = experimentalDisabledHelpMsg("getaddressmempool", enableArg); + } + if (fHelp || params.size() != 1) + throw runtime_error( + "getaddressmempool {\"addresses\": [\"taddr\", ...]}\n" + "\nReturns all mempool deltas for an address.\n" + + disabledMsg + + "\nArguments:\n" + "{\n" + " \"addresses\":\n" + " [\n" + " \"address\" (string) The base58check encoded address\n" + " ,...\n" + " ]\n" + "}\n" + "(or)\n" + "\"address\" (string) The base58check encoded address\n" + "\nResult:\n" + "[\n" + " {\n" + " \"address\" (string) The base58check encoded address\n" + " \"txid\" (string) The related txid\n" + " \"index\" (number) The related input or output index\n" + " \"satoshis\" (number) The difference of zatoshis\n" + " \"timestamp\" (number) The time the transaction entered the mempool (seconds)\n" + " \"prevtxid\" (string) The previous txid (if spending)\n" + " \"prevout\" (string) The previous transaction output index (if spending)\n" + " }\n" + "]\n" + "\nExamples:\n" + + HelpExampleCli("getaddressmempool", "'{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"]}'") + + HelpExampleRpc("getaddressmempool", "{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"]}") + ); + + if (!fEnableGetAddressMempool) { + throw JSONRPCError(RPC_MISC_ERROR, "Error: getaddressmempool is disabled. " + "Run './zcash-cli help getaddressmempool' for instructions on how to enable this feature."); + } + + std::vector> addresses; + + if (!getAddressesFromParams(params, addresses)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); + } + std::vector> indexes; + mempool.getAddressIndex(addresses, indexes); + std::sort(indexes.begin(), indexes.end(), + [](const std::pair& a, + const std::pair& b) -> bool { + return a.second.time < b.second.time; + }); + + UniValue result(UniValue::VARR); + + for (const auto& it : indexes) { + std::string address; + if (!getAddressFromIndex(it.first.type, it.first.addressBytes, address)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown address type"); + } + UniValue delta(UniValue::VOBJ); + delta.push_back(Pair("address", address)); + delta.push_back(Pair("txid", it.first.txhash.GetHex())); + delta.push_back(Pair("index", (int)it.first.index)); + delta.push_back(Pair("satoshis", it.second.amount)); + delta.push_back(Pair("timestamp", it.second.time)); + if (it.second.amount < 0) { + delta.push_back(Pair("prevtxid", it.second.prevhash.GetHex())); + delta.push_back(Pair("prevout", (int)it.second.prevout)); + } + result.push_back(delta); + } + return result; +} + +UniValue getaddressutxos(const UniValue& params, bool fHelp) +{ + std::string enableArg = "insightexplorer"; + bool fEnableGetAddressUtxos = fExperimentalMode && fInsightExplorer; + std::string disabledMsg = ""; + if (!fEnableGetAddressUtxos) { + disabledMsg = experimentalDisabledHelpMsg("getaddressutxos", enableArg); + } + if (fHelp || params.size() != 1) + throw runtime_error( + "getaddressutxos {\"addresses\": [\"taddr\", ...], (\"chainInfo\": true|false)}\n" + "\nReturns all unspent outputs for an address.\n" + + disabledMsg + + "\nArguments:\n" + "{\n" + " \"addresses\":\n" + " [\n" + " \"address\" (string) The base58check encoded address\n" + " ,...\n" + " ],\n" + " \"chainInfo\" (boolean, optional, default=false) Include chain info with results\n" + "}\n" + "(or)\n" + "\"address\" (string) The base58check encoded address\n" + "\nResult\n" + "[\n" + " {\n" + " \"address\" (string) The address base58check encoded\n" + " \"txid\" (string) The output txid\n" + " \"height\" (number) The block height\n" + " \"outputIndex\" (number) The output index\n" + " \"script\" (string) The script hex encoded\n" + " \"satoshis\" (number) The number of zatoshis of the output\n" + " }, ...\n" + "]\n\n" + "(or, if chainInfo is true):\n\n" + "{\n" + " \"utxos\":\n" + " [\n" + " {\n" + " \"address\" (string) The address base58check encoded\n" + " \"txid\" (string) The output txid\n" + " \"height\" (number) The block height\n" + " \"outputIndex\" (number) The output index\n" + " \"script\" (string) The script hex encoded\n" + " \"satoshis\" (number) The number of zatoshis of the output\n" + " }, ...\n" + " ],\n" + " \"hash\" (string) The block hash\n" + " \"height\" (numeric) The block height\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("getaddressutxos", "'{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"], \"chainInfo\": true}'") + + HelpExampleRpc("getaddressutxos", "{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"], \"chainInfo\": true}") + ); + + if (!fEnableGetAddressUtxos) { + throw JSONRPCError(RPC_MISC_ERROR, "Error: getaddressutxos is disabled. " + "Run './zcash-cli help getaddressutxos' for instructions on how to enable this feature."); + } + + bool includeChainInfo = false; + if (params[0].isObject()) { + UniValue chainInfo = find_value(params[0].get_obj(), "chainInfo"); + if (!chainInfo.isNull()) { + includeChainInfo = chainInfo.get_bool(); + } + } + std::vector> addresses; + if (!getAddressesFromParams(params, addresses)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); + } + std::vector unspentOutputs; + for (const auto& it : addresses) { + if (!GetAddressUnspent(it.first, it.second, unspentOutputs)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address"); + } + } + std::sort(unspentOutputs.begin(), unspentOutputs.end(), + [](const CAddressUnspentDbEntry& a, const CAddressUnspentDbEntry& b) -> bool { + return a.second.blockHeight < b.second.blockHeight; + }); + + UniValue utxos(UniValue::VARR); + for (const auto& it : unspentOutputs) { + UniValue output(UniValue::VOBJ); + std::string address; + if (!getAddressFromIndex(it.first.type, it.first.hashBytes, address)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown address type"); + } + + output.push_back(Pair("address", address)); + output.push_back(Pair("txid", it.first.txhash.GetHex())); + output.push_back(Pair("outputIndex", (int)it.first.index)); + output.push_back(Pair("script", HexStr(it.second.script.begin(), it.second.script.end()))); + output.push_back(Pair("satoshis", it.second.satoshis)); + output.push_back(Pair("height", it.second.blockHeight)); + utxos.push_back(output); + } + + if (!includeChainInfo) + return utxos; + + UniValue result(UniValue::VOBJ); + result.push_back(Pair("utxos", utxos)); + + LOCK(cs_main); // for chainActive + result.push_back(Pair("hash", chainActive.Tip()->GetBlockHash().GetHex())); + result.push_back(Pair("height", (int)chainActive.Height())); + return result; +} + +static void getHeightRange(const UniValue& params, int& start, int& end) +{ + start = 0; + end = 0; + if (params[0].isObject()) { + UniValue startValue = find_value(params[0].get_obj(), "start"); + UniValue endValue = find_value(params[0].get_obj(), "end"); + // If either is not specified, the other is ignored. + if (!startValue.isNull() && !endValue.isNull()) { + start = startValue.get_int(); + end = endValue.get_int(); + if (start <= 0 || end <= 0) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, + "Start and end are expected to be greater than zero"); + } + if (end < start) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, + "End value is expected to be greater than start"); + } + } + } + + LOCK(cs_main); // for chainActive + if (start > chainActive.Height() || end > chainActive.Height()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Start or end is outside chain range"); + } +} + +// Parse an address list then fetch the corresponding addressindex information. +static void getAddressesInHeightRange( + const UniValue& params, + int start, int end, + std::vector>& addresses, + std::vector> &addressIndex) +{ + if (!getAddressesFromParams(params, addresses)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); + } + for (const auto& it : addresses) { + if (!GetAddressIndex(it.first, it.second, addressIndex, start, end)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, + "No information available for address"); + } + } +} + +UniValue getaddressdeltas(const UniValue& params, bool fHelp) +{ + std::string enableArg = "insightexplorer"; + bool fEnableGetAddressDeltas = fExperimentalMode && fInsightExplorer; + std::string disabledMsg = ""; + if (!fEnableGetAddressDeltas) { + disabledMsg = experimentalDisabledHelpMsg("getaddressdeltas", enableArg); + } + if (fHelp || params.size() != 1) + throw runtime_error( + "getaddressdeltas {\"addresses\": [\"taddr\", ...], (\"start\": n), (\"end\": n), (\"chainInfo\": true|false)}\n" + "\nReturns all changes for an address.\n" + "\nReturns information about all changes to the given transparent addresses within the given (inclusive)\n" + "\nblock height range, default is the full blockchain.\n" + + disabledMsg + + "\nArguments:\n" + "{\n" + " \"addresses\":\n" + " [\n" + " \"address\" (string) The base58check encoded address\n" + " ,...\n" + " ]\n" + " \"start\" (number, optional) The start block height\n" + " \"end\" (number, optional) The end block height\n" + " \"chainInfo\" (boolean, optional, default=false) Include chain info in results, only applies if start and end specified\n" + "}\n" + "(or)\n" + "\"address\" (string) The base58check encoded address\n" + "\nResult:\n" + "[\n" + " {\n" + " \"satoshis\" (number) The difference of zatoshis\n" + " \"txid\" (string) The related txid\n" + " \"index\" (number) The related input or output index\n" + " \"height\" (number) The block height\n" + " \"address\" (string) The base58check encoded address\n" + " }, ...\n" + "]\n\n" + "(or, if chainInfo is true):\n\n" + "{\n" + " \"deltas\":\n" + " [\n" + " {\n" + " \"satoshis\" (number) The difference of zatoshis\n" + " \"txid\" (string) The related txid\n" + " \"index\" (number) The related input or output index\n" + " \"height\" (number) The block height\n" + " \"address\" (string) The address base58check encoded\n" + " }, ...\n" + " ],\n" + " \"start\":\n" + " {\n" + " \"hash\" (string) The start block hash\n" + " \"height\" (numeric) The height of the start block\n" + " }\n" + " \"end\":\n" + " {\n" + " \"hash\" (string) The end block hash\n" + " \"height\" (numeric) The height of the end block\n" + " }\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("getaddressdeltas", "'{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"], \"start\": 1000, \"end\": 2000, \"chainInfo\": true}'") + + HelpExampleRpc("getaddressdeltas", "{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"], \"start\": 1000, \"end\": 2000, \"chainInfo\": true}") + ); + + if (!fEnableGetAddressDeltas) { + throw JSONRPCError(RPC_MISC_ERROR, "Error: getaddressdeltas is disabled. " + "Run './zcash-cli help getaddressdeltas' for instructions on how to enable this feature."); + } + + int start = 0; + int end = 0; + getHeightRange(params, start, end); + + std::vector> addresses; + std::vector> addressIndex; + getAddressesInHeightRange(params, start, end, addresses, addressIndex); + + bool includeChainInfo = false; + if (params[0].isObject()) { + UniValue chainInfo = find_value(params[0].get_obj(), "chainInfo"); + if (!chainInfo.isNull()) { + includeChainInfo = chainInfo.get_bool(); + } + } + + UniValue deltas(UniValue::VARR); + for (const auto& it : addressIndex) { + std::string address; + if (!getAddressFromIndex(it.first.type, it.first.hashBytes, address)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown address type"); + } + + UniValue delta(UniValue::VOBJ); + delta.push_back(Pair("address", address)); + delta.push_back(Pair("blockindex", (int)it.first.txindex)); + delta.push_back(Pair("height", it.first.blockHeight)); + delta.push_back(Pair("index", (int)it.first.index)); + delta.push_back(Pair("satoshis", it.second)); + delta.push_back(Pair("txid", it.first.txhash.GetHex())); + deltas.push_back(delta); + } + + UniValue result(UniValue::VOBJ); + + if (!(includeChainInfo && start > 0 && end > 0)) { + return deltas; + } + + UniValue startInfo(UniValue::VOBJ); + UniValue endInfo(UniValue::VOBJ); + { + LOCK(cs_main); // for chainActive + if (start > chainActive.Height() || end > chainActive.Height()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Start or end is outside chain range"); + } + startInfo.push_back(Pair("hash", chainActive[start]->GetBlockHash().GetHex())); + endInfo.push_back(Pair("hash", chainActive[end]->GetBlockHash().GetHex())); + } + startInfo.push_back(Pair("height", start)); + endInfo.push_back(Pair("height", end)); + + result.push_back(Pair("deltas", deltas)); + result.push_back(Pair("start", startInfo)); + result.push_back(Pair("end", endInfo)); + + return result; +} + +UniValue getaddressbalance(const UniValue& params, bool fHelp) +{ + std::string enableArg = "insightexplorer"; + bool fEnableGetAddressBalance = fExperimentalMode && fInsightExplorer; + std::string disabledMsg = ""; + if (!fEnableGetAddressBalance) { + disabledMsg = experimentalDisabledHelpMsg("getaddressbalance", enableArg); + } + if (fHelp || params.size() != 1) + throw runtime_error( + "getaddressbalance {\"addresses\": [\"taddr\", ...]}\n" + "\nReturns the balance for addresses.\n" + + disabledMsg + + "\nArguments:\n" + "{\n" + " \"addresses:\"\n" + " [\n" + " \"address\" (string) The base58check encoded address\n" + " ,...\n" + " ]\n" + "}\n" + "(or)\n" + "\"address\" (string) The base58check encoded address\n" + "\nResult:\n" + "{\n" + " \"balance\" (string) The current balance in zatoshis\n" + " \"received\" (string) The total number of zatoshis received (including change)\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("getaddressbalance", "'{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"]}'") + + HelpExampleRpc("getaddressbalance", "{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"]}") + ); + + if (!fEnableGetAddressBalance) { + throw JSONRPCError(RPC_MISC_ERROR, "Error: getaddressbalance is disabled. " + "Run './zcash-cli help getaddressbalance' for instructions on how to enable this feature."); + } + + std::vector> addresses; + std::vector> addressIndex; + // this method doesn't take start and end block height params, so set + // to zero (full range, entire blockchain) + getAddressesInHeightRange(params, 0, 0, addresses, addressIndex); + + CAmount balance = 0; + CAmount received = 0; + for (const auto& it : addressIndex) { + if (it.second > 0) { + received += it.second; + } + balance += it.second; + } + UniValue result(UniValue::VOBJ); + result.push_back(Pair("balance", balance)); + result.push_back(Pair("received", received)); + return result; +} + +UniValue getaddresstxids(const UniValue& params, bool fHelp) +{ + std::string enableArg = "insightexplorer"; + bool fEnableGetAddressTxids = fExperimentalMode && fInsightExplorer; + std::string disabledMsg = ""; + if (!fEnableGetAddressTxids) { + disabledMsg = experimentalDisabledHelpMsg("getaddresstxids", enableArg); + } + if (fHelp || params.size() != 1) + throw runtime_error( + "getaddresstxids {\"addresses\": [\"taddr\", ...], (\"start\": n), (\"end\": n)}\n" + "\nReturns the txids for given transparent addresses within the given (inclusive)\n" + "\nblock height range, default is the full blockchain.\n" + + disabledMsg + + "\nArguments:\n" + "{\n" + " \"addresses\":\n" + " [\n" + " \"taddr\" (string) The base58check encoded address\n" + " ,...\n" + " ]\n" + " \"start\" (number, optional) The start block height\n" + " \"end\" (number, optional) The end block height\n" + "}\n" + "(or)\n" + "\"address\" (string) The base58check encoded address\n" + "\nResult:\n" + "[\n" + " \"transactionid\" (string) The transaction id\n" + " ,...\n" + "]\n" + "\nExamples:\n" + + HelpExampleCli("getaddresstxids", "'{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"], \"start\": 1000, \"end\": 2000}'") + + HelpExampleRpc("getaddresstxids", "{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"], \"start\": 1000, \"end\": 2000}") + ); + + if (!fEnableGetAddressTxids) { + throw JSONRPCError(RPC_MISC_ERROR, "Error: getaddresstxids is disabled. " + "Run './zcash-cli help getaddresstxids' for instructions on how to enable this feature."); + } + + int start = 0; + int end = 0; + getHeightRange(params, start, end); + + std::vector> addresses; + std::vector> addressIndex; + getAddressesInHeightRange(params, start, end, addresses, addressIndex); + + // This is an ordered set, sorted by height, so result also sorted by height. + std::set> txids; + + for (const auto& it : addressIndex) { + const int height = it.first.blockHeight; + const std::string txid = it.first.txhash.GetHex(); + // Duplicate entries (two addresses in same tx) are suppressed + txids.insert(std::make_pair(height, txid)); + } + UniValue result(UniValue::VARR); + for (const auto& it : txids) { + // only push the txid, not the height + result.push_back(it.second); + } + return result; +} + + static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // --------------------- ------------------------ ----------------------- ---------- @@ -492,6 +1054,13 @@ static const CRPCCommand commands[] = { "util", "createmultisig", &createmultisig, true }, { "util", "verifymessage", &verifymessage, true }, + /* Address index */ + { "addressindex", "getaddresstxids", &getaddresstxids, false }, /* insight explorer */ + { "addressindex", "getaddressbalance", &getaddressbalance, false }, /* insight explorer */ + { "addressindex", "getaddressdeltas", &getaddressdeltas, false }, /* insight explorer */ + { "addressindex", "getaddressutxos", &getaddressutxos, false }, /* insight explorer */ + { "addressindex", "getaddressmempool", &getaddressmempool, true }, /* insight explorer */ + /* Not shown in help */ { "hidden", "setmocktime", &setmocktime, true }, }; diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 26de01a9501..932c36241fa 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -66,7 +66,9 @@ UniValue TxJoinSplitToJSON(const CTransaction& tx) { UniValue joinsplit(UniValue::VOBJ); joinsplit.push_back(Pair("vpub_old", ValueFromAmount(jsdescription.vpub_old))); + joinsplit.push_back(Pair("vpub_oldZat", jsdescription.vpub_old)); joinsplit.push_back(Pair("vpub_new", ValueFromAmount(jsdescription.vpub_new))); + joinsplit.push_back(Pair("vpub_newZat", jsdescription.vpub_new)); joinsplit.push_back(Pair("anchor", jsdescription.anchor.GetHex())); @@ -178,10 +180,10 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) in.push_back(Pair("value", ValueFromAmount(spentInfo.satoshis))); in.push_back(Pair("valueSat", spentInfo.satoshis)); - boost::optional dest = + CTxDestination dest = DestFromAddressHash(spentInfo.addressType, spentInfo.addressHash); - if (dest) { - in.push_back(Pair("address", EncodeDestination(*dest))); + if (IsValidDestination(dest)) { + in.push_back(Pair("address", EncodeDestination(dest))); } } } @@ -217,6 +219,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) if (tx.fOverwintered && tx.nVersion >= SAPLING_TX_VERSION) { entry.push_back(Pair("valueBalance", ValueFromAmount(tx.valueBalance))); + entry.push_back(Pair("valueBalanceZat", tx.valueBalance)); UniValue vspenddesc = TxShieldedSpendsToJSON(tx); entry.push_back(Pair("vShieldedSpend", vspenddesc)); UniValue voutputdesc = TxShieldedOutputsToJSON(tx); diff --git a/src/script/script.cpp b/src/script/script.cpp index bbbc7cdb3c1..e2b2be3a5c1 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -248,7 +248,7 @@ CScript::ScriptType CScript::GetType() const return CScript::P2PKH; if (this->IsPayToScriptHash()) return CScript::P2SH; - // We don't know this script + // We don't know this script type return CScript::UNKNOWN; } @@ -262,7 +262,7 @@ uint160 CScript::AddressHash() const else if (this->IsPayToScriptHash()) start = 2; else { - // unknown script type; return zeros + // unknown script type; return zeros (this can happen) vector hashBytes; hashBytes.resize(20); return uint160(hashBytes); diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 209e8879d93..e94dfb38bd6 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -322,7 +322,7 @@ bool IsValidDestination(const CTxDestination& dest) { } // insightexplorer -boost::optional DestFromAddressHash(int scriptType, uint160& addressHash) +CTxDestination DestFromAddressHash(int scriptType, uint160& addressHash) { switch (scriptType) { case CScript::P2PKH: @@ -330,6 +330,9 @@ boost::optional DestFromAddressHash(int scriptType, uint160& add case CScript::P2SH: return CTxDestination(CScriptID(addressHash)); default: - return boost::none; + // This probably won't ever happen, because it would mean that + // the addressindex contains a type (say, 3) that we (currently) + // don't recognize; maybe we "dropped support" for it? + return CNoDestination(); } } diff --git a/src/script/standard.h b/src/script/standard.h index 94cd119bf19..b3db522bae3 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -97,6 +97,6 @@ CScript GetScriptForDestination(const CTxDestination& dest); CScript GetScriptForMultisig(int nRequired, const std::vector& keys); // insightexplorer -boost::optional DestFromAddressHash(int scriptType, uint160& addressHash); +CTxDestination DestFromAddressHash(int scriptType, uint160& addressHash); #endif // BITCOIN_SCRIPT_STANDARD_H diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 02d827ad5dd..7ce9172e591 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -6,6 +6,7 @@ #include "rpc/client.h" #include "key_io.h" +#include "main.h" #include "netbase.h" #include "utilstrencodings.h" @@ -55,6 +56,19 @@ UniValue CallRPC(string args) } +void CheckRPCThrows(std::string rpcString, std::string expectedErrorMessage) { + try { + CallRPC(rpcString); + // Note: CallRPC catches (const UniValue& objError) and rethrows a runtime_error + BOOST_FAIL("Should have caused an error"); + } catch (const std::runtime_error& e) { + BOOST_CHECK_EQUAL(expectedErrorMessage, e.what()); + } catch(const std::exception& e) { + BOOST_FAIL(std::string("Unexpected exception: ") + typeid(e).name() + ", message=\"" + e.what() + "\""); + } +} + + BOOST_FIXTURE_TEST_SUITE(rpc_tests, TestingSetup) BOOST_AUTO_TEST_CASE(rpc_rawparams) @@ -346,4 +360,65 @@ BOOST_AUTO_TEST_CASE(rpc_getnetworksolps) BOOST_CHECK_NO_THROW(CallRPC("getnetworksolps 120 -1")); } +// Test parameter processing (not functionality) +BOOST_AUTO_TEST_CASE(rpc_insightexplorer) +{ + CheckRPCThrows("getaddressmempool \"a\"", + "Error: getaddressmempool is disabled. " + "Run './zcash-cli help getaddressmempool' for instructions on how to enable this feature."); + CheckRPCThrows("getaddressutxos \"a\"", + "Error: getaddressutxos is disabled. " + "Run './zcash-cli help getaddressutxos' for instructions on how to enable this feature."); + CheckRPCThrows("getaddressdeltas \"a\"", + "Error: getaddressdeltas is disabled. " + "Run './zcash-cli help getaddressdeltas' for instructions on how to enable this feature."); + CheckRPCThrows("getaddressbalance \"a\"", + "Error: getaddressbalance is disabled. " + "Run './zcash-cli help getaddressbalance' for instructions on how to enable this feature."); + CheckRPCThrows("getaddresstxids \"a\"", + "Error: getaddresstxids is disabled. " + "Run './zcash-cli help getaddresstxids' for instructions on how to enable this feature."); + + fExperimentalMode = true; + fInsightExplorer = true; + + // must be a legal mainnet address + const string addr = "t1T3G72ToPuCDTiCEytrU1VUBRHsNupEBut"; + BOOST_CHECK_NO_THROW(CallRPC("getaddressmempool \"" + addr + "\"")); + BOOST_CHECK_NO_THROW(CallRPC("getaddressmempool {\"addresses\":[\"" + addr + "\"]}")); + BOOST_CHECK_NO_THROW(CallRPC("getaddressmempool {\"addresses\":[\"" + addr + "\",\"" + addr + "\"]}")); + + BOOST_CHECK_NO_THROW(CallRPC("getaddressutxos {\"addresses\":[],\"chainInfo\":true}")); + CheckRPCThrows("getaddressutxos {}", + "Addresses is expected to be an array"); + CheckRPCThrows("getaddressutxos {\"addressesmisspell\":[]}", + "Addresses is expected to be an array"); + CheckRPCThrows("getaddressutxos {\"addresses\":[],\"chainInfo\":1}", + "JSON value is not a boolean as expected"); + + BOOST_CHECK_NO_THROW(CallRPC("getaddressdeltas {\"addresses\":[]}")); + CheckRPCThrows("getaddressdeltas {\"addresses\":[],\"start\":0,\"end\":0,\"chainInfo\":true}", + "Start and end are expected to be greater than zero"); + CheckRPCThrows("getaddressdeltas {\"addresses\":[],\"start\":3,\"end\":2,\"chainInfo\":true}", + "End value is expected to be greater than start"); + // in this test environment, only the genesis block (0) exists + CheckRPCThrows("getaddressdeltas {\"addresses\":[],\"start\":2,\"end\":3,\"chainInfo\":true}", + "Start or end is outside chain range"); + + BOOST_CHECK_NO_THROW(CallRPC("getaddressbalance {\"addresses\":[]}")); + + BOOST_CHECK_NO_THROW(CallRPC("getaddresstxids {\"addresses\":[]}")); + CheckRPCThrows("getaddresstxids {\"addresses\":[],\"start\":0,\"end\":0,\"chainInfo\":true}", + "Start and end are expected to be greater than zero"); + CheckRPCThrows("getaddresstxids {\"addresses\":[],\"start\":3,\"end\":2,\"chainInfo\":true}", + "End value is expected to be greater than start"); + // in this test environment, only the genesis block (0) exists + CheckRPCThrows("getaddresstxids {\"addresses\":[],\"start\":2,\"end\":3,\"chainInfo\":true}", + "Start or end is outside chain range"); + + // revert + fExperimentalMode = false; + fInsightExplorer = false; +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index 6e1cb2cb744..26c94de424a 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -1674,19 +1674,6 @@ BOOST_AUTO_TEST_CASE(rpc_z_shieldcoinbase_internals) } - -void CheckRPCThrows(std::string rpcString, std::string expectedErrorMessage) { - try { - CallRPC(rpcString); - // Note: CallRPC catches (const UniValue& objError) and rethrows a runtime_error - BOOST_FAIL("Should have caused an error"); - } catch (const std::runtime_error& e) { - BOOST_CHECK_EQUAL(expectedErrorMessage, e.what()); - } catch(const std::exception& e) { - BOOST_FAIL(std::string("Unexpected exception: ") + typeid(e).name() + ", message=\"" + e.what() + "\""); - } -} - BOOST_AUTO_TEST_CASE(rpc_z_mergetoaddress_parameters) { SelectParams(CBaseChainParams::TESTNET); diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h index ff1ad48e202..d1f9b2e54bb 100644 --- a/src/test/test_bitcoin.h +++ b/src/test/test_bitcoin.h @@ -68,4 +68,7 @@ struct TestMemPoolEntryHelper TestMemPoolEntryHelper &SpendsCoinbase(bool _flag) { spendsCoinbase = _flag; return *this; } TestMemPoolEntryHelper &BranchId(uint32_t _branchId) { nBranchId = _branchId; return *this; } }; + +void CheckRPCThrows(std::string rpcString, std::string expectedErrorMessage); + #endif diff --git a/src/txdb.cpp b/src/txdb.cpp index 9ccd4378ed8..1e556152413 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -326,7 +326,7 @@ bool CBlockTreeDB::ReadAddressUnspentIndex(uint160 addressHash, int type, std::v if (!(pcursor->GetKey(key) && key.first == DB_ADDRESSUNSPENTINDEX && key.second.hashBytes == addressHash)) break; CAddressUnspentValue nValue; - if (pcursor->GetValue(nValue)) + if (!pcursor->GetValue(nValue)) return error("failed to get address unspent value"); unspentOutputs.push_back(make_pair(key.second, nValue)); pcursor->Next(); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index bc9e3ba2a91..2fc82cfb4ef 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -121,6 +121,65 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, return true; } +void CTxMemPool::addAddressIndex(const CTxMemPoolEntry &entry, const CCoinsViewCache &view) +{ + LOCK(cs); + const CTransaction& tx = entry.GetTx(); + std::vector inserted; + + uint256 txhash = tx.GetHash(); + for (unsigned int j = 0; j < tx.vin.size(); j++) { + const CTxIn input = tx.vin[j]; + const CTxOut &prevout = view.GetOutputFor(input); + CScript::ScriptType type = prevout.scriptPubKey.GetType(); + if (type == CScript::UNKNOWN) + continue; + CMempoolAddressDeltaKey key(type, prevout.scriptPubKey.AddressHash(), txhash, j, 1); + CMempoolAddressDelta delta(entry.GetTime(), prevout.nValue * -1, input.prevout.hash, input.prevout.n); + mapAddress.insert(make_pair(key, delta)); + inserted.push_back(key); + } + + for (unsigned int j = 0; j < tx.vout.size(); j++) { + const CTxOut &out = tx.vout[j]; + CScript::ScriptType type = out.scriptPubKey.GetType(); + if (type == CScript::UNKNOWN) + continue; + CMempoolAddressDeltaKey key(type, out.scriptPubKey.AddressHash(), txhash, j, 0); + mapAddress.insert(make_pair(key, CMempoolAddressDelta(entry.GetTime(), out.nValue))); + inserted.push_back(key); + } + + mapAddressInserted.insert(make_pair(txhash, inserted)); +} + +void CTxMemPool::getAddressIndex( + const std::vector>& addresses, + std::vector>& results) +{ + LOCK(cs); + for (const auto& it : addresses) { + auto ait = mapAddress.lower_bound(CMempoolAddressDeltaKey(it.second, it.first)); + while (ait != mapAddress.end() && (*ait).first.addressBytes == it.first && (*ait).first.type == it.second) { + results.push_back(*ait); + ait++; + } + } +} + +void CTxMemPool::removeAddressIndex(const uint256& txhash) +{ + LOCK(cs); + auto it = mapAddressInserted.find(txhash); + + if (it != mapAddressInserted.end()) { + std::vector keys = it->second; + for (const auto& mit : keys) { + mapAddress.erase(mit); + } + mapAddressInserted.erase(it); + } +} void CTxMemPool::remove(const CTransaction &origTx, std::list& removed, bool fRecursive) { @@ -172,6 +231,9 @@ void CTxMemPool::remove(const CTransaction &origTx, std::list& rem mapTx.erase(hash); nTransactionsUpdated++; minerPolicyEstimator->removeTx(hash); + // insightexplorer + if (fAddressIndex) + removeAddressIndex(hash); } } } diff --git a/src/txmempool.h b/src/txmempool.h index 396c24e97cf..d3689c64f2e 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -12,6 +12,7 @@ #include "coins.h" #include "primitives/transaction.h" #include "sync.h" +#include "addressindex.h" #undef foreach #include "boost/multi_index_container.hpp" @@ -152,6 +153,12 @@ class CTxMemPool mutable CCriticalSection cs; indexed_transaction_set mapTx; + +private: + std::map mapAddress; + std::map > mapAddressInserted; + +public: std::map mapNextTx; std::map > mapDeltas; @@ -168,6 +175,12 @@ class CTxMemPool void setSanityCheck(double dFrequency = 1.0) { nCheckFrequency = static_cast(dFrequency * 4294967295.0); } bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, bool fCurrentEstimate = true); + + void addAddressIndex(const CTxMemPoolEntry &entry, const CCoinsViewCache &view); + void getAddressIndex(const std::vector>& addresses, + std::vector>& results); + void removeAddressIndex(const uint256& txhash); + void remove(const CTransaction &tx, std::list& removed, bool fRecursive = false); void removeWithAnchor(const uint256 &invalidRoot, ShieldedType type); void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags); From e358e89db9d1893fbeb52a342ced7bf237137f26 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 31 Jul 2019 12:20:15 -0600 Subject: [PATCH 192/395] PartitionCheck tests for shorter block times --- src/test/alert_tests.cpp | 70 +++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index 9be91645c19..83e966cda94 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -19,6 +19,7 @@ #include "streams.h" #include "util.h" #include "utilstrencodings.h" +#include "utiltest.h" #include "test/test_bitcoin.h" @@ -385,41 +386,40 @@ BOOST_AUTO_TEST_CASE(AlertDisablesRPC) static bool falseFunc(const CChainParams&) { return false; } -BOOST_AUTO_TEST_CASE(PartitionAlert) +void PartitionAlertTestImpl(const Consensus::Params& params, int startTime, int expectedTotal, int expectedSlow, int expectedFast) { // Test PartitionCheck CCriticalSection csDummy; - CBlockIndex indexDummy[400]; - CChainParams& params = Params(CBaseChainParams::MAIN); - int64_t nPowTargetSpacing = params.GetConsensus().PoWTargetSpacing(0); // First 400 blocks are pre-Blossom + CBlockIndex indexDummy[800]; - // Generate fake blockchain timestamps relative to - // an arbitrary time: - int64_t now = 1427379054; - SetMockTime(now); - for (int i = 0; i < 400; i++) + int64_t start = startTime; + for (int i = 0; i < 800; i++) { indexDummy[i].phashBlock = NULL; - if (i == 0) indexDummy[i].pprev = NULL; - else indexDummy[i].pprev = &indexDummy[i-1]; + indexDummy[i].pprev = i ? &indexDummy[i-1] : NULL; indexDummy[i].nHeight = i; - indexDummy[i].nTime = now - (400-i)*nPowTargetSpacing; + indexDummy[i].nTime = i ? indexDummy[i - 1].nTime + params.PoWTargetSpacing(i) : start; // Other members don't matter, the partition check code doesn't // use them } + // Generate fake blockchain timestamps relative to + // an arbitrary time: + int64_t now = indexDummy[799].nTime + params.PoWTargetSpacing(800); + SetMockTime(now); // Test 1: chain with blocks every nPowTargetSpacing seconds, // as normal, no worries: strMiscWarning = ""; - PartitionCheck(falseFunc, csDummy, &indexDummy[399]); + PartitionCheck(falseFunc, csDummy, &indexDummy[799]); BOOST_CHECK_EQUAL("", strMiscWarning); // Test 2: go 3.5 hours without a block, expect a warning: now += 3*60*60+30*60; SetMockTime(now); strMiscWarning = ""; - PartitionCheck(falseFunc, csDummy, &indexDummy[399]); - BOOST_CHECK_EQUAL("WARNING: check your network connection, 12 blocks received in the last 4 hours (96 expected)", strMiscWarning); + PartitionCheck(falseFunc, csDummy, &indexDummy[799]); + std::string expectedSlowErr = strprintf("WARNING: check your network connection, %d blocks received in the last 4 hours (%d expected)", expectedSlow, expectedTotal); + BOOST_CHECK_EQUAL(expectedSlowErr, strMiscWarning); BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); // Test 3: test the "partition alerts only go off once per day" @@ -427,24 +427,50 @@ BOOST_AUTO_TEST_CASE(PartitionAlert) now += 60*10; SetMockTime(now); strMiscWarning = ""; - PartitionCheck(falseFunc, csDummy, &indexDummy[399]); + PartitionCheck(falseFunc, csDummy, &indexDummy[799]); BOOST_CHECK_EQUAL("", strMiscWarning); // Test 4: get 2.5 times as many blocks as expected: - now += 60*60*24; // Pretend it is a day later + start = now + 60*60*24; // Pretend it is a day later + for (int i = 0; i < 800; i++) { + // Tweak chain timestamps: + indexDummy[i].nTime = i ? indexDummy[i - 1].nTime + params.PoWTargetSpacing(i) * 2/5 : start; + } + now = indexDummy[799].nTime + params.PoWTargetSpacing(0) * 2/5; SetMockTime(now); - int64_t quickSpacing = nPowTargetSpacing*2/5; - for (int i = 0; i < 400; i++) // Tweak chain timestamps: - indexDummy[i].nTime = now - (400-i)*quickSpacing; + strMiscWarning = ""; - PartitionCheck(falseFunc, csDummy, &indexDummy[399]); - BOOST_CHECK_EQUAL("WARNING: abnormally high number of blocks generated, 240 blocks received in the last 4 hours (96 expected)", strMiscWarning); + PartitionCheck(falseFunc, csDummy, &indexDummy[799]); + std::string expectedFastErr = strprintf("WARNING: abnormally high number of blocks generated, %d blocks received in the last 4 hours (%d expected)", expectedFast, expectedTotal); + BOOST_CHECK_EQUAL(expectedFastErr, strMiscWarning); BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); strMiscWarning = ""; SetMockTime(0); } +BOOST_AUTO_TEST_CASE(PartitionAlert) +{ + CChainParams& params = Params(CBaseChainParams::MAIN); + PartitionAlertTestImpl(params.GetConsensus(), 1000000000, 96, 12, 240); +} + +BOOST_AUTO_TEST_CASE(PartitionAlertBlossomOnly) +{ + PartitionAlertTestImpl(RegtestActivateBlossom(false), 1500000000, 96 * 2, 12 * 2, 240 * 2); + RegtestDeactivateBlossom(); +} + +BOOST_AUTO_TEST_CASE(PartitionAlertBlossomActivates) +{ + // 48 pre blossom blocks, 96 blossom blocks will take 48 * 150s + 96 * 75s = 4hrs + // in the slow case, all of the blocks will be blossom blocks + // in the fast case, 96 blocks will be blossom => 96 * 75s * 2/5 = 2880s spent on on blossom + // => (14400 - 2880) / (150 * 2/5) = 11520 / 60 = 192 pre blossom blocks + PartitionAlertTestImpl(RegtestActivateBlossom(false, 799 - 96), 2000000000, 144, 12 * 2, 192 + 96); + RegtestDeactivateBlossom(); +} + BOOST_AUTO_TEST_SUITE_END() #endif From ecfcb817ae7f4d9b91e6764e0eab3f671c817250 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 31 Jul 2019 14:34:48 -0600 Subject: [PATCH 193/395] Add test for Blossom default tx expiry delta --- src/gtest/test_checktransaction.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/gtest/test_checktransaction.cpp b/src/gtest/test_checktransaction.cpp index e4b3d33617c..7e6eb9a84a5 100644 --- a/src/gtest/test_checktransaction.cpp +++ b/src/gtest/test_checktransaction.cpp @@ -691,6 +691,14 @@ TEST(checktransaction_tests, OverwinterExpiryHeight) { } } +TEST(checktransaction_tests, BlossomExpiryHeight) { + const Consensus::Params& params = RegtestActivateBlossom(false, 100); + CMutableTransaction preBlossomMtx = CreateNewContextualCMutableTransaction(params, 99); + EXPECT_EQ(preBlossomMtx.nExpiryHeight, 99 + 20); + CMutableTransaction blossomMtx = CreateNewContextualCMutableTransaction(params, 100); + EXPECT_EQ(blossomMtx.nExpiryHeight, 100 + 40); + RegtestDeactivateBlossom(); +} // Test that a Sprout tx with a negative version number is detected // given the new Overwinter logic From 6c1df957ba476e8e996b888721354ccf23b8c45c Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 31 Jul 2019 15:16:25 -0600 Subject: [PATCH 194/395] Update metrics block height estimation for shorter block times --- src/gtest/test_metrics.cpp | 52 ++++++++++---------------------------- src/metrics.cpp | 47 +++++++++++++--------------------- src/metrics.h | 5 ++-- 3 files changed, 33 insertions(+), 71 deletions(-) diff --git a/src/gtest/test_metrics.cpp b/src/gtest/test_metrics.cpp index 143fe46d601..b818e4c132b 100644 --- a/src/gtest/test_metrics.cpp +++ b/src/gtest/test_metrics.cpp @@ -1,6 +1,7 @@ #include #include "metrics.h" +#include "utiltest.h" #include "utiltime.h" @@ -93,43 +94,16 @@ TEST(Metrics, GetLocalSolPS) { EXPECT_EQ(1, GetLocalSolPS()); } -TEST(Metrics, EstimateNetHeightInner) { - // Ensure that the (rounded) current height is returned if the tip is current - SetMockTime(15000); - EXPECT_EQ(100, EstimateNetHeightInner(100, 14100, 50, 7500, 0, 150)); - SetMockTime(15150); - EXPECT_EQ(100, EstimateNetHeightInner(101, 14250, 50, 7500, 0, 150)); - - // Ensure that correct estimates are returned if the tip is in the past - SetMockTime(15300); // Tip is 2 blocks behind - EXPECT_EQ(100, EstimateNetHeightInner(100, 14100, 50, 7500, 0, 150)); - SetMockTime(15900); // Tip is 6 blocks behind - EXPECT_EQ(110, EstimateNetHeightInner(100, 14100, 50, 7500, 0, 150)); - - // Check estimates during resync - SetMockTime(15000); - EXPECT_EQ(100, EstimateNetHeightInner( 0, 0, 50, 7500, 0, 150)); - EXPECT_EQ(100, EstimateNetHeightInner( 7, 600, 50, 7500, 0, 150)); - EXPECT_EQ(100, EstimateNetHeightInner( 8, 600, 50, 7500, 0, 150)); - EXPECT_EQ(100, EstimateNetHeightInner(10, 750, 50, 7500, 0, 150)); - EXPECT_EQ(100, EstimateNetHeightInner(11, 900, 50, 7500, 0, 150)); - EXPECT_EQ(100, EstimateNetHeightInner(20, 2100, 50, 7500, 0, 150)); - EXPECT_EQ(100, EstimateNetHeightInner(49, 6450, 50, 7500, 0, 150)); - EXPECT_EQ(100, EstimateNetHeightInner(50, 6600, 50, 7500, 0, 150)); - EXPECT_EQ(100, EstimateNetHeightInner(51, 6750, 50, 7500, 0, 150)); - EXPECT_EQ(100, EstimateNetHeightInner(55, 7350, 50, 7500, 0, 150)); - EXPECT_EQ(100, EstimateNetHeightInner(56, 7500, 50, 7500, 0, 150)); - EXPECT_EQ(100, EstimateNetHeightInner(57, 7650, 50, 7500, 0, 150)); - EXPECT_EQ(100, EstimateNetHeightInner(75, 10350, 50, 7500, 0, 150)); - - // More complex calculations: - SetMockTime(20000); - // - Checkpoint spacing: 200 - // -> Average spacing: 175 - // -> estimated height: 127 -> 130 - EXPECT_EQ(130, EstimateNetHeightInner(100, 14100, 50, 5250, 0, 150)); - // - Checkpoint spacing: 50 - // -> Average spacing: 100 - // -> estimated height: 153 -> 150 - EXPECT_EQ(150, EstimateNetHeightInner(100, 14100, 50, 12000, 0, 150)); +TEST(Metrics, EstimateNetHeight) { + auto params = RegtestActivateBlossom(false, 200); + int64_t blockTimes[400]; + for (int i = 0; i < 400; i++) { + blockTimes[i] = i ? blockTimes[i - 1] + params.PoWTargetSpacing(i) : 0; + } + SetMockTime(blockTimes[399]); + for (int i = 0; i < 400; i++) { + // Check that we are within 1 of the correct height + EXPECT_LT(std::abs(399 - EstimateNetHeight(params, i, blockTimes[i])), 2); + } + RegtestDeactivateBlossom(); } diff --git a/src/metrics.cpp b/src/metrics.cpp index 877167de947..40cc06260aa 100644 --- a/src/metrics.cpp +++ b/src/metrics.cpp @@ -7,6 +7,7 @@ #include "chainparams.h" #include "checkpoints.h" #include "main.h" +#include "timedata.h" #include "ui_interface.h" #include "util.h" #include "utiltime.h" @@ -108,34 +109,22 @@ double GetLocalSolPS() return miningTimer.rate(solutionTargetChecks); } -int EstimateNetHeightInner(int height, int64_t tipmediantime, - int heightLastCheckpoint, int64_t timeLastCheckpoint, - int64_t genesisTime, int64_t targetSpacing) +int EstimateNetHeight(const Consensus::Params& params, int currentBlockHeight, int64_t currentBlockTime) { - // We average the target spacing with the observed spacing to the last - // checkpoint (either from below or above depending on the current height), - // and use that to estimate the current network height. - int medianHeight = height > CBlockIndex::nMedianTimeSpan ? - height - (1 + ((CBlockIndex::nMedianTimeSpan - 1) / 2)) : - height / 2; - double checkpointSpacing = medianHeight > heightLastCheckpoint ? - (double (tipmediantime - timeLastCheckpoint)) / (medianHeight - heightLastCheckpoint) : - (double (timeLastCheckpoint - genesisTime)) / heightLastCheckpoint; - double averageSpacing = (targetSpacing + checkpointSpacing) / 2; - int netheight = medianHeight + ((GetTime() - tipmediantime) / averageSpacing); - // Round to nearest ten to reduce noise - return ((netheight + 5) / 10) * 10; -} + int64_t now = GetAdjustedTime(); -int EstimateNetHeight(int height, int64_t tipmediantime, CChainParams chainParams) -{ - auto checkpointData = chainParams.Checkpoints(); - return EstimateNetHeightInner( - height, tipmediantime, - Checkpoints::GetTotalBlocksEstimate(checkpointData), - checkpointData.nTimeLastCheckpoint, - chainParams.GenesisBlock().nTime, - chainParams.GetConsensus().PoWTargetSpacing(height)); + int estimatedHeight = currentBlockHeight + (now - currentBlockTime) / params.PoWTargetSpacing(currentBlockHeight); + + int blossomActivationHeight = params.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; + if (currentBlockHeight >= blossomActivationHeight || estimatedHeight <= blossomActivationHeight) { + return estimatedHeight; + } + + int numPreBlossomBlocks = blossomActivationHeight - currentBlockHeight; + int64_t preBlossomTime = numPreBlossomBlocks * params.PoWTargetSpacing(blossomActivationHeight - 1); + int64_t blossomActivationTime = currentBlockTime + preBlossomTime; + + return blossomActivationHeight + (now - blossomActivationTime) / params.PoWTargetSpacing(blossomActivationHeight); } void TriggerRefresh() @@ -204,20 +193,20 @@ int printStats(bool mining) int lines = 4; int height; - int64_t tipmediantime; + int64_t time; size_t connections; int64_t netsolps; { LOCK2(cs_main, cs_vNodes); height = chainActive.Height(); - tipmediantime = chainActive.Tip()->GetMedianTimePast(); + time = chainActive.Tip()->GetBlockTime(); connections = vNodes.size(); netsolps = GetNetworkHashPS(120, -1); } auto localsolps = GetLocalSolPS(); if (IsInitialBlockDownload(Params())) { - int netheight = EstimateNetHeight(height, tipmediantime, Params()); + int netheight = EstimateNetHeight(Params().GetConsensus(), height, time); int downloadPercent = height * 100 / netheight; std::cout << " " << _("Downloading blocks") << " | " << height << " / ~" << netheight << " (" << downloadPercent << "%)" << std::endl; } else { diff --git a/src/metrics.h b/src/metrics.h index 2d60d30ca6a..7a99102cb37 100644 --- a/src/metrics.h +++ b/src/metrics.h @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "uint256.h" +#include "consensus/params.h" #include #include @@ -63,9 +64,7 @@ void TrackMinedBlock(uint256 hash); void MarkStartTime(); double GetLocalSolPS(); -int EstimateNetHeightInner(int height, int64_t tipmediantime, - int heightLastCheckpoint, int64_t timeLastCheckpoint, - int64_t genesisTime, int64_t targetSpacing); +int EstimateNetHeight(const Consensus::Params& params, int currentBlockHeight, int64_t currentBlockTime); void TriggerRefresh(); From 8e48ca1fb231a79263ec81503457d84f6bd5f174 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 1 Aug 2019 10:21:27 +0100 Subject: [PATCH 195/395] test: Fix permissions on wallet_changeaddresses RPC test --- qa/rpc-tests/wallet_changeaddresses.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 qa/rpc-tests/wallet_changeaddresses.py diff --git a/qa/rpc-tests/wallet_changeaddresses.py b/qa/rpc-tests/wallet_changeaddresses.py old mode 100644 new mode 100755 From 907554be3a7e137de3a99aa0260733c99fc76ed8 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 1 Aug 2019 10:43:03 +0100 Subject: [PATCH 196/395] test: Fix pyflakes warnings --- qa/rpc-tests/wallet_changeaddresses.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/qa/rpc-tests/wallet_changeaddresses.py b/qa/rpc-tests/wallet_changeaddresses.py index f1c2aee7ed4..ceb8b0094a5 100755 --- a/qa/rpc-tests/wallet_changeaddresses.py +++ b/qa/rpc-tests/wallet_changeaddresses.py @@ -6,9 +6,7 @@ import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." from test_framework.test_framework import BitcoinTestFramework -from test_framework.authproxy import JSONRPCException from test_framework.util import ( - assert_equal, connect_nodes_bi, get_coinbase_address, initialize_chain_clean, @@ -45,14 +43,14 @@ def run_test(self): # Obtain some transparent funds midAddr = self.nodes[0].z_getnewaddress('sapling') myopid = self.nodes[0].z_shieldcoinbase(get_coinbase_address(self.nodes[0]), midAddr, 0)['opid'] - txid1 = wait_and_assert_operationid_status(self.nodes[0], myopid) + wait_and_assert_operationid_status(self.nodes[0], myopid) self.nodes[1].generate(1) self.sync_all() taddrSource = self.nodes[0].getnewaddress() for _ in range(6): recipients = [{"address": taddrSource, "amount": Decimal('2')}] myopid = self.nodes[0].z_sendmany(midAddr, recipients, 1, 0) - txid1 = wait_and_assert_operationid_status(self.nodes[0], myopid) + wait_and_assert_operationid_status(self.nodes[0], myopid) self.nodes[1].generate(1) self.sync_all() From 65df6225a693fe0c387c41ab3f6a846ac494eb3f Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 2 Aug 2019 16:01:20 -0600 Subject: [PATCH 197/395] Do not create transactions that will expire after the next epoch --- qa/rpc-tests/shorter_block_times.py | 32 +++++++++++++++++++++++++---- src/bitcoin-tx.cpp | 3 ++- src/main.cpp | 24 ++++++++++++---------- src/transaction_builder.cpp | 4 ++++ 4 files changed, 47 insertions(+), 16 deletions(-) diff --git a/qa/rpc-tests/shorter_block_times.py b/qa/rpc-tests/shorter_block_times.py index 74857740112..b34882e2621 100755 --- a/qa/rpc-tests/shorter_block_times.py +++ b/qa/rpc-tests/shorter_block_times.py @@ -5,11 +5,14 @@ import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." +from decimal import Decimal from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, + get_coinbase_address, initialize_chain_clean, start_nodes, + wait_and_assert_operationid_status, ) @@ -18,7 +21,7 @@ def setup_nodes(self): return start_nodes(4, self.options.tmpdir, [[ '-nuparams=5ba81b19:0', # Overwinter '-nuparams=76b809bb:0', # Sapling - '-nuparams=2bb40e60:101', # Blossom + '-nuparams=2bb40e60:103', # Blossom ]] * 4) def setup_chain(self): @@ -27,24 +30,45 @@ def setup_chain(self): def run_test(self): print "Mining blocks..." - self.nodes[0].generate(99) + self.nodes[0].generate(101) self.sync_all() # Sanity-check the block height - assert_equal(self.nodes[0].getblockcount(), 99) + assert_equal(self.nodes[0].getblockcount(), 101) + + # Make sure we can send a transaction on the last pre-Blossom block + node0_taddr = get_coinbase_address(self.nodes[0]) + node0_zaddr = self.nodes[0].z_getnewaddress('sapling') + recipients = [{'address': node0_zaddr, 'amount': Decimal('10')}] + myopid = self.nodes[0].z_sendmany(node0_taddr, recipients, 1, Decimal('0')) + txid = wait_and_assert_operationid_status(self.nodes[0], myopid) + assert_equal(105, self.nodes[0].getrawtransaction(txid, 1)['expiryheight']) # Blossom activation - 1 + 3 + self.sync_all() print "Mining last pre-Blossom block" # Activate blossom self.nodes[1].generate(1) self.sync_all() - assert_equal(10, self.nodes[1].getwalletinfo()['immature_balance']) + # Check that the last pre-Blossom transaction was mined + assert_equal(10, Decimal(self.nodes[0].z_gettotalbalance()['private'])) + # Check that we received a pre-Blossom mining reward + assert_equal(10, Decimal(self.nodes[1].getwalletinfo()['immature_balance'])) # After blossom activation the block reward will be halved print "Mining first Blossom block" self.nodes[1].generate(1) self.sync_all() + # Check that we received an additional Blossom mining reward assert_equal(15, self.nodes[1].getwalletinfo()['immature_balance']) + # Send and mine a transaction after activation + myopid = self.nodes[0].z_sendmany(node0_taddr, recipients, 1, Decimal('0')) + txid = wait_and_assert_operationid_status(self.nodes[0], myopid) + assert_equal(144, self.nodes[0].getrawtransaction(txid, 1)['expiryheight']) # height + 1 + 40 + self.nodes[1].generate(1) + self.sync_all() + assert_equal(20, Decimal(self.nodes[0].z_gettotalbalance()['private'])) + if __name__ == '__main__': ShorterBlockTimes().main() diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 3ee3c01697c..8b7c2ac3543 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -174,7 +174,8 @@ static void MutateTxVersion(CMutableTransaction& tx, const std::string& cmdVal) static void MutateTxExpiry(CMutableTransaction& tx, const std::string& cmdVal) { int64_t newExpiry = atoi64(cmdVal); - if (newExpiry >= TX_EXPIRY_HEIGHT_THRESHOLD) { + // Review: is newExpiry == 0 allowed? Is this coinbase only? + if (newExpiry <= 0 || newExpiry >= TX_EXPIRY_HEIGHT_THRESHOLD) { throw std::runtime_error("Invalid TX expiry requested"); } tx.nExpiryHeight = (int) newExpiry; diff --git a/src/main.cpp b/src/main.cpp index 1537a76b113..970dbe05277 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6658,9 +6658,17 @@ CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Para bool isOverwintered = consensusParams.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_OVERWINTER); if (isOverwintered) { mtx.fOverwintered = true; + if (consensusParams.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_SAPLING)) { + mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID; + mtx.nVersion = SAPLING_TX_VERSION; + } else { + mtx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID; + mtx.nVersion = OVERWINTER_TX_VERSION; + } + mtx.nExpiryHeight = nHeight + (expiryDeltaArg ? expiryDeltaArg.get() : consensusParams.DefaultExpiryDelta(nHeight)); - // Review: Should the following if() be checking the expiry delta rather than the transaction height? + // Review: is mtx.nExpiryHeight == 0 allowed? Is this coinbase only? if (mtx.nExpiryHeight <= 0 || mtx.nExpiryHeight >= TX_EXPIRY_HEIGHT_THRESHOLD) { throw new std::runtime_error("CreateNewContextualCMutableTransaction: invalid expiry height"); } @@ -6668,16 +6676,10 @@ CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Para // NOTE: If the expiry height crosses into an incompatible consensus epoch, and it is changed to the last block // of the current epoch (see below: Overwinter->Sapling), the transaction will be rejected if it falls within // the expiring soon threshold of 3 blocks (for DoS mitigation) based on the current height. - // TODO: Generalise this code so behaviour applies to all post-Overwinter epochs - if (consensusParams.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_SAPLING)) { - mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID; - mtx.nVersion = SAPLING_TX_VERSION; - } else { - mtx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID; - mtx.nVersion = OVERWINTER_TX_VERSION; - mtx.nExpiryHeight = std::min( - mtx.nExpiryHeight, - static_cast(consensusParams.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight - 1)); + auto nextActivationHeight = NextActivationHeight(nHeight, consensusParams); + if (nextActivationHeight) { + // We need to add TX_EXPIRING_SOON_THRESHOLD otherwise we cannot send transactions just prior to the next epoch + mtx.nExpiryHeight = std::min(mtx.nExpiryHeight, static_cast(nextActivationHeight.get()) - 1 + TX_EXPIRING_SOON_THRESHOLD); } } return mtx; diff --git a/src/transaction_builder.cpp b/src/transaction_builder.cpp index f81bcc4debb..b3e6cdb77f9 100644 --- a/src/transaction_builder.cpp +++ b/src/transaction_builder.cpp @@ -79,6 +79,10 @@ struct JSDescException : public std::exception void TransactionBuilder::SetExpiryHeight(uint32_t nExpiryHeight) { mtx.nExpiryHeight = nExpiryHeight; + // Review: is mtx.nExpiryHeight == 0 allowed? Is this coinbase only? + if (mtx.nExpiryHeight <= 0 || mtx.nExpiryHeight >= TX_EXPIRY_HEIGHT_THRESHOLD) { + throw new std::runtime_error("TransactionBuilder::SetExpiryHeight: invalid expiry height"); + } } void TransactionBuilder::AddSaplingSpend( From e6c0f743aa80e7e0dfa415bed451eb22b2df5716 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 2 Aug 2019 16:12:42 -0600 Subject: [PATCH 198/395] Do not send migration transactions that would expire after a network upgrade --- src/wallet/asyncrpcoperation_saplingmigration.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/wallet/asyncrpcoperation_saplingmigration.cpp b/src/wallet/asyncrpcoperation_saplingmigration.cpp index a8ac453ad51..3bb57fab8b4 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.cpp +++ b/src/wallet/asyncrpcoperation_saplingmigration.cpp @@ -69,6 +69,14 @@ void AsyncRPCOperation_saplingmigration::main() { bool AsyncRPCOperation_saplingmigration::main_impl() { LogPrint("zrpcunsafe", "%s: Beginning AsyncRPCOperation_saplingmigration.\n", getId()); + auto consensusParams = Params().GetConsensus(); + auto nextActivationHeight = NextActivationHeight(targetHeight_, consensusParams); + if (nextActivationHeight && targetHeight_ + MIGRATION_EXPIRY_DELTA >= nextActivationHeight.get()) { + LogPrint("zrpcunsafe", "%s: Migration txs would be created before a NU activation but may expire after. Skipping this round.\n", getId()); + setMigrationResult(0, 0, std::vector()); + return true; + } + std::vector sproutEntries; std::vector saplingEntries; { @@ -93,7 +101,6 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { HDSeed seed = pwalletMain->GetHDSeedForRPC(); libzcash::SaplingPaymentAddress migrationDestAddress = getMigrationDestAddress(seed); - auto consensusParams = Params().GetConsensus(); // Up to the limit of 5, as many transactions are sent as are needed to migrate the remaining funds int numTxCreated = 0; From 27ee4d64f270a24fcd3526562436ebcb2059da4f Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 2 Aug 2019 19:35:53 -0600 Subject: [PATCH 199/395] Fix integer truncation in Blossom halving calculation --- src/main.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 970dbe05277..fbdbf980ee8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1770,8 +1770,15 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) int halvings; if (blossomActive) { int blossomActivationHeight = consensusParams.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; - halvings = (blossomActivationHeight - consensusParams.SubsidySlowStartShift()) / consensusParams.nPreBlossomSubsidyHalvingInterval - + (nHeight - blossomActivationHeight) / consensusParams.nPostBlossomSubsidyHalvingInterval; + // // Ideally we would say: + // halvings = (blossomActivationHeight - consensusParams.SubsidySlowStartShift()) / consensusParams.nPreBlossomSubsidyHalvingInterval + // + (nHeight - blossomActivationHeight) / consensusParams.nPostBlossomSubsidyHalvingInterval; + // But, (blossomActivationHeight - consensusParams.SubsidySlowStartShift()) / consensusParams.nPreBlossomSubsidyHalvingInterval + // needs to be a treated rational number or this does not work. + // Define scaledHalvings := halvings * consensusParams.nPreBlossomSubsidyHalvingInterval; + int scaledHalvings = (blossomActivationHeight - consensusParams.SubsidySlowStartShift()) + + (nHeight - blossomActivationHeight) / Consensus::BLOSSOM_POW_TARGET_SPACING_RATIO; + halvings = scaledHalvings / consensusParams.nPreBlossomSubsidyHalvingInterval; } else { halvings = (nHeight - consensusParams.SubsidySlowStartShift()) / consensusParams.nPreBlossomSubsidyHalvingInterval; } From 797713284c52d6fb8c1a43a4c38f56255c3feaee Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 2 Aug 2019 19:37:02 -0600 Subject: [PATCH 200/395] Update main_tests for shorter block times --- src/test/main_tests.cpp | 83 ++++++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 30 deletions(-) diff --git a/src/test/main_tests.cpp b/src/test/main_tests.cpp index b731e89131e..8af388473c3 100644 --- a/src/test/main_tests.cpp +++ b/src/test/main_tests.cpp @@ -10,78 +10,101 @@ #include #include + BOOST_FIXTURE_TEST_SUITE(main_tests, TestingSetup) +const CAmount INITIAL_SUBSIDY = 12.5 * COIN; + +static int GetTotalHalvings(const Consensus::Params& consensusParams) { + return consensusParams.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight == Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT ? 64 : 65; +} + static void TestBlockSubsidyHalvings(const Consensus::Params& consensusParams) { - int maxHalvings = 64; - CAmount nInitialSubsidy = 12.5 * COIN; - - CAmount nPreviousSubsidy = nInitialSubsidy * 2; // for height == 0 - BOOST_CHECK_EQUAL(nPreviousSubsidy, nInitialSubsidy * 2); - for (int nHalvings = 0; nHalvings < maxHalvings; nHalvings++) { - int nHeight; - if (nHalvings > 0) // Check subsidy right at halvings + bool blossomActive = false; + int blossomActivationHeight = consensusParams.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; + int nHeight = consensusParams.nSubsidySlowStartInterval; + BOOST_CHECK_EQUAL(GetBlockSubsidy(nHeight, consensusParams), INITIAL_SUBSIDY); + CAmount nPreviousSubsidy = INITIAL_SUBSIDY; + for (int nHalvings = 1; nHalvings < GetTotalHalvings(consensusParams); nHalvings++) { + if (blossomActive) { + if (nHeight == blossomActivationHeight) { + int preBlossomHeight = (nHalvings - 1) * consensusParams.nPreBlossomSubsidyHalvingInterval + consensusParams.SubsidySlowStartShift(); + nHeight += (preBlossomHeight - blossomActivationHeight) * Consensus::BLOSSOM_POW_TARGET_SPACING_RATIO; + } else { + nHeight += consensusParams.nPostBlossomSubsidyHalvingInterval; + } + } else { nHeight = nHalvings * consensusParams.nPreBlossomSubsidyHalvingInterval + consensusParams.SubsidySlowStartShift(); - else // Check subsidy just after end of slow start - nHeight = consensusParams.nSubsidySlowStartInterval; + if (consensusParams.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_BLOSSOM)) { + nHeight = blossomActivationHeight; + blossomActive = true; + } + } + BOOST_CHECK_EQUAL(GetBlockSubsidy(nHeight - 1, consensusParams), nPreviousSubsidy); CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams); - BOOST_CHECK(nSubsidy <= nInitialSubsidy); + BOOST_CHECK(nSubsidy <= INITIAL_SUBSIDY); BOOST_CHECK_EQUAL(nSubsidy, nPreviousSubsidy / 2); nPreviousSubsidy = nSubsidy; } - BOOST_CHECK_EQUAL(GetBlockSubsidy((maxHalvings * consensusParams.nPreBlossomSubsidyHalvingInterval) + consensusParams.SubsidySlowStartShift(), consensusParams), 0); + BOOST_CHECK_EQUAL(GetBlockSubsidy(nHeight, consensusParams), 0); } -static void TestBlockSubsidyHalvings(int nSubsidySlowStartInterval, int nPreBlossomSubsidyHalvingInterval) +static void TestBlockSubsidyHalvings(int nSubsidySlowStartInterval, int nPreBlossomSubsidyHalvingInterval, int blossomActivationHeight) { Consensus::Params consensusParams; consensusParams.nSubsidySlowStartInterval = nSubsidySlowStartInterval; consensusParams.nPreBlossomSubsidyHalvingInterval = nPreBlossomSubsidyHalvingInterval; + consensusParams.nPostBlossomSubsidyHalvingInterval = nPreBlossomSubsidyHalvingInterval * 2; + consensusParams.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight = blossomActivationHeight; TestBlockSubsidyHalvings(consensusParams); } BOOST_AUTO_TEST_CASE(block_subsidy_test) { TestBlockSubsidyHalvings(Params(CBaseChainParams::MAIN).GetConsensus()); // As in main - TestBlockSubsidyHalvings(50, 150); // As in regtest - TestBlockSubsidyHalvings(500, 1000); // Just another interval + TestBlockSubsidyHalvings(20000, Consensus::PRE_BLOSSOM_HALVING_INTERVAL, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); // Pre-Blossom + TestBlockSubsidyHalvings(50, 150, 80); // As in regtest + TestBlockSubsidyHalvings(500, 1000, 900); // Just another interval + TestBlockSubsidyHalvings(500, 1000, 3000); // Multiple halvings before activation } BOOST_AUTO_TEST_CASE(subsidy_limit_test) { const Consensus::Params& consensusParams = Params(CBaseChainParams::MAIN).GetConsensus(); + CAmount nSum = 0; + int nHeight = 0; // Mining slow start - for (int nHeight = 0; nHeight < consensusParams.nSubsidySlowStartInterval; nHeight ++) { + for (; nHeight < consensusParams.nSubsidySlowStartInterval; nHeight++) { CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams); BOOST_CHECK(nSubsidy <= 12.5 * COIN); nSum += nSubsidy; BOOST_CHECK(MoneyRange(nSum)); } BOOST_CHECK_EQUAL(nSum, 12500000000000ULL); - // Remainder of first period - for (int nHeight = consensusParams.nSubsidySlowStartInterval; nHeight < consensusParams.nPreBlossomSubsidyHalvingInterval + consensusParams.SubsidySlowStartShift(); nHeight ++) { - CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams); - BOOST_CHECK(nSubsidy <= 12.5 * COIN); - nSum += nSubsidy; - BOOST_CHECK(MoneyRange(nSum)); - } - BOOST_CHECK_EQUAL(nSum, 1050000000000000ULL); + // Regular mining - for (int nHeight = consensusParams.nPreBlossomSubsidyHalvingInterval + consensusParams.SubsidySlowStartShift(); nHeight < 56000000; nHeight += 1000) { - CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams); - BOOST_CHECK(nSubsidy <= 12.5 * COIN); - nSum += nSubsidy * 1000; - BOOST_CHECK(MoneyRange(nSum)); - } + CAmount nSubsidy; + do { + nSubsidy = GetBlockSubsidy(nHeight, consensusParams); + nSum += nSubsidy; + BOOST_ASSERT(MoneyRange(nSum)); + ++nHeight; + } while (nSubsidy > 0); + // Changing the block interval from 10 to 2.5 minutes causes truncation // effects to occur earlier (from the 9th halving interval instead of the // 11th), decreasing the total monetary supply by 0.0693 ZEC. If the // transaction output field is widened, this discrepancy will become smaller // or disappear entirely. //BOOST_CHECK_EQUAL(nSum, 2099999997690000ULL); + // Reducing the interval further to 1.25 minutes has a similar effect, + // decreasing the total monetary supply by another 0.09240 ZEC. + // TODO Change this assert when setting the blossom activation height + // Note that these numbers may or may not change depending on the activation height BOOST_CHECK_EQUAL(nSum, 2099999990760000ULL); + // BOOST_CHECK_EQUAL(nSum, 2099999981520000LL); } bool ReturnFalse() { return false; } From 3eb90d4040f21259672961df777d6e6a9daa7a9d Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 2 Aug 2019 20:53:41 -0600 Subject: [PATCH 201/395] Use pre-Blossom max FR height when calculating address change interval --- src/chainparams.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 50af3616baf..82d60af3182 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -571,7 +571,7 @@ bool SelectParamsFromCommandLine() // Block height must be >0 and <=last founders reward block height // Index variable i ranges from 0 - (vFoundersRewardAddress.size()-1) std::string CChainParams::GetFoundersRewardAddressAtHeight(int nHeight) const { - int maxHeight = consensus.GetLastFoundersRewardBlockHeight(nHeight); + int preBlossomMaxHeight = consensus.GetLastFoundersRewardBlockHeight(0); // zip208 // FounderAddressAdjustedHeight(height) := // height, if not IsBlossomActivated(height) @@ -581,9 +581,8 @@ std::string CChainParams::GetFoundersRewardAddressAtHeight(int nHeight) const { int blossomActivationHeight = consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; nHeight = blossomActivationHeight + ((nHeight - blossomActivationHeight) / Consensus::BLOSSOM_POW_TARGET_SPACING_RATIO); } - assert(nHeight > 0 && nHeight <= maxHeight); - - size_t addressChangeInterval = (maxHeight + vFoundersRewardAddress.size()) / vFoundersRewardAddress.size(); + assert(nHeight > 0 && nHeight <= preBlossomMaxHeight); + size_t addressChangeInterval = (preBlossomMaxHeight + vFoundersRewardAddress.size()) / vFoundersRewardAddress.size(); size_t i = nHeight / addressChangeInterval; return vFoundersRewardAddress[i]; } From 93452c97bfad8c8c475b99850cce55f96d880f48 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 2 Aug 2019 20:54:52 -0600 Subject: [PATCH 202/395] Make founders reward tests pass before and after Blossom activation height is set --- src/gtest/test_foundersreward.cpp | 37 +++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/src/gtest/test_foundersreward.cpp b/src/gtest/test_foundersreward.cpp index 1f4f8241125..726129b66cb 100644 --- a/src/gtest/test_foundersreward.cpp +++ b/src/gtest/test_foundersreward.cpp @@ -84,14 +84,19 @@ TEST(founders_reward_test, create_testnet_2of3multisig) { #endif +static int GetLastFoundersRewardHeight(const Consensus::Params& params){ + int blossomActivationHeight = Params().GetConsensus().vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; + bool blossom = blossomActivationHeight != Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; + return params.GetLastFoundersRewardBlockHeight(blossom ? blossomActivationHeight : 0); +} + // Utility method to check the number of unique addresses from height 1 to maxHeight void checkNumberOfUniqueAddresses(int nUnique) { - int maxHeight = Params().GetConsensus().GetLastFoundersRewardBlockHeight(0); std::set addresses; - for (int i = 1; i <= maxHeight; i++) { + for (int i = 1; i <= GetLastFoundersRewardHeight(Params().GetConsensus()); i++) { addresses.insert(Params().GetFoundersRewardAddressAtHeight(i)); } - ASSERT_TRUE(addresses.size() == nUnique); + EXPECT_EQ(addresses.size(), nUnique); } @@ -157,11 +162,14 @@ TEST(founders_reward_test, regtest) { // Test that 10% founders reward is fully rewarded after the first halving and slow start shift. // On Mainnet, this would be 2,100,000 ZEC after 850,000 blocks (840,000 + 10,000). -TEST(founders_reward_test, slow_start_subsidy) { // TODO: Update this test when the Blossom activation height is set +TEST(founders_reward_test, slow_start_subsidy) { SelectParams(CBaseChainParams::MAIN); CChainParams params = Params(); - int maxHeight = params.GetConsensus().GetLastFoundersRewardBlockHeight(0); + int blossomActivationHeight = Params().GetConsensus().vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; + bool blossom = blossomActivationHeight != Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; + int maxHeight = Params().GetConsensus().GetLastFoundersRewardBlockHeight(blossom ? blossomActivationHeight : 0); + CAmount totalSubsidy = 0; for (int nHeight = 1; nHeight <= maxHeight; nHeight++) { CAmount nSubsidy = GetBlockSubsidy(nHeight, params.GetConsensus()) / 5; @@ -176,17 +184,22 @@ TEST(founders_reward_test, slow_start_subsidy) { // TODO: Update this test when // Verify the number of rewards each individual address receives. void verifyNumberOfRewards() { CChainParams params = Params(); - int maxHeight = params.GetConsensus().GetLastFoundersRewardBlockHeight(0); - std::multiset ms; + int maxHeight = GetLastFoundersRewardHeight(params.GetConsensus()); + std::map ms; for (int nHeight = 1; nHeight <= maxHeight; nHeight++) { - ms.insert(params.GetFoundersRewardAddressAtHeight(nHeight)); + std::string addr = params.GetFoundersRewardAddressAtHeight(nHeight); + if (ms.count(addr) == 0) { + ms[addr] = 0; + } + ms[addr] = ms[addr] + GetBlockSubsidy(nHeight, params.GetConsensus()) / 5; } - ASSERT_TRUE(ms.count(params.GetFoundersRewardAddressAtIndex(0)) == 17708); - for (int i = 1; i <= 46; i++) { - ASSERT_TRUE(ms.count(params.GetFoundersRewardAddressAtIndex(i)) == 17709); + EXPECT_EQ(ms[params.GetFoundersRewardAddressAtIndex(0)], 1960039937500); + EXPECT_EQ(ms[params.GetFoundersRewardAddressAtIndex(1)], 4394460062500); + for (int i = 2; i <= 46; i++) { + EXPECT_EQ(ms[params.GetFoundersRewardAddressAtIndex(i)], 17709 * COIN * 2.5); } - ASSERT_TRUE(ms.count(params.GetFoundersRewardAddressAtIndex(47)) == 17677); + EXPECT_EQ(ms[params.GetFoundersRewardAddressAtIndex(47)], 17677 * COIN * 2.5); } // Verify the number of rewards going to each mainnet address From f9d6b3e7ef58e238506ea572b34f75b4ef34ba92 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 2 Aug 2019 21:37:48 -0600 Subject: [PATCH 203/395] Extract Halvings method and add tests --- src/consensus/params.cpp | 21 +++++++++++++++++++++ src/consensus/params.h | 2 ++ src/gtest/test_foundersreward.cpp | 20 +++++++++++++------- src/main.cpp | 23 ++--------------------- 4 files changed, 38 insertions(+), 28 deletions(-) diff --git a/src/consensus/params.cpp b/src/consensus/params.cpp index 35cc6c9d24e..08bd3f72236 100644 --- a/src/consensus/params.cpp +++ b/src/consensus/params.cpp @@ -8,6 +8,27 @@ namespace Consensus { return NetworkUpgradeState(nHeight, *this, idx) == UPGRADE_ACTIVE; } + int Params::Halvings(int nHeight) const { + // zip208 + // Halving(height) := + // floor((height - SlowStartShift) / PreBlossomHalvingInterval), if not IsBlossomActivated(height) + // floor((BlossomActivationHeight - SlowStartShift) / PreBlossomHalvingInterval + (height - BlossomActivationHeight) / PostBlossomHalvingInterval), otherwise + if (NetworkUpgradeActive(nHeight, Consensus::UPGRADE_BLOSSOM)) { + int blossomActivationHeight = vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; + // // Ideally we would say: + // halvings = (blossomActivationHeight - consensusParams.SubsidySlowStartShift()) / consensusParams.nPreBlossomSubsidyHalvingInterval + // + (nHeight - blossomActivationHeight) / consensusParams.nPostBlossomSubsidyHalvingInterval; + // But, (blossomActivationHeight - consensusParams.SubsidySlowStartShift()) / consensusParams.nPreBlossomSubsidyHalvingInterval + // needs to be a treated rational number or this does not work. + // Define scaledHalvings := halvings * consensusParams.nPreBlossomSubsidyHalvingInterval; + int scaledHalvings = (blossomActivationHeight - SubsidySlowStartShift()) + + (nHeight - blossomActivationHeight) / Consensus::BLOSSOM_POW_TARGET_SPACING_RATIO; + return scaledHalvings / nPreBlossomSubsidyHalvingInterval; + } else { + return (nHeight - SubsidySlowStartShift()) / nPreBlossomSubsidyHalvingInterval; + } + } + int Params::GetLastFoundersRewardBlockHeight(int nHeight) const { // zip208 // FoundersRewardLastBlockHeight := max({ height ⦂ N | Halving(height) < 1 }) diff --git a/src/consensus/params.h b/src/consensus/params.h index 979d294bff6..8644b087f26 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -103,6 +103,8 @@ struct Params { int nPreBlossomSubsidyHalvingInterval; int nPostBlossomSubsidyHalvingInterval; + int Halvings(int nHeight) const; + int GetLastFoundersRewardBlockHeight(int nHeight) const; unsigned int DefaultExpiryDelta(int nHeight) const; diff --git a/src/gtest/test_foundersreward.cpp b/src/gtest/test_foundersreward.cpp index 726129b66cb..3b745647995 100644 --- a/src/gtest/test_foundersreward.cpp +++ b/src/gtest/test_foundersreward.cpp @@ -125,14 +125,20 @@ TEST(founders_reward_test, general) { EXPECT_DEATH(params.GetFoundersRewardAddressAtHeight(maxHeight+1), "nHeight"); } -TEST(founders_reward_test, get_last_block_blossom) { - int blossomActivationHeight = /*slowStartShift*/ + Consensus::PRE_BLOSSOM_REGTEST_HALVING_INTERVAL / 2; // = 75 +TEST(founders_reward_test, regtest_get_last_block_blossom) { + int blossomActivationHeight = Consensus::PRE_BLOSSOM_REGTEST_HALVING_INTERVAL / 2; // = 75 auto params = RegtestActivateBlossom(false, blossomActivationHeight); - int slowStartShift = params.SubsidySlowStartShift(); // 0 for regtest - EXPECT_EQ(Consensus::PRE_BLOSSOM_REGTEST_HALVING_INTERVAL + slowStartShift - 1, params.GetLastFoundersRewardBlockHeight(0)); - EXPECT_EQ(Consensus::PRE_BLOSSOM_REGTEST_HALVING_INTERVAL + slowStartShift - 1, params.GetLastFoundersRewardBlockHeight(blossomActivationHeight - 1)); - int blossomBlocks = (Consensus::PRE_BLOSSOM_REGTEST_HALVING_INTERVAL- blossomActivationHeight) * Consensus::BLOSSOM_POW_TARGET_SPACING_RATIO; - EXPECT_EQ(blossomActivationHeight + blossomBlocks + slowStartShift - 1, params.GetLastFoundersRewardBlockHeight(blossomActivationHeight)); + int lastFRHeight = params.GetLastFoundersRewardBlockHeight(blossomActivationHeight); + EXPECT_EQ(0, params.Halvings(lastFRHeight)); + EXPECT_EQ(1, params.Halvings(lastFRHeight + 1)); +} + +TEST(founders_reward_test, mainnet_get_last_block) { + SelectParams(CBaseChainParams::MAIN); + auto params = Params().GetConsensus(); + int lastFRHeight = GetLastFoundersRewardHeight(params); + EXPECT_EQ(0, params.Halvings(lastFRHeight)); + EXPECT_EQ(1, params.Halvings(lastFRHeight + 1)); } #define NUM_MAINNET_FOUNDER_ADDRESSES 48 diff --git a/src/main.cpp b/src/main.cpp index fbdbf980ee8..01478ce976c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1762,26 +1762,7 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) assert(nHeight > consensusParams.SubsidySlowStartShift()); - // zip208 - // Halving(height) := - // floor((height - SlowStartShift) / PreBlossomHalvingInterval), if not IsBlossomActivated(height) - // floor((BlossomActivationHeight - SlowStartShift) / PreBlossomHalvingInterval + (height - BlossomActivationHeight) / PostBlossomHalvingInterval), otherwise - bool blossomActive = consensusParams.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_BLOSSOM); - int halvings; - if (blossomActive) { - int blossomActivationHeight = consensusParams.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; - // // Ideally we would say: - // halvings = (blossomActivationHeight - consensusParams.SubsidySlowStartShift()) / consensusParams.nPreBlossomSubsidyHalvingInterval - // + (nHeight - blossomActivationHeight) / consensusParams.nPostBlossomSubsidyHalvingInterval; - // But, (blossomActivationHeight - consensusParams.SubsidySlowStartShift()) / consensusParams.nPreBlossomSubsidyHalvingInterval - // needs to be a treated rational number or this does not work. - // Define scaledHalvings := halvings * consensusParams.nPreBlossomSubsidyHalvingInterval; - int scaledHalvings = (blossomActivationHeight - consensusParams.SubsidySlowStartShift()) - + (nHeight - blossomActivationHeight) / Consensus::BLOSSOM_POW_TARGET_SPACING_RATIO; - halvings = scaledHalvings / consensusParams.nPreBlossomSubsidyHalvingInterval; - } else { - halvings = (nHeight - consensusParams.SubsidySlowStartShift()) / consensusParams.nPreBlossomSubsidyHalvingInterval; - } + int halvings = consensusParams.Halvings(nHeight); // Force block reward to zero when right shift is undefined. if (halvings >= 64) @@ -1793,7 +1774,7 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) // SlowStartRate · (height + 1), if SlowStartInterval / 2 ≤ height and height < SlowStartInterval // floor(MaxBlockSubsidy / 2^Halving(height)), if SlowStartInterval ≤ height and not IsBlossomActivated(height) // floor(MaxBlockSubsidy / (BlossomPoWTargetSpacingRatio · 2^Halving(height))), otherwise - if (blossomActive) { + if (consensusParams.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_BLOSSOM)) { return (nSubsidy / Consensus::BLOSSOM_POW_TARGET_SPACING_RATIO) >> halvings; } else { // Subsidy is cut in half every 840,000 blocks which will occur approximately every 4 years. From 297252132345525bc668ecd2e63022ade49ea917 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 2 Aug 2019 21:43:17 -0600 Subject: [PATCH 204/395] Add comments and fix typos --- src/consensus/params.cpp | 6 +++++- src/gtest/test_pow.cpp | 6 +++--- src/test/alert_tests.cpp | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/consensus/params.cpp b/src/consensus/params.cpp index 08bd3f72236..553e5451db3 100644 --- a/src/consensus/params.cpp +++ b/src/consensus/params.cpp @@ -29,9 +29,12 @@ namespace Consensus { } } - int Params::GetLastFoundersRewardBlockHeight(int nHeight) const { + int Params::GetLastFoundersRewardBlockHeight(int nHeight) const { // zip208 // FoundersRewardLastBlockHeight := max({ height ⦂ N | Halving(height) < 1 }) + // Halving(h) is defined as floor(f(h)) where f is a strictly increasing rational + // function, so it's sufficient to solve for f(height) = 1 in the rationals and + // then take ceiling(height - 1). // H := blossom activation height; SS := SubsidySlowStartShift(); R := BLOSSOM_POW_TARGET_SPACING_RATIO // preBlossom: // 1 = (height - SS) / preInterval @@ -43,6 +46,7 @@ namespace Consensus { bool blossomActive = NetworkUpgradeActive(nHeight, Consensus::UPGRADE_BLOSSOM); if (blossomActive) { int blossomActivationHeight = vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; + // The following calculation depends on BLOSSOM_POW_TARGET_SPACING_RATIO being an integer. return blossomActivationHeight + nPostBlossomSubsidyHalvingInterval + (SubsidySlowStartShift() - blossomActivationHeight) * BLOSSOM_POW_TARGET_SPACING_RATIO - 1; } else { diff --git a/src/gtest/test_pow.cpp b/src/gtest/test_pow.cpp index 4e0e8fcdc5c..709296f7802 100644 --- a/src/gtest/test_pow.cpp +++ b/src/gtest/test_pow.cpp @@ -6,7 +6,7 @@ #include "random.h" #include "utiltest.h" -void TestDifficultyAveragigingImpl(const Consensus::Params& params) +void TestDifficultyAveragingImpl(const Consensus::Params& params) { size_t lastBlk = 2*params.nPowAveragingWindow; size_t firstBlk = lastBlk - params.nPowAveragingWindow; @@ -75,11 +75,11 @@ void TestDifficultyAveragigingImpl(const Consensus::Params& params) TEST(PoW, DifficultyAveraging) { SelectParams(CBaseChainParams::MAIN); - TestDifficultyAveragigingImpl(Params().GetConsensus()); + TestDifficultyAveragingImpl(Params().GetConsensus()); } TEST(PoW, DifficultyAveragingBlossom) { - TestDifficultyAveragigingImpl(RegtestActivateBlossom(true)); + TestDifficultyAveragingImpl(RegtestActivateBlossom(true)); RegtestDeactivateBlossom(); } diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index 83e966cda94..c8ecbd58dde 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -465,7 +465,7 @@ BOOST_AUTO_TEST_CASE(PartitionAlertBlossomActivates) { // 48 pre blossom blocks, 96 blossom blocks will take 48 * 150s + 96 * 75s = 4hrs // in the slow case, all of the blocks will be blossom blocks - // in the fast case, 96 blocks will be blossom => 96 * 75s * 2/5 = 2880s spent on on blossom + // in the fast case, 96 blocks will be blossom => 96 * 75s * 2/5 = 2880s spent on blossom // => (14400 - 2880) / (150 * 2/5) = 11520 / 60 = 192 pre blossom blocks PartitionAlertTestImpl(RegtestActivateBlossom(false, 799 - 96), 2000000000, 144, 12 * 2, 192 + 96); RegtestDeactivateBlossom(); From bde2e4807c8b577e99c480e66047b208aa613f9c Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 2 Aug 2019 22:51:21 -0600 Subject: [PATCH 205/395] Improve EstimateNetHeight calculation --- src/metrics.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/metrics.cpp b/src/metrics.cpp index 40cc06260aa..e6390572662 100644 --- a/src/metrics.cpp +++ b/src/metrics.cpp @@ -112,6 +112,9 @@ double GetLocalSolPS() int EstimateNetHeight(const Consensus::Params& params, int currentBlockHeight, int64_t currentBlockTime) { int64_t now = GetAdjustedTime(); + if (currentBlockTime >= now) { + return currentBlockHeight; + } int estimatedHeight = currentBlockHeight + (now - currentBlockTime) / params.PoWTargetSpacing(currentBlockHeight); @@ -123,6 +126,9 @@ int EstimateNetHeight(const Consensus::Params& params, int currentBlockHeight, i int numPreBlossomBlocks = blossomActivationHeight - currentBlockHeight; int64_t preBlossomTime = numPreBlossomBlocks * params.PoWTargetSpacing(blossomActivationHeight - 1); int64_t blossomActivationTime = currentBlockTime + preBlossomTime; + if (blossomActivationTime >= now) { + return blossomActivationHeight; + } return blossomActivationHeight + (now - blossomActivationTime) / params.PoWTargetSpacing(blossomActivationHeight); } @@ -193,20 +199,20 @@ int printStats(bool mining) int lines = 4; int height; - int64_t time; + int64_t blockTime; size_t connections; int64_t netsolps; { LOCK2(cs_main, cs_vNodes); - height = chainActive.Height(); - time = chainActive.Tip()->GetBlockTime(); + height = pindexBestHeader->nHeight; + blockTime = pindexBestHeader->nTime; connections = vNodes.size(); netsolps = GetNetworkHashPS(120, -1); } auto localsolps = GetLocalSolPS(); if (IsInitialBlockDownload(Params())) { - int netheight = EstimateNetHeight(Params().GetConsensus(), height, time); + int netheight = EstimateNetHeight(Params().GetConsensus(), height, blockTime); int downloadPercent = height * 100 / netheight; std::cout << " " << _("Downloading blocks") << " | " << height << " / ~" << netheight << " (" << downloadPercent << "%)" << std::endl; } else { From 8068491d2c5e813ecaaf50f4eefd6501795fad2d Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Sun, 4 Aug 2019 14:35:47 -0600 Subject: [PATCH 206/395] Fix check transaction tests --- src/gtest/test_checktransaction.cpp | 113 ++++++++++------------------ src/main.cpp | 2 + 2 files changed, 42 insertions(+), 73 deletions(-) diff --git a/src/gtest/test_checktransaction.cpp b/src/gtest/test_checktransaction.cpp index 7e6eb9a84a5..3f4b7b0a8ff 100644 --- a/src/gtest/test_checktransaction.cpp +++ b/src/gtest/test_checktransaction.cpp @@ -694,7 +694,7 @@ TEST(checktransaction_tests, OverwinterExpiryHeight) { TEST(checktransaction_tests, BlossomExpiryHeight) { const Consensus::Params& params = RegtestActivateBlossom(false, 100); CMutableTransaction preBlossomMtx = CreateNewContextualCMutableTransaction(params, 99); - EXPECT_EQ(preBlossomMtx.nExpiryHeight, 99 + 20); + EXPECT_EQ(preBlossomMtx.nExpiryHeight, 100 - 1 + TX_EXPIRING_SOON_THRESHOLD); CMutableTransaction blossomMtx = CreateNewContextualCMutableTransaction(params, 100); EXPECT_EQ(blossomMtx.nExpiryHeight, 100 + 40); RegtestDeactivateBlossom(); @@ -891,89 +891,56 @@ TEST(checktransaction_tests, OverwinterInvalidSoftForkVersion) { } } +static void ContextualCreateTxCheck(const Consensus::Params& params, int nHeight, + int expectedVersion, bool expectedOverwintered, int expectedVersionGroupId, int expectedExpiryHeight) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(params, nHeight); + EXPECT_EQ(mtx.nVersion, expectedVersion); + EXPECT_EQ(mtx.fOverwintered, expectedOverwintered); + EXPECT_EQ(mtx.nVersionGroupId, expectedVersionGroupId); + EXPECT_EQ(mtx.nExpiryHeight, expectedExpiryHeight); +} + // Test CreateNewContextualCMutableTransaction sets default values based on height TEST(checktransaction_tests, OverwinteredContextualCreateTx) { SelectParams(CBaseChainParams::REGTEST); - const Consensus::Params& consensusParams = Params().GetConsensus(); - int activationHeight = 5; + const Consensus::Params& params = Params().GetConsensus(); + int overwinterActivationHeight = 5; int saplingActivationHeight = 30; - UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, activationHeight); + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, overwinterActivationHeight); UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, saplingActivationHeight); - { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction( - consensusParams, activationHeight - 1); - - EXPECT_EQ(mtx.nVersion, 1); - EXPECT_EQ(mtx.fOverwintered, false); - EXPECT_EQ(mtx.nVersionGroupId, 0); - EXPECT_EQ(mtx.nExpiryHeight, 0); - } - + ContextualCreateTxCheck(params, overwinterActivationHeight - 1, + 1, false, 0, 0); // Overwinter activates - { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction( - consensusParams, activationHeight); - - EXPECT_EQ(mtx.nVersion, 3); - EXPECT_EQ(mtx.fOverwintered, true); - EXPECT_EQ(mtx.nVersionGroupId, OVERWINTER_VERSION_GROUP_ID); - EXPECT_EQ(mtx.nExpiryHeight, activationHeight + DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA); - } - + ContextualCreateTxCheck(params, overwinterActivationHeight, + 3, true, OVERWINTER_VERSION_GROUP_ID, overwinterActivationHeight + DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA); // Close to Sapling activation - { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction( - consensusParams, saplingActivationHeight - DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA - 2); - - EXPECT_EQ(mtx.fOverwintered, true); - EXPECT_EQ(mtx.nVersionGroupId, OVERWINTER_VERSION_GROUP_ID); - EXPECT_EQ(mtx.nVersion, OVERWINTER_TX_VERSION); - EXPECT_EQ(mtx.nExpiryHeight, saplingActivationHeight - 2); - } - - { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction( - consensusParams, saplingActivationHeight - DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA - 1); - - EXPECT_EQ(mtx.fOverwintered, true); - EXPECT_EQ(mtx.nVersionGroupId, OVERWINTER_VERSION_GROUP_ID); - EXPECT_EQ(mtx.nVersion, OVERWINTER_TX_VERSION); - EXPECT_EQ(mtx.nExpiryHeight, saplingActivationHeight - 1); - } - - { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction( - consensusParams, saplingActivationHeight - DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA); - - EXPECT_EQ(mtx.fOverwintered, true); - EXPECT_EQ(mtx.nVersionGroupId, OVERWINTER_VERSION_GROUP_ID); - EXPECT_EQ(mtx.nVersion, OVERWINTER_TX_VERSION); - EXPECT_EQ(mtx.nExpiryHeight, saplingActivationHeight - 1); - } - + ContextualCreateTxCheck(params, saplingActivationHeight - DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA - 2, + 3, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 2); + ContextualCreateTxCheck(params, saplingActivationHeight - DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA - 1, + 3, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); + ContextualCreateTxCheck(params, saplingActivationHeight - DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA, + 3, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight); + ContextualCreateTxCheck(params, saplingActivationHeight - DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA + 1, + 3, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight + 1); + ContextualCreateTxCheck(params, saplingActivationHeight - DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA + 2, + 3, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight + 2); + ContextualCreateTxCheck(params, saplingActivationHeight - DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA + 3, + 3, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1 + TX_EXPIRING_SOON_THRESHOLD); // Just before Sapling activation - { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction( - consensusParams, saplingActivationHeight - 1); - - EXPECT_EQ(mtx.fOverwintered, true); - EXPECT_EQ(mtx.nVersionGroupId, OVERWINTER_VERSION_GROUP_ID); - EXPECT_EQ(mtx.nVersion, OVERWINTER_TX_VERSION); - EXPECT_EQ(mtx.nExpiryHeight, saplingActivationHeight - 1); - } - + ContextualCreateTxCheck(params, saplingActivationHeight - 4, + 3, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1 + TX_EXPIRING_SOON_THRESHOLD); + ContextualCreateTxCheck(params, saplingActivationHeight - 3, + 3, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1 + TX_EXPIRING_SOON_THRESHOLD); + ContextualCreateTxCheck(params, saplingActivationHeight - 2, + 3, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1 + TX_EXPIRING_SOON_THRESHOLD); + ContextualCreateTxCheck(params, saplingActivationHeight - 1, + 3, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1 + TX_EXPIRING_SOON_THRESHOLD); // Sapling activates - { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction( - consensusParams, saplingActivationHeight); - - EXPECT_EQ(mtx.fOverwintered, true); - EXPECT_EQ(mtx.nVersionGroupId, SAPLING_VERSION_GROUP_ID); - EXPECT_EQ(mtx.nVersion, SAPLING_TX_VERSION); - EXPECT_EQ(mtx.nExpiryHeight, saplingActivationHeight + DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA); - } + ContextualCreateTxCheck(params, saplingActivationHeight, + SAPLING_TX_VERSION, true, SAPLING_VERSION_GROUP_ID, saplingActivationHeight + DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA); // Revert to default RegtestDeactivateSapling(); diff --git a/src/main.cpp b/src/main.cpp index 01478ce976c..1e6ce458ac5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6667,6 +6667,8 @@ CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Para auto nextActivationHeight = NextActivationHeight(nHeight, consensusParams); if (nextActivationHeight) { // We need to add TX_EXPIRING_SOON_THRESHOLD otherwise we cannot send transactions just prior to the next epoch + // The idea is that the transaction will not be rejected as expiring soon until the same block that it is + // The rejected for being created during the last epoch. mtx.nExpiryHeight = std::min(mtx.nExpiryHeight, static_cast(nextActivationHeight.get()) - 1 + TX_EXPIRING_SOON_THRESHOLD); } } From 2c35e162a60bca6f44360f776e5a3f9158808c37 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Sun, 4 Aug 2019 17:03:48 -0600 Subject: [PATCH 207/395] Make sure to deactivate blossom in test case --- src/gtest/test_foundersreward.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gtest/test_foundersreward.cpp b/src/gtest/test_foundersreward.cpp index 3b745647995..d4b45a15716 100644 --- a/src/gtest/test_foundersreward.cpp +++ b/src/gtest/test_foundersreward.cpp @@ -131,6 +131,7 @@ TEST(founders_reward_test, regtest_get_last_block_blossom) { int lastFRHeight = params.GetLastFoundersRewardBlockHeight(blossomActivationHeight); EXPECT_EQ(0, params.Halvings(lastFRHeight)); EXPECT_EQ(1, params.Halvings(lastFRHeight + 1)); + RegtestDeactivateBlossom(); } TEST(founders_reward_test, mainnet_get_last_block) { From 82c291b6df2e3d9999c1c6b88db7d3df84bca5e4 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Sun, 4 Aug 2019 17:11:31 -0600 Subject: [PATCH 208/395] Fix parsing txexpirydelta argument --- src/init.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index a1f5c30e30d..c9ebe0617fd 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1066,7 +1066,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } nTxConfirmTarget = GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET); if (mapArgs.count("-txexpirydelta")) { - int64_t expiryDelta = atoi64(mapArgs["txexpirydelta"]); + int64_t expiryDelta = atoi64(mapArgs["-txexpirydelta"]); uint32_t minExpiryDelta = TX_EXPIRING_SOON_THRESHOLD + 1; if (expiryDelta < minExpiryDelta) { return InitError(strprintf(_("Invalid value for -txexpirydelta='%u' (must be least %u)"), expiryDelta, minExpiryDelta)); From 9f70b7469241aaa88f10e36c232bf5780cd39cb2 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 5 Aug 2019 11:50:05 -0600 Subject: [PATCH 209/395] Do not add expiring soon threshold to expiry height of txs near NU activation --- src/gtest/test_checktransaction.cpp | 24 ++++++++++++------------ src/main.cpp | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/gtest/test_checktransaction.cpp b/src/gtest/test_checktransaction.cpp index 3f4b7b0a8ff..762686ef589 100644 --- a/src/gtest/test_checktransaction.cpp +++ b/src/gtest/test_checktransaction.cpp @@ -694,7 +694,7 @@ TEST(checktransaction_tests, OverwinterExpiryHeight) { TEST(checktransaction_tests, BlossomExpiryHeight) { const Consensus::Params& params = RegtestActivateBlossom(false, 100); CMutableTransaction preBlossomMtx = CreateNewContextualCMutableTransaction(params, 99); - EXPECT_EQ(preBlossomMtx.nExpiryHeight, 100 - 1 + TX_EXPIRING_SOON_THRESHOLD); + EXPECT_EQ(preBlossomMtx.nExpiryHeight, 100 - 1); CMutableTransaction blossomMtx = CreateNewContextualCMutableTransaction(params, 100); EXPECT_EQ(blossomMtx.nExpiryHeight, 100 + 40); RegtestDeactivateBlossom(); @@ -915,29 +915,29 @@ TEST(checktransaction_tests, OverwinteredContextualCreateTx) { 1, false, 0, 0); // Overwinter activates ContextualCreateTxCheck(params, overwinterActivationHeight, - 3, true, OVERWINTER_VERSION_GROUP_ID, overwinterActivationHeight + DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA); + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, overwinterActivationHeight + DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA); // Close to Sapling activation ContextualCreateTxCheck(params, saplingActivationHeight - DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA - 2, - 3, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 2); + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 2); ContextualCreateTxCheck(params, saplingActivationHeight - DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA - 1, - 3, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); ContextualCreateTxCheck(params, saplingActivationHeight - DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA, - 3, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight); + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); ContextualCreateTxCheck(params, saplingActivationHeight - DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA + 1, - 3, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight + 1); + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); ContextualCreateTxCheck(params, saplingActivationHeight - DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA + 2, - 3, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight + 2); + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); ContextualCreateTxCheck(params, saplingActivationHeight - DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA + 3, - 3, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1 + TX_EXPIRING_SOON_THRESHOLD); + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); // Just before Sapling activation ContextualCreateTxCheck(params, saplingActivationHeight - 4, - 3, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1 + TX_EXPIRING_SOON_THRESHOLD); + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); ContextualCreateTxCheck(params, saplingActivationHeight - 3, - 3, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1 + TX_EXPIRING_SOON_THRESHOLD); + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); ContextualCreateTxCheck(params, saplingActivationHeight - 2, - 3, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1 + TX_EXPIRING_SOON_THRESHOLD); + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); ContextualCreateTxCheck(params, saplingActivationHeight - 1, - 3, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1 + TX_EXPIRING_SOON_THRESHOLD); + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); // Sapling activates ContextualCreateTxCheck(params, saplingActivationHeight, SAPLING_TX_VERSION, true, SAPLING_VERSION_GROUP_ID, saplingActivationHeight + DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA); diff --git a/src/main.cpp b/src/main.cpp index 1e6ce458ac5..3819afd3beb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6669,7 +6669,7 @@ CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Para // We need to add TX_EXPIRING_SOON_THRESHOLD otherwise we cannot send transactions just prior to the next epoch // The idea is that the transaction will not be rejected as expiring soon until the same block that it is // The rejected for being created during the last epoch. - mtx.nExpiryHeight = std::min(mtx.nExpiryHeight, static_cast(nextActivationHeight.get()) - 1 + TX_EXPIRING_SOON_THRESHOLD); + mtx.nExpiryHeight = std::min(mtx.nExpiryHeight, static_cast(nextActivationHeight.get()) - 1); } } return mtx; From 7ddcf427c00d92c051cf41a940bac525f5bf0cac Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 5 Aug 2019 12:41:31 -0600 Subject: [PATCH 210/395] Fix/update comments --- src/consensus/params.cpp | 4 ++-- src/main.cpp | 7 ++----- src/test/alert_tests.cpp | 4 ++-- src/test/main_tests.cpp | 2 +- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/consensus/params.cpp b/src/consensus/params.cpp index 553e5451db3..c0e332892c9 100644 --- a/src/consensus/params.cpp +++ b/src/consensus/params.cpp @@ -15,11 +15,11 @@ namespace Consensus { // floor((BlossomActivationHeight - SlowStartShift) / PreBlossomHalvingInterval + (height - BlossomActivationHeight) / PostBlossomHalvingInterval), otherwise if (NetworkUpgradeActive(nHeight, Consensus::UPGRADE_BLOSSOM)) { int blossomActivationHeight = vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; - // // Ideally we would say: + // Ideally we would say: // halvings = (blossomActivationHeight - consensusParams.SubsidySlowStartShift()) / consensusParams.nPreBlossomSubsidyHalvingInterval // + (nHeight - blossomActivationHeight) / consensusParams.nPostBlossomSubsidyHalvingInterval; // But, (blossomActivationHeight - consensusParams.SubsidySlowStartShift()) / consensusParams.nPreBlossomSubsidyHalvingInterval - // needs to be a treated rational number or this does not work. + // would need to be treated as a rational number in order for this to work. // Define scaledHalvings := halvings * consensusParams.nPreBlossomSubsidyHalvingInterval; int scaledHalvings = (blossomActivationHeight - SubsidySlowStartShift()) + (nHeight - blossomActivationHeight) / Consensus::BLOSSOM_POW_TARGET_SPACING_RATIO; diff --git a/src/main.cpp b/src/main.cpp index 3819afd3beb..44ac8db0d70 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6662,13 +6662,10 @@ CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Para } // NOTE: If the expiry height crosses into an incompatible consensus epoch, and it is changed to the last block - // of the current epoch (see below: Overwinter->Sapling), the transaction will be rejected if it falls within - // the expiring soon threshold of 3 blocks (for DoS mitigation) based on the current height. + // of the current epoch, the transaction will be rejected if it falls within the expiring soon threshold of + // TX_EXPIRING_SOON_THRESHOLD (3) blocks (for DoS mitigation) based on the current height. auto nextActivationHeight = NextActivationHeight(nHeight, consensusParams); if (nextActivationHeight) { - // We need to add TX_EXPIRING_SOON_THRESHOLD otherwise we cannot send transactions just prior to the next epoch - // The idea is that the transaction will not be rejected as expiring soon until the same block that it is - // The rejected for being created during the last epoch. mtx.nExpiryHeight = std::min(mtx.nExpiryHeight, static_cast(nextActivationHeight.get()) - 1); } } diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index c8ecbd58dde..ffbc46b65f9 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -392,6 +392,8 @@ void PartitionAlertTestImpl(const Consensus::Params& params, int startTime, int CCriticalSection csDummy; CBlockIndex indexDummy[800]; + // Generate fake blockchain timestamps relative to + // an arbitrary time: int64_t start = startTime; for (int i = 0; i < 800; i++) { @@ -402,8 +404,6 @@ void PartitionAlertTestImpl(const Consensus::Params& params, int startTime, int // Other members don't matter, the partition check code doesn't // use them } - // Generate fake blockchain timestamps relative to - // an arbitrary time: int64_t now = indexDummy[799].nTime + params.PoWTargetSpacing(800); SetMockTime(now); diff --git a/src/test/main_tests.cpp b/src/test/main_tests.cpp index 8af388473c3..b3930e55090 100644 --- a/src/test/main_tests.cpp +++ b/src/test/main_tests.cpp @@ -66,7 +66,7 @@ BOOST_AUTO_TEST_CASE(block_subsidy_test) TestBlockSubsidyHalvings(20000, Consensus::PRE_BLOSSOM_HALVING_INTERVAL, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); // Pre-Blossom TestBlockSubsidyHalvings(50, 150, 80); // As in regtest TestBlockSubsidyHalvings(500, 1000, 900); // Just another interval - TestBlockSubsidyHalvings(500, 1000, 3000); // Multiple halvings before activation + TestBlockSubsidyHalvings(500, 1000, 3000); // Multiple halvings before Blossom activation } BOOST_AUTO_TEST_CASE(subsidy_limit_test) From 0f0512128cc661cbba3b250f956eba204920281d Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 5 Aug 2019 12:57:10 -0600 Subject: [PATCH 211/395] Make sure that expiry height is not less than height --- src/bitcoin-tx.cpp | 1 - src/main.cpp | 2 +- src/transaction_builder.cpp | 5 ++--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 8b7c2ac3543..799d3cb91fd 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -174,7 +174,6 @@ static void MutateTxVersion(CMutableTransaction& tx, const std::string& cmdVal) static void MutateTxExpiry(CMutableTransaction& tx, const std::string& cmdVal) { int64_t newExpiry = atoi64(cmdVal); - // Review: is newExpiry == 0 allowed? Is this coinbase only? if (newExpiry <= 0 || newExpiry >= TX_EXPIRY_HEIGHT_THRESHOLD) { throw std::runtime_error("Invalid TX expiry requested"); } diff --git a/src/main.cpp b/src/main.cpp index 44ac8db0d70..615998d45e4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6656,7 +6656,7 @@ CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Para mtx.nExpiryHeight = nHeight + (expiryDeltaArg ? expiryDeltaArg.get() : consensusParams.DefaultExpiryDelta(nHeight)); - // Review: is mtx.nExpiryHeight == 0 allowed? Is this coinbase only? + // mtx.nExpiryHeight == 0 is valid for coinbase transactions if (mtx.nExpiryHeight <= 0 || mtx.nExpiryHeight >= TX_EXPIRY_HEIGHT_THRESHOLD) { throw new std::runtime_error("CreateNewContextualCMutableTransaction: invalid expiry height"); } diff --git a/src/transaction_builder.cpp b/src/transaction_builder.cpp index b3e6cdb77f9..dca951dd455 100644 --- a/src/transaction_builder.cpp +++ b/src/transaction_builder.cpp @@ -78,11 +78,10 @@ struct JSDescException : public std::exception void TransactionBuilder::SetExpiryHeight(uint32_t nExpiryHeight) { - mtx.nExpiryHeight = nExpiryHeight; - // Review: is mtx.nExpiryHeight == 0 allowed? Is this coinbase only? - if (mtx.nExpiryHeight <= 0 || mtx.nExpiryHeight >= TX_EXPIRY_HEIGHT_THRESHOLD) { + if (nExpiryHeight < nHeight || nExpiryHeight <= 0 || nExpiryHeight >= TX_EXPIRY_HEIGHT_THRESHOLD) { throw new std::runtime_error("TransactionBuilder::SetExpiryHeight: invalid expiry height"); } + mtx.nExpiryHeight = nExpiryHeight; } void TransactionBuilder::AddSaplingSpend( From 609bb38ad82c7a228a9d27c6014fe416e610c24a Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 5 Aug 2019 13:01:01 -0600 Subject: [PATCH 212/395] Clarify documentation --- src/rpc/rawtransaction.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 065d1498292..156bfe87435 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -502,8 +502,8 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) " ,...\n" " }\n" "3. locktime (numeric, optional, default=0) Raw locktime. Non-0 value also locktime-activates inputs\n" - "4. expiryheight (numeric, optional, default=nextblockheight+" - + strprintf("%d (pre-Blossom) or %d (post-Blossom)", DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA, DEFAULT_POST_BLOSSOM_TX_EXPIRY_DELTA) + ") " + "4. expiryheight (numeric, optional, default=" + + strprintf("nextblockheight+%d (pre-Blossom) or nextblockheight+%d (post-Blossom)", DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA, DEFAULT_POST_BLOSSOM_TX_EXPIRY_DELTA) + ") " "Expiry height of transaction (if Overwinter is active)\n" "\nResult:\n" "\"transaction\" (string) hex string of the transaction\n" From 832134f4cd4a564d7e438478335a512ba8380a37 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 5 Aug 2019 13:16:13 -0600 Subject: [PATCH 213/395] Update PoW related assertions --- src/chainparams.cpp | 1 - src/consensus/params.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 82d60af3182..f85786be707 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -509,7 +509,6 @@ class CRegTestParams : public CChainParams { void UpdateRegtestPow(int64_t nPowMaxAdjustDown, int64_t nPowMaxAdjustUp, uint256 powLimit) { - assert(strNetworkID == "regtest"); consensus.nPowMaxAdjustDown = nPowMaxAdjustDown; consensus.nPowMaxAdjustUp = nPowMaxAdjustUp; consensus.powLimit = powLimit; diff --git a/src/consensus/params.h b/src/consensus/params.h index 8644b087f26..5599d6cbe09 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -68,6 +68,7 @@ static_assert(POST_BLOSSOM_POW_TARGET_SPACING < PRE_BLOSSOM_POW_TARGET_SPACING, static const unsigned int PRE_BLOSSOM_HALVING_INTERVAL = 840000; static const unsigned int PRE_BLOSSOM_REGTEST_HALVING_INTERVAL = 150; static const int BLOSSOM_POW_TARGET_SPACING_RATIO = PRE_BLOSSOM_POW_TARGET_SPACING / POST_BLOSSOM_POW_TARGET_SPACING; +static_assert(BLOSSOM_POW_TARGET_SPACING_RATIO * POST_BLOSSOM_POW_TARGET_SPACING == PRE_BLOSSOM_POW_TARGET_SPACING, "Invalid BLOSSOM_POW_TARGET_SPACING_RATIO"); static const unsigned int POST_BLOSSOM_HALVING_INTERVAL = PRE_BLOSSOM_HALVING_INTERVAL * BLOSSOM_POW_TARGET_SPACING_RATIO; static const unsigned int POST_BLOSSOM_REGTEST_HALVING_INTERVAL = PRE_BLOSSOM_REGTEST_HALVING_INTERVAL * BLOSSOM_POW_TARGET_SPACING_RATIO; From 8f0a54c142ba2d535373e56fa95bd28e0af4904c Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 5 Aug 2019 13:40:06 -0600 Subject: [PATCH 214/395] Remove DefaultExpiryDelta method --- src/consensus/params.cpp | 5 ----- src/consensus/params.h | 2 -- src/main.cpp | 6 ++++-- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/consensus/params.cpp b/src/consensus/params.cpp index c0e332892c9..3987260ae4c 100644 --- a/src/consensus/params.cpp +++ b/src/consensus/params.cpp @@ -1,6 +1,5 @@ #include "params.h" -#include "main.h" #include "upgrades.h" namespace Consensus { @@ -54,10 +53,6 @@ namespace Consensus { } } - unsigned int Params::DefaultExpiryDelta(int nHeight) const { - return NetworkUpgradeActive(nHeight, Consensus::UPGRADE_BLOSSOM) ? DEFAULT_POST_BLOSSOM_TX_EXPIRY_DELTA : DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA; - } - int64_t Params::PoWTargetSpacing(int nHeight) const { // zip208 // PoWTargetSpacing(height) := diff --git a/src/consensus/params.h b/src/consensus/params.h index 5599d6cbe09..84fff232a42 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -108,8 +108,6 @@ struct Params { int GetLastFoundersRewardBlockHeight(int nHeight) const; - unsigned int DefaultExpiryDelta(int nHeight) const; - /** Used to check majorities for block version upgrade */ int nMajorityEnforceBlockUpgrade; int nMajorityRejectBlockOutdated; diff --git a/src/main.cpp b/src/main.cpp index 615998d45e4..3ebe6b3712f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6653,8 +6653,10 @@ CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Para mtx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID; mtx.nVersion = OVERWINTER_TX_VERSION; } - - mtx.nExpiryHeight = nHeight + (expiryDeltaArg ? expiryDeltaArg.get() : consensusParams.DefaultExpiryDelta(nHeight)); + + bool blossomActive = consensusParams.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_BLOSSOM); + unsigned int defaultExpiryDelta = blossomActive ? DEFAULT_POST_BLOSSOM_TX_EXPIRY_DELTA : DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA; + mtx.nExpiryHeight = nHeight + (expiryDeltaArg ? expiryDeltaArg.get() : defaultExpiryDelta); // mtx.nExpiryHeight == 0 is valid for coinbase transactions if (mtx.nExpiryHeight <= 0 || mtx.nExpiryHeight >= TX_EXPIRY_HEIGHT_THRESHOLD) { From f97b9c5d9f4d9479eebcc386cc1172eac376d354 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 5 Aug 2019 14:02:31 -0600 Subject: [PATCH 215/395] Algebraic improvements related to halving --- src/consensus/params.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/consensus/params.cpp b/src/consensus/params.cpp index 3987260ae4c..b0ae2b9ea36 100644 --- a/src/consensus/params.cpp +++ b/src/consensus/params.cpp @@ -19,10 +19,10 @@ namespace Consensus { // + (nHeight - blossomActivationHeight) / consensusParams.nPostBlossomSubsidyHalvingInterval; // But, (blossomActivationHeight - consensusParams.SubsidySlowStartShift()) / consensusParams.nPreBlossomSubsidyHalvingInterval // would need to be treated as a rational number in order for this to work. - // Define scaledHalvings := halvings * consensusParams.nPreBlossomSubsidyHalvingInterval; - int scaledHalvings = (blossomActivationHeight - SubsidySlowStartShift()) - + (nHeight - blossomActivationHeight) / Consensus::BLOSSOM_POW_TARGET_SPACING_RATIO; - return scaledHalvings / nPreBlossomSubsidyHalvingInterval; + // Define scaledHalvings := halvings * consensusParams.nPostBlossomSubsidyHalvingInterval; + int scaledHalvings = ((blossomActivationHeight - SubsidySlowStartShift()) * Consensus::BLOSSOM_POW_TARGET_SPACING_RATIO) + + (nHeight - blossomActivationHeight); + return scaledHalvings / nPostBlossomSubsidyHalvingInterval; } else { return (nHeight - SubsidySlowStartShift()) / nPreBlossomSubsidyHalvingInterval; } @@ -40,14 +40,15 @@ namespace Consensus { // height = preInterval + SS // postBlossom: // 1 = (H - SS) / preInterval + (height - H) / postInterval - // height = H + postInterval + (SS - H) * (postInterval / preInterval) - // height = H + postInterval + (SS - H) * R + // height = H + postInterval - (H - SS) * (postInterval / preInterval) + // height = H + postInterval - (H - SS) * R + // Note: This depends on R being an integer bool blossomActive = NetworkUpgradeActive(nHeight, Consensus::UPGRADE_BLOSSOM); if (blossomActive) { int blossomActivationHeight = vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; // The following calculation depends on BLOSSOM_POW_TARGET_SPACING_RATIO being an integer. return blossomActivationHeight + nPostBlossomSubsidyHalvingInterval - + (SubsidySlowStartShift() - blossomActivationHeight) * BLOSSOM_POW_TARGET_SPACING_RATIO - 1; + - (blossomActivationHeight - SubsidySlowStartShift()) * BLOSSOM_POW_TARGET_SPACING_RATIO - 1; } else { return nPreBlossomSubsidyHalvingInterval + SubsidySlowStartShift() - 1; } From 5a93638981972059bfd301eb08bf8a026f323e86 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 5 Aug 2019 14:20:25 -0600 Subject: [PATCH 216/395] Distinguish between height and current header height on metrics screen --- src/metrics.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/metrics.cpp b/src/metrics.cpp index e6390572662..e92734d003a 100644 --- a/src/metrics.cpp +++ b/src/metrics.cpp @@ -109,28 +109,29 @@ double GetLocalSolPS() return miningTimer.rate(solutionTargetChecks); } -int EstimateNetHeight(const Consensus::Params& params, int currentBlockHeight, int64_t currentBlockTime) +int EstimateNetHeight(const Consensus::Params& params, int currentHeadersHeight, int64_t currentHeadersTime) { int64_t now = GetAdjustedTime(); - if (currentBlockTime >= now) { - return currentBlockHeight; + if (currentHeadersTime >= now) { + return currentHeadersHeight; } - int estimatedHeight = currentBlockHeight + (now - currentBlockTime) / params.PoWTargetSpacing(currentBlockHeight); + int estimatedHeight = currentHeadersHeight + (now - currentHeadersTime) / params.PoWTargetSpacing(currentHeadersHeight); int blossomActivationHeight = params.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; - if (currentBlockHeight >= blossomActivationHeight || estimatedHeight <= blossomActivationHeight) { + if (currentHeadersHeight >= blossomActivationHeight || estimatedHeight <= blossomActivationHeight) { return estimatedHeight; } - int numPreBlossomBlocks = blossomActivationHeight - currentBlockHeight; + int numPreBlossomBlocks = blossomActivationHeight - currentHeadersHeight; int64_t preBlossomTime = numPreBlossomBlocks * params.PoWTargetSpacing(blossomActivationHeight - 1); - int64_t blossomActivationTime = currentBlockTime + preBlossomTime; + int64_t blossomActivationTime = currentHeadersTime + preBlossomTime; if (blossomActivationTime >= now) { return blossomActivationHeight; } - return blossomActivationHeight + (now - blossomActivationTime) / params.PoWTargetSpacing(blossomActivationHeight); + int netheight = blossomActivationHeight + (now - blossomActivationTime) / params.PoWTargetSpacing(blossomActivationHeight); + return ((netheight + 5) / 10) * 10; } void TriggerRefresh() @@ -199,20 +200,22 @@ int printStats(bool mining) int lines = 4; int height; - int64_t blockTime; + int64_t currentHeadersHeight; + int64_t currentHeadersTime; size_t connections; int64_t netsolps; { LOCK2(cs_main, cs_vNodes); - height = pindexBestHeader->nHeight; - blockTime = pindexBestHeader->nTime; + height = chainActive.Tip()->nHeight; + currentHeadersHeight = pindexBestHeader->nHeight; + currentHeadersTime = pindexBestHeader->nTime; connections = vNodes.size(); netsolps = GetNetworkHashPS(120, -1); } auto localsolps = GetLocalSolPS(); if (IsInitialBlockDownload(Params())) { - int netheight = EstimateNetHeight(Params().GetConsensus(), height, blockTime); + int netheight = EstimateNetHeight(Params().GetConsensus(), currentHeadersHeight, currentHeadersTime); int downloadPercent = height * 100 / netheight; std::cout << " " << _("Downloading blocks") << " | " << height << " / ~" << netheight << " (" << downloadPercent << "%)" << std::endl; } else { From 42a21ef0045a04f01b35c9c8714c5a1645bee20c Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 5 Aug 2019 14:52:34 -0600 Subject: [PATCH 217/395] Test clean up and fixes --- qa/rpc-tests/shorter_block_times.py | 16 +++++++++------- src/gtest/test_foundersreward.cpp | 10 +++------- src/test/main_tests.cpp | 7 +++++-- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/qa/rpc-tests/shorter_block_times.py b/qa/rpc-tests/shorter_block_times.py index b34882e2621..8e807e4661a 100755 --- a/qa/rpc-tests/shorter_block_times.py +++ b/qa/rpc-tests/shorter_block_times.py @@ -21,7 +21,7 @@ def setup_nodes(self): return start_nodes(4, self.options.tmpdir, [[ '-nuparams=5ba81b19:0', # Overwinter '-nuparams=76b809bb:0', # Sapling - '-nuparams=2bb40e60:103', # Blossom + '-nuparams=2bb40e60:106', # Blossom ]] * 4) def setup_chain(self): @@ -36,21 +36,23 @@ def run_test(self): # Sanity-check the block height assert_equal(self.nodes[0].getblockcount(), 101) - # Make sure we can send a transaction on the last pre-Blossom block node0_taddr = get_coinbase_address(self.nodes[0]) node0_zaddr = self.nodes[0].z_getnewaddress('sapling') recipients = [{'address': node0_zaddr, 'amount': Decimal('10')}] myopid = self.nodes[0].z_sendmany(node0_taddr, recipients, 1, Decimal('0')) txid = wait_and_assert_operationid_status(self.nodes[0], myopid) - assert_equal(105, self.nodes[0].getrawtransaction(txid, 1)['expiryheight']) # Blossom activation - 1 + 3 + assert_equal(105, self.nodes[0].getrawtransaction(txid, 1)['expiryheight']) # Blossom activation - 1 self.sync_all() + self.nodes[0].generate(1) + self.sync_all() + assert_equal(10, Decimal(self.nodes[0].z_gettotalbalance()['private'])) - print "Mining last pre-Blossom block" + self.nodes[0].generate(2) + self.sync_all() + print "Mining last pre-Blossom blocks" # Activate blossom self.nodes[1].generate(1) self.sync_all() - # Check that the last pre-Blossom transaction was mined - assert_equal(10, Decimal(self.nodes[0].z_gettotalbalance()['private'])) # Check that we received a pre-Blossom mining reward assert_equal(10, Decimal(self.nodes[1].getwalletinfo()['immature_balance'])) @@ -64,7 +66,7 @@ def run_test(self): # Send and mine a transaction after activation myopid = self.nodes[0].z_sendmany(node0_taddr, recipients, 1, Decimal('0')) txid = wait_and_assert_operationid_status(self.nodes[0], myopid) - assert_equal(144, self.nodes[0].getrawtransaction(txid, 1)['expiryheight']) # height + 1 + 40 + assert_equal(147, self.nodes[0].getrawtransaction(txid, 1)['expiryheight']) # height + 1 + 40 self.nodes[1].generate(1) self.sync_all() assert_equal(20, Decimal(self.nodes[0].z_gettotalbalance()['private'])) diff --git a/src/gtest/test_foundersreward.cpp b/src/gtest/test_foundersreward.cpp index d4b45a15716..7eeb7fa0df4 100644 --- a/src/gtest/test_foundersreward.cpp +++ b/src/gtest/test_foundersreward.cpp @@ -84,7 +84,7 @@ TEST(founders_reward_test, create_testnet_2of3multisig) { #endif -static int GetLastFoundersRewardHeight(const Consensus::Params& params){ +static int GetLastFoundersRewardHeight(const Consensus::Params& params) { int blossomActivationHeight = Params().GetConsensus().vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; bool blossom = blossomActivationHeight != Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; return params.GetLastFoundersRewardBlockHeight(blossom ? blossomActivationHeight : 0); @@ -116,7 +116,7 @@ TEST(founders_reward_test, general) { EXPECT_EQ(HexStr(params.GetFoundersRewardScriptAtHeight(53127)), "a91455d64928e69829d9376c776550b6cc710d42715387"); EXPECT_EQ(params.GetFoundersRewardAddressAtHeight(53127), "t2ENg7hHVqqs9JwU5cgjvSbxnT2a9USNfhy"); - int maxHeight = params.GetConsensus().GetLastFoundersRewardBlockHeight(0); + int maxHeight = GetLastFoundersRewardHeight(params.GetConsensus()); // If the block height parameter is out of bounds, there is an assert. EXPECT_DEATH(params.GetFoundersRewardScriptAtHeight(0), "nHeight"); @@ -173,12 +173,8 @@ TEST(founders_reward_test, slow_start_subsidy) { SelectParams(CBaseChainParams::MAIN); CChainParams params = Params(); - int blossomActivationHeight = Params().GetConsensus().vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; - bool blossom = blossomActivationHeight != Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; - int maxHeight = Params().GetConsensus().GetLastFoundersRewardBlockHeight(blossom ? blossomActivationHeight : 0); - CAmount totalSubsidy = 0; - for (int nHeight = 1; nHeight <= maxHeight; nHeight++) { + for (int nHeight = 1; nHeight <= GetLastFoundersRewardHeight(Params().GetConsensus()); nHeight++) { CAmount nSubsidy = GetBlockSubsidy(nHeight, params.GetConsensus()) / 5; totalSubsidy += nSubsidy; } diff --git a/src/test/main_tests.cpp b/src/test/main_tests.cpp index b3930e55090..5e2cb8a86b8 100644 --- a/src/test/main_tests.cpp +++ b/src/test/main_tests.cpp @@ -16,6 +16,8 @@ BOOST_FIXTURE_TEST_SUITE(main_tests, TestingSetup) const CAmount INITIAL_SUBSIDY = 12.5 * COIN; static int GetTotalHalvings(const Consensus::Params& consensusParams) { + // This assumes that BLOSSOM_POW_TARGET_SPACING_RATIO == 2 + // and treats blossom activation as a halving event return consensusParams.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight == Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT ? 64 : 65; } @@ -55,7 +57,7 @@ static void TestBlockSubsidyHalvings(int nSubsidySlowStartInterval, int nPreBlos Consensus::Params consensusParams; consensusParams.nSubsidySlowStartInterval = nSubsidySlowStartInterval; consensusParams.nPreBlossomSubsidyHalvingInterval = nPreBlossomSubsidyHalvingInterval; - consensusParams.nPostBlossomSubsidyHalvingInterval = nPreBlossomSubsidyHalvingInterval * 2; + consensusParams.nPostBlossomSubsidyHalvingInterval = nPreBlossomSubsidyHalvingInterval * Consensus::BLOSSOM_POW_TARGET_SPACING_RATIO; consensusParams.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight = blossomActivationHeight; TestBlockSubsidyHalvings(consensusParams); } @@ -78,7 +80,7 @@ BOOST_AUTO_TEST_CASE(subsidy_limit_test) // Mining slow start for (; nHeight < consensusParams.nSubsidySlowStartInterval; nHeight++) { CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams); - BOOST_CHECK(nSubsidy <= 12.5 * COIN); + BOOST_CHECK(nSubsidy <= INITIAL_SUBSIDY); nSum += nSubsidy; BOOST_CHECK(MoneyRange(nSum)); } @@ -88,6 +90,7 @@ BOOST_AUTO_TEST_CASE(subsidy_limit_test) CAmount nSubsidy; do { nSubsidy = GetBlockSubsidy(nHeight, consensusParams); + BOOST_CHECK(nSubsidy <= INITIAL_SUBSIDY); nSum += nSubsidy; BOOST_ASSERT(MoneyRange(nSum)); ++nHeight; From 2f007290613dc5d40d3646ee770590fecea8c399 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 5 Aug 2019 19:05:11 -0600 Subject: [PATCH 218/395] Add copyright info --- qa/rpc-tests/shorter_block_times.py | 2 +- src/consensus/params.cpp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/qa/rpc-tests/shorter_block_times.py b/qa/rpc-tests/shorter_block_times.py index 8e807e4661a..3141a7e7701 100755 --- a/qa/rpc-tests/shorter_block_times.py +++ b/qa/rpc-tests/shorter_block_times.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2019 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." diff --git a/src/consensus/params.cpp b/src/consensus/params.cpp index b0ae2b9ea36..b0f2079e730 100644 --- a/src/consensus/params.cpp +++ b/src/consensus/params.cpp @@ -1,3 +1,7 @@ +// Copyright (c) 2019 The Zcash developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + #include "params.h" #include "upgrades.h" From cdb6757095467f36c47b256ac6540a993d7cef4d Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Tue, 6 Aug 2019 09:45:17 -0600 Subject: [PATCH 219/395] NPE defense in metrics screen --- src/metrics.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/metrics.cpp b/src/metrics.cpp index e92734d003a..9268013e8ec 100644 --- a/src/metrics.cpp +++ b/src/metrics.cpp @@ -120,7 +120,7 @@ int EstimateNetHeight(const Consensus::Params& params, int currentHeadersHeight, int blossomActivationHeight = params.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; if (currentHeadersHeight >= blossomActivationHeight || estimatedHeight <= blossomActivationHeight) { - return estimatedHeight; + return ((estimatedHeight + 5) / 10) * 10; } int numPreBlossomBlocks = blossomActivationHeight - currentHeadersHeight; @@ -206,9 +206,9 @@ int printStats(bool mining) int64_t netsolps; { LOCK2(cs_main, cs_vNodes); - height = chainActive.Tip()->nHeight; - currentHeadersHeight = pindexBestHeader->nHeight; - currentHeadersTime = pindexBestHeader->nTime; + height = chainActive.Height(); + currentHeadersHeight = pindexBestHeader ? pindexBestHeader->nHeight: -1; + currentHeadersTime = pindexBestHeader ? pindexBestHeader->nTime : 0; connections = vNodes.size(); netsolps = GetNetworkHashPS(120, -1); } From d9ef43dc2549072767f568313fd78d7a08272686 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 7 Aug 2019 10:04:30 -0600 Subject: [PATCH 220/395] Do not estimate height if there is no best header --- src/metrics.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/metrics.cpp b/src/metrics.cpp index 9268013e8ec..9e03735b6d9 100644 --- a/src/metrics.cpp +++ b/src/metrics.cpp @@ -215,7 +215,8 @@ int printStats(bool mining) auto localsolps = GetLocalSolPS(); if (IsInitialBlockDownload(Params())) { - int netheight = EstimateNetHeight(Params().GetConsensus(), currentHeadersHeight, currentHeadersTime); + int netheight = currentHeadersHeight == -1 || currentHeadersTime == 0 ? + 0 : EstimateNetHeight(Params().GetConsensus(), currentHeadersHeight, currentHeadersTime); int downloadPercent = height * 100 / netheight; std::cout << " " << _("Downloading blocks") << " | " << height << " / ~" << netheight << " (" << downloadPercent << "%)" << std::endl; } else { From b99003c1ecc1917989e8bcaf53ee19cfaf79e73e Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 7 Aug 2019 10:05:01 -0600 Subject: [PATCH 221/395] Rename method and use int64_t --- src/consensus/params.cpp | 8 ++++---- src/consensus/params.h | 2 +- src/gtest/test_foundersreward.cpp | 8 ++++---- src/main.cpp | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/consensus/params.cpp b/src/consensus/params.cpp index b0f2079e730..1062df349c7 100644 --- a/src/consensus/params.cpp +++ b/src/consensus/params.cpp @@ -11,22 +11,22 @@ namespace Consensus { return NetworkUpgradeState(nHeight, *this, idx) == UPGRADE_ACTIVE; } - int Params::Halvings(int nHeight) const { + int Params::Halving(int nHeight) const { // zip208 // Halving(height) := // floor((height - SlowStartShift) / PreBlossomHalvingInterval), if not IsBlossomActivated(height) // floor((BlossomActivationHeight - SlowStartShift) / PreBlossomHalvingInterval + (height - BlossomActivationHeight) / PostBlossomHalvingInterval), otherwise if (NetworkUpgradeActive(nHeight, Consensus::UPGRADE_BLOSSOM)) { - int blossomActivationHeight = vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; + int64_t blossomActivationHeight = vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; // Ideally we would say: // halvings = (blossomActivationHeight - consensusParams.SubsidySlowStartShift()) / consensusParams.nPreBlossomSubsidyHalvingInterval // + (nHeight - blossomActivationHeight) / consensusParams.nPostBlossomSubsidyHalvingInterval; // But, (blossomActivationHeight - consensusParams.SubsidySlowStartShift()) / consensusParams.nPreBlossomSubsidyHalvingInterval // would need to be treated as a rational number in order for this to work. // Define scaledHalvings := halvings * consensusParams.nPostBlossomSubsidyHalvingInterval; - int scaledHalvings = ((blossomActivationHeight - SubsidySlowStartShift()) * Consensus::BLOSSOM_POW_TARGET_SPACING_RATIO) + int64_t scaledHalvings = ((blossomActivationHeight - SubsidySlowStartShift()) * Consensus::BLOSSOM_POW_TARGET_SPACING_RATIO) + (nHeight - blossomActivationHeight); - return scaledHalvings / nPostBlossomSubsidyHalvingInterval; + return (int) (scaledHalvings / nPostBlossomSubsidyHalvingInterval); } else { return (nHeight - SubsidySlowStartShift()) / nPreBlossomSubsidyHalvingInterval; } diff --git a/src/consensus/params.h b/src/consensus/params.h index 84fff232a42..a3bbbd3134c 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -104,7 +104,7 @@ struct Params { int nPreBlossomSubsidyHalvingInterval; int nPostBlossomSubsidyHalvingInterval; - int Halvings(int nHeight) const; + int Halving(int nHeight) const; int GetLastFoundersRewardBlockHeight(int nHeight) const; diff --git a/src/gtest/test_foundersreward.cpp b/src/gtest/test_foundersreward.cpp index 7eeb7fa0df4..70826ae2a76 100644 --- a/src/gtest/test_foundersreward.cpp +++ b/src/gtest/test_foundersreward.cpp @@ -129,8 +129,8 @@ TEST(founders_reward_test, regtest_get_last_block_blossom) { int blossomActivationHeight = Consensus::PRE_BLOSSOM_REGTEST_HALVING_INTERVAL / 2; // = 75 auto params = RegtestActivateBlossom(false, blossomActivationHeight); int lastFRHeight = params.GetLastFoundersRewardBlockHeight(blossomActivationHeight); - EXPECT_EQ(0, params.Halvings(lastFRHeight)); - EXPECT_EQ(1, params.Halvings(lastFRHeight + 1)); + EXPECT_EQ(0, params.Halving(lastFRHeight)); + EXPECT_EQ(1, params.Halving(lastFRHeight + 1)); RegtestDeactivateBlossom(); } @@ -138,8 +138,8 @@ TEST(founders_reward_test, mainnet_get_last_block) { SelectParams(CBaseChainParams::MAIN); auto params = Params().GetConsensus(); int lastFRHeight = GetLastFoundersRewardHeight(params); - EXPECT_EQ(0, params.Halvings(lastFRHeight)); - EXPECT_EQ(1, params.Halvings(lastFRHeight + 1)); + EXPECT_EQ(0, params.Halving(lastFRHeight)); + EXPECT_EQ(1, params.Halving(lastFRHeight + 1)); } #define NUM_MAINNET_FOUNDER_ADDRESSES 48 diff --git a/src/main.cpp b/src/main.cpp index 3ebe6b3712f..7447e2f32d5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1762,7 +1762,7 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) assert(nHeight > consensusParams.SubsidySlowStartShift()); - int halvings = consensusParams.Halvings(nHeight); + int halvings = consensusParams.Halving(nHeight); // Force block reward to zero when right shift is undefined. if (halvings >= 64) From 86b23f37adcfc7aa7ab9228f7ae4239187c10843 Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Wed, 7 Aug 2019 14:23:42 -0600 Subject: [PATCH 222/395] add spentindex RPC for bitcore block explorer --- qa/pull-tester/rpc-tests.sh | 1 + qa/rpc-tests/addressindex.py | 5 + qa/rpc-tests/getrawtransaction_insight.py | 9 +- qa/rpc-tests/spentindex.py | 182 ++++++++++++++++++++++ src/main.cpp | 7 + src/rpc/blockchain.cpp | 175 +++++++++++++++++++++ src/rpc/client.cpp | 1 + src/rpc/misc.cpp | 98 ++++++++++-- src/rpc/rawtransaction.cpp | 1 + src/test/rpc_tests.cpp | 17 ++ src/txmempool.cpp | 50 ++++++ src/txmempool.h | 10 ++ 12 files changed, 537 insertions(+), 19 deletions(-) create mode 100755 qa/rpc-tests/spentindex.py diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index 9148a6a8a67..b5c3f708793 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -58,6 +58,7 @@ testScripts=( 'nodehandling.py' 'reindex.py' 'addressindex.py' + 'spentindex.py' 'decodescript.py' 'blockchain.py' 'disablewallet.py' diff --git a/qa/rpc-tests/addressindex.py b/qa/rpc-tests/addressindex.py index 4e18d95140e..f924f087506 100755 --- a/qa/rpc-tests/addressindex.py +++ b/qa/rpc-tests/addressindex.py @@ -202,6 +202,11 @@ def check_balance(node_index, address, expected_balance, expected_received=None) # a single address can be specified as a string (not json object) assert_equal([mempool[1]], self.nodes[0].getaddressmempool(addr1)) + tx = self.nodes[0].getrawtransaction(txid, 1) + assert_equal(tx['vin'][0]['address'], addr1) + assert_equal(tx['vin'][0]['value'], 4) + assert_equal(tx['vin'][0]['valueSat'], 4 * COIN) + txids_a1.append(txid) expected_deltas.append({ 'height': 111, diff --git a/qa/rpc-tests/getrawtransaction_insight.py b/qa/rpc-tests/getrawtransaction_insight.py index 85f39ccd7f4..620f86bfce2 100755 --- a/qa/rpc-tests/getrawtransaction_insight.py +++ b/qa/rpc-tests/getrawtransaction_insight.py @@ -64,10 +64,11 @@ def run_test(self): self.sync_all() tx_a = self.nodes[2].getrawtransaction(txid_a, 1) - # txid_b is not yet confirmed, so these should not be set - assert('spentTxId' not in tx_a['vout'][0]) - assert('spentIndex' not in tx_a['vout'][0]) - assert('spentHeight' not in tx_a['vout'][0]) + # txid_b is not yet confirmed, so height is invalid (-1) + vout = filter(lambda o: o['value'] == 2, tx_a['vout']) + assert_equal(vout[0]['spentTxId'], txid_b) + assert_equal(vout[0]['spentIndex'], 0) + assert_equal(vout[0]['spentHeight'], -1) # confirm txid_b (a to b transaction) self.nodes[0].generate(1) diff --git a/qa/rpc-tests/spentindex.py b/qa/rpc-tests/spentindex.py new file mode 100755 index 00000000000..28e626573d2 --- /dev/null +++ b/qa/rpc-tests/spentindex.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python +# Copyright (c) 2019 The Zcash developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Test spentindex generation and fetching +# + +import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.authproxy import JSONRPCException + +from test_framework.util import assert_equal +from test_framework.util import initialize_chain_clean +from test_framework.util import start_nodes, stop_nodes, connect_nodes +from test_framework.util import wait_bitcoinds +from test_framework.util import fail + +from test_framework.mininode import COIN + +class SpentIndexTest(BitcoinTestFramework): + + def setup_chain(self): + print("Initializing test directory "+self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 3) + + def setup_network(self): + # -insightexplorer causes spentindex to be enabled (fSpentIndex = true) + + self.nodes = start_nodes(3, self.options.tmpdir, + [['-debug', '-txindex', '-experimentalfeatures', '-insightexplorer']]*3) + connect_nodes(self.nodes[0], 1) + connect_nodes(self.nodes[0], 2) + + self.is_network_split = False + self.sync_all() + + def run_test(self): + self.nodes[0].generate(105) + self.sync_all() + + chain_height = self.nodes[1].getblockcount() + assert_equal(chain_height, 105) + + # Test getrawtransaction changes and the getspentinfo RPC + + # send coinbase to address addr1 + addr1 = self.nodes[1].getnewaddress() + txid1 = self.nodes[0].sendtoaddress(addr1, 2) + self.sync_all() + block_hash1 = self.nodes[0].generate(1) + self.sync_all() + + # send from addr1 to addr2 + # (the only utxo on node 1 is from address addr1) + addr2 = self.nodes[2].getnewaddress() + txid2 = self.nodes[1].sendtoaddress(addr2, 1) + self.sync_all() + + # addr1 to addr2 transaction is not confirmed, so it has no height + tx2 = self.nodes[2].getrawtransaction(txid2, 1) + assert('height' not in tx2) + + # confirm addr1 to addr2 transaction + block_hash2 = self.nodes[0].generate(1) + self.sync_all() + + # Restart all nodes to ensure index files are saved to disk and recovered + stop_nodes(self.nodes) + wait_bitcoinds() + self.setup_network() + + # Check new fields added to getrawtransaction + tx1 = self.nodes[2].getrawtransaction(txid1, 1) + assert_equal(tx1['vin'][0]['value'], 10) # coinbase + assert_equal(tx1['vin'][0]['valueSat'], 10*COIN) + # we want the non-change (payment) output + vout = filter(lambda o: o['value'] == 2, tx1['vout']) + n = vout[0]['n'] + assert_equal(vout[0]['spentTxId'], txid2) + assert_equal(vout[0]['spentIndex'], 0) + assert_equal(vout[0]['spentHeight'], 107) + assert_equal(tx1['height'], 106) + + tx2 = self.nodes[2].getrawtransaction(txid2, 1) + assert_equal(tx2['vin'][0]['address'], addr1) + assert_equal(tx2['vin'][0]['value'], 2) + assert_equal(tx2['vin'][0]['valueSat'], 2*COIN) + # since this transaction's outputs haven't yet been + # spent, these fields should not be present + assert('spentTxId' not in tx2['vout'][0]) + assert('spentIndex' not in tx2['vout'][0]) + assert('spentHeight' not in tx2['vout'][0]) + assert_equal(tx2['height'], 107) + + # Given a transaction output, getspentinfo() returns a reference + # to the (later, confirmed) transaction that spent that output, + # that is, the transaction that used this output as an input. + spentinfo = self.nodes[2].getspentinfo({'txid': txid1, 'index': n}) + assert_equal(spentinfo['height'], 107) + assert_equal(spentinfo['index'], 0) + assert_equal(spentinfo['txid'], txid2) + + # specifying an output that hasn't been spent should fail + try: + self.nodes[1].getspentinfo({'txid': txid2, 'index': 0}) + fail('getspentinfo should have thrown an exception') + except JSONRPCException, e: + assert_equal(e.error['message'], "Unable to get spent info") + + block_hash_next = self.nodes[0].generate(1) + self.sync_all() + + # Test the getblockdeltas RPC + blockdeltas = self.nodes[2].getblockdeltas(block_hash1[0]) + assert_equal(blockdeltas['confirmations'], 3) + assert_equal(blockdeltas['height'], 106) + assert_equal(blockdeltas['version'], 4) + assert_equal(blockdeltas['hash'], block_hash1[0]) + assert_equal(blockdeltas['nextblockhash'], block_hash2[0]) + deltas = blockdeltas['deltas'] + # block contains two transactions, coinbase, and earlier coinbase to addr1 + assert_equal(len(deltas), 2) + coinbase_tx = deltas[0] + assert_equal(coinbase_tx['index'], 0) + assert_equal(len(coinbase_tx['inputs']), 0) + assert_equal(len(coinbase_tx['outputs']), 2) + assert_equal(coinbase_tx['outputs'][0]['index'], 0) + assert_equal(coinbase_tx['outputs'][1]['index'], 1) + assert_equal(coinbase_tx['outputs'][1]['satoshis'], 2.5*COIN) + + to_a_tx = deltas[1] + assert_equal(to_a_tx['index'], 1) + assert_equal(to_a_tx['txid'], txid1) + + assert_equal(len(to_a_tx['inputs']), 1) + assert_equal(to_a_tx['inputs'][0]['index'], 0) + assert_equal(to_a_tx['inputs'][0]['prevout'], 0) + assert_equal(to_a_tx['inputs'][0]['satoshis'], -10*COIN) + + assert_equal(len(to_a_tx['outputs']), 2) + # find the nonchange output, which is the payment to addr1 + out = filter(lambda o: o['satoshis'] == 2*COIN, to_a_tx['outputs']) + assert_equal(len(out), 1) + assert_equal(out[0]['address'], addr1) + + blockdeltas = self.nodes[2].getblockdeltas(block_hash2[0]) + assert_equal(blockdeltas['confirmations'], 2) + assert_equal(blockdeltas['height'], 107) + assert_equal(blockdeltas['version'], 4) + assert_equal(blockdeltas['hash'], block_hash2[0]) + assert_equal(blockdeltas['previousblockhash'], block_hash1[0]) + assert_equal(blockdeltas['nextblockhash'], block_hash_next[0]) + deltas = blockdeltas['deltas'] + assert_equal(len(deltas), 2) + coinbase_tx = deltas[0] + assert_equal(coinbase_tx['index'], 0) + assert_equal(len(coinbase_tx['inputs']), 0) + assert_equal(len(coinbase_tx['outputs']), 2) + assert_equal(coinbase_tx['outputs'][0]['index'], 0) + assert_equal(coinbase_tx['outputs'][1]['index'], 1) + assert_equal(coinbase_tx['outputs'][1]['satoshis'], 2.5*COIN) + + to_b_tx = deltas[1] + assert_equal(to_b_tx['index'], 1) + assert_equal(to_b_tx['txid'], txid2) + + assert_equal(len(to_b_tx['inputs']), 1) + assert_equal(to_b_tx['inputs'][0]['index'], 0) + assert_equal(to_b_tx['inputs'][0]['prevtxid'], txid1) + assert_equal(to_b_tx['inputs'][0]['satoshis'], -2*COIN) + + assert_equal(len(to_b_tx['outputs']), 2) + # find the nonchange output, which is the payment to addr2 + out = filter(lambda o: o['satoshis'] == 1*COIN, to_b_tx['outputs']) + assert_equal(len(out), 1) + assert_equal(out[0]['address'], addr2) + +if __name__ == '__main__': + SpentIndexTest().main() diff --git a/src/main.cpp b/src/main.cpp index c0cd9b043ea..793b824d620 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1604,6 +1604,11 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (fAddressIndex) { pool.addAddressIndex(entry, view); } + + // insightexplorer: Add memory spent index + if (fSpentIndex) { + pool.addSpentIndex(entry, view); + } } SyncWithWallets(tx, NULL); @@ -1616,6 +1621,8 @@ bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value) AssertLockHeld(cs_main); if (!fSpentIndex) return false; + if (mempool.getSpentIndex(key, value)) + return true; return pblocktree->ReadSpentIndex(key, value); } diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 580ba8b11c7..86f01d9bd3f 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -8,6 +8,7 @@ #include "chainparams.h" #include "checkpoints.h" #include "consensus/validation.h" +#include "key_io.h" #include "main.h" #include "primitives/transaction.h" #include "rpc/server.h" @@ -125,6 +126,94 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex) return result; } +// insightexplorer +UniValue blockToDeltasJSON(const CBlock& block, const CBlockIndex* blockindex) +{ + UniValue result(UniValue::VOBJ); + result.push_back(Pair("hash", block.GetHash().GetHex())); + // Only report confirmations if the block is on the main chain + if (!chainActive.Contains(blockindex)) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block is an orphan"); + int confirmations = chainActive.Height() - blockindex->nHeight + 1; + result.push_back(Pair("confirmations", confirmations)); + result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); + result.push_back(Pair("height", blockindex->nHeight)); + result.push_back(Pair("version", block.nVersion)); + result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); + + UniValue deltas(UniValue::VARR); + for (unsigned int i = 0; i < block.vtx.size(); i++) { + const CTransaction &tx = block.vtx[i]; + const uint256 txhash = tx.GetHash(); + + UniValue entry(UniValue::VOBJ); + entry.push_back(Pair("txid", txhash.GetHex())); + entry.push_back(Pair("index", (int)i)); + + UniValue inputs(UniValue::VARR); + if (!tx.IsCoinBase()) { + for (size_t j = 0; j < tx.vin.size(); j++) { + const CTxIn input = tx.vin[j]; + UniValue delta(UniValue::VOBJ); + CSpentIndexValue spentInfo; + CSpentIndexKey spentKey(input.prevout.hash, input.prevout.n); + + if (!GetSpentIndex(spentKey, spentInfo)) { + throw JSONRPCError(RPC_INTERNAL_ERROR, "Spent information not available"); + } + CTxDestination dest = DestFromAddressHash(spentInfo.addressType, spentInfo.addressHash); + if (IsValidDestination(dest)) { + delta.push_back(Pair("address", EncodeDestination(dest))); + } + delta.push_back(Pair("satoshis", -1 * spentInfo.satoshis)); + delta.push_back(Pair("index", (int)j)); + delta.push_back(Pair("prevtxid", input.prevout.hash.GetHex())); + delta.push_back(Pair("prevout", (int)input.prevout.n)); + + inputs.push_back(delta); + } + } + entry.push_back(Pair("inputs", inputs)); + + UniValue outputs(UniValue::VARR); + for (unsigned int k = 0; k < tx.vout.size(); k++) { + const CTxOut &out = tx.vout[k]; + UniValue delta(UniValue::VOBJ); + const uint160 addrhash = out.scriptPubKey.AddressHash(); + CTxDestination dest; + + if (out.scriptPubKey.IsPayToScriptHash()) { + dest = CScriptID(addrhash); + } else if (out.scriptPubKey.IsPayToPublicKeyHash()) { + dest = CKeyID(addrhash); + } + if (IsValidDestination(dest)) { + delta.push_back(Pair("address", EncodeDestination(dest))); + } + delta.push_back(Pair("satoshis", out.nValue)); + delta.push_back(Pair("index", (int)k)); + + outputs.push_back(delta); + } + entry.push_back(Pair("outputs", outputs)); + deltas.push_back(entry); + } + result.push_back(Pair("deltas", deltas)); + result.push_back(Pair("time", block.GetBlockTime())); + result.push_back(Pair("mediantime", (int64_t)blockindex->GetMedianTimePast())); + result.push_back(Pair("nonce", block.nNonce.GetHex())); + result.push_back(Pair("bits", strprintf("%08x", block.nBits))); + result.push_back(Pair("difficulty", GetDifficulty(blockindex))); + result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); + + if (blockindex->pprev) + result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); + CBlockIndex *pnext = chainActive.Next(blockindex); + if (pnext) + result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex())); + return result; +} + UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false) { UniValue result(UniValue::VOBJ); @@ -313,6 +402,89 @@ UniValue getrawmempool(const UniValue& params, bool fHelp) return mempoolToJSON(fVerbose); } +// insightexplorer +UniValue getblockdeltas(const UniValue& params, bool fHelp) +{ + std::string enableArg = "insightexplorer"; + bool enabled = fExperimentalMode && fInsightExplorer; + std::string disabledMsg = ""; + if (!enabled) { + disabledMsg = experimentalDisabledHelpMsg("getblockdeltas", enableArg); + } + if (fHelp || params.size() != 1) + throw runtime_error( + "getblockdeltas \"blockhash\"\n" + "\nReturns the txid and index where an output is spent.\n" + + disabledMsg + + "\nArguments:\n" + "1. \"hash\" (string, required) The block hash\n" + "\nResult:\n" + "{\n" + " \"hash\": \"hash\", (string) block ID\n" + " \"confirmations\": n, (numeric) number of confirmations\n" + " \"size\": n, (numeric) block size in bytes\n" + " \"height\": n, (numeric) block height\n" + " \"version\": n, (numeric) block version (e.g. 4)\n" + " \"merkleroot\": \"hash\", (string) block Merkle root\n" + " \"deltas\": [\n" + " {\n" + " \"txid\": \"hash\", (string) transaction ID\n" + " \"index\": n, (numeric) tx index in block\n" + " \"inputs\": [\n" + " {\n" + " \"address\": \"taddr\", (string) transparent address\n" + " \"satoshis\": n, (numeric) negative of spend amount\n" + " \"index\": n, (numeric) vin index\n" + " \"prevtxid\": \"hash\", (string) source utxo tx ID\n" + " \"prevout\": n (numeric) source utxo index\n" + " }, ...\n" + " ],\n" + " \"outputs\": [\n" + " {\n" + " \"address\": \"taddr\", (string) transparent address\n" + " \"satoshis\": n, (numeric) amount\n" + " \"index\": n (numeric) vout index\n" + " }, ...\n" + " ]\n" + " }, ...\n" + " ],\n" + " \"time\": n,\n" + " \"mediantime\": n,\n" + " \"nonce\": \"hexstring\",\n" + " \"bits\": \"hexstring\",\n" + " \"difficulty\": ,\n" + " \"chainwork\": \"hexstring\",\n" + " \"previousblockhash\": \"hash\",\n" + " \"nextblockhash\": \"hash\"\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("getblockdeltas", "00227e566682aebd6a7a5b772c96d7a999cadaebeaf1ce96f4191a3aad58b00b") + + HelpExampleRpc("getblockdeltas", "\"00227e566682aebd6a7a5b772c96d7a999cadaebeaf1ce96f4191a3aad58b00b\"") + ); + + if (!enabled) { + throw JSONRPCError(RPC_MISC_ERROR, "Error: getblockdeltas is disabled. " + "Run './zcash-cli help getblockdeltas' for instructions on how to enable this feature."); + } + + std::string strHash = params[0].get_str(); + uint256 hash(uint256S(strHash)); + + if (mapBlockIndex.count(hash) == 0) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + + CBlock block; + CBlockIndex* pblockindex = mapBlockIndex[hash]; + + if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); + + if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); + + return blockToDeltasJSON(block, pblockindex); +} + UniValue getblockhash(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) @@ -1046,6 +1218,9 @@ static const CRPCCommand commands[] = { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true }, { "blockchain", "verifychain", &verifychain, true }, + // insightexplorer + { "blockchain", "getblockdeltas", &getblockdeltas, false }, + /* Not shown in help */ { "hidden", "invalidateblock", &invalidateblock, true }, { "hidden", "reconsiderblock", &reconsiderblock, true }, diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 137210a2313..8ba3c851596 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -99,6 +99,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "prioritisetransaction", 2 }, { "setban", 2 }, { "setban", 3 }, + { "getspentinfo", 0}, { "getaddresstxids", 0}, { "getaddressbalance", 0}, { "getaddressdeltas", 0}, diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index a34d7b2503c..84a2b47a1f1 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -484,6 +484,7 @@ UniValue setmocktime(const UniValue& params, bool fHelp) return NullUniValue; } +// insightexplorer static bool getAddressFromIndex( int type, const uint160 &hash, std::string &address) { @@ -520,6 +521,7 @@ static bool getIndexKey( return false; } +// insightexplorer static bool getAddressesFromParams( const UniValue& params, std::vector> &addresses) @@ -552,12 +554,13 @@ static bool getAddressesFromParams( return true; } +// insightexplorer UniValue getaddressmempool(const UniValue& params, bool fHelp) { std::string enableArg = "insightexplorer"; - bool fEnableGetAddressMempool = fExperimentalMode && fInsightExplorer; + bool enabled = fExperimentalMode && fInsightExplorer; std::string disabledMsg = ""; - if (!fEnableGetAddressMempool) { + if (!enabled) { disabledMsg = experimentalDisabledHelpMsg("getaddressmempool", enableArg); } if (fHelp || params.size() != 1) @@ -592,7 +595,7 @@ UniValue getaddressmempool(const UniValue& params, bool fHelp) + HelpExampleRpc("getaddressmempool", "{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"]}") ); - if (!fEnableGetAddressMempool) { + if (!enabled) { throw JSONRPCError(RPC_MISC_ERROR, "Error: getaddressmempool is disabled. " "Run './zcash-cli help getaddressmempool' for instructions on how to enable this feature."); } @@ -632,12 +635,13 @@ UniValue getaddressmempool(const UniValue& params, bool fHelp) return result; } +// insightexplorer UniValue getaddressutxos(const UniValue& params, bool fHelp) { std::string enableArg = "insightexplorer"; - bool fEnableGetAddressUtxos = fExperimentalMode && fInsightExplorer; + bool enabled = fExperimentalMode && fInsightExplorer; std::string disabledMsg = ""; - if (!fEnableGetAddressUtxos) { + if (!enabled) { disabledMsg = experimentalDisabledHelpMsg("getaddressutxos", enableArg); } if (fHelp || params.size() != 1) @@ -688,7 +692,7 @@ UniValue getaddressutxos(const UniValue& params, bool fHelp) + HelpExampleRpc("getaddressutxos", "{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"], \"chainInfo\": true}") ); - if (!fEnableGetAddressUtxos) { + if (!enabled) { throw JSONRPCError(RPC_MISC_ERROR, "Error: getaddressutxos is disabled. " "Run './zcash-cli help getaddressutxos' for instructions on how to enable this feature."); } @@ -790,12 +794,13 @@ static void getAddressesInHeightRange( } } +// insightexplorer UniValue getaddressdeltas(const UniValue& params, bool fHelp) { std::string enableArg = "insightexplorer"; - bool fEnableGetAddressDeltas = fExperimentalMode && fInsightExplorer; + bool enabled = fExperimentalMode && fInsightExplorer; std::string disabledMsg = ""; - if (!fEnableGetAddressDeltas) { + if (!enabled) { disabledMsg = experimentalDisabledHelpMsg("getaddressdeltas", enableArg); } if (fHelp || params.size() != 1) @@ -856,7 +861,7 @@ UniValue getaddressdeltas(const UniValue& params, bool fHelp) + HelpExampleRpc("getaddressdeltas", "{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"], \"start\": 1000, \"end\": 2000, \"chainInfo\": true}") ); - if (!fEnableGetAddressDeltas) { + if (!enabled) { throw JSONRPCError(RPC_MISC_ERROR, "Error: getaddressdeltas is disabled. " "Run './zcash-cli help getaddressdeltas' for instructions on how to enable this feature."); } @@ -920,12 +925,13 @@ UniValue getaddressdeltas(const UniValue& params, bool fHelp) return result; } +// insightexplorer UniValue getaddressbalance(const UniValue& params, bool fHelp) { std::string enableArg = "insightexplorer"; - bool fEnableGetAddressBalance = fExperimentalMode && fInsightExplorer; + bool enabled = fExperimentalMode && fInsightExplorer; std::string disabledMsg = ""; - if (!fEnableGetAddressBalance) { + if (!enabled) { disabledMsg = experimentalDisabledHelpMsg("getaddressbalance", enableArg); } if (fHelp || params.size() != 1) @@ -953,7 +959,7 @@ UniValue getaddressbalance(const UniValue& params, bool fHelp) + HelpExampleRpc("getaddressbalance", "{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"]}") ); - if (!fEnableGetAddressBalance) { + if (!enabled) { throw JSONRPCError(RPC_MISC_ERROR, "Error: getaddressbalance is disabled. " "Run './zcash-cli help getaddressbalance' for instructions on how to enable this feature."); } @@ -978,12 +984,13 @@ UniValue getaddressbalance(const UniValue& params, bool fHelp) return result; } +// insightexplorer UniValue getaddresstxids(const UniValue& params, bool fHelp) { std::string enableArg = "insightexplorer"; - bool fEnableGetAddressTxids = fExperimentalMode && fInsightExplorer; + bool enabled = fExperimentalMode && fInsightExplorer; std::string disabledMsg = ""; - if (!fEnableGetAddressTxids) { + if (!enabled) { disabledMsg = experimentalDisabledHelpMsg("getaddresstxids", enableArg); } if (fHelp || params.size() != 1) @@ -1014,7 +1021,7 @@ UniValue getaddresstxids(const UniValue& params, bool fHelp) + HelpExampleRpc("getaddresstxids", "{\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"], \"start\": 1000, \"end\": 2000}") ); - if (!fEnableGetAddressTxids) { + if (!enabled) { throw JSONRPCError(RPC_MISC_ERROR, "Error: getaddresstxids is disabled. " "Run './zcash-cli help getaddresstxids' for instructions on how to enable this feature."); } @@ -1044,6 +1051,64 @@ UniValue getaddresstxids(const UniValue& params, bool fHelp) return result; } +// insightexplorer +UniValue getspentinfo(const UniValue& params, bool fHelp) +{ + std::string enableArg = "insightexplorer"; + bool enabled = fExperimentalMode && fInsightExplorer; + std::string disabledMsg = ""; + if (!enabled) { + disabledMsg = experimentalDisabledHelpMsg("getspentinfo", enableArg); + } + if (fHelp || params.size() != 1 || !params[0].isObject()) + throw runtime_error( + "getspentinfo {\"txid\": \"txidhex\", \"index\": n}\n" + "\nReturns the txid and index where an output is spent.\n" + + disabledMsg + + "\nArguments:\n" + "{\n" + " \"txid\" (string) The hex string of the txid\n" + " \"index\" (number) The vout (output) index\n" + "}\n" + "\nResult:\n" + "{\n" + " \"txid\" (string) The transaction id\n" + " \"index\" (number) The spending (vin, input) index\n" + " ,...\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("getspentinfo", "'{\"txid\": \"0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9\", \"index\": 0}'") + + HelpExampleRpc("getspentinfo", "{\"txid\": \"0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9\", \"index\": 0}") + ); + + if (!enabled) { + throw JSONRPCError(RPC_MISC_ERROR, "Error: getspentinfo is disabled. " + "Run './zcash-cli help getspentinfo' for instructions on how to enable this feature."); + } + + UniValue txidValue = find_value(params[0].get_obj(), "txid"); + UniValue indexValue = find_value(params[0].get_obj(), "index"); + + if (!txidValue.isStr()) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid txid, must be a string"); + if (!indexValue.isNum()) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid index, must be an integer"); + uint256 txid = ParseHashV(txidValue, "txid"); + int outputIndex = indexValue.get_int(); + + CSpentIndexKey key(txid, outputIndex); + CSpentIndexValue value; + + if (!GetSpentIndex(key, value)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to get spent info"); + } + UniValue obj(UniValue::VOBJ); + obj.push_back(Pair("txid", value.txid.GetHex())); + obj.push_back(Pair("index", (int)value.inputIndex)); + obj.push_back(Pair("height", value.blockHeight)); + + return obj; +} static const CRPCCommand commands[] = { // category name actor (function) okSafeMode @@ -1054,12 +1119,15 @@ static const CRPCCommand commands[] = { "util", "createmultisig", &createmultisig, true }, { "util", "verifymessage", &verifymessage, true }, + // START insightexplorer /* Address index */ { "addressindex", "getaddresstxids", &getaddresstxids, false }, /* insight explorer */ { "addressindex", "getaddressbalance", &getaddressbalance, false }, /* insight explorer */ { "addressindex", "getaddressdeltas", &getaddressdeltas, false }, /* insight explorer */ { "addressindex", "getaddressutxos", &getaddressutxos, false }, /* insight explorer */ { "addressindex", "getaddressmempool", &getaddressmempool, true }, /* insight explorer */ + { "blockchain", "getspentinfo", &getspentinfo, false }, /* insight explorer */ + // END insightexplorer /* Not shown in help */ { "hidden", "setmocktime", &setmocktime, true }, diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 932c36241fa..441d3766cf5 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -197,6 +197,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) UniValue out(UniValue::VOBJ); out.push_back(Pair("value", ValueFromAmount(txout.nValue))); out.push_back(Pair("valueZat", txout.nValue)); + out.push_back(Pair("valueSat", txout.nValue)); out.push_back(Pair("n", (int64_t)i)); UniValue o(UniValue::VOBJ); ScriptPubKeyToJSON(txout.scriptPubKey, o, true); diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 7ce9172e591..5b2315687f4 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -378,6 +378,12 @@ BOOST_AUTO_TEST_CASE(rpc_insightexplorer) CheckRPCThrows("getaddresstxids \"a\"", "Error: getaddresstxids is disabled. " "Run './zcash-cli help getaddresstxids' for instructions on how to enable this feature."); + CheckRPCThrows("getspentinfo {\"a\":1}", + "Error: getspentinfo is disabled. " + "Run './zcash-cli help getspentinfo' for instructions on how to enable this feature."); + CheckRPCThrows("getblockdeltas \"a\"", + "Error: getblockdeltas is disabled. " + "Run './zcash-cli help getblockdeltas' for instructions on how to enable this feature."); fExperimentalMode = true; fInsightExplorer = true; @@ -416,6 +422,17 @@ BOOST_AUTO_TEST_CASE(rpc_insightexplorer) CheckRPCThrows("getaddresstxids {\"addresses\":[],\"start\":2,\"end\":3,\"chainInfo\":true}", "Start or end is outside chain range"); + // transaction does not exist: + CheckRPCThrows("getspentinfo {\"txid\":\"b4cc287e58f87cdae59417329f710f3ecd75a4ee1d2872b7248f50977c8493f3\",\"index\":0}", + "Unable to get spent info"); + CheckRPCThrows("getspentinfo {\"txid\":\"b4cc287e58f87cdae59417329f710f3ecd75a4ee1d2872b7248f50977c8493f3\"}", + "Invalid index, must be an integer"); + CheckRPCThrows("getspentinfo {\"txid\":\"hello\",\"index\":0}", + "txid must be hexadecimal string (not 'hello')"); + + CheckRPCThrows("getblockdeltas \"00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08\"", + "Block not found"); + // revert fExperimentalMode = false; fInsightExplorer = false; diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 2fc82cfb4ef..9c03b023d6f 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -153,6 +153,7 @@ void CTxMemPool::addAddressIndex(const CTxMemPoolEntry &entry, const CCoinsViewC mapAddressInserted.insert(make_pair(txhash, inserted)); } +// START insightexplorer void CTxMemPool::getAddressIndex( const std::vector>& addresses, std::vector>& results) @@ -181,6 +182,52 @@ void CTxMemPool::removeAddressIndex(const uint256& txhash) } } +void CTxMemPool::addSpentIndex(const CTxMemPoolEntry &entry, const CCoinsViewCache &view) +{ + LOCK(cs); + const CTransaction& tx = entry.GetTx(); + uint256 txhash = tx.GetHash(); + std::vector inserted; + + for (unsigned int j = 0; j < tx.vin.size(); j++) { + const CTxIn input = tx.vin[j]; + const CTxOut &prevout = view.GetOutputFor(input); + CSpentIndexKey key = CSpentIndexKey(input.prevout.hash, input.prevout.n); + CSpentIndexValue value = CSpentIndexValue(txhash, j, -1, prevout.nValue, + prevout.scriptPubKey.GetType(), + prevout.scriptPubKey.AddressHash()); + mapSpent.insert(make_pair(key, value)); + inserted.push_back(key); + } + mapSpentInserted.insert(make_pair(txhash, inserted)); +} + +bool CTxMemPool::getSpentIndex(const CSpentIndexKey &key, CSpentIndexValue &value) +{ + LOCK(cs); + std::map::iterator it = mapSpent.find(key); + if (it != mapSpent.end()) { + value = it->second; + return true; + } + return false; +} + +void CTxMemPool::removeSpentIndex(const uint256 txhash) +{ + LOCK(cs); + auto it = mapSpentInserted.find(txhash); + + if (it != mapSpentInserted.end()) { + std::vector keys = (*it).second; + for (std::vector::iterator mit = keys.begin(); mit != keys.end(); mit++) { + mapSpent.erase(*mit); + } + mapSpentInserted.erase(it); + } +} +// END insightexplorer + void CTxMemPool::remove(const CTransaction &origTx, std::list& removed, bool fRecursive) { // Remove transaction from memory pool @@ -231,9 +278,12 @@ void CTxMemPool::remove(const CTransaction &origTx, std::list& rem mapTx.erase(hash); nTransactionsUpdated++; minerPolicyEstimator->removeTx(hash); + // insightexplorer if (fAddressIndex) removeAddressIndex(hash); + if (fSpentIndex) + removeSpentIndex(hash); } } } diff --git a/src/txmempool.h b/src/txmempool.h index d3689c64f2e..6cd87a79c40 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -13,6 +13,7 @@ #include "primitives/transaction.h" #include "sync.h" #include "addressindex.h" +#include "spentindex.h" #undef foreach #include "boost/multi_index_container.hpp" @@ -155,8 +156,11 @@ class CTxMemPool indexed_transaction_set mapTx; private: + // insightexplorer std::map mapAddress; std::map > mapAddressInserted; + std::map mapSpent; + std::map> mapSpentInserted; public: std::map mapNextTx; @@ -176,11 +180,17 @@ class CTxMemPool bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, bool fCurrentEstimate = true); + // START insightexplorer void addAddressIndex(const CTxMemPoolEntry &entry, const CCoinsViewCache &view); void getAddressIndex(const std::vector>& addresses, std::vector>& results); void removeAddressIndex(const uint256& txhash); + void addSpentIndex(const CTxMemPoolEntry &entry, const CCoinsViewCache &view); + bool getSpentIndex(const CSpentIndexKey &key, CSpentIndexValue &value); + void removeSpentIndex(const uint256 txhash); + // END insightexplorer + void remove(const CTransaction &tx, std::list& removed, bool fRecursive = false); void removeWithAnchor(const uint256 &invalidRoot, ShieldedType type); void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags); From 2e505df3511f78396b3b4a9994888b857781d7ee Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Thu, 8 Aug 2019 14:35:07 -0600 Subject: [PATCH 223/395] add timestampindex related RPC getblockhashes --- qa/pull-tester/rpc-tests.sh | 1 + qa/rpc-tests/timestampindex.py | 94 ++++++++++++++++++++++++++++++++++ src/main.cpp | 13 +++++ src/main.h | 5 ++ src/rpc/blockchain.cpp | 84 ++++++++++++++++++++++++++++++ src/rpc/client.cpp | 3 ++ src/test/rpc_tests.cpp | 23 ++++++++- src/txdb.cpp | 2 +- src/txdb.h | 2 +- 9 files changed, 224 insertions(+), 3 deletions(-) create mode 100755 qa/rpc-tests/timestampindex.py diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index b5c3f708793..d82e7acddd0 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -59,6 +59,7 @@ testScripts=( 'reindex.py' 'addressindex.py' 'spentindex.py' + 'timestampindex.py' 'decodescript.py' 'blockchain.py' 'disablewallet.py' diff --git a/qa/rpc-tests/timestampindex.py b/qa/rpc-tests/timestampindex.py new file mode 100755 index 00000000000..f795bd5bfed --- /dev/null +++ b/qa/rpc-tests/timestampindex.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python +# Copyright (c) 2019 The Zcash developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . +# +# Test timestampindex generation and fetching for insightexplorer + +import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." + +import time + +from test_framework.test_framework import BitcoinTestFramework + +from test_framework.util import ( + assert_equal, + initialize_chain_clean, + start_nodes, + stop_nodes, + connect_nodes, + wait_bitcoinds, +) + + +class TimestampIndexTest(BitcoinTestFramework): + + def setup_chain(self): + print("Initializing test directory "+self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 3) + + def setup_network(self): + # -insightexplorer causes spentindex to be enabled (fSpentIndex = true) + + self.nodes = start_nodes( + 3, self.options.tmpdir, + [['-debug', '-txindex', '-experimentalfeatures', '-insightexplorer']]*3) + connect_nodes(self.nodes[0], 1) + connect_nodes(self.nodes[0], 2) + + self.is_network_split = False + self.sync_all() + + def run_test(self): + blockhashes = [] + print "Mining blocks..." + for _ in range(8): + blockhashes.extend(self.nodes[0].generate(1)) + time.sleep(1) + self.sync_all() + times = [self.nodes[1].getblock(b)['time'] for b in blockhashes] + assert_equal(blockhashes, self.nodes[1].getblockhashes(times[0]+100, 0)) + # test various ranges; the api returns blocks have times LESS THAN + # 'high' (first argument), not less than or equal, hence the +1 + assert_equal(blockhashes[0:8], self.nodes[1].getblockhashes(times[8-1]+1, times[0])) + assert_equal(blockhashes[2:6], self.nodes[1].getblockhashes(times[6-1]+1, times[2])) + assert_equal(blockhashes[5:8], self.nodes[1].getblockhashes(times[8-1]+1, times[5])) + assert_equal(blockhashes[6:7], self.nodes[1].getblockhashes(times[7-1]+1, times[6])) + assert_equal(blockhashes[4:6], self.nodes[1].getblockhashes(times[6-1]+1, times[4])) + assert_equal(blockhashes[1:1], self.nodes[1].getblockhashes(times[1-1]+1, times[1])) + + # Restart all nodes to ensure indices are saved to disk and recovered + stop_nodes(self.nodes) + wait_bitcoinds() + self.setup_network() + + # generating multiple blocks within the same second should + # result in timestamp index entries with unique times + # (not realistic but there is logic to ensure this) + blockhashes = self.nodes[0].generate(10) + self.sync_all() + firsttime = self.nodes[1].getblock(blockhashes[0])['time'] + assert_equal(blockhashes, self.nodes[1].getblockhashes(firsttime+10+1, firsttime)) + + # the api can also return 'logical' times, which is the key of the + # timestamp index (the content being blockhash). Logical times are + # block times when possible, but since keys must be unique, and the + # previous 10 block were generated in much less than 10 seconds, + # each logical time should be one greater than the previous. + results = self.nodes[1].getblockhashes( + firsttime+10+1, firsttime, + {'logicalTimes': True}) + ltimes = [r['logicalts'] for r in results] + assert_equal(ltimes, range(firsttime, firsttime+10)) + + # there's also a flag to exclude orphaned blocks; results should + # be the same in this test + assert_equal( + results, + self.nodes[1].getblockhashes( + firsttime+10+1, firsttime, + {'logicalTimes': True, 'noOrphans': True})) + + +if __name__ == '__main__': + TimestampIndexTest().main() diff --git a/src/main.cpp b/src/main.cpp index 793b824d620..92f2df7459a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1616,6 +1616,18 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa return true; } +bool GetTimestampIndex(unsigned int high, unsigned int low, bool fActiveOnly, + std::vector > &hashes) +{ + if (!fTimestampIndex) + return error("Timestamp index not enabled"); + + if (!pblocktree->ReadTimestampIndex(high, low, fActiveOnly, hashes)) + return error("Unable to get hashes for timestamps"); + + return true; +} + bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value) { AssertLockHeld(cs_main); @@ -4427,6 +4439,7 @@ bool static LoadBlockIndexDB() LogPrintf("%s: insight explorer %s\n", __func__, fAddressIndex ? "enabled" : "disabled"); fAddressIndex = fInsightExplorer; fSpentIndex = fInsightExplorer; + fTimestampIndex = fInsightExplorer; // Fill in-memory data BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex) diff --git a/src/main.h b/src/main.h index f3b46e3d9d5..cc07d24226f 100644 --- a/src/main.h +++ b/src/main.h @@ -150,6 +150,9 @@ extern bool fAddressIndex; // Maintain a full spent index, used to query the spending txid and input index for an outpoint extern bool fSpentIndex; +// Maintain a full timestamp index, used to query for blocks within a time range +extern bool fTimestampIndex; + // END insightexplorer extern bool fIsBareMultisigStd; @@ -444,6 +447,8 @@ bool GetAddressIndex(const uint160& addressHash, int type, int start = 0, int end = 0); bool GetAddressUnspent(const uint160& addressHash, int type, std::vector& unspentOutputs); +bool GetTimestampIndex(unsigned int high, unsigned int low, bool fActiveOnly, + std::vector > &hashes); /** Functions for disk access for blocks */ bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 86f01d9bd3f..382a59e0b07 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -485,6 +485,89 @@ UniValue getblockdeltas(const UniValue& params, bool fHelp) return blockToDeltasJSON(block, pblockindex); } +// insightexplorer +UniValue getblockhashes(const UniValue& params, bool fHelp) +{ + std::string enableArg = "insightexplorer"; + bool fEnableGetBlockHashes = fExperimentalMode && fInsightExplorer; + std::string disabledMsg = ""; + if (!fEnableGetBlockHashes) { + disabledMsg = experimentalDisabledHelpMsg("getblockhashes", enableArg); + } + if (fHelp || params.size() < 2) + throw runtime_error( + "getblockhashes high low ( {\"noOrphans\": true|false, \"logicalTimes\": true|false} )\n" + "\nReturns array of hashes of blocks within the timestamp range provided,\n" + "\ngreater or equal to low, less than high.\n" + + disabledMsg + + "\nArguments:\n" + "1. high (numeric, required) The newer block timestamp\n" + "2. low (numeric, required) The older block timestamp\n" + "3. options (string, optional) A json object\n" + " {\n" + " \"noOrphans\": true|false (boolean) will only include blocks on the main chain\n" + " \"logicalTimes\": true|false (boolean) will include logical timestamps with hashes\n" + " }\n" + "\nResult:\n" + "[\n" + " \"xxxx\" (hex string) The block hash\n" + "]\n" + "or\n" + "[\n" + " {\n" + " \"blockhash\": \"xxxx\" (hex string) The block hash\n" + " \"logicalts\": n (numeric) The logical timestamp\n" + " }\n" + "]\n" + "\nExamples:\n" + + HelpExampleCli("getblockhashes", "1558141697 1558141576") + + HelpExampleRpc("getblockhashes", "1558141697, 1558141576") + + HelpExampleCli("getblockhashes", "1558141697 1558141576 '{\"noOrphans\":false, \"logicalTimes\":true}'") + ); + + if (!fEnableGetBlockHashes) { + throw JSONRPCError(RPC_MISC_ERROR, "Error: getblockhashes is disabled. " + "Run './zcash-cli help getblockhashes' for instructions on how to enable this feature."); + } + + unsigned int high = params[0].get_int(); + unsigned int low = params[1].get_int(); + bool fActiveOnly = false; + bool fLogicalTS = false; + + if (params.size() > 2) { + UniValue noOrphans = find_value(params[2].get_obj(), "noOrphans"); + if (!noOrphans.isNull()) + fActiveOnly = noOrphans.get_bool(); + + UniValue returnLogical = find_value(params[2].get_obj(), "logicalTimes"); + if (!returnLogical.isNull()) + fLogicalTS = returnLogical.get_bool(); + } + + std::vector > blockHashes; + { + LOCK(cs_main); + if (!GetTimestampIndex(high, low, fActiveOnly, blockHashes)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, + "No information available for block hashes"); + } + } + UniValue result(UniValue::VARR); + for (std::vector >::const_iterator it=blockHashes.begin(); + it!=blockHashes.end(); it++) { + if (fLogicalTS) { + UniValue item(UniValue::VOBJ); + item.push_back(Pair("blockhash", it->first.GetHex())); + item.push_back(Pair("logicalts", (int)it->second)); + result.push_back(item); + } else { + result.push_back(it->first.GetHex()); + } + } + return result; +} + UniValue getblockhash(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) @@ -1220,6 +1303,7 @@ static const CRPCCommand commands[] = // insightexplorer { "blockchain", "getblockdeltas", &getblockdeltas, false }, + { "blockchain", "getblockhashes", &getblockhashes, true }, /* Not shown in help */ { "hidden", "invalidateblock", &invalidateblock, true }, diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 8ba3c851596..5abe8dcbdb5 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -105,6 +105,9 @@ static const CRPCConvertParam vRPCConvertParams[] = { "getaddressdeltas", 0}, { "getaddressutxos", 0}, { "getaddressmempool", 0}, + { "getblockhashes", 0}, + { "getblockhashes", 1}, + { "getblockhashes", 2}, { "zcrawjoinsplit", 1 }, { "zcrawjoinsplit", 2 }, { "zcrawjoinsplit", 3 }, diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 5b2315687f4..cd34ef7bd93 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -360,7 +360,8 @@ BOOST_AUTO_TEST_CASE(rpc_getnetworksolps) BOOST_CHECK_NO_THROW(CallRPC("getnetworksolps 120 -1")); } -// Test parameter processing (not functionality) +// Test parameter processing (not functionality). +// These tests also ensure that src/rpc/client.cpp has the correct entries. BOOST_AUTO_TEST_CASE(rpc_insightexplorer) { CheckRPCThrows("getaddressmempool \"a\"", @@ -384,9 +385,17 @@ BOOST_AUTO_TEST_CASE(rpc_insightexplorer) CheckRPCThrows("getblockdeltas \"a\"", "Error: getblockdeltas is disabled. " "Run './zcash-cli help getblockdeltas' for instructions on how to enable this feature."); + CheckRPCThrows("getblockhashes 0 0", + "Error: getblockhashes is disabled. " + "Run './zcash-cli help getblockhashes' for instructions on how to enable this feature."); + // During startup of the real system, fInsightExplorer ("-insightexplorer") + // automatically enables the next three, but not here, must explicitly enable. fExperimentalMode = true; fInsightExplorer = true; + fAddressIndex = true; + fSpentIndex = true; + fTimestampIndex = true; // must be a legal mainnet address const string addr = "t1T3G72ToPuCDTiCEytrU1VUBRHsNupEBut"; @@ -433,9 +442,21 @@ BOOST_AUTO_TEST_CASE(rpc_insightexplorer) CheckRPCThrows("getblockdeltas \"00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08\"", "Block not found"); + BOOST_CHECK_NO_THROW(CallRPC("getblockhashes 1477641360 1477641360")); + BOOST_CHECK_NO_THROW(CallRPC("getblockhashes 1477641360 1477641360 {\"noOrphans\":true,\"logicalTimes\":true}")); + // Unfortunately, an unknown or mangled key is ignored + BOOST_CHECK_NO_THROW(CallRPC("getblockhashes 1477641360 1477641360 {\"AAAnoOrphans\":true,\"logicalTimes\":true}")); + CheckRPCThrows("getblockhashes 1477641360 1477641360 {\"noOrphans\":true,\"logicalTimes\":1}", + "JSON value is not a boolean as expected"); + CheckRPCThrows("getblockhashes 1477641360 1477641360 {\"noOrphans\":True,\"logicalTimes\":false}", + "Error parsing JSON:{\"noOrphans\":True,\"logicalTimes\":false}"); + // revert fExperimentalMode = false; fInsightExplorer = false; + fAddressIndex = false; + fSpentIndex = false; + fTimestampIndex = false; } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/txdb.cpp b/src/txdb.cpp index 1e556152413..59cd7a86650 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -399,7 +399,7 @@ bool CBlockTreeDB::WriteTimestampIndex(const CTimestampIndexKey ×tampIndex) return WriteBatch(batch); } -bool CBlockTreeDB::ReadTimestampIndex(const unsigned int &high, const unsigned int &low, +bool CBlockTreeDB::ReadTimestampIndex(unsigned int high, unsigned int low, const bool fActiveOnly, std::vector > &hashes) { boost::scoped_ptr pcursor(NewIterator()); diff --git a/src/txdb.h b/src/txdb.h index 2e35d87bdf2..eebbc049273 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -125,7 +125,7 @@ class CBlockTreeDB : public CDBWrapper bool ReadSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value); bool UpdateSpentIndex(const std::vector &vect); bool WriteTimestampIndex(const CTimestampIndexKey ×tampIndex); - bool ReadTimestampIndex(const unsigned int &high, const unsigned int &low, + bool ReadTimestampIndex(unsigned int high, unsigned int low, const bool fActiveOnly, std::vector > &vect); bool WriteTimestampBlockIndex(const CTimestampBlockIndexKey &blockhashIndex, const CTimestampBlockIndexValue &logicalts); From 5bba8493d5ef0a4470935ec5d20ce6a001feb130 Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Thu, 8 Aug 2019 14:38:45 -0600 Subject: [PATCH 224/395] fix getblockdeltas documentation formatting --- src/rpc/blockchain.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 382a59e0b07..685b4d4ea67 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -414,7 +414,7 @@ UniValue getblockdeltas(const UniValue& params, bool fHelp) if (fHelp || params.size() != 1) throw runtime_error( "getblockdeltas \"blockhash\"\n" - "\nReturns the txid and index where an output is spent.\n" + "\nReturns information about the given block and its transactions.\n" + disabledMsg + "\nArguments:\n" "1. \"hash\" (string, required) The block hash\n" @@ -425,12 +425,12 @@ UniValue getblockdeltas(const UniValue& params, bool fHelp) " \"size\": n, (numeric) block size in bytes\n" " \"height\": n, (numeric) block height\n" " \"version\": n, (numeric) block version (e.g. 4)\n" - " \"merkleroot\": \"hash\", (string) block Merkle root\n" + " \"merkleroot\": \"hash\", (hexstring) block Merkle root\n" " \"deltas\": [\n" " {\n" - " \"txid\": \"hash\", (string) transaction ID\n" - " \"index\": n, (numeric) tx index in block\n" - " \"inputs\": [\n" + " \"txid\": \"hash\", (hexstring) transaction ID\n" + " \"index\": n, (numeric) The offset of the tx in the block\n" + " \"inputs\": [ (array of json objects)\n" " {\n" " \"address\": \"taddr\", (string) transparent address\n" " \"satoshis\": n, (numeric) negative of spend amount\n" @@ -439,7 +439,7 @@ UniValue getblockdeltas(const UniValue& params, bool fHelp) " \"prevout\": n (numeric) source utxo index\n" " }, ...\n" " ],\n" - " \"outputs\": [\n" + " \"outputs\": [ (array of json objects)\n" " {\n" " \"address\": \"taddr\", (string) transparent address\n" " \"satoshis\": n, (numeric) amount\n" @@ -448,14 +448,14 @@ UniValue getblockdeltas(const UniValue& params, bool fHelp) " ]\n" " }, ...\n" " ],\n" - " \"time\": n,\n" - " \"mediantime\": n,\n" - " \"nonce\": \"hexstring\",\n" - " \"bits\": \"hexstring\",\n" - " \"difficulty\": ,\n" - " \"chainwork\": \"hexstring\",\n" - " \"previousblockhash\": \"hash\",\n" - " \"nextblockhash\": \"hash\"\n" + " \"time\" : n, (numeric) The block version\n" + " \"mediantime\": n, (numeric) The most recent blocks' ave time\n" + " \"nonce\" : \"nonce\", (hex string) The nonce\n" + " \"bits\" : \"1d00ffff\", (hex string) The bits\n" + " \"difficulty\": n, (numeric) the current difficulty\n" + " \"chainwork\": \"xxxx\" (hex string) total amount of work in active chain\n" + " \"previousblockhash\" : \"hash\",(hex string) The hash of the previous block\n" + " \"nextblockhash\" : \"hash\" (hex string) The hash of the next block\n" "}\n" "\nExamples:\n" + HelpExampleCli("getblockdeltas", "00227e566682aebd6a7a5b772c96d7a999cadaebeaf1ce96f4191a3aad58b00b") From 6e7e50be4d42cea1e40388b48b3eda8840fae272 Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Thu, 8 Aug 2019 14:45:30 -0600 Subject: [PATCH 225/395] insightexplorer minor bug fixes --- src/main.cpp | 2 +- src/rpc/blockchain.cpp | 1 + src/rpc/client.cpp | 1 + src/test/rpc_tests.cpp | 5 ++++- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 92f2df7459a..d7f0da26f61 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1632,7 +1632,7 @@ bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value) { AssertLockHeld(cs_main); if (!fSpentIndex) - return false; + return error("spent index not enabled"); if (mempool.getSpentIndex(key, value)) return true; return pblocktree->ReadSpentIndex(key, value); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 685b4d4ea67..a140d42a49e 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -190,6 +190,7 @@ UniValue blockToDeltasJSON(const CBlock& block, const CBlockIndex* blockindex) if (IsValidDestination(dest)) { delta.push_back(Pair("address", EncodeDestination(dest))); } + delta.push_back(Pair("address", EncodeDestination(dest))); delta.push_back(Pair("satoshis", out.nValue)); delta.push_back(Pair("index", (int)k)); diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 5abe8dcbdb5..8abc834aa78 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -108,6 +108,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "getblockhashes", 0}, { "getblockhashes", 1}, { "getblockhashes", 2}, + { "getblockdeltas", 0}, { "zcrawjoinsplit", 1 }, { "zcrawjoinsplit", 2 }, { "zcrawjoinsplit", 3 }, diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index cd34ef7bd93..c95c123e5a0 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -439,7 +439,10 @@ BOOST_AUTO_TEST_CASE(rpc_insightexplorer) CheckRPCThrows("getspentinfo {\"txid\":\"hello\",\"index\":0}", "txid must be hexadecimal string (not 'hello')"); - CheckRPCThrows("getblockdeltas \"00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08\"", + // only the mainnet genesis block exists + BOOST_CHECK_NO_THROW(CallRPC("getblockdeltas \"00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08\"")); + // damage the block hash (change last digit) + CheckRPCThrows("getblockdeltas \"00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce09\"", "Block not found"); BOOST_CHECK_NO_THROW(CallRPC("getblockhashes 1477641360 1477641360")); From 70bda8416a410e2618e641b587d0bc845feec088 Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Thu, 8 Aug 2019 14:54:47 -0600 Subject: [PATCH 226/395] insightexplorer fix LogPrintf --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index d7f0da26f61..f5ced690676 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4436,7 +4436,7 @@ bool static LoadBlockIndexDB() // insightexplorer // Check whether block explorer features are enabled pblocktree->ReadFlag("insightexplorer", fInsightExplorer); - LogPrintf("%s: insight explorer %s\n", __func__, fAddressIndex ? "enabled" : "disabled"); + LogPrintf("%s: insight explorer %s\n", __func__, fInsightExplorer ? "enabled" : "disabled"); fAddressIndex = fInsightExplorer; fSpentIndex = fInsightExplorer; fTimestampIndex = fInsightExplorer; From 7c5a791b73775c4c51767113d50cb4f931a53591 Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Fri, 9 Aug 2019 15:27:52 -0600 Subject: [PATCH 227/395] insightexplorer: formatting, pyflakes cleanups --- qa/rpc-tests/addressindex.py | 21 ++++++++++----------- qa/rpc-tests/spentindex.py | 27 ++++++++++++++++----------- src/rpc/misc.cpp | 4 ++-- 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/qa/rpc-tests/addressindex.py b/qa/rpc-tests/addressindex.py index f924f087506..b4562f9ef38 100755 --- a/qa/rpc-tests/addressindex.py +++ b/qa/rpc-tests/addressindex.py @@ -1,8 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2019 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # # Test addressindex generation and fetching for insightexplorer # @@ -13,23 +12,20 @@ # getaddressdeltas # getaddressutxos # getaddressmempool -# import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." from test_framework.test_framework import BitcoinTestFramework - from test_framework.util import ( assert_equal, initialize_chain_clean, start_nodes, stop_nodes, connect_nodes, + wait_bitcoinds, ) -from test_framework.util import wait_bitcoinds - from test_framework.script import ( CScript, OP_HASH160, @@ -38,8 +34,11 @@ OP_DROP, ) -from test_framework.mininode import COIN, CTransaction -from test_framework.mininode import CTxIn, CTxOut, COutPoint +from test_framework.mininode import ( + COIN, + CTransaction, + CTxIn, CTxOut, COutPoint, +) from binascii import hexlify @@ -100,7 +99,7 @@ def check_balance(node_index, address, expected_balance, expected_received=None) assert_equal(self.nodes[1].getbalance(), 0) # only the oldest 5; subsequent are not yet mature - unspent_txids = [ u['txid'] for u in self.nodes[0].listunspent() ] + unspent_txids = [u['txid'] for u in self.nodes[0].listunspent()] # Currently our only unspents are coinbase transactions, choose any one tx = self.nodes[0].getrawtransaction(unspent_txids[0], 1) @@ -139,7 +138,7 @@ def check_balance(node_index, address, expected_balance, expected_received=None) txids_a1 = [] addr1 = self.nodes[1].getnewaddress() expected = 0 - expected_deltas = [] # for checking getaddressdeltas (below) + expected_deltas = [] # for checking getaddressdeltas (below) for i in range(5): # first transaction happens at height 105, mined in block 106 txid = self.nodes[0].sendtoaddress(addr1, i + 1) @@ -213,7 +212,7 @@ def check_balance(node_index, address, expected_balance, expected_received=None) 'satoshis': (-4) * COIN, 'txid': txid, }) - self.sync_all() # ensure transaction is included in the next block + self.sync_all() # ensure transaction is included in the next block self.nodes[0].generate(1) self.sync_all() diff --git a/qa/rpc-tests/spentindex.py b/qa/rpc-tests/spentindex.py index 28e626573d2..dbda29090ac 100755 --- a/qa/rpc-tests/spentindex.py +++ b/qa/rpc-tests/spentindex.py @@ -1,25 +1,28 @@ #!/usr/bin/env python # Copyright (c) 2019 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -# -# Test spentindex generation and fetching +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # +# Test spentindex generation and fetching for insightexplorer import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." from test_framework.test_framework import BitcoinTestFramework from test_framework.authproxy import JSONRPCException -from test_framework.util import assert_equal -from test_framework.util import initialize_chain_clean -from test_framework.util import start_nodes, stop_nodes, connect_nodes -from test_framework.util import wait_bitcoinds -from test_framework.util import fail +from test_framework.util import ( + assert_equal, + initialize_chain_clean, + start_nodes, + stop_nodes, + connect_nodes, + wait_bitcoinds, + fail, +) from test_framework.mininode import COIN + class SpentIndexTest(BitcoinTestFramework): def setup_chain(self): @@ -29,7 +32,8 @@ def setup_chain(self): def setup_network(self): # -insightexplorer causes spentindex to be enabled (fSpentIndex = true) - self.nodes = start_nodes(3, self.options.tmpdir, + self.nodes = start_nodes( + 3, self.options.tmpdir, [['-debug', '-txindex', '-experimentalfeatures', '-insightexplorer']]*3) connect_nodes(self.nodes[0], 1) connect_nodes(self.nodes[0], 2) @@ -74,7 +78,7 @@ def run_test(self): # Check new fields added to getrawtransaction tx1 = self.nodes[2].getrawtransaction(txid1, 1) - assert_equal(tx1['vin'][0]['value'], 10) # coinbase + assert_equal(tx1['vin'][0]['value'], 10) # coinbase assert_equal(tx1['vin'][0]['valueSat'], 10*COIN) # we want the non-change (payment) output vout = filter(lambda o: o['value'] == 2, tx1['vout']) @@ -178,5 +182,6 @@ def run_test(self): assert_equal(len(out), 1) assert_equal(out[0]['address'], addr2) + if __name__ == '__main__': SpentIndexTest().main() diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 84a2b47a1f1..00e76a81d2b 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -1077,8 +1077,8 @@ UniValue getspentinfo(const UniValue& params, bool fHelp) " ,...\n" "}\n" "\nExamples:\n" - + HelpExampleCli("getspentinfo", "'{\"txid\": \"0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9\", \"index\": 0}'") - + HelpExampleRpc("getspentinfo", "{\"txid\": \"0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9\", \"index\": 0}") + + HelpExampleCli("getspentinfo", "'{\"txid\": \"33990288fb116981260be1de10b8c764f997674545ab14f9240f00346333b780\", \"index\": 4}'") + + HelpExampleRpc("getspentinfo", "{\"txid\": \"33990288fb116981260be1de10b8c764f997674545ab14f9240f00346333b780\", \"index\": 4}") ); if (!enabled) { From 0b83bf493a75a42172945765bf88256fb9d1d802 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 9 Aug 2019 16:52:27 -0600 Subject: [PATCH 228/395] make-release.py: Versioning changes for 2.0.7-rc1. --- README.md | 2 +- configure.ac | 4 ++-- contrib/gitian-descriptors/gitian-linux.yml | 2 +- src/clientversion.h | 4 ++-- src/deprecation.h | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d189099feb1..afcc3b9e92f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Zcash 2.0.6 +Zcash 2.0.7-rc1 =========== diff --git a/configure.ac b/configure.ac index 05b4667e822..45de7879ad6 100644 --- a/configure.ac +++ b/configure.ac @@ -2,8 +2,8 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 2) define(_CLIENT_VERSION_MINOR, 0) -define(_CLIENT_VERSION_REVISION, 6) -define(_CLIENT_VERSION_BUILD, 50) +define(_CLIENT_VERSION_REVISION, 7) +define(_CLIENT_VERSION_BUILD, 25) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index d770c29fc31..18367845d3e 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "zcash-2.0.6" +name: "zcash-2.0.7-rc1" enable_cache: true distro: "debian" suites: diff --git a/src/clientversion.h b/src/clientversion.h index edca19ca9e4..9bda73361a5 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -17,8 +17,8 @@ //! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 2 #define CLIENT_VERSION_MINOR 0 -#define CLIENT_VERSION_REVISION 6 -#define CLIENT_VERSION_BUILD 50 +#define CLIENT_VERSION_REVISION 7 +#define CLIENT_VERSION_BUILD 25 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/deprecation.h b/src/deprecation.h index ab7ffb299f3..e9e527ff277 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -8,7 +8,7 @@ // Deprecation policy: // * Shut down 16 weeks' worth of blocks after the estimated release block height. // * A warning is shown during the 2 weeks' worth of blocks prior to shut down. -static const int APPROX_RELEASE_HEIGHT = 553000; +static const int APPROX_RELEASE_HEIGHT = 584200; static const int WEEKS_UNTIL_DEPRECATION = 16; static const int DEPRECATION_HEIGHT = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 24); From 9055babafd3c99c92cba54a40662e70d17c87938 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 9 Aug 2019 17:05:51 -0600 Subject: [PATCH 229/395] make-release.py: Updated manpages for 2.0.7-rc1. --- doc/man/zcash-cli.1 | 10 +++++----- doc/man/zcash-tx.1 | 10 +++++----- doc/man/zcashd.1 | 15 ++++++++------- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/doc/man/zcash-cli.1 b/doc/man/zcash-cli.1 index 741de3dba72..d14a26b3eb7 100644 --- a/doc/man/zcash-cli.1 +++ b/doc/man/zcash-cli.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4. -.TH ZCASH-CLI "1" "June 2019" "zcash-cli v2.0.6" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. +.TH ZCASH-CLI "1" "August 2019" "zcash-cli v2.0.7-rc1" "User Commands" .SH NAME -zcash-cli \- manual page for zcash-cli v2.0.6 +zcash-cli \- manual page for zcash-cli v2.0.7-rc1 .SH DESCRIPTION -Zcash RPC client version v2.0.6 +Zcash RPC client version v2.0.7\-rc1 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . @@ -81,7 +81,7 @@ Copyright (C) 2015-2019 The Zcash Developers This is experimental software. Distributed under the MIT software license, see the accompanying file COPYING -or . +or . This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit and cryptographic software written diff --git a/doc/man/zcash-tx.1 b/doc/man/zcash-tx.1 index 1353e34a7f4..51d2305d611 100644 --- a/doc/man/zcash-tx.1 +++ b/doc/man/zcash-tx.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4. -.TH ZCASH-TX "1" "June 2019" "zcash-tx v2.0.6" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. +.TH ZCASH-TX "1" "August 2019" "zcash-tx v2.0.7-rc1" "User Commands" .SH NAME -zcash-tx \- manual page for zcash-tx v2.0.6 +zcash-tx \- manual page for zcash-tx v2.0.7-rc1 .SH DESCRIPTION -Zcash zcash\-tx utility version v2.0.6 +Zcash zcash\-tx utility version v2.0.7\-rc1 .SS "Usage:" .TP zcash\-tx [options] [commands] @@ -94,7 +94,7 @@ Copyright (C) 2015-2019 The Zcash Developers This is experimental software. Distributed under the MIT software license, see the accompanying file COPYING -or . +or . This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit and cryptographic software written diff --git a/doc/man/zcashd.1 b/doc/man/zcashd.1 index 491550c9768..fe8979d8769 100644 --- a/doc/man/zcashd.1 +++ b/doc/man/zcashd.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4. -.TH ZCASHD "1" "June 2019" "zcashd v2.0.6" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. +.TH ZCASHD "1" "August 2019" "zcashd v2.0.7-rc1" "User Commands" .SH NAME -zcashd \- manual page for zcashd v2.0.6 +zcashd \- manual page for zcashd v2.0.7-rc1 .SH DESCRIPTION -Zcash Daemon version v2.0.6 +Zcash Daemon version v2.0.7\-rc1 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . @@ -75,7 +75,7 @@ limit applied) .HP \fB\-par=\fR .IP -Set the number of script verification threads (\fB\-6\fR to 16, 0 = auto, <0 = +Set the number of script verification threads (\fB\-4\fR to 16, 0 = auto, <0 = leave that many cores free, default: 0) .HP \fB\-pid=\fR @@ -276,7 +276,8 @@ confirmation on average within n blocks (default: 2) \fB\-txexpirydelta\fR .IP Set the number of blocks after which a transaction that has not been -mined will become invalid (min: 4, default: 20) +mined will become invalid (min: 4, default: 20 (pre\-Blossom) or 40 +(post\-Blossom)) .HP \fB\-maxtxfee=\fR .IP @@ -484,7 +485,7 @@ Copyright (C) 2015-2019 The Zcash Developers This is experimental software. Distributed under the MIT software license, see the accompanying file COPYING -or . +or . This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit and cryptographic software written From 017c933e371b06cca42c9b56ea8f36c5f9444885 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 9 Aug 2019 17:05:52 -0600 Subject: [PATCH 230/395] make-release.py: Updated release notes and changelog for 2.0.7-rc1. --- contrib/debian/changelog | 6 + doc/release-notes/release-notes-2.0.7-rc1.md | 118 +++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 doc/release-notes/release-notes-2.0.7-rc1.md diff --git a/contrib/debian/changelog b/contrib/debian/changelog index ed12564cf6c..3a636d1edef 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,9 @@ +zcash (2.0.7~rc1) stable; urgency=medium + + * 2.0.7-rc1 release. + + -- Electric Coin Company Fri, 09 Aug 2019 17:05:51 -0600 + zcash (2.0.6) stable; urgency=medium * 2.0.6 release. diff --git a/doc/release-notes/release-notes-2.0.7-rc1.md b/doc/release-notes/release-notes-2.0.7-rc1.md new file mode 100644 index 00000000000..ab448862a21 --- /dev/null +++ b/doc/release-notes/release-notes-2.0.7-rc1.md @@ -0,0 +1,118 @@ +Changelog +========= + +Daira Hopwood (10): + Add MIT license to Makefiles + Add MIT license to build-aux/m4/bitcoin_* scripts, and a permissive license to build-aux/m4/l_atomic.m4 . + Update copyright information for Zcash, leveldb, and libsnark. + Add license information for Autoconf macros. refs #2827 + Update contrib/debian/copyright for ax_boost_thread.m4 + Replace http with https: in links to the MIT license. Also change MIT/X11 to just MIT, since no distinction was intended. + qa/zcash/checksec.sh is under a BSD license, with a specialized non-endorsement clause. + Link to ticket #2827 using URL + Release process doc: add step to set the gpg key id. + Release process doc: mention the commit message. + +Dimitris Apostolou (5): + Rename vjoinsplit to vJoinSplit + Fix naming inconsistency + Rename joinsplit to shielded + Rename FindWalletTx to FindWalletTxToZap + Fix RPC undefined behavior. + +Eirik Ogilvie-Wigley (47): + Make nextHeight required in CalculateNextWorkRequired + Fix nondeterministic failure in sapling migration test + Clean up and fix typo + Apply suggestions from code review + Shorter block times rpc test + Update pow_tests for shorter block times + Update test_pow for shorter block times + Update block subsidy halving for zip208 + Make NetworkUpgradeAvailable a method of Params + Temporarily disable test + Simplify PartitionCheck + Use static_assert + Add missing new line at end of file + pow test cleanup + Add message to static_assert + Update expiry height for shorter block times + Fix zip208 founders reward calculation and update test + PartitionCheck tests for shorter block times + Add test for Blossom default tx expiry delta + Update metrics block height estimation for shorter block times + Do not create transactions that will expire after the next epoch + Do not send migration transactions that would expire after a network upgrade + Fix integer truncation in Blossom halving calculation + Update main_tests for shorter block times + Use pre-Blossom max FR height when calculating address change interval + Make founders reward tests pass before and after Blossom activation height is set + Extract Halvings method and add tests + Add comments and fix typos + Improve EstimateNetHeight calculation + Fix check transaction tests + Make sure to deactivate blossom in test case + Fix parsing txexpirydelta argument + Do not add expiring soon threshold to expiry height of txs near NU activation + Fix/update comments + Make sure that expiry height is not less than height + Clarify documentation + Update PoW related assertions + Remove DefaultExpiryDelta method + Algebraic improvements related to halving + Distinguish between height and current header height on metrics screen + Test clean up and fixes + Add copyright info + NPE defense in metrics screen + Do not estimate height if there is no best header + Rename method and use int64_t + make-release.py: Versioning changes for 2.0.7-rc1. + make-release.py: Updated manpages for 2.0.7-rc1. + +Eirik Ogilvie-Wigley (8): + Use CommitTransaction() rather than sendrawtransaction() + Move reused async rpc send logic to separate file + Move reused sign and send logic + Do not shadow the return value when testmode is true + Inline sign_send_raw_transaction + Allow passing optional reserve key as a parameter to SendTransaction + Use reserve key for transparent change when sending to Sapling + Fix comment in mergetoaddress RPC test + +Jack Grigg (4): + test: Check for change t-addr reuse in z_sendmany + Use reserve key for transparent change when sending to Sprout + test: Fix permissions on wallet_changeaddresses RPC test + test: Fix pyflakes warnings + +Larry Ruane (6): + add addressindex related RPCs + add spentindex RPC for bitcore block explorer + add timestampindex related RPC getblockhashes + fix getblockdeltas documentation formatting + insightexplorer minor bug fixes + insightexplorer fix LogPrintf + +Luke Dashjr (2): + Add MIT license to autogen.sh and share/genbuild.sh + Trivial: build-aux/m4/l_atomic: Fix typo + +Simon Liu (8): + Redefine PoW functions to accept height parameter. + Remove use of redundant member nPowTargetSpacing. + Replace nPoWTargetSpacing -> PoWTargetSpacing() + Update PoW function calls to pass in height. + Update GetBlockTimeout() to take height parameter. + Replace nPoWTargetSpacing -> PoWTargetSpacing() in ProcessMessage() + Replace nPoWTargetSpacing -> PoWTargetSpacing() in tests + Modify PartitionCheck to be aware of pre & post Blossom target spacing. + +William M Peaster (1): + Handful of copyedits to README.md + +codetriage-readme-bot (1): + Link to development guidelines in CONTRIBUTING.md + +Jack Grigg (1): + Update README.md + From 929b302e4082279a602059c737b958bf01327ef5 Mon Sep 17 00:00:00 2001 From: zebambam Date: Wed, 14 Aug 2019 11:42:31 -0700 Subject: [PATCH 231/395] Updated location to new download server --- qa/zcash/test-depends-sources-mirror.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qa/zcash/test-depends-sources-mirror.py b/qa/zcash/test-depends-sources-mirror.py index e09c2c238f6..85dd146b8b5 100755 --- a/qa/zcash/test-depends-sources-mirror.py +++ b/qa/zcash/test-depends-sources-mirror.py @@ -12,7 +12,7 @@ import os import requests -MIRROR_URL_DIR="https://z.cash/depends-sources/" +MIRROR_URL_DIR="https://download.z.cash/depends-sources/" DEPENDS_SOURCES_DIR=os.path.realpath(os.path.join( os.path.dirname(__file__), "..", "..", "depends", "sources" From c4bfc3a257c975e75baa1bfa6ce183aa1d9e8137 Mon Sep 17 00:00:00 2001 From: zebambam Date: Tue, 13 Aug 2019 16:38:26 -0700 Subject: [PATCH 232/395] Fixes 4097, improves caching on parameter downloads --- zcutil/fetch-params.sh | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/zcutil/fetch-params.sh b/zcutil/fetch-params.sh index 1c1bec5fb64..300e12341a9 100755 --- a/zcutil/fetch-params.sh +++ b/zcutil/fetch-params.sh @@ -13,7 +13,7 @@ SPROUT_VKEY_NAME='sprout-verifying.key' SAPLING_SPEND_NAME='sapling-spend.params' SAPLING_OUTPUT_NAME='sapling-output.params' SAPLING_SPROUT_GROTH16_NAME='sprout-groth16.params' -SPROUT_URL="https://z.cash/downloads" +SPROUT_URL="https://download.z.cash/downloads" SPROUT_IPFS="/ipfs/QmZKKx7Xup7LiAtFRhYsE1M7waXcv9ir9eCECyXAFGxhEo" SHA256CMD="$(command -v sha256sum || echo shasum)" @@ -107,13 +107,27 @@ function fetch_params { if ! [ -f "$output" ] then - for method in wget ipfs curl failure; do - if "fetch_$method" "$filename" "$dlname"; then - echo "Download successful!" - break + for i in 1 2 + do + for method in wget ipfs curl failure; do + if "fetch_$method" "${filename}.part.${i}" "${dlname}.part.${i}"; then + echo "Download of part ${i} successful!" + break + fi + done + done + + for i in 1 2 + do + if ! [ -f "${dlname}.part.${i}" ] + then + fetch_failure fi done + cat "${dlname}.part.1" "${dlname}.part.2" > "${dlname}" + rm "${dlname}.part.1" "${dlname}.part.2" + "$SHA256CMD" $SHA256ARGS -c < Date: Thu, 18 Jul 2019 12:13:27 +0200 Subject: [PATCH 233/395] test: Fix AuthServiceProxy closed conn detection --- qa/rpc-tests/test_framework/authproxy.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/qa/rpc-tests/test_framework/authproxy.py b/qa/rpc-tests/test_framework/authproxy.py index 28b33e2867c..c3b3e7eb307 100644 --- a/qa/rpc-tests/test_framework/authproxy.py +++ b/qa/rpc-tests/test_framework/authproxy.py @@ -120,10 +120,12 @@ def _request(self, method, path, postdata): return self._get_response() except Exception as e: # If connection was closed, try again. + # Python 2.7 error message was changed in https://github.com/python/cpython/pull/2825 # Python 3.5+ raises BrokenPipeError instead of BadStatusLine when the connection was reset. # ConnectionResetError happens on FreeBSD with Python 3.4. # These classes don't exist in Python 2.x, so we can't refer to them directly. - if ((isinstance(e, httplib.BadStatusLine) and e.line == "''") + if ((isinstance(e, httplib.BadStatusLine) + and e.line in ("''", "No status line received - the server has closed the connection")) or e.__class__.__name__ in ('BrokenPipeError', 'ConnectionResetError')): self.__conn.close() self.__conn.request(method, path, postdata, headers) From f58bc7b638c74c667c7750f2d25ce55dc9479fd3 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 16 Aug 2019 20:18:40 +0100 Subject: [PATCH 234/395] Add RPC test and test framework constants for Sapling->Blossom activation. Signed-off-by: Daira Hopwood --- qa/rpc-tests/mempool_nu_activation.py | 19 +++++++++++++++---- qa/rpc-tests/test_framework/mininode.py | 13 ++++++++++++- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/qa/rpc-tests/mempool_nu_activation.py b/qa/rpc-tests/mempool_nu_activation.py index 6a862635b48..8a88deed125 100755 --- a/qa/rpc-tests/mempool_nu_activation.py +++ b/qa/rpc-tests/mempool_nu_activation.py @@ -6,9 +6,11 @@ import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal, initialize_chain_clean, \ - start_node, connect_nodes, wait_and_assert_operationid_status, \ +from test_framework.util import ( + assert_equal, assert_true, initialize_chain_clean, + start_node, connect_nodes, wait_and_assert_operationid_status, get_coinbase_address +) from test_framework.authproxy import JSONRPCException from decimal import Decimal @@ -22,6 +24,7 @@ def setup_network(self): args = ["-checkmempool", "-debug=mempool", "-blockmaxsize=4000", "-nuparams=5ba81b19:200", # Overwinter "-nuparams=76b809bb:210", # Sapling + "-nuparams=2bb40e60:220", # Blossom ] self.nodes = [] self.nodes.append(start_node(0, self.options.tmpdir, args)) @@ -72,10 +75,10 @@ def nu_activation_checks(): while self.nodes[1].getmempoolinfo()['bytes'] < 2 * 4000: try: x_txids.append(self.nodes[1].sendtoaddress(node0_taddr, Decimal('0.001'))) - assert_equal(chaintip_branchid, "00000000") except JSONRPCException: # This fails due to expiring soon threshold, which applies from Overwinter onwards. - assert_equal(info["upgrades"][chaintip_branchid]["name"], "Overwinter") + upgrade_name = info["upgrades"][chaintip_branchid]["name"] + assert_true(upgrade_name in ("Overwinter", "Sapling"), upgrade_name) break self.sync_all() @@ -156,5 +159,13 @@ def nu_activation_checks(): nu_activation_checks() # Current height = 215 + self.nodes[0].generate(2) + self.sync_all() + + print('Testing Sapling -> Blossom activation boundary') + # Current height = 217 + nu_activation_checks() + # Current height = 225 + if __name__ == '__main__': MempoolUpgradeActivationTest().main() diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index bbeaaf8f88f..fc9693e5b6b 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -39,13 +39,24 @@ zcash_person, ) -OVERWINTER_PROTO_VERSION = 170003 BIP0031_VERSION = 60000 SPROUT_PROTO_VERSION = 170002 # past bip-31 for ping/pong +OVERWINTER_PROTO_VERSION = 170003 SAPLING_PROTO_VERSION = 170006 +BLOSSOM_TESTNET_PROTO_VERSION = 170007 +BLOSSOM_PROTO_VERSION = 170008 + MY_SUBVERSION = "/python-mininode-tester:0.0.1/" +SPROUT_VERSION_GROUP_ID = 0x00000000 OVERWINTER_VERSION_GROUP_ID = 0x03C48270 +SAPLING_VERSION_GROUP_ID = 0x892F2085 +# No transaction format change in Blossom. + +SPROUT_BRANCH_ID = 0x00000000 +OVERWINTER_BRANCH_ID = 0x5BA81B19 +SAPLING_BRANCH_ID = 0x76B809BB +BLOSSOM_BRANCH_ID = 0x2BB40E60 MAX_INV_SZ = 50000 From b49e782ebae52363353f15476fefa739ea13d4d1 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 16 Aug 2019 12:47:43 -0600 Subject: [PATCH 235/395] Update download path --- depends/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/depends/Makefile b/depends/Makefile index 5c1fb9fdd34..aa07755f0d9 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -4,7 +4,7 @@ SOURCES_PATH ?= $(BASEDIR)/sources BASE_CACHE ?= $(BASEDIR)/built SDK_PATH ?= $(BASEDIR)/SDKs NO_WALLET ?= -PRIORITY_DOWNLOAD_PATH ?= https://z.cash/depends-sources +PRIORITY_DOWNLOAD_PATH ?= https://download.z.cash/depends-sources BUILD ?= $(shell ./config.guess) HOST ?= $(BUILD) From 1288fb1dd8b89b1bf0bf4eba270d7b6b93d88fc8 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 16 Aug 2019 12:55:41 -0600 Subject: [PATCH 236/395] Set testnet Blossom activation height --- src/chainparams.cpp | 3 +-- src/version.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index cf21eceb089..f322df6f6b3 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -306,8 +306,7 @@ class CTestNetParams : public CChainParams { consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nProtocolVersion = 170007; consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = 280000; consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].nProtocolVersion = 170008; - consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight = - Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; + consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight = 584000; // The best chain should have at least this much work. consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000000000001d0c4d9cd"); diff --git a/src/version.h b/src/version.h index ed0b111b11d..6a1a25f9bc9 100644 --- a/src/version.h +++ b/src/version.h @@ -9,7 +9,7 @@ * network protocol versioning */ -static const int PROTOCOL_VERSION = 170007; +static const int PROTOCOL_VERSION = 170008; //! initial proto version, to be increased after version/verack negotiation static const int INIT_PROTO_VERSION = 209; From 6bb36fb379f848e1e7598e0ddb57bf4290e18a70 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 16 Aug 2019 13:13:53 -0600 Subject: [PATCH 237/395] Notable changes for v2.0.7 --- doc/release-notes.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index a29094b5174..8b46eb35f5e 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,3 +4,14 @@ release-notes at release time) Notable changes =============== +Shorter Block Times +------------------- +Shorter block times are coming to Zcash! In the v2.0.7 release we have implemented [ZIP208](https://github.com/zcash/zips/blob/master/zip-0208.rst) which take effect when Blossom activates. Upon activation, the block times for Zcash will decrease from 150s to 75s, and the block reward will will decrease accordingly. This effects at what block height halving events will occur, but should not effect the overall rate at which Zcash is mined. The total founder's reward stays the same, and the total supply of Zcash is decreased microscopically due to rounding. + +Blossom Activation on Testnet +----------------------------- +The v2.0.7 release includes Blossom activation on testnet bringing shorter block times. Testnet Blossom activation height is 584000. + +Insight Explorer +---------------- +The insight explorer has been incorporated in to Zcash. *This is an experimental feature* and therefore is subject change. To enable add the `experimentalfeatures=1`, `txindex=1`, and `insightexplorer=1` flags to `zcash.conf`. This feature adds several RPCs to `zcashd` which allow the user to run an insight explorer. From 94f642c80abab38dbb545bb13cbdf1eb4ce8d3b3 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 16 Aug 2019 13:17:21 -0600 Subject: [PATCH 238/395] Enable shorter block times rpc test --- qa/pull-tester/rpc-tests.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index 73da74b6c83..d7035144486 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -77,8 +77,7 @@ testScripts=( 'p2p_node_bloom.py' 'regtest_signrawtransaction.py' 'finalsaplingroot.py' - # TODO: enable the following test when updating PROTOCOL_VERSION in version.h for Blossom - # 'shorter_block_times.py' + 'shorter_block_times.py' 'sprout_sapling_migration.py' 'turnstile.py' ); From b6499624fe8c115edd992d5fa03998ef4da34696 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 16 Aug 2019 16:07:15 -0600 Subject: [PATCH 239/395] Grammatical fixes and improvements Co-Authored-By: Daira Hopwood --- doc/release-notes.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index 8b46eb35f5e..0fba2dc2c42 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -6,12 +6,12 @@ Notable changes Shorter Block Times ------------------- -Shorter block times are coming to Zcash! In the v2.0.7 release we have implemented [ZIP208](https://github.com/zcash/zips/blob/master/zip-0208.rst) which take effect when Blossom activates. Upon activation, the block times for Zcash will decrease from 150s to 75s, and the block reward will will decrease accordingly. This effects at what block height halving events will occur, but should not effect the overall rate at which Zcash is mined. The total founder's reward stays the same, and the total supply of Zcash is decreased microscopically due to rounding. +Shorter block times are coming to Zcash! In the v2.0.7 release we have implemented [ZIP208](https://github.com/zcash/zips/blob/master/zip-0208.rst) which will take effect when Blossom activates. Upon activation, the block times for Zcash will decrease from 150 seconds to 75 seconds, and the block reward will decrease accordingly. This affects at what block height halving events will occur, but should not affect the overall rate at which Zcash is mined. The total founders' reward stays the same, and the total supply of Zcash is decreased only microscopically due to rounding. Blossom Activation on Testnet ----------------------------- -The v2.0.7 release includes Blossom activation on testnet bringing shorter block times. Testnet Blossom activation height is 584000. +The v2.0.7 release includes Blossom activation on testnet, bringing shorter block times. The testnet Blossom activation height is 584000. Insight Explorer ---------------- -The insight explorer has been incorporated in to Zcash. *This is an experimental feature* and therefore is subject change. To enable add the `experimentalfeatures=1`, `txindex=1`, and `insightexplorer=1` flags to `zcash.conf`. This feature adds several RPCs to `zcashd` which allow the user to run an insight explorer. +Changes needed for the Insight explorer have been incorporated into Zcash. *This is an experimental feature* and therefore is subject to change. To enable, add the `experimentalfeatures=1`, `txindex=1`, and `insightexplorer=1` flags to `zcash.conf`. This feature adds several RPCs to `zcashd` which allow the user to run an Insight explorer. From 5ac48d8ebc7decc5cb4e97851aa49524af53b558 Mon Sep 17 00:00:00 2001 From: zebambam Date: Wed, 14 Aug 2019 11:42:31 -0700 Subject: [PATCH 240/395] Updated location to new download server, fixing #4100 --- qa/zcash/test-depends-sources-mirror.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qa/zcash/test-depends-sources-mirror.py b/qa/zcash/test-depends-sources-mirror.py index 85dd146b8b5..5f36a3d5956 100755 --- a/qa/zcash/test-depends-sources-mirror.py +++ b/qa/zcash/test-depends-sources-mirror.py @@ -1,6 +1,6 @@ #!/usr/bin/env python2 -# This script tests that the package mirror at https://z.cash/depends-sources/ +# This script tests that the package mirror at https://download.z.cash/depends-sources/ # contains all of the packages required to build this version of Zcash. # # This script assumes you've just built Zcash, and that as a result of that From b54725fbed20978fdd8fe4f53244e40e769dd943 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 19 Aug 2019 12:30:24 -0600 Subject: [PATCH 241/395] Remove constant Co-Authored-By: str4d --- qa/rpc-tests/test_framework/mininode.py | 1 - 1 file changed, 1 deletion(-) diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index fc9693e5b6b..89b7ecf40b4 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -43,7 +43,6 @@ SPROUT_PROTO_VERSION = 170002 # past bip-31 for ping/pong OVERWINTER_PROTO_VERSION = 170003 SAPLING_PROTO_VERSION = 170006 -BLOSSOM_TESTNET_PROTO_VERSION = 170007 BLOSSOM_PROTO_VERSION = 170008 MY_SUBVERSION = "/python-mininode-tester:0.0.1/" From 93a03a1a20c6b55e6291effd86724a0c357db833 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 19 Aug 2019 14:36:31 -0600 Subject: [PATCH 242/395] make-release.py: Versioning changes for 2.0.7. --- README.md | 2 +- configure.ac | 2 +- contrib/gitian-descriptors/gitian-linux.yml | 2 +- src/clientversion.h | 2 +- src/deprecation.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index afcc3b9e92f..5fcb48e7ed5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Zcash 2.0.7-rc1 +Zcash 2.0.7 =========== diff --git a/configure.ac b/configure.ac index 45de7879ad6..90dd4e44500 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 2) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_REVISION, 7) -define(_CLIENT_VERSION_BUILD, 25) +define(_CLIENT_VERSION_BUILD, 50) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 18367845d3e..335365667c1 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "zcash-2.0.7-rc1" +name: "zcash-2.0.7" enable_cache: true distro: "debian" suites: diff --git a/src/clientversion.h b/src/clientversion.h index 9bda73361a5..0c5e47fd823 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -18,7 +18,7 @@ #define CLIENT_VERSION_MAJOR 2 #define CLIENT_VERSION_MINOR 0 #define CLIENT_VERSION_REVISION 7 -#define CLIENT_VERSION_BUILD 25 +#define CLIENT_VERSION_BUILD 50 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/deprecation.h b/src/deprecation.h index e9e527ff277..10bb3195d80 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -8,7 +8,7 @@ // Deprecation policy: // * Shut down 16 weeks' worth of blocks after the estimated release block height. // * A warning is shown during the 2 weeks' worth of blocks prior to shut down. -static const int APPROX_RELEASE_HEIGHT = 584200; +static const int APPROX_RELEASE_HEIGHT = 588500; static const int WEEKS_UNTIL_DEPRECATION = 16; static const int DEPRECATION_HEIGHT = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 24); From 21aa63558fe27b5c20de9acfce797e311b0679c3 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 19 Aug 2019 15:09:13 -0600 Subject: [PATCH 243/395] make-release.py: Updated manpages for 2.0.7. --- doc/man/zcash-cli.1 | 6 +++--- doc/man/zcash-tx.1 | 6 +++--- doc/man/zcashd.1 | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/man/zcash-cli.1 b/doc/man/zcash-cli.1 index d14a26b3eb7..777624816ac 100644 --- a/doc/man/zcash-cli.1 +++ b/doc/man/zcash-cli.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-CLI "1" "August 2019" "zcash-cli v2.0.7-rc1" "User Commands" +.TH ZCASH-CLI "1" "August 2019" "zcash-cli v2.0.7" "User Commands" .SH NAME -zcash-cli \- manual page for zcash-cli v2.0.7-rc1 +zcash-cli \- manual page for zcash-cli v2.0.7 .SH DESCRIPTION -Zcash RPC client version v2.0.7\-rc1 +Zcash RPC client version v2.0.7 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . diff --git a/doc/man/zcash-tx.1 b/doc/man/zcash-tx.1 index 51d2305d611..16df92b2f50 100644 --- a/doc/man/zcash-tx.1 +++ b/doc/man/zcash-tx.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-TX "1" "August 2019" "zcash-tx v2.0.7-rc1" "User Commands" +.TH ZCASH-TX "1" "August 2019" "zcash-tx v2.0.7" "User Commands" .SH NAME -zcash-tx \- manual page for zcash-tx v2.0.7-rc1 +zcash-tx \- manual page for zcash-tx v2.0.7 .SH DESCRIPTION -Zcash zcash\-tx utility version v2.0.7\-rc1 +Zcash zcash\-tx utility version v2.0.7 .SS "Usage:" .TP zcash\-tx [options] [commands] diff --git a/doc/man/zcashd.1 b/doc/man/zcashd.1 index fe8979d8769..b0c77f3c546 100644 --- a/doc/man/zcashd.1 +++ b/doc/man/zcashd.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASHD "1" "August 2019" "zcashd v2.0.7-rc1" "User Commands" +.TH ZCASHD "1" "August 2019" "zcashd v2.0.7" "User Commands" .SH NAME -zcashd \- manual page for zcashd v2.0.7-rc1 +zcashd \- manual page for zcashd v2.0.7 .SH DESCRIPTION -Zcash Daemon version v2.0.7\-rc1 +Zcash Daemon version v2.0.7 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . From 5540259d4e81eb476528741768af45033deca8d8 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 19 Aug 2019 15:09:14 -0600 Subject: [PATCH 244/395] make-release.py: Updated release notes and changelog for 2.0.7. --- contrib/debian/changelog | 6 + doc/authors.md | 18 +-- doc/release-notes.md | 11 -- doc/release-notes/release-notes-2.0.7.md | 149 +++++++++++++++++++++++ 4 files changed, 165 insertions(+), 19 deletions(-) create mode 100644 doc/release-notes/release-notes-2.0.7.md diff --git a/contrib/debian/changelog b/contrib/debian/changelog index 3a636d1edef..fda4225518f 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,9 @@ +zcash (2.0.7) stable; urgency=medium + + * 2.0.7 release. + + -- Electric Coin Company Mon, 19 Aug 2019 15:09:14 -0600 + zcash (2.0.7~rc1) stable; urgency=medium * 2.0.7-rc1 release. diff --git a/doc/authors.md b/doc/authors.md index 6afdb557cdf..68291ff73eb 100644 --- a/doc/authors.md +++ b/doc/authors.md @@ -1,11 +1,11 @@ Zcash Contributors ================== -Jack Grigg (873) -Simon Liu (451) +Jack Grigg (874) +Simon Liu (459) Sean Bowe (278) -Eirik Ogilvie-Wigley (152) -Daira Hopwood (124) +Eirik Ogilvie-Wigley (160) +Daira Hopwood (135) Jay Graber (89) Wladimir J. van der Laan (82) Taylor Hornby (73) @@ -14,7 +14,7 @@ Nathan Wilcox (56) Pieter Wuille (54) Kevin Gallagher (38) Cory Fields (35) -Larry Ruane (23) +Larry Ruane (29) Marshall Gaucher (22) Jonathan "Duke" Leto (17) syd (15) @@ -26,10 +26,12 @@ Jorge Timón (10) nomnombtc (9) kozyilmaz (8) fanquake (8) +Luke Dashjr (8) +Dimitris Apostolou (8) Jeff Garzik (7) Gregory Maxwell (7) +Benjamin Winston (7) Marius Kjærstad (6) -Luke Dashjr (6) David Mercer (6) Daniel Cousens (6) Charlie O'Keefe (6) @@ -46,14 +48,12 @@ João Barbosa (4) George Tankersley (4) Gareth Davies (4) Daniel Kraft (4) -Benjamin Winston (4) lpescher (3) ca333 (3) Per Grön (3) Patick Strateman (3) Jason Davies (3) James O'Beirne (3) -Dimitris Apostolou (3) Alfie John (3) rofl0r (2) mruddy (2) @@ -89,9 +89,11 @@ instagibbs (1) emilrus (1) dexX7 (1) daniel (1) +codetriage-readme-bot (1) calebogden (1) ayleph (1) Za Wilcox (1) +William M Peaster (1) Tom Ritter (1) Tom Harding (1) Stephen (1) diff --git a/doc/release-notes.md b/doc/release-notes.md index 0fba2dc2c42..a29094b5174 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,14 +4,3 @@ release-notes at release time) Notable changes =============== -Shorter Block Times -------------------- -Shorter block times are coming to Zcash! In the v2.0.7 release we have implemented [ZIP208](https://github.com/zcash/zips/blob/master/zip-0208.rst) which will take effect when Blossom activates. Upon activation, the block times for Zcash will decrease from 150 seconds to 75 seconds, and the block reward will decrease accordingly. This affects at what block height halving events will occur, but should not affect the overall rate at which Zcash is mined. The total founders' reward stays the same, and the total supply of Zcash is decreased only microscopically due to rounding. - -Blossom Activation on Testnet ------------------------------ -The v2.0.7 release includes Blossom activation on testnet, bringing shorter block times. The testnet Blossom activation height is 584000. - -Insight Explorer ----------------- -Changes needed for the Insight explorer have been incorporated into Zcash. *This is an experimental feature* and therefore is subject to change. To enable, add the `experimentalfeatures=1`, `txindex=1`, and `insightexplorer=1` flags to `zcash.conf`. This feature adds several RPCs to `zcashd` which allow the user to run an Insight explorer. diff --git a/doc/release-notes/release-notes-2.0.7.md b/doc/release-notes/release-notes-2.0.7.md new file mode 100644 index 00000000000..6c5e8bc9dc6 --- /dev/null +++ b/doc/release-notes/release-notes-2.0.7.md @@ -0,0 +1,149 @@ +Notable changes +=============== + +Shorter Block Times +------------------- +Shorter block times are coming to Zcash! In the v2.0.7 release we have implemented [ZIP208](https://github.com/zcash/zips/blob/master/zip-0208.rst) which will take effect when Blossom activates. Upon activation, the block times for Zcash will decrease from 150 seconds to 75 seconds, and the block reward will decrease accordingly. This affects at what block height halving events will occur, but should not affect the overall rate at which Zcash is mined. The total founders' reward stays the same, and the total supply of Zcash is decreased only microscopically due to rounding. + +Blossom Activation on Testnet +----------------------------- +The v2.0.7 release includes Blossom activation on testnet, bringing shorter block times. The testnet Blossom activation height is 584000. + +Insight Explorer +---------------- +Changes needed for the Insight explorer have been incorporated into Zcash. *This is an experimental feature* and therefore is subject to change. To enable, add the `experimentalfeatures=1`, `txindex=1`, and `insightexplorer=1` flags to `zcash.conf`. This feature adds several RPCs to `zcashd` which allow the user to run an Insight explorer. + +Changelog +========= + +Daira Hopwood (11): + Add MIT license to Makefiles + Add MIT license to build-aux/m4/bitcoin_* scripts, and a permissive license to build-aux/m4/l_atomic.m4 . + Update copyright information for Zcash, leveldb, and libsnark. + Add license information for Autoconf macros. refs #2827 + Update contrib/debian/copyright for ax_boost_thread.m4 + Replace http with https: in links to the MIT license. Also change MIT/X11 to just MIT, since no distinction was intended. + qa/zcash/checksec.sh is under a BSD license, with a specialized non-endorsement clause. + Link to ticket #2827 using URL + Release process doc: add step to set the gpg key id. + Release process doc: mention the commit message. + Add RPC test and test framework constants for Sapling->Blossom activation. + +Dimitris Apostolou (5): + Rename vjoinsplit to vJoinSplit + Fix naming inconsistency + Rename joinsplit to shielded + Rename FindWalletTx to FindWalletTxToZap + Fix RPC undefined behavior. + +Eirik Ogilvie-Wigley (56): + Make nextHeight required in CalculateNextWorkRequired + Fix nondeterministic failure in sapling migration test + Clean up and fix typo + Apply suggestions from code review + Shorter block times rpc test + Update pow_tests for shorter block times + Update test_pow for shorter block times + Update block subsidy halving for zip208 + Make NetworkUpgradeAvailable a method of Params + Temporarily disable test + Simplify PartitionCheck + Use static_assert + Add missing new line at end of file + pow test cleanup + Add message to static_assert + Update expiry height for shorter block times + Fix zip208 founders reward calculation and update test + PartitionCheck tests for shorter block times + Add test for Blossom default tx expiry delta + Update metrics block height estimation for shorter block times + Do not create transactions that will expire after the next epoch + Do not send migration transactions that would expire after a network upgrade + Fix integer truncation in Blossom halving calculation + Update main_tests for shorter block times + Use pre-Blossom max FR height when calculating address change interval + Make founders reward tests pass before and after Blossom activation height is set + Extract Halvings method and add tests + Add comments and fix typos + Improve EstimateNetHeight calculation + Fix check transaction tests + Make sure to deactivate blossom in test case + Fix parsing txexpirydelta argument + Do not add expiring soon threshold to expiry height of txs near NU activation + Fix/update comments + Make sure that expiry height is not less than height + Clarify documentation + Update PoW related assertions + Remove DefaultExpiryDelta method + Algebraic improvements related to halving + Distinguish between height and current header height on metrics screen + Test clean up and fixes + Add copyright info + NPE defense in metrics screen + Do not estimate height if there is no best header + Rename method and use int64_t + make-release.py: Versioning changes for 2.0.7-rc1. + make-release.py: Updated manpages for 2.0.7-rc1. + make-release.py: Updated release notes and changelog for 2.0.7-rc1. + Update download path + Set testnet Blossom activation height + Notable changes for v2.0.7 + Enable shorter block times rpc test + Grammatical fixes and improvements + Remove constant + make-release.py: Versioning changes for 2.0.7. + make-release.py: Updated manpages for 2.0.7. + +Eirik Ogilvie-Wigley (8): + Use CommitTransaction() rather than sendrawtransaction() + Move reused async rpc send logic to separate file + Move reused sign and send logic + Do not shadow the return value when testmode is true + Inline sign_send_raw_transaction + Allow passing optional reserve key as a parameter to SendTransaction + Use reserve key for transparent change when sending to Sapling + Fix comment in mergetoaddress RPC test + +Jack Grigg (5): + test: Check for change t-addr reuse in z_sendmany + Use reserve key for transparent change when sending to Sprout + test: Fix permissions on wallet_changeaddresses RPC test + test: Fix pyflakes warnings + test: Fix AuthServiceProxy closed conn detection + +Larry Ruane (6): + add addressindex related RPCs + add spentindex RPC for bitcore block explorer + add timestampindex related RPC getblockhashes + fix getblockdeltas documentation formatting + insightexplorer minor bug fixes + insightexplorer fix LogPrintf + +Luke Dashjr (2): + Add MIT license to autogen.sh and share/genbuild.sh + Trivial: build-aux/m4/l_atomic: Fix typo + +Simon Liu (8): + Redefine PoW functions to accept height parameter. + Remove use of redundant member nPowTargetSpacing. + Replace nPoWTargetSpacing -> PoWTargetSpacing() + Update PoW function calls to pass in height. + Update GetBlockTimeout() to take height parameter. + Replace nPoWTargetSpacing -> PoWTargetSpacing() in ProcessMessage() + Replace nPoWTargetSpacing -> PoWTargetSpacing() in tests + Modify PartitionCheck to be aware of pre & post Blossom target spacing. + +William M Peaster (1): + Handful of copyedits to README.md + +codetriage-readme-bot (1): + Link to development guidelines in CONTRIBUTING.md + +Jack Grigg (1): + Update README.md + +Benjamin Winston (3): + Updated location to new download server + Fixes 4097, improves caching on parameter downloads + Updated location to new download server, fixing #4100 + From 63dac4b08ac7c8c1c07bb054ff05f6aaf42dd6d8 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 19 Aug 2019 15:16:12 -0600 Subject: [PATCH 245/395] Update nMinimumChainWork --- src/chainparams.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index f322df6f6b3..cf47610f602 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -117,7 +117,7 @@ class CMainParams : public CChainParams { Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; // The best chain should have at least this much work. - consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000000eeaf43c4e72d49"); + consensus.nMinimumChainWork = uint256S("000000000000000000000000000000000000000000000000017e73a331fae01c"); /** * The message start string should be awesome! ⓩ❤ From b4a2665a3a358ae40626f2375b42a7afe3bead2f Mon Sep 17 00:00:00 2001 From: Alex Tsankov Date: Tue, 20 Aug 2019 16:09:24 -0400 Subject: [PATCH 246/395] Update INSTALL --- INSTALL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INSTALL b/INSTALL index 647c89a39d3..d8e23d1fdf0 100644 --- a/INSTALL +++ b/INSTALL @@ -1,5 +1,5 @@ Building Zcash -See the Zcash github wiki (https://github.com/zcash/zcash/wiki) for instructions on building zcashd, +See the Zcash documenation wiki (https://zcash.readthedocs.io/en/latest/rtd_pages/user_guide.html) for instructions on building zcashd, the intended-for-services, no-graphical-interface, reference implementation of Zcash. From 6e3f19e745785bf8d60ab35caddd4f48d71f9b0e Mon Sep 17 00:00:00 2001 From: Alex Tsankov Date: Wed, 21 Aug 2019 11:17:21 -0400 Subject: [PATCH 247/395] Typo Fix --- INSTALL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INSTALL b/INSTALL index d8e23d1fdf0..eecfe36e154 100644 --- a/INSTALL +++ b/INSTALL @@ -1,5 +1,5 @@ Building Zcash -See the Zcash documenation wiki (https://zcash.readthedocs.io/en/latest/rtd_pages/user_guide.html) for instructions on building zcashd, +See the Zcash documentation wiki (https://zcash.readthedocs.io/en/latest/rtd_pages/user_guide.html) for instructions on building zcashd, the intended-for-services, no-graphical-interface, reference implementation of Zcash. From 34297c3dec075cba5f1b0e2bc9fc09df444012a0 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 25 Jun 2019 10:07:24 +0200 Subject: [PATCH 248/395] Always skip verification for old Sprout proofs --- src/primitives/transaction.cpp | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index 49ee45dfcfd..27cfd18f200 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -96,18 +96,9 @@ class SproutProofVerifier : public boost::static_visitor bool operator()(const libzcash::PHGRProof& proof) const { - return params.verify( - proof, - verifier, - joinSplitPubKey, - jsdesc.randomSeed, - jsdesc.macs, - jsdesc.nullifiers, - jsdesc.commitments, - jsdesc.vpub_old, - jsdesc.vpub_new, - jsdesc.anchor - ); + // We checkpoint after Sapling activation, so we can skip verification + // for all Sprout proofs. + return true; } bool operator()(const libzcash::GrothProof& proof) const From 1e812cd694abb41a69ddeb9ad083a48aac686c31 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 25 Jun 2019 11:09:12 +0200 Subject: [PATCH 249/395] Remove ability to create non-Groth16 Sprout JSDescriptions --- src/zcash/JoinSplit.cpp | 47 ++--------------------------------------- 1 file changed, 2 insertions(+), 45 deletions(-) diff --git a/src/zcash/JoinSplit.cpp b/src/zcash/JoinSplit.cpp index 669b5f63a5d..6344ec71e68 100644 --- a/src/zcash/JoinSplit.cpp +++ b/src/zcash/JoinSplit.cpp @@ -330,51 +330,8 @@ class JoinSplitCircuit : public JoinSplit { return proof; } - if (!computeProof) { - return PHGRProof(); - } - - protoboard pb; - { - joinsplit_gadget g(pb); - g.generate_r1cs_constraints(); - g.generate_r1cs_witness( - phi, - rt, - h_sig, - inputs, - out_notes, - vpub_old, - vpub_new - ); - } - - // The constraint system must be satisfied or there is an unimplemented - // or incorrect sanity check above. Or the constraint system is broken! - assert(pb.is_satisfied()); - - // TODO: These are copies, which is not strictly necessary. - std::vector primary_input = pb.primary_input(); - std::vector aux_input = pb.auxiliary_input(); - - // Swap A and B if it's beneficial (less arithmetic in G2) - // In our circuit, we already know that it's beneficial - // to swap, but it takes so little time to perform this - // estimate that it doesn't matter if we check every time. - pb.constraint_system.swap_AB_if_beneficial(); - - std::ifstream fh(pkPath, std::ios::binary); - - if(!fh.is_open()) { - throw std::runtime_error(strprintf("could not load param file at %s", pkPath)); - } - - return PHGRProof(r1cs_ppzksnark_prover_streaming( - fh, - primary_input, - aux_input, - pb.constraint_system - )); + // We have removed the ability to create pre-Sapling Sprout proofs. + throw std::invalid_argument("Cannot create non-Groth16 Sprout proofs"); } }; From 1b4cf1337c3ca9a85770c640715b1649e9d6d51c Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 25 Jun 2019 12:08:26 +0200 Subject: [PATCH 250/395] Use Sapling JSDescriptions in Boost tests --- src/test/rpc_wallet_tests.cpp | 31 ++++++++++++++++++------------- src/test/transaction_tests.cpp | 13 +++++++------ 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index e3a88339119..abae7ce78db 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -1035,15 +1035,17 @@ BOOST_AUTO_TEST_CASE(asyncrpcoperation_sign_send_raw_transaction) { BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals) { SelectParams(CBaseChainParams::TESTNET); + auto consensusParams = Params().GetConsensus(); LOCK(pwalletMain->cs_wallet); UniValue retValue; // Mutable tx containing contextual information we need to build tx - retValue = CallRPC("getblockcount"); - int nHeight = retValue.get_int(); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nHeight + 1); + // We removed the ability to create pre-Sapling Sprout proofs, so we can + // only create Sapling-onwards transactions. + int nHeight = consensusParams.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight; + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight + 1); if (mtx.nVersion == 1) { mtx.nVersion = 2; } @@ -1589,17 +1591,16 @@ BOOST_AUTO_TEST_CASE(rpc_z_shieldcoinbase_parameters) BOOST_AUTO_TEST_CASE(rpc_z_shieldcoinbase_internals) { SelectParams(CBaseChainParams::TESTNET); + auto consensusParams = Params().GetConsensus(); LOCK(pwalletMain->cs_wallet); // Mutable tx containing contextual information we need to build tx - UniValue retValue = CallRPC("getblockcount"); - int nHeight = retValue.get_int(); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nHeight + 1); - if (mtx.nVersion == 1) { - mtx.nVersion = 2; - } - + // We removed the ability to create pre-Sapling Sprout proofs, so we can + // only create Sapling-onwards transactions. + int nHeight = consensusParams.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight; + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight + 1); + // Test that option -mempooltxinputlimit is respected. mapArgs["-mempooltxinputlimit"] = "1"; @@ -1817,13 +1818,17 @@ BOOST_AUTO_TEST_CASE(rpc_z_mergetoaddress_parameters) BOOST_AUTO_TEST_CASE(rpc_z_mergetoaddress_internals) { SelectParams(CBaseChainParams::TESTNET); + auto consensusParams = Params().GetConsensus(); LOCK(pwalletMain->cs_wallet); + UniValue retValue; + // Mutable tx containing contextual information we need to build tx - UniValue retValue = CallRPC("getblockcount"); - int nHeight = retValue.get_int(); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nHeight + 1); + // We removed the ability to create pre-Sapling Sprout proofs, so we can + // only create Sapling-onwards transactions. + int nHeight = consensusParams.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight; + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight + 1); // Test that option -mempooltxinputlimit is respected. mapArgs["-mempooltxinputlimit"] = "1"; diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 42f380138d4..725d60cfeb3 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -373,14 +373,15 @@ BOOST_AUTO_TEST_CASE(test_basic_joinsplit_verification) auto verifier = libzcash::ProofVerifier::Strict(); { - JSDescription jsdesc(false, *pzcashParams, joinSplitPubKey, rt, inputs, outputs, 0, 0); + JSDescription jsdesc(true, *pzcashParams, joinSplitPubKey, rt, inputs, outputs, 0, 0); BOOST_CHECK(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey)); CDataStream ss(SER_DISK, CLIENT_VERSION); - ss << jsdesc; + auto os = WithVersion(&ss, SAPLING_TX_VERSION | 1 << 31); + os << jsdesc; JSDescription jsdesc_deserialized; - ss >> jsdesc_deserialized; + os >> jsdesc_deserialized; BOOST_CHECK(jsdesc_deserialized == jsdesc); BOOST_CHECK(jsdesc_deserialized.Verify(*pzcashParams, verifier, joinSplitPubKey)); @@ -388,13 +389,13 @@ BOOST_AUTO_TEST_CASE(test_basic_joinsplit_verification) { // Ensure that the balance equation is working. - BOOST_CHECK_THROW(JSDescription(false, *pzcashParams, joinSplitPubKey, rt, inputs, outputs, 10, 0), std::invalid_argument); - BOOST_CHECK_THROW(JSDescription(false, *pzcashParams, joinSplitPubKey, rt, inputs, outputs, 0, 10), std::invalid_argument); + BOOST_CHECK_THROW(JSDescription(true, *pzcashParams, joinSplitPubKey, rt, inputs, outputs, 10, 0), std::invalid_argument); + BOOST_CHECK_THROW(JSDescription(true, *pzcashParams, joinSplitPubKey, rt, inputs, outputs, 0, 10), std::invalid_argument); } { // Ensure that it won't verify if the root is changed. - auto test = JSDescription(false, *pzcashParams, joinSplitPubKey, rt, inputs, outputs, 0, 0); + auto test = JSDescription(true, *pzcashParams, joinSplitPubKey, rt, inputs, outputs, 0, 0); test.anchor = GetRandHash(); BOOST_CHECK(!test.Verify(*pzcashParams, verifier, joinSplitPubKey)); } From 79a7c072f6790851912ddf22f1959dc80b398b10 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 25 Jun 2019 12:26:33 +0200 Subject: [PATCH 251/395] Remove non-Groth16 Sprout proofs from joinsplit gtests --- src/gtest/test_joinsplit.cpp | 60 +++++++++--------------------------- 1 file changed, 15 insertions(+), 45 deletions(-) diff --git a/src/gtest/test_joinsplit.cpp b/src/gtest/test_joinsplit.cpp index 4de2fc47152..b324d10d671 100644 --- a/src/gtest/test_joinsplit.cpp +++ b/src/gtest/test_joinsplit.cpp @@ -22,10 +22,9 @@ using namespace libzcash; extern ZCJoinSplit* params; -typedef std::array SproutProofs; -// Make both the PHGR and Groth proof for a Sprout statement, -// and store the results in JSDescription objects. -SproutProofs makeSproutProofs( +// Make the Groth proof for a Sprout statement, +// and store the result in a JSDescription object. +JSDescription makeSproutProof( ZCJoinSplit& js, const std::array& inputs, const std::array& outputs, @@ -34,25 +33,17 @@ SproutProofs makeSproutProofs( uint64_t vpub_new, const uint256& rt ){ - //Making the PHGR proof - JSDescription phgr(false, js, joinSplitPubKey, rt, inputs, outputs, vpub_old, vpub_new); - //Making the Groth proof - JSDescription groth(true, js, joinSplitPubKey, rt, inputs, outputs, vpub_old, vpub_new); - - return {phgr, groth}; - + return JSDescription(true, js, joinSplitPubKey, rt, inputs, outputs, vpub_old, vpub_new); } -bool verifySproutProofs( +bool verifySproutProof( ZCJoinSplit& js, - const SproutProofs& jsdescs, + const JSDescription& jsdesc, const uint256& joinSplitPubKey ) { auto verifier = libzcash::ProofVerifier::Strict(); - bool phgrPassed = jsdescs[0].Verify(js, verifier, joinSplitPubKey); - bool grothPassed = jsdescs[1].Verify(js, verifier, joinSplitPubKey); - return phgrPassed && grothPassed; + return jsdesc.Verify(js, verifier, joinSplitPubKey); } @@ -73,7 +64,7 @@ void test_full_api(ZCJoinSplit* js) uint64_t vpub_new = 0; uint256 joinSplitPubKey = random_uint256(); uint256 rt = tree.root(); - SproutProofs jsdescs; + JSDescription jsdesc; { std::array inputs = { @@ -89,7 +80,7 @@ void test_full_api(ZCJoinSplit* js) std::array output_notes; // Perform the proofs - jsdescs = makeSproutProofs( + jsdesc = makeSproutProof( *js, inputs, outputs, @@ -101,13 +92,11 @@ void test_full_api(ZCJoinSplit* js) } // Verify both PHGR and Groth Proof: - ASSERT_TRUE(verifySproutProofs(*js, jsdescs, joinSplitPubKey)); + ASSERT_TRUE(verifySproutProof(*js, jsdesc, joinSplitPubKey)); - // Run tests using both phgr and groth as basis for field values - for (auto jsdesc : jsdescs) { SproutMerkleTree tree; - SproutProofs jsdescs2; + JSDescription jsdesc2; // Recipient should decrypt // Now the recipient should spend the money again auto h_sig = js->h_sig(jsdesc.randomSeed, jsdesc.nullifiers, joinSplitPubKey); @@ -153,7 +142,7 @@ void test_full_api(ZCJoinSplit* js) // Perform the proofs - jsdescs2 = makeSproutProofs( + jsdesc2 = makeSproutProof( *js, inputs, outputs, @@ -166,8 +155,8 @@ void test_full_api(ZCJoinSplit* js) } - // Verify both PHGR and Groth Proof: - ASSERT_TRUE(verifySproutProofs(*js, jsdescs2, joinSplitPubKey2)); + // Verify Groth Proof: + ASSERT_TRUE(verifySproutProof(*js, jsdesc2, joinSplitPubKey2)); } } @@ -191,27 +180,8 @@ void invokeAPI( std::array output_notes; - // PHGR - SproutProof proof = js->prove( - false, - inputs, - outputs, - output_notes, - ciphertexts, - ephemeralKey, - joinSplitPubKey, - randomSeed, - macs, - nullifiers, - commitments, - vpub_old, - vpub_new, - rt, - false - ); - // Groth - proof = js->prove( + SproutProof proof = js->prove( true, inputs, outputs, From c4b695e7b3a97002b3331d1cc24d59d618cfa154 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 25 Jun 2019 12:48:13 +0200 Subject: [PATCH 252/395] Migrate test utilities to generate Sapling-type Sprout proofs --- src/utiltest.cpp | 23 +++++++++++++++++------ src/utiltest.h | 6 ++++-- src/wallet/gtest/test_wallet.cpp | 30 +++++++++++++++++++++--------- 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/utiltest.cpp b/src/utiltest.cpp index 7e0e9a2799c..3965d148f29 100644 --- a/src/utiltest.cpp +++ b/src/utiltest.cpp @@ -14,8 +14,14 @@ CMutableTransaction GetValidSproutReceiveTransaction(ZCJoinSplit& params, const libzcash::SproutSpendingKey& sk, CAmount value, bool randomInputs, - int32_t version /* = 2 */) { + uint32_t versionGroupId, /* = SAPLING_VERSION_GROUP_ID */ + int32_t version /* = SAPLING_TX_VERSION */) { + // We removed the ability to create pre-Sapling Sprout transactions + assert(version >= SAPLING_TX_VERSION); + CMutableTransaction mtx; + mtx.fOverwintered = true; + mtx.nVersionGroupId = versionGroupId; mtx.nVersion = version; mtx.vin.resize(2); if (randomInputs) { @@ -46,7 +52,7 @@ CMutableTransaction GetValidSproutReceiveTransaction(ZCJoinSplit& params, // Prepare JoinSplits uint256 rt; - JSDescription jsdesc {false, params, mtx.joinSplitPubKey, rt, + JSDescription jsdesc {true, params, mtx.joinSplitPubKey, rt, inputs, outputs, 2*value, 0, false}; mtx.vJoinSplit.push_back(jsdesc); @@ -78,10 +84,11 @@ CWalletTx GetValidSproutReceive(ZCJoinSplit& params, const libzcash::SproutSpendingKey& sk, CAmount value, bool randomInputs, - int32_t version /* = 2 */) + uint32_t versionGroupId, /* = SAPLING_VERSION_GROUP_ID */ + int32_t version /* = SAPLING_TX_VERSION */) { CMutableTransaction mtx = GetValidSproutReceiveTransaction( - params, sk, value, randomInputs, version + params, sk, value, randomInputs, versionGroupId, version ); CTransaction tx {mtx}; CWalletTx wtx {NULL, tx}; @@ -92,10 +99,11 @@ CWalletTx GetInvalidCommitmentSproutReceive(ZCJoinSplit& params, const libzcash::SproutSpendingKey& sk, CAmount value, bool randomInputs, - int32_t version /* = 2 */) + uint32_t versionGroupId, /* = SAPLING_VERSION_GROUP_ID */ + int32_t version /* = SAPLING_TX_VERSION */) { CMutableTransaction mtx = GetValidSproutReceiveTransaction( - params, sk, value, randomInputs, version + params, sk, value, randomInputs, versionGroupId, version ); mtx.vJoinSplit[0].commitments[0] = uint256(); mtx.vJoinSplit[0].commitments[1] = uint256(); @@ -123,6 +131,9 @@ CWalletTx GetValidSproutSpend(ZCJoinSplit& params, const libzcash::SproutNote& note, CAmount value) { CMutableTransaction mtx; + mtx.fOverwintered = true; + mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID; + mtx.nVersion = SAPLING_TX_VERSION; mtx.vout.resize(2); mtx.vout[0].nValue = value; mtx.vout[1].nValue = 0; diff --git a/src/utiltest.h b/src/utiltest.h index 6ea887ff2f4..85977f1adcb 100644 --- a/src/utiltest.h +++ b/src/utiltest.h @@ -17,12 +17,14 @@ CWalletTx GetValidSproutReceive(ZCJoinSplit& params, const libzcash::SproutSpendingKey& sk, CAmount value, bool randomInputs, - int32_t version = 2); + uint32_t versionGroupId = SAPLING_VERSION_GROUP_ID, + int32_t version = SAPLING_TX_VERSION); CWalletTx GetInvalidCommitmentSproutReceive(ZCJoinSplit& params, const libzcash::SproutSpendingKey& sk, CAmount value, bool randomInputs, - int32_t version = 2); + uint32_t versionGroupId = SAPLING_VERSION_GROUP_ID, + int32_t version = SAPLING_TX_VERSION); libzcash::SproutNote GetSproutNote(ZCJoinSplit& params, const libzcash::SproutSpendingKey& sk, const CTransaction& tx, size_t js, size_t n); diff --git a/src/wallet/gtest/test_wallet.cpp b/src/wallet/gtest/test_wallet.cpp index b5b9a237ae0..d9fefa72c40 100644 --- a/src/wallet/gtest/test_wallet.cpp +++ b/src/wallet/gtest/test_wallet.cpp @@ -71,12 +71,24 @@ class TestWallet : public CWallet { } }; -CWalletTx GetValidSproutReceive(const libzcash::SproutSpendingKey& sk, CAmount value, bool randomInputs, int32_t version = 2) { - return GetValidSproutReceive(*params, sk, value, randomInputs, version); +CWalletTx GetValidSproutReceive( + const libzcash::SproutSpendingKey& sk, + CAmount value, + bool randomInputs, + int32_t versionGroupId = SAPLING_VERSION_GROUP_ID, + int32_t version = SAPLING_TX_VERSION) +{ + return GetValidSproutReceive(*params, sk, value, randomInputs, versionGroupId, version); } -CWalletTx GetInvalidCommitmentSproutReceive(const libzcash::SproutSpendingKey& sk, CAmount value, bool randomInputs, int32_t version = 2) { - return GetInvalidCommitmentSproutReceive(*params, sk, value, randomInputs, version); +CWalletTx GetInvalidCommitmentSproutReceive( + const libzcash::SproutSpendingKey& sk, + CAmount value, + bool randomInputs, + int32_t versionGroupId = SAPLING_VERSION_GROUP_ID, + int32_t version = SAPLING_TX_VERSION) +{ + return GetInvalidCommitmentSproutReceive(*params, sk, value, randomInputs, versionGroupId, version); } libzcash::SproutNote GetSproutNote(const libzcash::SproutSpendingKey& sk, @@ -105,7 +117,7 @@ std::pair CreateValidBlock(TestWallet& wallet, CBlock& block, SproutMerkleTree& sproutTree, SaplingMerkleTree& saplingTree) { - auto wtx = GetValidSproutReceive(sk, 50, true, 4); + auto wtx = GetValidSproutReceive(sk, 50, true); auto note = GetSproutNote(sk, wtx, 0, 1); auto nullifier = note.nullifier(sk); @@ -1121,7 +1133,7 @@ TEST(WalletTests, CachedWitnessesEmptyChain) { auto sk = libzcash::SproutSpendingKey::random(); wallet.AddSproutSpendingKey(sk); - auto wtx = GetValidSproutReceive(sk, 10, true, 4); + auto wtx = GetValidSproutReceive(sk, 10, true); auto note = GetSproutNote(sk, wtx, 0, 0); auto note2 = GetSproutNote(sk, wtx, 0, 1); auto nullifier = note.nullifier(sk); @@ -1202,7 +1214,7 @@ TEST(WalletTests, CachedWitnessesChainTip) { { // Second transaction - auto wtx = GetValidSproutReceive(sk, 50, true, 4); + auto wtx = GetValidSproutReceive(sk, 50, true); auto note = GetSproutNote(sk, wtx, 0, 1); auto nullifier = note.nullifier(sk); @@ -1311,7 +1323,7 @@ TEST(WalletTests, CachedWitnessesDecrementFirst) { { // Third transaction - never mined - auto wtx = GetValidSproutReceive(sk, 20, true, 4); + auto wtx = GetValidSproutReceive(sk, 20, true); auto note = GetSproutNote(sk, wtx, 0, 1); auto nullifier = note.nullifier(sk); @@ -1449,7 +1461,7 @@ TEST(WalletTests, ClearNoteWitnessCache) { auto sk = libzcash::SproutSpendingKey::random(); wallet.AddSproutSpendingKey(sk); - auto wtx = GetValidSproutReceive(sk, 10, true, 4); + auto wtx = GetValidSproutReceive(sk, 10, true); auto hash = wtx.GetHash(); auto note = GetSproutNote(sk, wtx, 0, 0); auto nullifier = note.nullifier(sk); From e573765641e5244ed615e16cec8f4ec8c06def31 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 25 Jun 2019 15:21:39 +0200 Subject: [PATCH 253/395] Use Sapling JSDescriptions in gtests --- src/gtest/test_transaction.cpp | 6 +++--- src/utiltest.cpp | 2 +- src/wallet/gtest/test_wallet.cpp | 11 ++++++++--- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/gtest/test_transaction.cpp b/src/gtest/test_transaction.cpp index 1350768ff93..099bb10314c 100644 --- a/src/gtest/test_transaction.cpp +++ b/src/gtest/test_transaction.cpp @@ -45,7 +45,7 @@ TEST(Transaction, JSDescriptionRandomized) { { auto jsdesc = JSDescription::Randomized( - false, + true, *params, joinSplitPubKey, rt, inputs, outputs, inputMap, outputMap, @@ -62,7 +62,7 @@ TEST(Transaction, JSDescriptionRandomized) { { auto jsdesc = JSDescription::Randomized( - false, + true, *params, joinSplitPubKey, rt, inputs, outputs, inputMap, outputMap, @@ -76,7 +76,7 @@ TEST(Transaction, JSDescriptionRandomized) { { auto jsdesc = JSDescription::Randomized( - false, + true, *params, joinSplitPubKey, rt, inputs, outputs, inputMap, outputMap, diff --git a/src/utiltest.cpp b/src/utiltest.cpp index 3965d148f29..f3d6d1c98ec 100644 --- a/src/utiltest.cpp +++ b/src/utiltest.cpp @@ -178,7 +178,7 @@ CWalletTx GetValidSproutSpend(ZCJoinSplit& params, // Prepare JoinSplits uint256 rt = tree.root(); - JSDescription jsdesc {false, params, mtx.joinSplitPubKey, rt, + JSDescription jsdesc {true, params, mtx.joinSplitPubKey, rt, inputs, outputs, 0, value, false}; mtx.vJoinSplit.push_back(jsdesc); diff --git a/src/wallet/gtest/test_wallet.cpp b/src/wallet/gtest/test_wallet.cpp index d9fefa72c40..cf2a12a0060 100644 --- a/src/wallet/gtest/test_wallet.cpp +++ b/src/wallet/gtest/test_wallet.cpp @@ -170,10 +170,11 @@ TEST(WalletTests, SproutNoteDataSerialisation) { noteData[jsoutpt] = nd; CDataStream ss(SER_DISK, CLIENT_VERSION); - ss << noteData; + auto os = WithVersion(&ss, SAPLING_TX_VERSION | 1 << 31); + os << noteData; mapSproutNoteData_t noteData2; - ss >> noteData2; + os >> noteData2; EXPECT_EQ(noteData, noteData2); EXPECT_EQ(noteData[jsoutpt].witnesses, noteData2[jsoutpt].witnesses); @@ -181,7 +182,8 @@ TEST(WalletTests, SproutNoteDataSerialisation) { TEST(WalletTests, FindUnspentSproutNotes) { - SelectParams(CBaseChainParams::TESTNET); + auto consensusParams = RegtestActivateSapling(); + CWallet wallet; auto sk = libzcash::SproutSpendingKey::random(); wallet.AddSproutSpendingKey(sk); @@ -350,6 +352,9 @@ TEST(WalletTests, FindUnspentSproutNotes) { mapBlockIndex.erase(blockHash); mapBlockIndex.erase(blockHash2); mapBlockIndex.erase(blockHash3); + + // Revert to default + RegtestDeactivateSapling(); } From 93dae1db7d315cab51852bfa5d8b3e3ad131e07e Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 25 Jun 2019 15:42:45 +0200 Subject: [PATCH 254/395] Revert "Allow user to ask server to save the Sprout R1CS out during startup." This reverts commit 685c0ab07fd90b244dac5e2cb1f069ac6151ec5c. --- src/init.cpp | 10 ---------- src/zcash/JoinSplit.cpp | 10 ---------- src/zcash/JoinSplit.hpp | 2 -- 3 files changed, 22 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index bbc6f3782ef..eec0ffde8ca 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -844,8 +844,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) return InitError(_("Payment disclosure requires -experimentalfeatures.")); } else if (mapArgs.count("-zmergetoaddress")) { return InitError(_("RPC method z_mergetoaddress requires -experimentalfeatures.")); - } else if (mapArgs.count("-savesproutr1cs")) { - return InitError(_("Saving the Sprout R1CS requires -experimentalfeatures.")); } else if (mapArgs.count("-insightexplorer")) { return InitError(_("Insight explorer requires -experimentalfeatures.")); } @@ -1238,14 +1236,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // Initialize Zcash circuit parameters ZC_LoadParams(chainparams); - if (GetBoolArg("-savesproutr1cs", false)) { - boost::filesystem::path r1cs_path = ZC_GetParamsDir() / "r1cs"; - - LogPrintf("Saving Sprout R1CS to %s\n", r1cs_path.string()); - - pzcashParams->saveR1CS(r1cs_path.string()); - } - /* Start the RPC server already. It will be started in "warmup" mode * and not really process calls already (but it will signify connections * that the server is there and will be ready later). Warmup mode will diff --git a/src/zcash/JoinSplit.cpp b/src/zcash/JoinSplit.cpp index 6344ec71e68..287d2ebcca8 100644 --- a/src/zcash/JoinSplit.cpp +++ b/src/zcash/JoinSplit.cpp @@ -101,16 +101,6 @@ class JoinSplitCircuit : public JoinSplit { saveToFile(pkPath, keypair.pk); } - void saveR1CS(std::string path) - { - protoboard pb; - joinsplit_gadget g(pb); - g.generate_r1cs_constraints(); - r1cs_constraint_system r1cs = pb.get_constraint_system(); - - saveToFile(path, r1cs); - } - bool verify( const PHGRProof& proof, ProofVerifier& verifier, diff --git a/src/zcash/JoinSplit.hpp b/src/zcash/JoinSplit.hpp index 2d3a61a6da5..c37926edeaf 100644 --- a/src/zcash/JoinSplit.hpp +++ b/src/zcash/JoinSplit.hpp @@ -67,8 +67,6 @@ class JoinSplit { const uint256& joinSplitPubKey ); - virtual void saveR1CS(std::string path) = 0; - // Compute nullifiers, macs, note commitments & encryptions, and SNARK proof virtual SproutProof prove( bool makeGrothProof, From 5f84491d829e26a9c676a4e7acfff1feb37f5545 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 25 Jun 2019 16:39:16 +0200 Subject: [PATCH 255/395] Remove libsnark code for pre-Sapling Sprout proofs --- src/Makefile.gtest.include | 2 - src/Makefile.test.include | 2 - src/gtest/main.cpp | 10 +- src/gtest/test_circuit.cpp | 183 - src/gtest/test_merkletree.cpp | 64 +- src/gtest/test_proofs.cpp | 702 -- src/init.cpp | 22 +- src/test/data/g1_compressed.json | 10002 ----------------------------- src/test/data/g2_compressed.json | 10002 ----------------------------- src/test/sighash_tests.cpp | 7 +- src/test/test_bitcoin.cpp | 4 +- src/wallet/rpcwallet.cpp | 2 +- src/zcash/JoinSplit.cpp | 128 +- src/zcash/JoinSplit.hpp | 19 +- src/zcash/Proof.cpp | 233 - src/zcash/Proof.hpp | 35 - src/zcbenchmarks.cpp | 18 - src/zcbenchmarks.h | 1 - 18 files changed, 15 insertions(+), 21421 deletions(-) delete mode 100644 src/gtest/test_circuit.cpp delete mode 100644 src/gtest/test_proofs.cpp delete mode 100644 src/test/data/g1_compressed.json delete mode 100644 src/test/data/g2_compressed.json diff --git a/src/Makefile.gtest.include b/src/Makefile.gtest.include index 26d57b54f91..be593103389 100644 --- a/src/Makefile.gtest.include +++ b/src/Makefile.gtest.include @@ -38,10 +38,8 @@ zcash_gtest_SOURCES += \ gtest/test_transaction_builder.cpp \ gtest/test_upgrades.cpp \ gtest/test_validation.cpp \ - gtest/test_circuit.cpp \ gtest/test_txid.cpp \ gtest/test_libzcash_utils.cpp \ - gtest/test_proofs.cpp \ gtest/test_pedersen_hash.cpp \ gtest/test_checkblock.cpp \ gtest/test_zip32.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index eb30cab4a8b..e65b35a45a8 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -44,8 +44,6 @@ JSON_TEST_FILES = \ test/data/merkle_witness_serialization_sapling.json \ test/data/merkle_path_sapling.json \ test/data/merkle_commitments_sapling.json \ - test/data/g1_compressed.json \ - test/data/g2_compressed.json \ test/data/sapling_key_components.json RAW_TEST_FILES = test/data/alertTests.raw diff --git a/src/gtest/main.cpp b/src/gtest/main.cpp index 5f32b5fef6d..6c8fd0c2b13 100644 --- a/src/gtest/main.cpp +++ b/src/gtest/main.cpp @@ -5,9 +5,6 @@ #include "zcash/JoinSplit.hpp" #include "util.h" -#include -#include - #include "librustzcash.h" struct ECCryptoClosure @@ -23,12 +20,7 @@ int main(int argc, char **argv) { assert(init_and_check_sodium() != -1); ECC_Start(); - libsnark::default_r1cs_ppzksnark_pp::init_public_params(); - libsnark::inhibit_profiling_info = true; - libsnark::inhibit_profiling_counters = true; - boost::filesystem::path pk_path = ZC_GetParamsDir() / "sprout-proving.key"; - boost::filesystem::path vk_path = ZC_GetParamsDir() / "sprout-verifying.key"; - params = ZCJoinSplit::Prepared(vk_path.string(), pk_path.string()); + params = ZCJoinSplit::Prepared(); boost::filesystem::path sapling_spend = ZC_GetParamsDir() / "sapling-spend.params"; boost::filesystem::path sapling_output = ZC_GetParamsDir() / "sapling-output.params"; diff --git a/src/gtest/test_circuit.cpp b/src/gtest/test_circuit.cpp deleted file mode 100644 index ab2a8ecb64f..00000000000 --- a/src/gtest/test_circuit.cpp +++ /dev/null @@ -1,183 +0,0 @@ -#include -#include "uint256.h" - -#include "zcash/util.h" - -#include -#include -#include - -#include -#include -#include -#include - -#include "zcash/IncrementalMerkleTree.hpp" - -using namespace libsnark; -using namespace libzcash; - -#include "zcash/circuit/utils.tcc" -#include "zcash/circuit/merkle.tcc" - -template -void test_value_equals(uint64_t i) { - protoboard pb; - pb_variable_array num; - num.allocate(pb, 64, ""); - num.fill_with_bits(pb, uint64_to_bool_vector(i)); - pb.add_r1cs_constraint(r1cs_constraint( - packed_addition(num), - FieldT::one(), - FieldT::one() * i - ), ""); - ASSERT_TRUE(pb.is_satisfied()); -} - -TEST(circuit, values) -{ - typedef Fr FieldT; - test_value_equals(0); - test_value_equals(1); - test_value_equals(3); - test_value_equals(5391); - test_value_equals(883128374); - test_value_equals(173419028459); - test_value_equals(2205843009213693953); -} - -TEST(circuit, endianness) -{ - std::vector before = { - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63 - }; - auto result = swap_endianness_u64(before); - - std::vector after = { - 56, 57, 58, 59, 60, 61, 62, 63, - 48, 49, 50, 51, 52, 53, 54, 55, - 40, 41, 42, 43, 44, 45, 46, 47, - 32, 33, 34, 35, 36, 37, 38, 39, - 24, 25, 26, 27, 28, 29, 30, 31, - 16, 17, 18, 19, 20, 21, 22, 23, - 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7 - }; - - EXPECT_EQ(after, result); - - std::vector bad = {0, 1, 2, 3}; - - ASSERT_THROW(swap_endianness_u64(bad), std::length_error); -} - -template -bool test_merkle_gadget( - bool enforce_a, - bool enforce_b, - bool write_root_first -) -{ - protoboard pb; - digest_variable root(pb, 256, "root"); - pb.set_input_sizes(256); - - digest_variable commitment1(pb, 256, "commitment1"); - digest_variable commitment2(pb, 256, "commitment2"); - - pb_variable commitment1_read; - commitment1_read.allocate(pb); - pb_variable commitment2_read; - commitment2_read.allocate(pb); - - merkle_tree_gadget mgadget1(pb, commitment1, root, commitment1_read); - merkle_tree_gadget mgadget2(pb, commitment2, root, commitment2_read); - - commitment1.generate_r1cs_constraints(); - commitment2.generate_r1cs_constraints(); - root.generate_r1cs_constraints(); - mgadget1.generate_r1cs_constraints(); - mgadget2.generate_r1cs_constraints(); - - SproutMerkleTree tree; - uint256 commitment1_data = uint256S("54d626e08c1c802b305dad30b7e54a82f102390cc92c7d4db112048935236e9c"); - uint256 commitment2_data = uint256S("59d2cde5e65c1414c32ba54f0fe4bdb3d67618125286e6a191317917c812c6d7"); - tree.append(commitment1_data); - auto wit1 = tree.witness(); - tree.append(commitment2_data); - wit1.append(commitment2_data); - auto wit2 = tree.witness(); - auto expected_root = tree.root(); - tree.append(uint256S("3e243c8798678570bb8d42616c23a536af44be15c4eef073490c2a44ae5f32c3")); - auto unexpected_root = tree.root(); - tree.append(uint256S("26d9b20c7f1c3d2528bbcd43cd63344b0afd3b6a0a8ebd37ec51cba34907bec7")); - auto badwit1 = tree.witness(); - tree.append(uint256S("02c2467c9cd15e0d150f74cd636505ed675b0b71b66a719f6f52fdb49a5937bb")); - auto badwit2 = tree.witness(); - - // Perform the test - - pb.val(commitment1_read) = enforce_a ? FieldT::one() : FieldT::zero(); - pb.val(commitment2_read) = enforce_b ? FieldT::one() : FieldT::zero(); - - commitment1.bits.fill_with_bits(pb, uint256_to_bool_vector(commitment1_data)); - commitment2.bits.fill_with_bits(pb, uint256_to_bool_vector(commitment2_data)); - - if (write_root_first) { - root.bits.fill_with_bits(pb, uint256_to_bool_vector(expected_root)); - } - - mgadget1.generate_r1cs_witness(wit1.path()); - mgadget2.generate_r1cs_witness(wit2.path()); - - // Overwrite with our expected root - root.bits.fill_with_bits(pb, uint256_to_bool_vector(expected_root)); - - return pb.is_satisfied(); -} - -TEST(circuit, merkle_tree_gadget_weirdness) -{ - /* - The merkle tree gadget takes a leaf in the merkle tree (the Note commitment), - a merkle tree authentication path, and a root (anchor). It also takes a parameter - called read_success, which is used to determine if the commitment actually needs to - appear in the tree. - - If two input notes use the same root (which our protocol does) then if `read_success` - is disabled on the first note but enabled on the second note (i.e., the first note - has value of zero and second note has nonzero value) then there is an edge case in - the witnessing behavior. The first witness will accidentally constrain the root to - equal null (the default value of the anchor) and the second witness will actually - copy the bits, violating the constraint system. - - Notice that this edge case is not in the constraint system but in the witnessing - behavior. - */ - - typedef Fr FieldT; - - // Test the normal case - ASSERT_TRUE(test_merkle_gadget(true, true, false)); - ASSERT_TRUE(test_merkle_gadget(true, true, true)); - - // Test the case where the first commitment is enforced but the second isn't - // Works because the first read is performed before the second one - ASSERT_TRUE(test_merkle_gadget(true, false, false)); - ASSERT_TRUE(test_merkle_gadget(true, false, true)); - - // Test the case where the first commitment isn't enforced but the second is - // Doesn't work because the first multipacker witnesses the existing root (which - // is null) - ASSERT_TRUE(!test_merkle_gadget(false, true, false)); - - // Test the last again, except this time write the root first. - ASSERT_TRUE(test_merkle_gadget(false, true, true)); -} diff --git a/src/gtest/test_merkletree.cpp b/src/gtest/test_merkletree.cpp index d55cb13179c..dd9fbf85067 100644 --- a/src/gtest/test_merkletree.cpp +++ b/src/gtest/test_merkletree.cpp @@ -26,17 +26,11 @@ #include "zcash/IncrementalMerkleTree.hpp" #include "zcash/util.h" -#include -#include -#include -#include - #include #include "json_test_vectors.h" using namespace std; -using namespace libsnark; template<> void expect_deser_same(const SproutTestingWitness& expected) @@ -58,8 +52,7 @@ void test_tree( UniValue root_tests, UniValue ser_tests, UniValue witness_ser_tests, - UniValue path_tests, - bool libsnark_test + UniValue path_tests ) { size_t witness_ser_i = 0; @@ -115,55 +108,6 @@ void test_tree( } else { auto path = wit.path(); expect_test_vector(path_tests[path_i++], path); - - if (libsnark_test) { - typedef Fr FieldT; - - protoboard pb; - pb_variable_array positions; - digest_variable commitment(pb, 256, "commitment"); - digest_variable root(pb, 256, "root"); - positions.allocate(pb, INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, "pos"); - merkle_authentication_path_variable> authvars(pb, INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, "auth"); - merkle_tree_check_read_gadget> auth( - pb, INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, positions, commitment, root, authvars, ONE, "path" - ); - commitment.generate_r1cs_constraints(); - root.generate_r1cs_constraints(); - authvars.generate_r1cs_constraints(); - auth.generate_r1cs_constraints(); - - std::vector commitment_bv; - { - uint256 witnessed_commitment = wit.element(); - std::vector commitment_v(witnessed_commitment.begin(), witnessed_commitment.end()); - commitment_bv = convertBytesVectorToVector(commitment_v); - } - - size_t path_index = convertVectorToInt(path.index); - - commitment.bits.fill_with_bits(pb, bit_vector(commitment_bv)); - positions.fill_with_bits_of_uint64(pb, path_index); - - authvars.generate_r1cs_witness(path_index, path.authentication_path); - auth.generate_r1cs_witness(); - - std::vector root_bv; - { - uint256 witroot = wit.root(); - std::vector root_v(witroot.begin(), witroot.end()); - root_bv = convertBytesVectorToVector(root_v); - } - - root.bits.fill_with_bits(pb, bit_vector(root_bv)); - - ASSERT_TRUE(pb.is_satisfied()); - - root_bv[0] = !root_bv[0]; - root.bits.fill_with_bits(pb, bit_vector(root_bv)); - - ASSERT_TRUE(!pb.is_satisfied()); - } } // Check witness serialization @@ -200,8 +144,7 @@ TEST(merkletree, vectors) { root_tests, ser_tests, witness_ser_tests, - path_tests, - true + path_tests ); } @@ -217,8 +160,7 @@ TEST(merkletree, SaplingVectors) { root_tests, ser_tests, witness_ser_tests, - path_tests, - false + path_tests ); } diff --git a/src/gtest/test_proofs.cpp b/src/gtest/test_proofs.cpp deleted file mode 100644 index 5b5c19395f2..00000000000 --- a/src/gtest/test_proofs.cpp +++ /dev/null @@ -1,702 +0,0 @@ -#include -#include "zcash/Proof.hpp" - -#include - -#include -#include -#include - -using namespace libzcash; - -typedef libsnark::default_r1cs_ppzksnark_pp curve_pp; -typedef libsnark::default_r1cs_ppzksnark_pp::G1_type curve_G1; -typedef libsnark::default_r1cs_ppzksnark_pp::G2_type curve_G2; -typedef libsnark::default_r1cs_ppzksnark_pp::GT_type curve_GT; -typedef libsnark::default_r1cs_ppzksnark_pp::Fp_type curve_Fr; -typedef libsnark::default_r1cs_ppzksnark_pp::Fq_type curve_Fq; -typedef libsnark::default_r1cs_ppzksnark_pp::Fqe_type curve_Fq2; - -#include "streams.h" -#include "version.h" -#include "utilstrencodings.h" - -TEST(proofs, g1_pairing_at_infinity) -{ - for (size_t i = 0; i < 100; i++) { - auto r1 = curve_G1::random_element(); - auto r2 = curve_G2::random_element(); - ASSERT_TRUE( - curve_pp::reduced_pairing(curve_G1::zero(), r2) == - curve_GT::one() - ); - ASSERT_TRUE( - curve_pp::final_exponentiation( - curve_pp::double_miller_loop( - curve_pp::precompute_G1(curve_G1::zero()), - curve_pp::precompute_G2(r2), - curve_pp::precompute_G1(curve_G1::zero()), - curve_pp::precompute_G2(r2) - ) - ) == - curve_GT::one() - ); - ASSERT_TRUE( - curve_pp::final_exponentiation( - curve_pp::double_miller_loop( - curve_pp::precompute_G1(r1), - curve_pp::precompute_G2(r2), - curve_pp::precompute_G1(curve_G1::zero()), - curve_pp::precompute_G2(r2) - ) - ) == - curve_pp::reduced_pairing(r1, r2) - ); - ASSERT_TRUE( - curve_pp::final_exponentiation( - curve_pp::double_miller_loop( - curve_pp::precompute_G1(curve_G1::zero()), - curve_pp::precompute_G2(r2), - curve_pp::precompute_G1(r1), - curve_pp::precompute_G2(r2) - ) - ) == - curve_pp::reduced_pairing(r1, r2) - ); - } -} - -TEST(proofs, g2_subgroup_check) -{ - // all G2 elements are order r - ASSERT_TRUE(libsnark::alt_bn128_modulus_r * curve_G2::random_element() == curve_G2::zero()); - - // but that doesn't mean all elements that satisfy the curve equation are in G2... - curve_G2 p = curve_G2::one(); - - while (1) { - // This will construct an order r(2q-r) point with high probability - p.X = curve_Fq2::random_element(); - try { - p.Y = ((p.X.squared() * p.X) + libsnark::alt_bn128_twist_coeff_b).sqrt(); - break; - } catch(...) {} - } - - ASSERT_TRUE(p.is_well_formed()); // it's on the curve - ASSERT_TRUE(libsnark::alt_bn128_modulus_r * p != curve_G2::zero()); // but not the order r subgroup.. - - { - // libsnark unfortunately doesn't check, and the pairing will complete - auto e = curve_Fr("149"); - auto a = curve_pp::reduced_pairing(curve_G1::one(), p); - auto b = curve_pp::reduced_pairing(e * curve_G1::one(), p); - - // though it will not preserve bilinearity - ASSERT_TRUE((a^e) != b); - } - - { - // so, our decompression API should not allow you to decompress G2 elements of that form! - CompressedG2 badp(p); - try { - auto newp = badp.to_libsnark_g2(); - FAIL() << "Expected std::runtime_error"; - } catch (std::runtime_error const & err) { - EXPECT_EQ(err.what(), std::string("point is not in G2")); - } catch(...) { - FAIL() << "Expected std::runtime_error"; - } - } - - // educational purposes: showing that E'(Fp2) is of order r(2q-r), - // by multiplying our random point in E' by (2q-r) = (q + q - r) to - // get an element in G2 - { - auto p1 = libsnark::alt_bn128_modulus_q * p; - p1 = p1 + p1; - p1 = p1 - (libsnark::alt_bn128_modulus_r * p); - - ASSERT_TRUE(p1.is_well_formed()); - ASSERT_TRUE(libsnark::alt_bn128_modulus_r * p1 == curve_G2::zero()); - - CompressedG2 goodp(p1); - auto newp = goodp.to_libsnark_g2(); - - ASSERT_TRUE(newp == p1); - } -} - -TEST(proofs, sqrt_zero) -{ - ASSERT_TRUE(curve_Fq::zero() == curve_Fq::zero().sqrt()); - ASSERT_TRUE(curve_Fq2::zero() == curve_Fq2::zero().sqrt()); -} - -TEST(proofs, sqrt_fq) -{ - // Poor man's PRNG - curve_Fq acc = curve_Fq("348957923485290374852379485") ^ 1000; - - size_t quadratic_residues = 0; - size_t quadratic_nonresidues = 0; - - for (size_t i = 1; i < 1000; i++) { - try { - acc += curve_Fq("45634563456") ^ i; - - curve_Fq x = acc.sqrt(); - ASSERT_TRUE((x*x) == acc); - quadratic_residues += 1; - } catch (std::runtime_error &e) { - quadratic_nonresidues += 1; - } - } - - // Half of all nonzero elements in Fp are quadratic residues - ASSERT_TRUE(quadratic_residues == 511); - ASSERT_TRUE(quadratic_nonresidues == 488); - - for (size_t i = 0; i < 1000; i++) { - curve_Fq x = curve_Fq::random_element(); - curve_Fq x2 = x * x; - - ASSERT_TRUE((x2.sqrt() == x) || (x2.sqrt() == -x)); - } - - // Test vectors - ASSERT_TRUE( - curve_Fq("5204065062716160319596273903996315000119019512886596366359652578430118331601") - == - curve_Fq("348579348568").sqrt() - ); - ASSERT_THROW(curve_Fq("348579348569").sqrt(), std::runtime_error); -} - -TEST(proofs, sqrt_fq2) -{ - curve_Fq2 acc = curve_Fq2( - curve_Fq("3456293840592348059238409578239048769348760238476029347885092384059238459834") ^ 1000, - curve_Fq("2394578084760439457823945729347502374590283479582739485723945729384759823745") ^ 1000 - ); - - size_t quadratic_residues = 0; - size_t quadratic_nonresidues = 0; - - for (size_t i = 1; i < 1000; i++) { - try { - acc = acc + curve_Fq2( - curve_Fq("5204065062716160319596273903996315000119019512886596366359652578430118331601") ^ i, - curve_Fq("348957923485290374852379485348957923485290374852379485348957923485290374852") ^ i - ); - - curve_Fq2 x = acc.sqrt(); - ASSERT_TRUE((x*x) == acc); - quadratic_residues += 1; - } catch (std::runtime_error &e) { - quadratic_nonresidues += 1; - } - } - - // Half of all nonzero elements in Fp^k are quadratic residues as long - // as p != 2 - ASSERT_TRUE(quadratic_residues == 505); - ASSERT_TRUE(quadratic_nonresidues == 494); - - for (size_t i = 0; i < 1000; i++) { - curve_Fq2 x = curve_Fq2::random_element(); - curve_Fq2 x2 = x * x; - - ASSERT_TRUE((x2.sqrt() == x) || (x2.sqrt() == -x)); - } - - // Test vectors - ASSERT_THROW(curve_Fq2( - curve_Fq("2"), - curve_Fq("1") - ).sqrt(), std::runtime_error); - - ASSERT_THROW(curve_Fq2( - curve_Fq("3345897230485723946872934576923485762803457692345760237495682347502347589473"), - curve_Fq("1234912378405347958234756902345768290345762348957605678245967234857634857676") - ).sqrt(), std::runtime_error); - - curve_Fq2 x = curve_Fq2( - curve_Fq("12844195307879678418043983815760255909500142247603239203345049921980497041944"), - curve_Fq("7476417578426924565731404322659619974551724117137577781074613937423560117731") - ); - - curve_Fq2 nx = -x; - - curve_Fq2 x2 = curve_Fq2( - curve_Fq("3345897230485723946872934576923485762803457692345760237495682347502347589474"), - curve_Fq("1234912378405347958234756902345768290345762348957605678245967234857634857676") - ); - - ASSERT_TRUE(x == x2.sqrt()); - ASSERT_TRUE(nx == -x2.sqrt()); - ASSERT_TRUE(x*x == x2); - ASSERT_TRUE(nx*nx == x2); -} - -TEST(proofs, size_is_expected) -{ - PHGRProof p; - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << p; - - ASSERT_EQ(ss.size(), 296); -} - -TEST(proofs, fq_serializes_properly) -{ - for (size_t i = 0; i < 1000; i++) { - curve_Fq e = curve_Fq::random_element(); - - Fq e2(e); - - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << e2; - - Fq e3; - ss >> e3; - - curve_Fq e4 = e3.to_libsnark_fq(); - - ASSERT_TRUE(e == e4); - } -} - -TEST(proofs, fq2_serializes_properly) -{ - for (size_t i = 0; i < 1000; i++) { - curve_Fq2 e = curve_Fq2::random_element(); - - Fq2 e2(e); - - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << e2; - - Fq2 e3; - ss >> e3; - - curve_Fq2 e4 = e3.to_libsnark_fq2(); - - ASSERT_TRUE(e == e4); - } -} - -template -T deserialize_tv(std::string s) -{ - T e; - CDataStream ss(ParseHex(s), SER_NETWORK, PROTOCOL_VERSION); - ss >> e; - - return e; -} - -curve_Fq deserialize_fq(std::string s) -{ - return deserialize_tv(s).to_libsnark_fq(); -} - -curve_Fq2 deserialize_fq2(std::string s) -{ - return deserialize_tv(s).to_libsnark_fq2(); -} - -TEST(proofs, fq_valid) -{ - curve_Fq e = deserialize_fq("30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46"); - - ASSERT_TRUE(e == curve_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582")); - ASSERT_TRUE(e != curve_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208581")); - - curve_Fq e2 = deserialize_fq("30644e72e131a029b75045b68181585d97816a916871ca8d3c208c16d87cfd46"); - - ASSERT_TRUE(e2 == curve_Fq("21888242871839275222221885816603420866962577604863418715751138068690288573766")); -} - -TEST(proofs, fq_invalid) -{ - // Should not be able to deserialize the modulus - ASSERT_THROW( - deserialize_fq("30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"), - std::logic_error - ); - - // Should not be able to deserialize the modulus plus one - ASSERT_THROW( - deserialize_fq("30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd48"), - std::logic_error - ); - - // Should not be able to deserialize a ridiculously out of bound int - ASSERT_THROW( - deserialize_fq("ff644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46"), - std::logic_error - ); -} - -TEST(proofs, fq2_valid) -{ - // (q - 1) * q + q - curve_Fq2 e = deserialize_fq2("0925c4b8763cbf9c599a6f7c0348d21cb00b85511637560626edfa5c34c6b38d04689e957a1242c84a50189c6d96cadca602072d09eac1013b5458a2275d69b0"); - ASSERT_TRUE(e.c0 == curve_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582")); - ASSERT_TRUE(e.c1 == curve_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582")); - - curve_Fq2 e2 = deserialize_fq2("000000000000000000000000000000000000000000000000010245be1c91e3186bbbe1c430a93fcfc5aada4ab10c3492f70eea97a91c7b29554db55acffa34d2"); - ASSERT_TRUE(e2.c0 == curve_Fq("238769481237490823")); - ASSERT_TRUE(e2.c1 == curve_Fq("384579238459723485")); - - curve_Fq2 e3 = deserialize_fq2("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - ASSERT_TRUE(e3.c0 == curve_Fq("0")); - ASSERT_TRUE(e3.c1 == curve_Fq("0")); - - curve_Fq2 e4 = deserialize_fq2("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"); - ASSERT_TRUE(e4.c0 == curve_Fq("1")); - ASSERT_TRUE(e4.c1 == curve_Fq("0")); -} - -TEST(proofs, fq2_invalid) -{ - // (q - 1) * q + q is invalid - ASSERT_THROW( - deserialize_fq2("0925c4b8763cbf9c599a6f7c0348d21cb00b85511637560626edfa5c34c6b38d04689e957a1242c84a50189c6d96cadca602072d09eac1013b5458a2275d69b1"), - std::logic_error - ); - - // q * q + (q - 1) is invalid - ASSERT_THROW( - deserialize_fq2("0925c4b8763cbf9c599a6f7c0348d21cb00b85511637560626edfa5c34c6b38d34cced085b43e2f202a05e52ef18233a3d8371be725c8b8e7774e4b8ffda66f7"), - std::logic_error - ); - - // Ridiculously out of bounds - ASSERT_THROW( - deserialize_fq2("0fffc4b8763cbf9c599a6f7c0348d21cb00b85511637560626edfa5c34c6b38d04689e957a1242c84a50189c6d96cadca602072d09eac1013b5458a2275d69b0"), - std::logic_error - ); - ASSERT_THROW( - deserialize_fq2("ffffffff763cbf9c599a6f7c0348d21cb00b85511637560626edfa5c34c6b38d04689e957a1242c84a50189c6d96cadca602072d09eac1013b5458a2275d69b0"), - std::logic_error - ); -} - -TEST(proofs, g1_serializes_properly) -{ - // Cannot serialize zero - { - ASSERT_THROW({CompressedG1 g = CompressedG1(curve_G1::zero());}, std::domain_error); - } - - for (size_t i = 0; i < 1000; i++) { - curve_G1 e = curve_G1::random_element(); - - CompressedG1 e2(e); - - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << e2; - - CompressedG1 e3; - ss >> e3; - - ASSERT_TRUE(e2 == e3); - - curve_G1 e4 = e3.to_libsnark_g1(); - - ASSERT_TRUE(e == e4); - } -} - -TEST(proofs, g2_serializes_properly) -{ - // Cannot serialize zero - { - ASSERT_THROW({CompressedG2 g = CompressedG2(curve_G2::zero());}, std::domain_error); - } - - for (size_t i = 0; i < 1000; i++) { - curve_G2 e = curve_G2::random_element(); - - CompressedG2 e2(e); - - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << e2; - - CompressedG2 e3; - ss >> e3; - - ASSERT_TRUE(e2 == e3); - - curve_G2 e4 = e3.to_libsnark_g2(); - - ASSERT_TRUE(e == e4); - } -} - -TEST(proofs, zksnark_serializes_properly) -{ - auto example = libsnark::generate_r1cs_example_with_field_input(250, 4); - example.constraint_system.swap_AB_if_beneficial(); - auto kp = libsnark::r1cs_ppzksnark_generator(example.constraint_system); - auto vkprecomp = libsnark::r1cs_ppzksnark_verifier_process_vk(kp.vk); - - for (size_t i = 0; i < 20; i++) { - auto badproof = PHGRProof::random_invalid(); - auto proof = badproof.to_libsnark_proof>(); - - auto verifierEnabled = ProofVerifier::Strict(); - auto verifierDisabled = ProofVerifier::Disabled(); - // This verifier should catch the bad proof - ASSERT_FALSE(verifierEnabled.check( - kp.vk, - vkprecomp, - example.primary_input, - proof - )); - // This verifier won't! - ASSERT_TRUE(verifierDisabled.check( - kp.vk, - vkprecomp, - example.primary_input, - proof - )); - } - - for (size_t i = 0; i < 20; i++) { - auto proof = libsnark::r1cs_ppzksnark_prover( - kp.pk, - example.primary_input, - example.auxiliary_input, - example.constraint_system - ); - - { - auto verifierEnabled = ProofVerifier::Strict(); - auto verifierDisabled = ProofVerifier::Disabled(); - ASSERT_TRUE(verifierEnabled.check( - kp.vk, - vkprecomp, - example.primary_input, - proof - )); - ASSERT_TRUE(verifierDisabled.check( - kp.vk, - vkprecomp, - example.primary_input, - proof - )); - } - - ASSERT_TRUE(libsnark::r1cs_ppzksnark_verifier_strong_IC( - kp.vk, - example.primary_input, - proof - )); - - PHGRProof compressed_proof_0(proof); - - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << compressed_proof_0; - - PHGRProof compressed_proof_1; - ss >> compressed_proof_1; - - ASSERT_TRUE(compressed_proof_0 == compressed_proof_1); - - auto newproof = compressed_proof_1.to_libsnark_proof>(); - - ASSERT_TRUE(proof == newproof); - ASSERT_TRUE(libsnark::r1cs_ppzksnark_verifier_strong_IC( - kp.vk, - example.primary_input, - newproof - )); - } -} - -TEST(proofs, g1_deserialization) -{ - CompressedG1 g; - curve_G1 expected; - - // Valid G1 element. - { - CDataStream ss(ParseHex("0230644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46"), SER_NETWORK, PROTOCOL_VERSION); - ss >> g; - - expected.X = curve_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582"); - expected.Y = curve_Fq("3969792565221544645472939191694882283483352126195956956354061729942568608776"); - expected.Z = curve_Fq::one(); - - ASSERT_TRUE(g.to_libsnark_g1() == expected); - } - - // Its negation. - { - CDataStream ss(ParseHex("0330644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46"), SER_NETWORK, PROTOCOL_VERSION); - ss >> g; - - expected.X = curve_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582"); - expected.Y = curve_Fq("3969792565221544645472939191694882283483352126195956956354061729942568608776"); - expected.Z = curve_Fq::one(); - - ASSERT_TRUE(g.to_libsnark_g1() == -expected); - } - - // Invalid leading bytes - { - CDataStream ss(ParseHex("ff30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46"), SER_NETWORK, PROTOCOL_VERSION); - - ASSERT_THROW(ss >> g, std::ios_base::failure); - } - - // Invalid point - { - CDataStream ss(ParseHex("0208c6d2adffacbc8438f09f321874ea66e2fcc29f8dcfec2caefa21ec8c96a77c"), SER_NETWORK, PROTOCOL_VERSION); - ss >> g; - - ASSERT_THROW(g.to_libsnark_g1(), std::runtime_error); - } - - // Point with out of bounds Fq - { - CDataStream ss(ParseHex("02ffc6d2adffacbc8438f09f321874ea66e2fcc29f8dcfec2caefa21ec8c96a77c"), SER_NETWORK, PROTOCOL_VERSION); - ss >> g; - - ASSERT_THROW(g.to_libsnark_g1(), std::logic_error); - } - - // Randomly produce valid G1 representations and fail/succeed to - // turn them into G1 points based on whether they are valid. - for (size_t i = 0; i < 5000; i++) { - curve_Fq e = curve_Fq::random_element(); - CDataStream ss(ParseHex("02"), SER_NETWORK, PROTOCOL_VERSION); - ss << Fq(e); - CompressedG1 g; - ss >> g; - - try { - curve_G1 g_real = g.to_libsnark_g1(); - } catch(...) { - - } - } -} - -TEST(proofs, g2_deserialization) -{ - CompressedG2 g; - curve_G2 expected = curve_G2::random_element(); - - // Valid G2 point - { - CDataStream ss(ParseHex("0a023aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984a"), SER_NETWORK, PROTOCOL_VERSION); - ss >> g; - - expected.X = curve_Fq2( - curve_Fq("5923585509243758863255447226263146374209884951848029582715967108651637186684"), - curve_Fq("5336385337059958111259504403491065820971993066694750945459110579338490853570") - ); - expected.Y = curve_Fq2( - curve_Fq("10374495865873200088116930399159835104695426846400310764827677226300185211748"), - curve_Fq("5256529835065685814318509161957442385362539991735248614869838648137856366932") - ); - expected.Z = curve_Fq2::one(); - - ASSERT_TRUE(g.to_libsnark_g2() == expected); - } - - // Its negation - { - CDataStream ss(ParseHex("0b023aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984a"), SER_NETWORK, PROTOCOL_VERSION); - ss >> g; - - expected.X = curve_Fq2( - curve_Fq("5923585509243758863255447226263146374209884951848029582715967108651637186684"), - curve_Fq("5336385337059958111259504403491065820971993066694750945459110579338490853570") - ); - expected.Y = curve_Fq2( - curve_Fq("10374495865873200088116930399159835104695426846400310764827677226300185211748"), - curve_Fq("5256529835065685814318509161957442385362539991735248614869838648137856366932") - ); - expected.Z = curve_Fq2::one(); - - ASSERT_TRUE(g.to_libsnark_g2() == -expected); - } - - // Invalid leading bytes - { - CDataStream ss(ParseHex("ff023aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984a"), SER_NETWORK, PROTOCOL_VERSION); - - ASSERT_THROW(ss >> g, std::ios_base::failure); - } - - - // Invalid point - { - CDataStream ss(ParseHex("0b023aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984b"), SER_NETWORK, PROTOCOL_VERSION); - ss >> g; - - ASSERT_THROW(g.to_libsnark_g2(), std::runtime_error); - } - - // Point with out of bounds Fq2 - { - CDataStream ss(ParseHex("0a0f3aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984a"), SER_NETWORK, PROTOCOL_VERSION); - ss >> g; - - ASSERT_THROW(g.to_libsnark_g2(), std::logic_error); - } - - // Randomly produce valid G2 representations and fail/succeed to - // turn them into G2 points based on whether they are valid. - for (size_t i = 0; i < 5000; i++) { - curve_Fq2 e = curve_Fq2::random_element(); - CDataStream ss(ParseHex("0a"), SER_NETWORK, PROTOCOL_VERSION); - ss << Fq2(e); - CompressedG2 g; - ss >> g; - - try { - curve_G2 g_real = g.to_libsnark_g2(); - } catch(...) { - - } - } -} - -#include "json_test_vectors.h" -#include "test/data/g1_compressed.json.h" - -TEST(proofs, g1_test_vectors) -{ - UniValue v = read_json(std::string(json_tests::g1_compressed, json_tests::g1_compressed + sizeof(json_tests::g1_compressed))); - - curve_G1 e = curve_Fr("34958239045823") * curve_G1::one(); - for (size_t i = 0; i < 10000; i++) { - e = (curve_Fr("34958239045823") ^ i) * e; - auto expected = CompressedG1(e); - - expect_test_vector(v[i], expected); - ASSERT_TRUE(expected.to_libsnark_g1() == e); - } -} - -#include "test/data/g2_compressed.json.h" - -TEST(proofs, g2_test_vectors) -{ - UniValue v = read_json(std::string(json_tests::g2_compressed, json_tests::g2_compressed + sizeof(json_tests::g2_compressed))); - - curve_G2 e = curve_Fr("34958239045823") * curve_G2::one(); - for (size_t i = 0; i < 10000; i++) { - e = (curve_Fr("34958239045823") ^ i) * e; - auto expected = CompressedG2(e); - - expect_test_vector(v[i], expected); - ASSERT_TRUE(expected.to_libsnark_g2() == e); - } -} diff --git a/src/init.cpp b/src/init.cpp index eec0ffde8ca..74f65324e09 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -59,8 +59,6 @@ #include #include -#include - #if ENABLE_ZMQ #include "zmq/zmqnotificationinterface.h" #endif @@ -527,7 +525,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-rpcservertimeout=", strprintf("Timeout during HTTP requests (default: %d)", DEFAULT_HTTP_SERVER_TIMEOUT)); } - // Disabled until we can lock notes and also tune performance of libsnark which by default uses multiple threads + // Disabled until we can lock notes and also tune performance of the prover which by default uses multiple threads //strUsage += HelpMessageOpt("-rpcasyncthreads=", strprintf(_("Set the number of threads to service Async RPC calls (default: %d)"), 1)); if (mode == HMM_BITCOIND) { @@ -687,15 +685,11 @@ static void ZC_LoadParams( struct timeval tv_start, tv_end; float elapsed; - boost::filesystem::path pk_path = ZC_GetParamsDir() / "sprout-proving.key"; - boost::filesystem::path vk_path = ZC_GetParamsDir() / "sprout-verifying.key"; boost::filesystem::path sapling_spend = ZC_GetParamsDir() / "sapling-spend.params"; boost::filesystem::path sapling_output = ZC_GetParamsDir() / "sapling-output.params"; boost::filesystem::path sprout_groth16 = ZC_GetParamsDir() / "sprout-groth16.params"; if (!( - boost::filesystem::exists(pk_path) && - boost::filesystem::exists(vk_path) && boost::filesystem::exists(sapling_spend) && boost::filesystem::exists(sapling_output) && boost::filesystem::exists(sprout_groth16) @@ -710,14 +704,7 @@ static void ZC_LoadParams( return; } - LogPrintf("Loading verifying key from %s\n", vk_path.string().c_str()); - gettimeofday(&tv_start, 0); - - pzcashParams = ZCJoinSplit::Prepared(vk_path.string(), pk_path.string()); - - gettimeofday(&tv_end, 0); - elapsed = float(tv_end.tv_sec-tv_start.tv_sec) + (tv_end.tv_usec-tv_start.tv_usec)/float(1000000); - LogPrintf("Loaded verifying key in %fs seconds.\n", elapsed); + pzcashParams = ZCJoinSplit::Prepared(); static_assert( sizeof(boost::filesystem::path::value_type) == sizeof(codeunit), @@ -1228,11 +1215,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) threadGroup.create_thread(&ThreadShowMetricsScreen); } - // These must be disabled for now, they are buggy and we probably don't - // want any of libsnark's profiling in production anyway. - libsnark::inhibit_profiling_info = true; - libsnark::inhibit_profiling_counters = true; - // Initialize Zcash circuit parameters ZC_LoadParams(chainparams); diff --git a/src/test/data/g1_compressed.json b/src/test/data/g1_compressed.json deleted file mode 100644 index 05656ec4005..00000000000 --- a/src/test/data/g1_compressed.json +++ /dev/null @@ -1,10002 +0,0 @@ -[ - "0313c596027e31905eb141332c2fcb81d0167a7d80f49bd5a28e3acf18992031af", - "03205567add6af2d301f0066aa9b0bdec694847a7f25d9bdbccfb32e27d52d9ad4", - "03261294f8587a11c981749e030a303030a358b9353ee068139ce46f3ff590ccc7", - "031f99bbbbb949b5f91fab79dc9229f874dbd6fb9c8aafa54acb4629a292b9e821", - "0314cf1831b3a6f01bc98ff7beacf546e2191598c3ea79821f26388071ea65fccc", - "0303bcbc83040376a75a07159e2b6181dab40f93e31228a1fc0d27644d78d73ce1", - "032fbcbb929e8bba71bfeb425e1339498e8207e70f4d2a9b9a0d9f0b35128c24a4", - "0205534f70aa1752558dd9e140be0523df4678048be687191d811b4967b8995f84", - "023010f5ecd43379c726c466ccddfe7e594b99ac38f3bd1b8c48fb546575948e05", - "032551bbeb4a21201c6254d8cd265b437685284b3777035811f71329b1b51dbf38", - "02153b4a4d07c05e1a982e34c1f575e40ebe9948524f0a8c9c9c7c38025df0429c", - "0307abfe0f44aa54791542c7afa034fb5bb220b6ff9b0a8372c817cde42f2c1c80", - "02269daff36da876ad299bbde6e334f9bbaf44e2e50a0babad87ccd6b5424902de", - "02068b95ac503e28d69418d8d0678393383e7a1eb65f038272fc880a309c7c7886", - "0228a9995f68c01aec41bfdb93ea650f71a52dac3b8163e098324b19ca5bdb7873", - "032aa71687f030088f7c1c6d739442cde195ecc42e48367f9bff277c4f4ac247cb", - "03149262403e5f10bfe9124ca5fc2efc6e7d9e7e3e4fb152bb5e886149ec51f062", - "02209bb5d92592fbf998aad99034b8fc57aaa7767508d7af9e01b09399c371a50e", - "021b17c98a5721c6c94dc58f4e333ac8c09fcc33377ce3df3e09463db4d6b15a19", - "020ce2597b7d283e7f7431ebbc446ca149183369a8f174dc248840c0eca53df553", - "0210200605e935ab1038124fd546fdaa2bf989d078dadef50cebed26a58fbcc22b", - "020cc33ead6f916268a6b7a957876e1c4fad9f255e422f31c7ee42d3a84e769a14", - "022e4ec8909cbe38b8880d7b78c1c8c1c4267161bdf626ea62ddd9efec96b82bd8", - "020fa0764a20456453396b2d5ba7bce7ba2157b9575e8cb789e6a6971911a56475", - "031001b7f9db262d36a4b6770e4a398872b1eebe00bbea1dd15cfc05f7b327f34d", - "032327bb0fab326aec011843a0a86a1f0ce594991bfe6101607dfae99de1e220d5", - "0320f582d355910b2e9f01638bf02cc49780a1bfe97fb4cd98fdd054ce5a6ad9dc", - "0319aa50bca07f74d4cbfe4963da165498bab5658553c27f6fdbbb45bde09ab197", - "021d098cdd8e6704ab1913cdfa8d8e38f07ff58ca27c39ad474cd7e15f7991ecbb", - "021f0058926a783d75df873d420df397181f2d4bfd28556aa5f88bd1842308bd09", - "0302ef7221d932e13c6714600386b59960d2a5ed97109be49fbda73b8a64a2b853", - "030acd288c4ef4c7f69e3dedaa21cc0dd06cee2b6b9c9c76aa2b1dfb9aac6a07ab", - "032e291b28f3e35e779591f7b6cc527963715f5a1c39dcb6c737e3dd73575a74ed", - "02104461202856c31ea70b8ab6c3a94e81a9724d8ce04de3526cc7def08d3c5943", - "0223ebbd9100308a82c78760ccb85a501e27b064527cc2dd67a9555f1b6c34b66d", - "030b5aeed2e910ac75d8b4209ff162667f7cd58471f750a04c20c1d3bd11b37087", - "030471ff0babfb21c5d96346b45d02a40bb3dcecd38f6fabc83d0daa7447f9c1e5", - "033054adf9df1e378d176787049aa1b2b363ece79fa747e944c02826bbd99ab926", - "022989c34c7d9670481ff62dcd4f57ed263350ddba4d7cbe0953ae4223448474c7", - "02070ae5fa41087fda4023f037c89e22d36dcee55afe9c9ebfdc794f2215213d14", - "021d2a53d5d599042b464a39d9daf6a8c8ad8e61f5ba454c464676be8d434b3df1", - "02219fd6a48a8d6eaa525bf39ef8b4fd68ff0bd7b672322ce126610cf371953dff", - "021b79660fb36b1da3c57c08b225b69b7e993d403b1d31fb739282057965157833", - "03173825cab7e02662f8563dd6728c408f23ada3bfd2b54425696cbcd617042f1d", - "0328b238ee4380d07932760e50688211ea45af0a4c59a51b52dd1862efae5a03f2", - "02156950a4c01844b3060d76b62e7d62e1a31e6b988c30237ca993666a5df52100", - "022d910d09d56e23ba7eacb08945b8466e09af78763228e68774dc30e500bd01e3", - "031ad87e269a442111ade3ff82c73191575db21db867a73b7a27592d1e34e9994e", - "0204a352b205ad3ef55d8748ecfda449f4bc1bb60045d3618cfe010c2941281701", - "021083e6e0b8aae706ad61504444f2b462bb2a11775006dc2b6b8851af7082df20", - "032490f3bc9fa1af1bc55fe8274cbd5626c1df122d04d51587597f589b6a0ed3e3", - "031ac4fe9c06883f914a409fdf9f08b15b3a2587d13cac8040d15b2e6c08d834c1", - "03141c10553e02baa186e3b9ba463772dcde2e3317d690e0ac6d2e45ab77eef4b5", - "0226601508c055a187473290cca01659ee68cb29960739ad8374814d36ac3c30ad", - "032966daea2b895741273461e6dbba70d0a2ca6848c6329ec559d5efe2212046c5", - "0227fed4f9bdac925cc25d5c9a36c1e005b739f05ce133781e448fdd46b395f04a", - "030943e956b4d725ef60fa4c2ec4a9077e6ed1217f277c328bf852acf67828b29f", - "022510033e9796256019f9fce82c6388ce619b1055093debf67445089dda98b869", - "021aa7f9775dc70077c1646d8831a02769fabec90cf856c44ef899d82e78421593", - "0313bc34dca0fc48deecfd98619d88dbf3b6b5dbb08d7bbf510deb8dd209c9561d", - "0222fcc0ef2aaf4961dc0e5a8284b91aaa7a333ceeaccb33ae3f0c7242731759ae", - "0216a58abb77cb87c69412a0da28c0ca16705b1e9c5de130f719702db81aa9a90f", - "030bf0e9408ede4d7cd79ee24c5870ca6104c3eb3beb377a8b614bb5a57db991d5", - "030e4a16f3f19fe195b5c159b8e7f0b8ec54a5de570eab1a5984ffe67c3cbc0f30", - "030e4c8190f2540767c5b527844359c479a4fc731879c70f737ed12df396164789", - "020d70042db011028e01762186f19190e30680ffd35dc11099dd8f072bd7740064", - "021161e17863951a3d3d80a4f752d71bf0fa0eb42a4e44ccb8a5e2617a9c974cdf", - "031f2bf0c9f7974f6a13b69dc40f3af73dd7874cde6e64e18bbad3da0b65c31fb1", - "032c053577f04688d104ec32a5d3e617bcf59ba959356a7a06dee25ee7af4f2e87", - "032ac51499daeae348f45e7b1a0e9a72b8847b4b76693986ef9800c8324b4ad225", - "032b1d15585bbfc6ced25394f7ca44e0ba0c260acb81d72e4c9332719cbe2afc9d", - "0218396f07a62fd73110e216ad8b7a6b6f7c82bf13e33eab5d698e79ca4447cfde", - "0228f29af2bcddd48968c4163cdccf34356abf93919262ddeeddbc8c54d2783a2e", - "020d08d0d5b343cd02fce28f841256a1901522583fd6f838d91fc2aa032031e6c2", - "030549edda292b33ea530ea7f246c52998e6d57fdefc9d93ba5512f64c2806be2f", - "0302f3877c5588d2242f66ffd9f26851626e0257ddea4700173a4f6782fcf86dcb", - "022e517dbc949e25c3c89a25bdfb48800717c37285bd66be5dbdd78e56ce4fe266", - "030b3137a7b66703ae85fdf7c3d96d7c453ca5b0188c6c70c24eb95828664f11c9", - "0211a7c22dcfaa104731c4fbc19ef362b1dadad3612efab6efae6bd048f05133d3", - "0203b4d65c15e0c68c7c13edd0818c5cbd486e3aacdbd5563529c78f76cfc955e5", - "030741bed8c823c9f058e92be533cf4afe9712dc4c50b277343a38a85b7a513251", - "03076f6ff0f74766c5caec4af484ad5f3c3ca6093299c85039bafd27579205f8d5", - "022672417356ab65e6edbece2178e6c1d88cb08f991c7df2516d6974e78c23a90b", - "031816c4f1f25f6ed3e8882f1124825dac9c4b20e90aaa91a492a68e846600b12d", - "022e9f6ab0f4e77f0170027218a1975bb203fa13ba56783eabc45ce4e655a65a74", - "031c4b273c819d7afd48ea90dc2bf8ca15e4efd4619a3084220ad0c79f1f8deffb", - "02137bc98fb79965a9804c4384ec7ecb3f183c7703488d37f4db26dbebd7907e07", - "02014863ab55f3b31ff86019f0a3c141b9e3528a3c61184c3334f6edfabcb6b956", - "020b19cd4d5e50f5f3ef0f3318399c63fe8afa6e8b8bc67b64e03e8814ec3c72d5", - "030b4a66f3b34e50b21a4943063646d1178551dcc183f02344c2a275431d06c002", - "0301c735eee1a20534860284f68236feaa71403dbf36a4e4814a845273d46a62c3", - "030334e7bba74751090a987aac901623b7adc68d8c74dc3db7085999ea2b801053", - "03045da3571a3fbde9af7392f7bc0cf2b0348337f75ae7fb9977033d23b02ad170", - "02219edcf4f7676b8ac4d9d344eacefea83c1bf66374c2c0ffc05966bc68d1f848", - "030dfe75e9c7b7b1b7e59500cb7c9abceecf599755d27c2880b29fd6b0503f2144", - "0310dd7c6acf4cfe90fe291f6dfb873f9301ae0735b730f303f92321e7de63b3f1", - "0309b32cc13a78f90ddd67d6f50163de0ef4173d910fe5ea5f34bd045e68ea46ab", - "032abc81668bee9f4633754048109911768ecc85428dea50e3ffccbe1bcd5a5bfe", - "030df2bc78e4b346337ac40fce14254bc25be1b45e7f15bc47f31f92d8821b355c", - "031778b77838beaadd42302650ed9d7675826f10d476b2694fa97d4e0950c3d4ae", - "021ea6bf88f8ee5b2bf17c7b5880b72cb7b6969fd27efea434ab58b4c96ebd7739", - "03155c19dc52aeb195c7051455100d1aaffb6442730d9b0b38ef217774daec6ff8", - "032077c191cd52ade13e9a6dacd506957cd02df9f676f27e86bb2641de2b76cc9f", - "02015256c0bef47bb7dc27682dfb069fd53b5adee1641d39533bee31c4ca81bc62", - "03138dc3dd0753e6f221c48d7297a3694a7667ce8316d72175b4fa6bea4bd7c2c9", - "0208f88e6ba38e37a95a0c34cbb042f5ec21be1d586ba30694ae1b63e8264e4c7c", - "0321452424f453cb04c46665fd5846b987274c945e8c3ef52ea893e27cf79e19d0", - "02235ac7de33b2f1f698346ce7b91c8ee3397576e1ef5503fec8ce98765138a5ea", - "020e01df5256fd8aa79f204948ce50363abb793f32728eccb3b0b56289bb4382d9", - "0328fc9f5bc639383ca8361ccb41f76567586e1edcd4347dc15ee673b914464860", - "0220011eae8dff754bb72b0f46ff5319a3447443c92015cd0bf5f95d5acdd0a1c1", - "0228f9a0523d550c5a2879bce6f6b2e142aa61e1ab9e25b387ade0f4a760691718", - "022b7f40cd95c9e0f02f2fa87eeed88254b15aa06198b0b4f4c096214062fd41ad", - "030bc9b2cf1b9a11f73804445ce983c9e5c7bb5078e26fbfbbc593714a093572b7", - "03290c8e62f3b1184fb24f28e796a1ef9b08e1b6579c8118dc0834da137f19473d", - "030c7b7ee1ea0d8e9f463681c6cd6e0a105dc79ccdbef75334818b4a4f45ec8ba5", - "021df5c9a1c74fecf6ba31c25aa7c6a8d449f423da7f418bc081ff9db348ebc133", - "0314d94ff3c66c3ff8a3a4318ce070f3c31428eee9ed37b314c2c5f01a939b8ec9", - "03275f6d77855a683e09335b3e29c82f33476c1e9215c520dd297a718bad30b805", - "021601448cf3aeda596fcd4617d55ca25acfa350651e3262f8a1585fa0f467a533", - "0215f2194551f5ac5c05ec8fc26f945075271c5fa07b05ed2e9a54ecbc51a54570", - "03074f1cca2b54669f76f73230f582ee3ec46f020ecd9ddcafe55eefdd9c4c8d0e", - "0220f1c8fac0d93166f290c2b822827bda6d9077831a77832d7922284c04c72c37", - "022eaa838c3e8e85fa8052ea4f698e6fa5f7be0f6dcf4a80ae5735e56d2af3ca70", - "0217d2c54ecd83cd64ca15ebd12755f55cfa2dcf9e764fc12000e136273628994f", - "0326f5365c67d15deaa46a07bec7f19c52f75b7b677e9d2ab7a8af39c27d3ab915", - "020106b4a5c31f316a78e121f79970341eeb868b43076bdce0181b195a7a4949e6", - "02249dcd91107acbad6afe3756fc7da1036bc67d8a8b78364c2f0fe3578e10bc26", - "031cb8d5517f3bae6796dc94ea6261e1a74fce698d395b215c9d16ada3fae4753f", - "020b9ba09bd981cef8fed5abaaa06a2838018ac475acbe2477d2466ddb2d855234", - "0317c19aebecf39b5759338322593c9d8299f9c1b9e0e1fd562bc8bb88ce37ca19", - "021b237e2498dd36f8483d41edd900b19c7d15405644173e0c8f09ac2e83d2bb70", - "020168dd92cc6206d1eed892f9908bca3761787b584d546ce9c884c9ece0331dcc", - "0315665bb45cfc2e65917522caf81b1be412fb77e40a68c2774f3f691263d35c1c", - "0300b6f779422ae33ccdc5c14307d865cc8e093fa65db75bf6e6056a68de330dba", - "032cf1e590f5dabb9ecd1ac0e1099cca97f4587f33c1b30f784ad0a93dce19949a", - "03060c46bea1bb7ad0e80fece6414a3358a49d46fcb71f881fc6eb681eb8db4288", - "020cba2337f7a82d5f6d2cb68e63cfa2b85cd021faf5db02aefb148710f136acac", - "0319a5a8c8e46792be8336d67a5649a06ffd5562ecae2ab8c61189bea21559a94b", - "03261cb1821c1f5950e89bded40195db4f7abbbccab0f369157062148a168463c4", - "0307b064a60fe2d50a7b6cb9f0566ad37dc9d2a6112a70c1e197a9e1052508fb33", - "031aafc545573b2548593b3e676fdf9477abaf358c527bd8ca25d831a9d60be15f", - "0204e30192d7987ad601e509b9848c115cac2584e568fc6ee624c788551f7579a6", - "030b81cd69fd491ee6764db1cfeb6702d38cb76660ff006b21486e323430a46f90", - "0222fc651efdb988754d21755385c518a02def15b90dfd828a73c98354d97de44d", - "03015f36c0c061f769104af43b2e0e58dcd10f8a9593b4364f4f6870a741af4d0b", - "030d41c53a863822d5c7c8496313b01c4a30bd235c1c5848e822f2c90848a3aa47", - "032ece7b223a7c70892233804c0c64f27506161bb745c43e9c7ac9bce0b0373f17", - "0208d025a7cbceb2ef5fb250a52e1f64dbc7ac57c65e0aa5a2ce177d563936e299", - "02283aa89e4949e9bf27458fe462b49c9b28b81964b1fe955ca660b7ac15e48eaf", - "03001e720cab9430ac5b92f3688aa7437b758b70113a82e97a4e8d782b1d339e18", - "032af6aa34085102b1c05ff22b6c7593e33b29d4063da52d331a8fd04b3dff7350", - "022c59bcb738438b37a8242e5670208dc78232710c93552ba39ae05a9a83081dd1", - "031614aab0de3359d00fa987a8bd63f242bec7d731efcd9a455447be40a7db1ebb", - "032f4fd98825adc6411dd88c7bc3c5b2a2a6df2745b02179a10fa9b7ea6e4c84fa", - "022a3516f407fb07079c66264201a1cd08b4afde38d23081f117fd665133e6fa36", - "031c334b8c20336dbed11952a10438b32d3398a5e664ab2255d79ee7fe55611ed2", - "032e32de5d6ebbc68a13f874c3c866114c71423e2d01d4db6122d77002c5cde613", - "021dbb4b428706d4a5c4ce3f49421e2f526a8f138d744be2fb94dbadd4f9f44f2b", - "0223e89cabb38ca5b8487c8408b0e994f6fa685ddcb67a1bb99e7a24877c823622", - "032e377b0cebc1825a701ca13c2a8069dfff8be70b0e2b1aafa053fb88fc4954c9", - "0201e71efc691e4cd33914c9b73d1e29cddc0365e903bc01011b76bc6316c7f2ce", - "032c82b9de25cf714c0a685c05527db2ee17f509275cbb83dd23f04b2ed03b7523", - "021bfa346c8a96cff6b8d4829ca4d6a5ca52a5b012995a555cae6d0b30c99cb681", - "0315272f30ccb9492b8886222fa29266b80e6fe7127a6bdbfe6ba403c54191e5aa", - "0321bba5e99ad89a2dc231b8093ac4d7a439fd4487f60a3b21cb9afe58599826ed", - "0310ecb4898944d79e9c07b41185e8159756ed7676ad34f22badf1d42e6604a2b6", - "031559bf0dd0df6a79209012c462842c1f61e11b6744b5a81132279b12cd2cc6c3", - "02095ec73d558836f9ec38f9c995519039c037327c66e56286220cef358fea219f", - "021e5948c52642dbaf501d6d1eff9a4314692c4dda3a973e0930b13d7d29ca40e8", - "021027943d3667bb66ef3cd58336bdc7deae233f9fef428bd900bf2e5607c26ec1", - "0206f1c8fc1c48911f758b2c3ff2616fa693ac7790ed8fd9422886d449bc6b49e6", - "03126381c9dba1f7df61d071fec2d61f87e3fce0004854480163d852bc06450c19", - "032ae51c23b9ab8d7bd8dfcf14dc89ffb5609220abb73d447d38c82eee34889347", - "02039f458b15a955f81fc6a954012760b5f1edcfd49aa25d0f1271faf96fe39917", - "032a9e6351644be066812535df43f31488ba3fff9834c6d7c23d6a36d123328a2f", - "032f5258bda82152fe10826858a051a18900a30b720fcfce73a11d1de20669797b", - "0223544e385609a5a12febb1c15bfcfa1eb96eb985ce9f1bd96a48789e6f0f2d7a", - "031961c0a4548bef14c98129d19a7ecad71ff977f29ffa9bc9c1e9371aa707d597", - "02135851f037ecb28a02a9099fa81fb4d1f2a196fdd935a09d811eb9e3d963322e", - "032c5eee7ee19505113052eb3ac351905870e4b69a0690f6bfe1145b60f9fa243a", - "02247871d2768d25b6e1a86bad412eb48e9d43a65f8ca86e11ded610a8c8de1953", - "021cea3cc991659b73c03679b9aabd7b510f719c084a6c5492fedb87dc296f862d", - "030bddc7cab7e18de378e44ddc213f182e00398f8ed75e76f09371bf00c5fa81c0", - "0206a247dcd0919dc10d84f85a7b5f7658a2922f3a462c7e18d867b9faf26fa3cf", - "02012c464c581ace21bc3612a30471dffcfc43ddab5caf13ca6b9a70ffa99ab73c", - "02154001f381bb4cc80fd5a3d4efaeb6d7b1a864a4d5615f82b4fd09d0b4e13150", - "031ab3227c267022bd5d832f246832d84a0a5a2d0ba74b607016fbe79120aa47d0", - "0313d0ffaac4713e3b82d7ffc396d6bd93b11afde228cb2ac0efd17c88d3b5c3a8", - "031e659714ecf453dabefa1ee97f643ca5a95547a314e6ae59f7ac7be86277369e", - "0326e6618286381f6f222c0e3b73efaff0c7bf082cc9e721f34722dcb1211bad56", - "0305871c3bee2873465a486163007fffc0fe8c7ce724188dd7022d5a5d6a6abea1", - "03167d0e61f0301e56ea57bbfb9420435e9c865d4b79e02b00be82e5c84d13210c", - "0305e88bf942227355fe820e467dc86063f32bdd54730ee5da1116b30d5a06a9f9", - "022f338bb187dd72eb2464883612ee046661761870450f843383e6d46d475edf4d", - "020acbc5744d74a2c80cda0c7362d21ee7ccc1e4d4f83767aa131e1e346578813f", - "032d730ccaea02b7777550e9600cdb62c5a81d4a55294d92e643051b49e6f14552", - "03215c3e4702e5f836d1ae28e5fbc24401cc02ed2de0df6cffcac59546b99d8eac", - "02047a5a7ef5711f4660135ead6f6cfa4436cb671983a8797d8b1b97579b56429e", - "032fa65a2d968050f4eae2aa0dc2d7f3e865d5a4042ea60bf56c5b8e0cba1f6f7e", - "022f8c89286ea8e646ab47404e252b8f7f74970d079f7af2b60e02e838f1dc2bc9", - "0317282a6208589637d1f3a77598937d30adca6006c8d889dd0e9e6f55252b85f3", - "031c3f85421b250c67eb5a8cdd77ce97d46c1296a4ad17d8f171b3f16ae7acbba5", - "02212e8b0b31640935253321c98fcb95270c8fc3588fd4ba758c4d60ea271604c5", - "020b08d83dde5ad1f90083b646ab37c80ccd9ba0837e066211aa3344512628d3bb", - "022df4bf98d7e725a41d0f9a0360a0a306f8bdac52082b209222cf91a761061e9d", - "0306a168fc7126c1d6d33f3cd96f5e1a7c9a372064868a3ac79863121a1a820b36", - "0207e8bdc17455fe03818725c12b6ea09a886f6edaf3873da195998a3befa19f29", - "030dc1844dab048920c417f4d33b21d790c52236dd1aa07db57c08173a73f14d35", - "030c246eaeace1be55a6b06dceef300b4760068c16461a1365f3efe23593ef219b", - "032c1938b039f9d13c7fba4f450e316687707d76e3e6e1971b455ecce8dd115cf7", - "031a5c3b5f1037e3b37a51c567374e3fb9bc4411ee173b5c25527dc580781d9e9c", - "031c144142a1bc93b98c8310521a7e7291e59bf5a6b0b350c18e0882c9a8c01be7", - "02245188efe261bc1f592f904d57a41341ceed1bcbbf0f495434b69eaa2445da56", - "021c9aa2509a39ce461ef1d3defc7bc86a385db778b512d3879906f4546df1ee9f", - "022ade67b31b1db1669860ffa12dc82d395b9422396071afef04e878e5ca0e27e9", - "0229d6660e07d0961215a4725cb78469739ed16efcccbb157847865fa8ae67abea", - "032b74f0bea611f59c7cb8ff953d5f1362ffe5c88c774d93c14fe35875daa9ae40", - "02077e22c948f49c344affb98974e47b7f3dd4a02835ce32622209cb4d9876b55a", - "0305c65ee9df35db8c4240ab66e210eb495ead20be6837b3ddd251b70ae576503c", - "03014f5dd94c4c07f5f4e4fbd800dbe89694bf3665c4f15006239395b58bfe63bb", - "0318e9afa72c07d3dbb36741896a7ea64d12babc2929a436af5c33ffe23fc7ed81", - "0301a666b5c738745baf8547073bbea534d40edb06554f3d585c08e42ce172d188", - "0308cc1003dd9c25c693b0d58742e31d0593f3ee9734e7006f234e278e1949bca3", - "03045dbe5d4f40286d7df56e9536ebbbff8b3a18c93b1fed40c2bcb76322a044a4", - "031cd87fac68b3a6c0422e4473361444bea47d68d2640fde10c0cdb80f95004c4e", - "03189dc0f2611c03d9ca2981d7e19b5348946319b1b0cc44620a19c9aa7462d759", - "031af2896881cb050aa7609b49b3dedb0d5989247b3e359045f67b1f54a0c1082b", - "031c1f451103644be559975fc200d5b38fb3bc0c9286eccd5d854587cf490355eb", - "0329622f66f7e8b662e057e4c76b11cbf2ddc738886705b92bdc70e0d2c2546f5c", - "022b02bf53daf646a0758302022a48bc4b11e383e9c837a4044eb17d32a9c764a6", - "020a238f4cd41d451735712c796ee29b8e840b148ee9cc1145663f3356d284d5c8", - "03006000f8b249a54635c8da3c51eabcef036403d9fc022d49320669583c42a2c7", - "02039805cf6002e55fc62e4d02559bf4fadbb2461c11fb054038a3360240207b2d", - "020c26fdd070ce4759e53035b1663baeb87a525f9b2bbe4c04fd3c6a669d6a6416", - "022490e3c842d2cd70458be5b03b5ae21578a12226cf593c0bfe72f4edd32b3467", - "03206a8e55210dfb7b214935d63a19e6afedb1d434865ab666e40eb471cc9c14db", - "032cd53069b18030bb5b4a2186e2c74fefa6accbaeec787b7bf6ee9ea8577f2b00", - "0224277b1262318b7b06c79d1ec3711330edf0680ece0a48b1dac200224cb70b41", - "022aedb4646aabdafa53e77b971796fa8bec76cc12530264af02af2869d954f2df", - "0226b14490f67822226da6a00884281a0d8b11b0a4fd01cbd121d1cc8d548a54cd", - "0325c32c76ea9610f530ef6b30b4bc589b3abeb1aadda287d2010de113685ae2b2", - "0303bf86f85dc8b0d4557ce890deaca7a905c68de17761539488b4db9cab850d2a", - "0310926e859d6fb7133fe0bad220f7963cf7e611f86ec168f1e298545732877280", - "0325e551b3ab464c43fab16a40d5521a0346baa5b1ed9caf273463d2f54c7498a3", - "0223acd37eb254a49bf64cb4f5fa92d3d1c457eb5a79f1f7fc79b165e60ebf9811", - "032b8b04c2b9b4ed8de277b2dc051ca8b3a1f25828db3589b80245920751306ac9", - "0206029e1b0436d94cb5916939d07d85049525b5c07572cd3b9430b6b22ab49336", - "022c86d5fed256e3d0f63fda2453a6125430cf8064253f6be1536b337778db2c16", - "0317ee66651d61d5ee55d026798586860fdbeac3fa3d98719845f795a1716b3da7", - "021c396d3dbd9cba808ff4ca413c0f3c76973b11e4ddeb91fa10b089b2e30bef0a", - "03189f72042b3e2a8cf75958995b406ae3dcb92a4b4e44e5194a969dac8ae2f8d5", - "021bab1d177a8d97a06064305c740372679813e207bb6d04f9e1a6dd62e7e14342", - "03264046b312fba6eebe663ba7a2f29489ba2aac2408b8898a91d35b2ef49d23bb", - "032a59035dc7b7c7f5b112e94157fb0aa8f7f1ad88e6f90d15b0f172fbed9a4429", - "0221055fcc94c38bfba36908b382407979ba34cce28bb0c23596f186f91eff321c", - "0323bf87dd118f34f34f62a15760216ce201f6d98cf59337ded39f18678e9aad6c", - "021d2752e0f217c36957b5e6993847fda4faad6b6ad907a95c4e1229a78ac24f7d", - "021e417872423af49570439d1b9a2392ba05d7e47b559ca62c3e0a1ab0bb19d1a2", - "0300cf555e17a470459d0885f7a1af05cec689dca52cf81acc24fd388c55cdaabe", - "0324d421853db41d4a954d6d307aa86059d1ef167e4e06c2e04a63313612ecf437", - "031ec6aa4cf23f2a9da7db82a0376a04e9ee8b332cb24638cfbfc28a1f00a5fb82", - "0216eca3e45f514daf7f627c0b48109bef56ebb0827ef044bb33c920b68d39dfb7", - "0215823c7e844d923b969ea2560877e515d437c1107048422d0df6b0935b25b8d7", - "031efb0d80089f8b1fe32762f21d11fea6ea9f30150eeb4676ff694cd4fda8ff2e", - "031fa6ddcca3fa3d5830de9b1357d8c4d38c72296aa1ea7b9f0d716ca4efe13125", - "0226f02162319d3c1d40455da806accee9185d4a1f47105ba01bcb23f35cf2aacf", - "021f1c8c5e80db64648300cc3ba0b06e7a6c08efa8967df44096a9e57c3c1e57f0", - "032f08eb1c8f0106a7d35753f6fd3491c659a8a67527c3f8ad24c6b34441c8ff88", - "022f8df9e89392e8fbd5caded0764355d1b55cc0049092685d9528f440e9c639b5", - "03123e1d605ca6412f4d570dcc50da00201b75633e741771560f8765399afffd9f", - "022b7ae4b2a97420d34f53c9c38e231e66ed2b06d13c9a356be51fdd340ba4a94d", - "022f0aa0bea02f263f885e145c35827a9a623fb2f42b207ee499224d40d7e918e9", - "031f6c110a757e63e2f3223fba2af46aa5b15c2439c41262ae6c6324614105fda4", - "022ac6cb714a68b71337d190ff7eb27a7a1ac72367b76f4719a1d87d1f57908714", - "031b5f9167fe281ac09fa2c1585e0bfb2533144af0327ec8bbccfe556de41e2d12", - "031422b426da7f388c39c93d2efc901123038af8c2bd72a208f093552aad58016a", - "0229c08cf93a483a680f45a9a65b4d97470632d9766aae4a631b0f464fe463002e", - "0304eee947660f87f2892149df2b9dde3ff932fca7a723afeea03bfe215e5c23c3", - "030860822a1d238f8b753729aa54293b10e73735bad87d03af2ab35b0d150dd9d3", - "031f5c53f5746a0e0414355e5e0a4b5057d878bd11aa75b0c3fd153beffe81e00c", - "0219d75718be18b3b98f46b7d838de99a059f7d5d4e38ed65dc347de958b3b3f16", - "030ccf50dddce1af7588599267739d0bb5cc1ebadc0caf137e5cc3870571ab0d14", - "0312fcf4aa54afbfc1082f28bf87308720f44fdc149b3d296a732ae2e9064d2103", - "022056dc349ae6e00f50af1aad1ba45004b575cf67da8b53c4fb6405a393abe0fc", - "032c32707973a1eed677fd04ca9ee07cdbff57869339b395e7ecea9eb295b70cd5", - "02172d0df242fd59b9f04bea3bb0c1811778d25a22b74b8542bc05e89860c0c6bf", - "0207140bcfedf217619f637874e2d20a25da0095a568ff887a6933f5247a7670d9", - "0226d44ca4420d2ff8e64dc9d4ac5df8934748666b3088cb2c4d320c93943ecd11", - "021d2effca83fbcbd3af87b2239b4db0638ede7ff1edec693c3086c63dedcd68b4", - "021d9ca9f5f0bc9b0e28e362592798b6b8ec58bf3184699b1b59bd0702d36e2e14", - "022b124a0c2c4e5f95bf0ba289b19cbfcb9ed7db89d21590e60e044d66e02101e1", - "031f0fb7b8e264d00dbde454aa6c2bda42c0c21b984d935792654f1b68a6a9fb47", - "0213af3fc04a839b41fa14cf2776018186d1efc9e997748ccae246c64736db3729", - "021d0654976611eeb524c59bf17c3406ff2a6f32fc89bd998400567ee0a151fb35", - "0209df36f8f6ff9794ed542248cbad125d641b3000eddb3d1677315d733ef8f489", - "0223a2ba79be5fbdf04808bcf7bd2ab796c2f1fcf40dcd3360112a6e1fd54f4181", - "030d74f124e07a68ff7d3812a04c822d5e9abac4a7c3dc0f4102d89fbf1c1a9b9d", - "021f3128c06cf63a6b507950168190cdae6dc218d5a822eab25ee3c6bc92de3ccb", - "02122f1f24110d0820d49d183fe4fe8e7774525cd2829e8ff7d5f2986bef7d02a5", - "03242527f782d88b3ec6d54b905718ccbe5ab6d63006d3c89f1d24f74bcbd35774", - "022acda46a94c3f004acd47f883b9091aa50f4312c04b075fa1582d1fad3ec3aeb", - "0213a01f9bde0e83cf0c54f5d86f24348a1d30d0c973a51eef73484c389a34e269", - "03049337ea654d77bdaa350f9092d52608fb1844c2d1c6c7d41f61c1df70713aed", - "032174d4331fca90905ed819496eb9d32b4cf5ba65915226eb383550fa65ddce1e", - "030f736a41a75a444ca127841b5729b5523d0495b523817a352ae828b9a6558253", - "0225600cda5d49cedcdde68228549cbe1880e4c0ea465ca3fb473ade942e264823", - "0212d1961f63816e89bf7b7340e2853a717e5d36ec99326782457df32054f5c953", - "0309ec53d4f54a032957576fbb349c92aa52b1d12e2642e34ec87b8aee9c2f3dfa", - "020c6f648b9c6ed9213d538401b87566f917c1ca30d94d58ee8dbd3013164657aa", - "0228c34256b136eed11487f4accdc9098a36e800c4bc7ad36f4a97b3b2cdf030cd", - "020348056447fdcdafed88d3e182abcf2cad4edf485e2476e1ef6e9149ab71859b", - "032f28f8a55c899a30acd3add6783c1e1909a5917b6d69b7d0528e7c9ed0381fdf", - "02122169841ccee409180ca775e031b7d8b01beae688b3f41312a0b24dd2bdd748", - "03028a6ec1ab64ec788d3e831b8c791b247de0dc4c85bb3969986d5e6ecb70bd80", - "032cd19586b6f923e211df0e6e1792696ac3205af757f9115b7e3c743308ebca9f", - "022ef0485849bffa0a5db2abfa8833c7b47df60111582408dbf91d3bd60aca1404", - "030f8ac23509b99877ff23e0e136e41f875d00e3ee2b2674dcc5480e1e8155d589", - "031ae1601b2ece139e520f0eaf1012a104744ad69e233ad857475621d00ff28325", - "030760dc406a63f07ed7c4f87846b6d34dbc9d64631c76367ffd29dc59b2fc5655", - "032ab924aa71271a4dd861ec73c2e0cc228969dbb3875f7b7f7dea0827f0be9cdc", - "032790e9ea58860b1794c6782e2be01a45e781eaa9ff84a35d9b644dfc8eddee21", - "032ddccd9e90766f917a39f709b964c531524753e14751f3a8b9706e2ecea00260", - "032a7af0ae01413a97c16deb26b9bc9c862c7b57bde2b597749111fe27e6b4bb06", - "030977fd8ab8236b5cbd0405b8a9af10a9491803127154c9227810d65869e4d6aa", - "0229168d382852eaf815616124e96016cf10be949380d1f2a557b78271853325cd", - "022f5779297c79350ae7d8401032b8a1994e40dcb708e82f44a47577f5b31e460c", - "030e5001a1b31d5781bb4190a7666ac7c254781f72a9f6ee3839c18a3b2deb767c", - "0326055f19ca6bbab8f4eaef1e848a817fa8da54966278384a47912382caf660b1", - "0200dd7dbacda49982e3c29e072d1500b23b0cde105c4007e84884bd896a824b9b", - "03079fcc4849b9b9103202a6aa1ab0e3dcb8a2a300d02dd0a254b37fac228e7d29", - "022b3096ccd93a79da393b779d9b521f53d0d10cccbd047a3088631d3bcc685403", - "0226b410d3e9603f05e43a2be9652b5bf4fcbb8b7af61d6853ec81bf4ac9565c10", - "0203052b2f8aa98e990239e7e87cacf322aba038255c116b4f50a06a84b2c86291", - "03049bf663e8a022d8109247dae067bbd95eb76ded7905f38507e1aaf279e938ad", - "02068012ce0ac78c5cde966b78aff33af61a0e8a29a86cc601de31ca4c37d790a3", - "030897c9d21ce581992bbe1873e8508e283fa28a0cb7362826c4bf391d23b99d01", - "0210106c04163e5fa852e53022dd6c90591e0749dd3136f67e2a4248f50f39dc82", - "03109f0ed62697259a00bb2ee9a65df7597c0a19dc4cffa87e928b2f04c87256f3", - "0313aad80b41136bc4bd54cbc463dc85cb85c9cbb641c1ad17e44d8093fb203f56", - "02077b01b1a8105a87673e8a58fdda62753e8efcf54b82d4e06dff70eb6637877f", - "022d509c99d76df3844965fbc91d15b3c97c96ae61f2e6edbb11279a9ff33ec381", - "03159cd7c3761e43ff26e09df920d648d13cdf033f3cb7634441fcbdb4eedb42f2", - "020bae85dc1b9aeab9220ac7dcbd9aa2c9e5234a4afb9d46d6b921cf3b823af473", - "020e637380d3c9db6635e44b177fe2f80ed469e39f93ca74ff30c1c0f617d9e2a3", - "02049ef4027789cb8ae856e4848292173b4c23d56017c228aaa729684f26308bf4", - "02213db372061edae318cae74b9974c432a557ac91cf481f29208e9c43a78eb878", - "032bc4e153503ba908db37465b9aaa9662076e065afd0e4b06bb6fec03cd8d7e4f", - "03051629900ee71dbcc3d3b80daea5fa09e6aaea7a6d2b3a6db016f2ff546dd68b", - "021fa1f89000d1399ec03ee7f7975cb84e3cb0381ca4385178335b829c303ff82e", - "020a28e1f96cfd51d558161fc3edcbd0ab23f820145424ec135334d925f8e26d5f", - "031c29da6d6100d4148f7531751a5f64fd296e3a093f52f4f79befff2f60c48f1e", - "020659dfb3e964d728b97bb4ce9517edfa388cd19093cdd096adcf1c1e630e69ac", - "030d4b052fa0fd055b14a2d62c304525c38e7ea6ae24d3d5f2b082d7c239141d81", - "020cbdf50804053ca5cb737562dc9e5b5957df97405c506d1ece2f7ea6a909c1d9", - "020aaf09c5d7a1c92d7ac4ce35497b56c41e5f797265e2d5411a0cc580fb35ac24", - "021b5ffc5f7f1990af046c03e1b79c9e0d7a5f5b6f9d6ec918574e1f08fea04db3", - "0316e5ba1aee5b6209dba6721b3dbe6918f3fcbb75dbd2d44c5d6bd7da793575d7", - "030682a7e0e0866a6179a756acf84fd526fa6fb1f4070bfb70de11eb5f9e885efd", - "0301847712f6150af55bc657ef09c9891675cbbe82b3fae62d1cfb506277351e12", - "031ea2a4a3e26a17e3501758c8f1210f75fa5d764aaac4a7bf7a1f4a4b8cb920b6", - "0307b6e8f049077e24ab0fd8198e1684356739923fe78c61e26196a36a46e160cb", - "022788726b822728ce6ade4edaa6cb118dea778130982d683f709816fb7e4fbc5a", - "0321a0d972ea764d3761f01ba39dafa4df2285ce6bc5eefb7c3543842332edff1a", - "030555097b262e4045c361fc9ae30679c4bf8aca383eaa83ef0bc44399189f1951", - "020ad8f722858f01d1204c9bf814b6fba0da1164396fe5de5509ddacdab56953ba", - "020c8e06fa0050ccb8c2fcf198c75d2320a4a68dd93f5013756d2a51c71b167dee", - "03224220c1a88249d8a3e3c5998b99f06efc2a4d50e78cb6a5bfde249995bad679", - "0304196010dfa7fe1cff59d8bd7b27665f424a5a2972042957f47629012c9900ba", - "022cb564575b36c014178f37013cf4153937e084372a2916f0a0956d7d6f1c99e9", - "020a900bfffb9733df435f95e491f233213079126050d568b39d2587415a37db60", - "021a41c388d4dd748984a5daae6c4a43a2a49b5bab3122d5ee376d6481c5f26f83", - "0206df693f0fa6f6ff337705d9d96c13995dc377733bd995807ac79fa036731f4b", - "0322913baba6d1889387d204e38e8efd6de2c199f1946052f0907587845636239f", - "03187fed48b71a2d9170ad4e49800d9ffd0c9b258ea120fcfa2710a3ae2289f8fe", - "02144311cc00bbeb09c022516552895b178f71d817b06cd3d0c6c1469fdd40ca57", - "0303809e93cddb9cceb9099fdd2c4c2b2b7adcb420c033cae2eac42749d78fcf84", - "02223fb0853d28720ac225ed6e42de887dbd1e9506ef0773f5be7170a603955644", - "020e0340af5f2b85f6c69a763120ec6f0ebbaef37dad7f7ae29d3c5c3fa35cee1f", - "030ffec3c5110e86bcc829df8d4e24d93d5fcd5618471c109a156aa208c8fcb6ea", - "03077ff5098592b1066ea1f600cf91cedf1d2a4048661dcf71ccd51c681ff3409a", - "032fca20c44543387365d14b9572f51a67a5c49d593b23748070426eea8629ce38", - "020c1cfa7f0dbf746445c175a9ea3589427a32e3b7c5a38a2c32d346112e72fc13", - "032be0ca57bf06e46e64cca5fe27a8a95c0a521332bf83177e972e18700cd53778", - "0212c8219b68963e2a43e92442ba8ae90737c664b89be6579a305605df4d13808c", - "020f5ec7ef3e00fb12f201cfc7c11c05586166f0ffd932d5eb3904c62dcd2c46f7", - "0202f2eadd8e34acbc291b21d521dcbcb69dec588bcc78fea121a599d1dc02e3e8", - "0306b63ea53717878788356dddf52040d57bcbfe99158c80956ce85fe3e1411a63", - "0317afdb9d87af99363eacefee29528fc602532bc749cabc4c9ef1ded66f0cf0e8", - "020284fbe8b54a3c6e5702a8f8ada4f83587e8136087bc88c86f405e1c6c1ff4dd", - "03216ad4c6b926ebe818574f8b48ab34e2bc3f072236be86314e2e1220f34b731e", - "021c9c002f1137ea1908213ee50a9450db77f6f305b48cf3639dd1553c00329a39", - "02235fc837be4cc2bd4740c76dd1b7e1e2866ed16570749c263ff9c1cf2b624466", - "03236da45660442559dbcd32e0497286af582eae9cb368500808040b7cc1974fa3", - "0200e0ed08ed5fcee5592faa52322b0a38ca9066539fb1b082e4711fcc1779f269", - "020a5cf1ba52266147e99ad2f973040d15612808faf3610ef5ee845c397dd61cd0", - "030135e211b650bb0b40e48d6d07979363af3c2dcdfb00b6869da2ff5735255c1e", - "0204087cf015268bb2b19a94fd105ffeb1f428a517947823221f3b66de8d06c372", - "022f865c35ea5fcf0d5eb7613bcbf85a028f9b3fdfe9f6205d41645b10f9d82dd5", - "02028f4257c442da21b8293e5088202c2a26cf59946d60c60542504ea93d40fcaa", - "0313829f2760d0e1b37963f033f50a72b424c94e0f228053b35777fead34424e91", - "022d1ecced9eaaae205f0264d6ca7d97faf315dc229a6a9e93abd2fcde174c0f7f", - "0202f0bbc412d185b5fea81a87131466a64b8f3a2a832d784a1e4a1a2b2f6e761d", - "030e4121a6e27030e748c0d82eb5a283b8c51227ae6753a2dd95172b79b7d5e4cd", - "030be6b02c291675d0a34d7a730871e976714cc881f71c7a88367bccfa53fe27b2", - "020934eaeef35ba280f82a522a438acd665c62d57c329586a7bb970d9e559ce835", - "021268b5e9463d248c59446419fe2924167fb961acd18060c189c7768642d386fb", - "022ca643b73fcfdee172c1eec574f5fcd95b6910fe403fa4b8d4f2d56d198e2da0", - "021b97fccd8bf20c5e829a23f24c8fa781c0d0c89ce68169dfa045baef7ddeca49", - "031573e9211e29231ebbb5cb9711b08bcfd751d729de0bb22dad5011d01c115ad8", - "02150d3090139cda70d33ce9f824b93edf003974331ffcda4241226cb30b60282e", - "03003a6e80c76809eb4715788b203071084fba40ae58caa7c3cdbdda9934a1ac82", - "032bdddeb616ed8bd0a9a875c04c6bcfab718d291c9a3ff63a0424859d39bf8dd4", - "032a5102c6e56059c701dd00573f20605dfaaa62611423c345d6eb77902ea93dc7", - "020d0e34642a9857399d7bc0007b4ce0f0fcd6a3229094d1c3a22361e38517f9a2", - "0211f772b12704409348c857fe3a18ede7a647422a364972a26e65d73e2a027c65", - "031ceb03faa5873321a3753092e01e63b6b7c03c19fc744f6bc923026d42bb9247", - "032732bd4df39cc15545b5b82866c8309ad9870d7f472760519a9288eea318c547", - "021e9cb73784f37f922b16b49616c0931ef7520509dba60a147021fea271abc555", - "032f58b1666f69450142d56bafcdce029f015492a0b48e9f35cb78f7b21e3333f7", - "0303b50ce94895d887c55c60070c4c13a76f6a53ea094acb3d126cb1bef23fa44d", - "032b7f2f35a34c1f70d9d3c3d8d89d5d03f3f849ad312a40bbc1302cd1ca3766fb", - "022cbb92eaa4e91868d36c1e0c83f47c239b3f5a12a4bdf72175e91889f65b7b7d", - "0303657d0c164db3c4ba8122015116ec0c9b839d60ff5063ede4db825d87af1378", - "031ea76894e893d1a70e452d0c430126724d382f080546a05ba4f4968baf4e8a81", - "02245d6c199cea74770a5b0a5348bc18129f004a2bfdfb24f192d4c5eb8a523dfe", - "03300efd566587ef83b55d7eb926669fc13567636f2b100b487ed0d563dfe3c2f0", - "031f2fa8a8661439afd97af0e34ade96cc0d974c564fd77b0bbcb2efb487b0924c", - "030d048a46278a4fa6e66581841eb4dba5da71f1d0d007330121c07f354817c2a4", - "03290ca2ed23911fe382106ead442f8367b944ab6a1c50f3c898d229c35b905daf", - "032e32da496c11700975e18a03972787448fd81533d43c3ade1c9254269e0fd0c5", - "0213447b9aa70be8061c048ac2f0d57f40076d511842f5be53b6debeed034c9e5e", - "030aa03ec1281928fd21a523e620a5dc1930b4c7062a1094783fded1df1bdcc155", - "032c38b70345d538bb51c3727140f412ae3bc53171ba50036a1ee6cd39bd3e1882", - "0213dd12114d101a400bada5c655582a707420b75ef164f57a67087fe96f6c24c6", - "02016e3d9a7de55c75a9d36820601bf327e55d2d783db2e5321c03972e74846ba0", - "021b87fa5c7f639ee5207ce84b3c24367ccdded9c317981c2c98ce080faf8f93f3", - "032d02e83678d599c867fecf0531968b09d08979ec4f8a3b437c6693c5715c62e4", - "032b80e13fe415032c5a2e7c980bd5762d44344b261897f8c2ca4f0c35d4292eda", - "02267bd47f6da7c602b5e82af5ab32867f7867c9da5993ae54892bd325ae94b106", - "021f1fd926f4486b8858f689af59c70ecd2a610e31ea531c724baf43d0d2518501", - "031bbc60b0f94be8a6cedbe1a4c6bf454fac6898a118e98027c8db4e47541e29c5", - "030c281ecbf4a9a67ce3a0fbea261392d4f5dba0c3896eb3c484393c3237cc6644", - "0313ab044609ba05d669bb26a67fd299c5aa3782e5a9a31d9c111b1f6f915cc36f", - "030d2a5ca3460ce9323a6fd7b890daecfef3b2228044f30118f4cf082a75070a8a", - "0212a04d949c598de4ba47c049da7704c797b358b2727427cdc3fea5a406e19b80", - "031996c3685f782a9ccd4e6af3c8d1774ba854158f1884dc0759ffd12d7bbaff4b", - "021cb2920bf9e4235d84b1b1c562e164b8c3a5fdab08a05a20bdd36bc960c193e9", - "032d9fba6553b2e7fda0847356a146d45839a26f4fcd3d38625f7e444c18e31e29", - "030f4e5a5dff12d5dc52840efe5772dd42204f68d46db77c48f3dc8e59b54358e6", - "0210009b177722715b27f0a7dc259a95054f466e03da8584f85faa9331d8efd762", - "0311a957cb0de019df29562510a889e34f94ab3b70933984cdac8e7e9186babb0f", - "0217fec49be508107e19ef0061c83074dbd8a3d653d460e8557687a321a027e733", - "022f088a26ead66685261e4fd7feb8f1a0afc504186db06ab1dc13c0d31776d7f4", - "03303d2e01532757805bc860c7bc28c98ac1239db378276176019ad69228bb4966", - "0225f74c61385e6eccbba1ed8299e24d755b3ae05dae13abd7a6760e4749629201", - "030e161ac83c91a24b96eef778ff0bf12a869118124994e98ca2a71dae3d042254", - "02184f26f237a18b171913405539efc4f2d1c587951f966d2aee301d8863b1da90", - "03200d0e0386d39ac90ec0b93cd30d1cc2a03b3fb4a18e70a41fa3725d9766504a", - "022c7d90d941b10274c0b5cb8ef05a05c2cc80dafd9f12bdf42c94c2b881925f27", - "030e769f564ef644c52f3213b464cd218c15de794871d63ba1bda21444ce34ce88", - "0304bed1495d81b1648113875723c951835ba3e54bb1d458b7470ad97a3297bcd5", - "031e504a0c618421c5f1a5fa2c270a347e4c9859f1681d3602e57c265bb435b8c9", - "021ea979e53d0ed098d7171ac3b1435eb69795b4122dd275fcdca9a6eac2870f9a", - "0301da028110d1c8c650ddd52471f22dd624fcd6c38da7956ad76f24acc9e69fab", - "030f838e6bdd60c7bb6da6ffccaa343cb1d3092398d9ce6df66dce4b6327bebe16", - "02228055776a4b4d1a4df768a84c39d6de192d68a3572708625500c028685ddacc", - "03082a5de483375a133399e10661f61435b832389d67adaf3019887d44171de41f", - "03246fa9af6ee2aef9217b1d08e51746c3d244a015410620db83e8e8a64c6d7004", - "0214faf7ac47b45dcfb23fa30d48e122f07a4d405964d906ecd022d42151a2e5d0", - "022e6a306f5126d807656af9073a58a7d13903634374b9bf114d1b8d3cc1937d74", - "021354c81aea0cd29328b295070d69494eded1fdc3e68e4c3def9ff1c8f4344a85", - "032f93a390fd0a50dd3f53b92511e5318ef00366bdd507eb2f4963f22a0c27eca9", - "031c3efa6d262c98e5649531e55df00287377233e50be4f747650966fcdca14997", - "021f8c38a54586968988a1ae0a1f661a90050244f62cb993758494a8690c330521", - "0320e215657cf43b8329e29f808ddd2c143b4785f8326647c91292965923fc6df6", - "022c9cd30ed06ade82b4658b4f19c81f4056db585ac335065aca44cb3340136737", - "032e4c4058c95ad1a05a5f3ddb3a9a11d3ded1ffa136f8e42c53bb97c4421fb0d5", - "03006a48462d3d6f61e07f81c6471b65e5911d5a8bc6ec4bd93765cbc98573d313", - "022e779e8a6422564a150b0af6e0cd65058b9638e7a82cf902b9892d6edc8c9b93", - "02034055dd7a975a25152bb5e113341a826d89fefc860e35fa08d497bd0a5b4b20", - "02066b700166b0b63b5eac3566caef0a2e2e2b1def883184e360ff1a537c2fe554", - "031e94d2052df881800caeef7fbe0943a069589b452aef555e3801194a075353e9", - "031e99f9711fc2d7290dd90b930a2b78781733fbf95eb43b6ee3c6ee2bc63bc183", - "031575161f531f4dffcb9b897b5d511538f5672b045f31538e771b99979402bcbe", - "0212f53f25e41c4cda711737462f5f1b56129d9b080c505db2d61b162b2e0414b2", - "0219d949f8e7ba4e1f703eba13f58f87443200ca47004eaea76889332ae0ce330d", - "031b20d6dc267b327d5b8697f842709515f910c34b46dc6a1a31f9972af1744878", - "030229f9579a5d5fb6c7e18c194b52eb32a16d356b3f58cfc304937cf843258b5f", - "031c1958def6ed79001af6876f5bdd4ee36accdf15b82d8a36602a4e5f4886d147", - "03103bbc8cce39eb6ee8067cb52139ba12da626a940117ba728fd9906c9e020f24", - "032aed1c568b78bb79d2e61bba87fdda0e429ec300a19f282f1c2e9612ec489527", - "032c3a15f35d656d3d4ab101136d63aa01896230325feb332f9b5231441a023e70", - "03005a523b94760dd3892e5ad8429b7acc549cfd5f764757b82df9ce695f4027ed", - "020295edecce865f1a04a5e05e1e2857f9b2be3baa837adc720bc4155c218bfaf1", - "02188e7b7cdaab4c6c6e6f24292a8f9fd39aca588e4a7705b690620d9ff0f34f41", - "020bce2029fd5df94f69d9b1b7cc3a5344a15094cc26ba9fc9409adf5b2561e311", - "030edaa5c9ac46fa7032242a85738fef848a0a559a51d3a482fc72f6777c727f66", - "0309f92dd8c46b2ae7743992954d01c9ccf68e2dfaf5bec91fc7e2a64ec9ebc43f", - "030e92199432e7ab3ac56adc17ec61457806c53935a2075c21c6e16ce6bcbfc140", - "03091c938c5607cbcc9f7d0e2ed675a490098bd80a326397c4d41ce332275995c7", - "0314dcc45309c92cffb9d46ba241026d9eba2959e24ba6f02b42d614e27d0183db", - "02063910db6243ce959aa348b4e3eea45bb0c82e13d7cfb029f426268b9da8a7ad", - "0312648b33a6a7e0d5b0cfab264c233c4f2022b41147c985bbbef179d66fe6d88a", - "022144456ce81024e07e94d6fafb1d2424bc57d127610b3d9880fb826f4b1e61aa", - "031fe7f4448f82b8883d8ec58fe8928c1b3975c33c38589faf9f4386a1a70757a4", - "03222144600a083a0ad92e86dacd76c7ad2fde42cf083907ffaf72b0a112170212", - "03208e4fa0754031514d0fb6ff3277f8c4a4d2e498d9925e7f66d109deec36e1a2", - "022f39371c5781e4c9a033f986a5169cf1804c8ce97e602836ef016d4dda6c4a85", - "02068457dfdcd760d51d4917bd9d0a3f8db1b62d5a4a91c3715fb789885ff8d4f6", - "0219ab4df152c02b6ed6bbb12630878c396a7475662699490564ab37b123148e45", - "022e137464cf0101c4f2384d53909a96c0b59d4320771b124d0e19554ee6b2a66a", - "03136d747ba1ebecea019276b3eff13914726cf7209c5d809ad37d4a86cae37379", - "03184c7f96294af0866593e46d3b9bd7ebecde866df0b7504e23cd0ad46410f833", - "020643b99e946e4c6efddf4ac69eeaf30fc4857bbb11add9c9a36576caa3a8d904", - "0209a4e0bbf1943b7e1e11e6f2dbd43c258797353b382f0abf2ca989fe47bb329f", - "0309e89736f93ba7cf72898a91108ce5166ac669d46af83589519df459a854a2f3", - "03031c63b203a1715de407dc5d2432e18f8718200d14313dade605549c7c95c50a", - "021422b2239bd452e25acb016beb85d440e52a1a8b70724776b7fcce9fcc4d917a", - "0302578f162955a90c6d1f267cc11df1c4bab5f4ecb5f7fd966fcdc224312c94e5", - "0308004236a4d30748a327317fd17168eb2cd098068e8f9468a167f8428064ba46", - "030a438c15903b2507b634e755197a09b3e6ab803127ad49dba75db26be8191694", - "0215dfaee09957a6b95691f66ba492bf5e0809bbcfd4b7fea62bf87213388fed91", - "032819bce9d7eb54d8bfe74430ffcbdee35e4d28f366d5feebfabbf695260c5032", - "02211a06270166db78fdffdf2d1821eb3e54a3deafa1d68bc4d29c6a74b6aa3ac9", - "031373ba5cdd43c6de65f68c558fb2d43de528ed8652f97043714630ca4dda2200", - "03080273cbd48cc88f74fc984d31a79948f7afb6a9e8319621363f3eeb3be4b83e", - "020701eb074b8cee386fb7762d7515a9025dca00360b1ed298c8dbf818e38aeb59", - "0229f49d6b33e21fc0b4eab9c58d544bfe0ccef0798032eb676154b2871dad1bf7", - "030ba00212a95ae50fbe2c325b2c3701c6a86ae52e504d0ff90dd7d3de0dcc58e8", - "02126e3985d2b5bf353a18568478d566fc13985a50cd5ad77eccc01197cb7d6393", - "03027db6959b6bb827edf010c7cdee4966af15f1e9861d28a6cef11a7ddd49b649", - "0313f5a416f1ea02721205bacca66b06f85bcdf172bdcd72b66bca5e52a656935e", - "0322e08539585bf4fe27cca05b71307a27b1ea73b9db11264d757d1529eb91d8bb", - "0302c6b85c8ff01598287292eae216384b7ca1ab342d6c1c889e37a1afb993d3ec", - "021f75c705f2b2dc800ee2a3f2a3dc5e0b3d6eff03ba40af3193dc7466e1d10462", - "020cf457ad392908c5fbaf8b363c88443ebd72cbdc654472ee7b5bc79a479e1b28", - "03245198d1c351fd63cba518a9f47067a2f1cb52baf5cd7d53680adc86a6668b83", - "031b92d0689099e950dd774b0f0040f34f338f07fdf8f70bfaaf2e4824dbb2c137", - "02246423f16b673082eec8e6f3cb8fcd2feaf9b6635f6881c6e9df08bdb7c67cce", - "0308085f578b40db4b22606345185385b30be58030182043442764b4a14cc3b132", - "020d87f6d794cf2e9074d22e708d43edb6c418c9807c4fb71ac90b42223bc4072f", - "022a4457cdc1abe1fda2f93d22615424c17ae6390298af28764b632f10d7f3ffe4", - "032374800a25b4d9b4f934948c81754cbd08eb4c46f49fa17bb214f599592911a4", - "020a8b3790a6eef57b9b135345fcb5e7656fe3cd7c6da0464b166f90833eadebe8", - "0308768df4f002e74ceadaf9bb62ff3eedfa3ec1bd1696e632db0065e9dcc69e67", - "0304f4462a983fa65b4159dd0bf029d6b30567588314bb7c8af618209f965d32c4", - "032998391b331b32ba16392b1209f9a74174b763f344aa280e933de0ebdb5cfdc2", - "0306075129004afc6dab17a4eb194b46bd527acdfd73228f446f05bd2ca982db01", - "022b5eb49429416457275fe980fd979ef49b14bbcd03e6a211b067dc09783da13b", - "0310096d26150fb548b3afcc077823e9dd7be4815d9a9f9be93dc7bfe8a40f5b96", - "02160786cec290427e4ddad22b5a373f81d7011c1ec5b87014a9734178780f6ddd", - "022c712f212a3ff2edf4b9cd956e8bb772eb9ca7a5cd76a56e4f0663894d4a5efd", - "03182b31d2e8913620418ef9f566483829cb42d0301cfa4f270218a3cb57e38873", - "032b97eee136a41573c5c907ccc9aa0419b1f45c68407df84fef4bca1e8f82b86d", - "021e561abf7c9935f2b461344c056fda1a70bd86b45785afb4fb6989d689bf2aca", - "0204b7f53761f068251134c3fcf70193855dacd826b841bf00eae560713eb9a5a3", - "0227fd8443429468a68eeeb0d7291b45a85c98b40875ec9fdb8eb769e98b538a14", - "021179c4c579177fa85ad72c21dc0537a38992c640c7952b4cefdbb284ea0aa952", - "030279f0cbd372ecf24c749db92095941758e37ed7557eab6d58e00c56559f37fc", - "02146ddd51753e653f299558c4fce4140cca67c61199ed51ee1c60dd2fdb04e02f", - "03264e4028cedb0656e5bc3a6fc074b57de9d0e4658e89ddb2b6f3281874b81687", - "031c5e2c1ae48f698c52dcff4eeb0214ec42d63ab5a24b49f3baf6f66cc41b4ffe", - "03119919ae5ad17128bf71f31c4ae1d94c160c71a91355a251a4b796d03417d087", - "03022c54f915f79be88f5c5c187b8ce8aa9324af28a59f7c155f13df0000e372ce", - "0323177947d8c77ca2cfb252cc18d1d786f062b784e9f64262e242b1a0b99c1370", - "0319f6a215aee3879bb3a859d27fa308004dfd5ea34c54a5add0d902b0022d7d07", - "03252145aee1550f0170a55b6ef2209063cb5178c7d53a7ce68b6a8b0079b137a6", - "03065d7394539c6e938754d3d37a12d608ac9fc538e866cc8d232017544b6e318f", - "032c6c749508250013de295ce142e321fe2c1663219e39759e5afd61435433c1fa", - "02149fadfcc3c8f753f2c0560048eb7d5162f7a3b7d7f9d34904bc4dfe8ad298a7", - "03219001af75c320fa7a52cef471e2210b1b681ec99fdaef66f23c6db282fa5ef5", - "0206f07e94af0949e5b1f52cf39e06acb5096bcac174e0b11776b1f3f7e30b4397", - "023000164790ea297843ff0c79efe363235db67e87837bd0171b613b5b93d0f8c0", - "0217c7e47d5d3dc7cb7adf8ffc11c99d6f947eb86f78e9f0b5996db2e6c52bb0ef", - "0221d9a362261288f335c2639785fd604e1859a391ee0e2fe1f62872e572818cfa", - "022a03ba2d8e683973f331281cb6fd894a3f66fa5b2047632e6a99c928b3914fa5", - "021a75cd5d00e63baac47ed561d895bb5d0dd39e36a6d89aaf59dcafd59cdc1379", - "020b521f58b952248aa8f0c82a11af07f075196a59fb8a5290503fe6e45dc856c2", - "0327e999dd4f5a210dc037e02730d21fe77ecc7179f05a712d4f159c5bf5aafc8f", - "021abc502c813307b18db275ac56b0524a9d2144ef83dfbadb0e208bdcb8a4935a", - "02190069605ffb6afa108ad85f053066b7f6d1c7bcfce67309eb2ec6ac9b469538", - "0311222f70836690558d7aa50b32a19ab28a30bb092f3dd00f8a8a9b8629a04f1e", - "022459c7811f1978a23d0e656cb564c81b6a3b0dacb6af185bba40b16a066c873b", - "022b204f9d9e7f43d47e6dde45f5da665c5b8dc94de35347ef6eda7e1208f2eaa1", - "0315b8e91ad6cd07989cb0957ff4b10692277681c0671fe666f824a023400529f2", - "0328e188abb2f32067f4355bb93ae78ab5254a62330af7af8dffa2fa214be33790", - "0304683b6fa96dc65d77f21ccacb8075a033ebe4753a760019d2a60f710c30826b", - "030c47d91066f67fca785159f1744623a4b98f56929ad0df36c16d1069759b3c40", - "03271e932dfa17df786d4948d67b9c7a6a844ec27e650bd2cdfb7bb04d4d0e9f3d", - "031c49f2b3bf78b2179ec74180d847530dc34b770e3247bb22f20b8e7d5f31d384", - "032149ceee993e11914a742a462788aceaa575012c297e774724abbb2e74eb5f78", - "031f2594f9ce37fda57ef25b4f78530369412ac33b881b1a5b49894c892e35f4e7", - "0327de4f86ecb4bf882246581ff3adb0f0efe43b621638859d20aa8abe1eb1f16c", - "03136995ded629dcad2990147c1c558038dff34288483464cfc718e92e85d09f98", - "032591a1653d00bcf87133e63103dc1bb3a5f27b975f356a3388b16cab93314de0", - "0220d2754340aa6fc90a1f2edb0cb7c0ec1bc692a727387c6e856f5af2db07cf2e", - "020b7a53397280d1f34a9a38e81e73c98fa99c1bdfef886d9953d5a134d0421182", - "0309c39a5b86fbd41239944bd1f91641a5e0b1eda0d67c48611c71d7880b3dcd78", - "021f38f0dfe2ad6aad12414b33639ed2674f708a07cf39b9f52e84f426caccb38d", - "02175540ecfa00257a3f801dd37e6f911fccc5621b5a765b5ccfd31a442359aa84", - "03295cb9a97277b08a36b027b8e9c5dd9dc53c42ff51012076d79350ddae6d1dd9", - "0210529dcb3cac5e99404dfde3c807516ecab20993621b7d1028171cc45524e40d", - "032dfa13018eeee8b261eb2a0fbd22596de7579dc4c106c47700e2e7d37547f201", - "02012f523e74fc1a695691eb4914fd152b795c616cb8b8a30c31cf698d90e63b09", - "022c7849d261fba59d6ce5ff37aa28bef7ede387c4c00a99d2dc06fe4c7cc68291", - "0209ce7deb8933b4ba5435c13c2ba88c30e41ae489b39bf89262000f357c2297b3", - "03055a558e5b3f3e80d02f1bb184fff4b4f351d6332925c9ad0e75ed7f93c7d12e", - "03117d2e5b6adc0b86632eac52531f6289f043c6589e4ea0c7ec2d18dec5ea0ecc", - "032dbdbf1ebab85f48a29a4c7979943ca0e165ae32af095a5ab0dc4f970cbcc57e", - "032b07814dfeee8379445331ec39b0429aa2d8ffe1b769a04a04d6120cd29df80c", - "0322c5636d5c59edd449c23a3902ad71e264d9ef3fc35da85e6a3352c03388137b", - "022a78781bd7e60679441ad2ca8ab6ca5f72b664f5dd822ecd9c76e085051965ee", - "03020477518557045dce18cf85319650f1e73b0e31b57844def65403332a3960cd", - "0208c46f017fa2bd3824ec5378cd865a73944343432a5e786482d7eb5f0c3b5fd1", - "031218796860f238157b841a5905876d9c8f056e36072f4e36a24bda89830ea5d0", - "022bacb587fdda119804b6bf7580701f15dd4d719c8187e8e66c0ad3e1d64ddae4", - "0317e37ce0e655185838c4bb5670d47a27ea20de4abadf0e9065827355845805a1", - "0320263b39ffbade848cf37c776c6a8ac024cf8c830eb32751770b1b5bf174b1ea", - "030843850133c74ce824c990d994a6c46aacc4918718a3f348ec7696869db67ec3", - "0214dbcd69fac030a9cbca865afe77506daec1fc6f8c442ada1a55262604462226", - "02090ba07d3351f778081b18ae65afa66f28f2d8853f553d66e4210a1927b9be1d", - "0221d509304c96a526f5a4ddacf065f3231529f399c9f1c758c2d5bd8f060c1323", - "031cc3137381fce0d698ba9bc0c978c7e822cf60f41b0a670ec26461d1a4333191", - "03030325fb34a7461fd5631a129e99f41cb929369987131264caaade4d697433c3", - "0324c8e8d16875d9f6045617fbd51dbde0f0e3deed07d144a347ea8f4f0bbed522", - "020f2a05f87728e6091daa63346d229d44ff9ce8fdb9c384fae907f60a24e6c307", - "020f524996445705ccb5190e25773909595a1f20e91b094c0cca1bf0518f55d538", - "021300ed506eb3de2b67325861044224e92423a11581ac1bb3534389212144e3f5", - "02019adf689bf24e9588346a61f6dcbe54aba6e95acc9c0a3518e18ea4aa727079", - "0312f489c9fe54f981fbbae11ea7d98ca29832ac61c903d0a5e87a9858e9ea5b3c", - "0225b716798506047526636c42e72e60982f842d3b26b8fa82b2a4d892afd6651f", - "031c793f2470ecd7bc8c71ed0e489723880eeb690465986aea91faf4248baa907d", - "022b5fdaf553d4454461b47cc345c74ef48cd36b4a32aa96d0e43fcc6750a84169", - "02158764cdb96425ffe0e2001b4158d5c9c24a7f0d1712cb245e47fb9b1e743f2e", - "0301736cee2794a8019bf9af606fae25005bef6d05ecdf195295e0fd1daf9505a6", - "03255b5ec90230f1dd0209df0e738a420ab667ad08ed0aabc4b453a36db264e035", - "0319c879c3138709d43718aecc96b926aed71506436efa34f43b7fd8668ea2ba30", - "03117f2b8be8d17e11daf6c209c60056d2d1aeacca9cd1332323de7ac23359fdd4", - "021de0fcae70f7f40f664af4e63d78b2a76bf7294cfe715a6e941817a5206cd688", - "0303c79d90c076d9bd92bf21e7f909a141c8ac6c93bab306de514d560b1325ffe3", - "032e69fb9714d72e1759d091668638516b65824bc61754c37a560a6a08f2dc6e61", - "020e3ce28a2ae8d20dafc5278fdc9e4bf5583938926d9f83843aa23454c5ec6ff5", - "0204d5f5f8251189ab7ed9fe33caf7fb9a17f67cc2b5b30d5c9141fba30aa644a9", - "0324ac92a9d4b23c7d332f374e03c49d0126b0bd2edca78558d4c4768eeff7ca26", - "022ae775f5cd9b97cc9cefcb22acfd85456a842a5fc149cca2faeb2ea78636f88e", - "0204e391ed85e141c86aa7585ba2f7c999c8fc9386bab05de49e8f3c53d9c7ad70", - "0320b5b10bcb5d9fd7fd4c54214af62da7dda172ce27d431f3bb712d115f368f45", - "020006efb94e3580bbf1f95b4b011f7ac29bd0a376fdabdeea40d20f5c4c328e0c", - "032d43f13a86d3b5487368b44f3e5cb0eed4463a41fb736c57d8bc27362e947b6b", - "022033f186d52aec7ff86035f1796b86d2b7003afeab4eddcc0c17030c03977630", - "022a3e739f8a50bbf812485b31cdbddfa77e460d0a1a17b0b9532552f995bdeb04", - "0300bdc2aea733ff76318c81c8714b424b1ee186ade837b78710505de3a1fcd32c", - "02007c49b85051a0b9ca911472cff6acbf37e687e81e6e55a58fbd47cee7e21506", - "0312c18f6e34d146d92d8748fcc08f10e52ac0df510589880dad692c97621e47c5", - "02054b7bc838df0e4fedc8c4903d624d897a48e927d7e02899b677f383b9f62358", - "032363403790ab654f99b51d9dd3a2811991150d496e2f3aa2a26c82d0f32bd457", - "03221343074c91bfcd5c4344d48c38ea779c417960de918186679a8505fb139749", - "021343a6ad9d5b2d68a6236b31ff65367f2c618929e68c038142c87366cdbada33", - "0211f702a410d41366a26220fcbf4036518eab22ab96e5c4f5d4056be5b2f46e3e", - "0306f747a604cd2aaed315dec8591197560a3822950d886772ff3076b61819b876", - "030d84eead6058374ea1bdaf1d0a9b53d2c4c5d6f28cb729da93bfc4f942159de5", - "0306e59f37f210394d873b61b0d18afe80c92001cb425560ef114654da3fcbab84", - "03066dba8f3747ff3caf7b6e3c082c33132d36e5267239f51599aca02bd86b6111", - "021f16a90b4b7ecdbc3d9b3216e9425e4ae5acf2223f25151518b70e15ea0fe74c", - "03103041465489f78282f5afa2844577701c4ca3e9ddbc8c977e917ae9dccada84", - "031eb9e4594dc6a9451c27db1c4aa2e68b9ef583f58266120a9b8512acea487964", - "02008c742477d7030d7e925b3697ec7e21865e5ba2e17b075499da50451de7e67c", - "0226ffefba416af593daf385c2d724a1c8cba27c39acff9324854f5a3f479d9efe", - "03160c31d5fde671241cdf624f67ec643c9a03b43cf3c7671b86e3da5a11eb3a87", - "032f0a583462207c1399edf80a8f49861893d2bfee07ed2801d5f1dc197bce39be", - "03123c13dce7c0816a63e7fdf977e2e6d02e06b203a632951bbd6f06a7ecdbfd9d", - "022b1b3b5d89f25c37e6a736413b2c41c159cc318047946f63255ef28a3f354f56", - "0310078f0892f4ff1a65e4f3a33ae8e6ed884d5fe1cd0413f549721bb3225eca21", - "0307856f487d893d7e9c79cfe30cc1c910a6a67193b29950a16af51f6bef9f111f", - "0324b281381aea51192da17a6c5d45c01422550eb906daf1c93633743f51072f81", - "022bf8c47271429acf485b64ad5c6f1aeea7106eb23408eb1f9fbe71f6530c2ac0", - "0225522fa9597e98fb5dba6d02a0668306d96250507c39339db4bc6aae7ef3177e", - "020ad13bfe63f5c510d8feaa6ef681b69e06257f44cf0f2d5fe3e9d95d8b756566", - "0225ad9a456024f2df439ca7670ecb2ecd291e50c8bcefda3860d6df1b690382cf", - "0208613a70e96a035d62542c491244c5286db168c4c576540b1536e1ece2c006fe", - "0303f60b731fa00f50a6e22dbec64d3a95ab6a4ce2d1a45aeb28042b07f02f1f60", - "0312495a3b6fd1f2c003f5728299adcfc2ce7381b4a17030214de46b9baa024c9b", - "0216330201259edb507b3322c8d94135bd1f17eda43ee64f1651f7aa2247c0bdd8", - "022ee19ba63db398310feb27e279f67a0541aa2a34324595abcb053b4f06a28071", - "0315da0bf29b3f5a942a2ba6c968c6ba7cb4bc9da3989577207a15b7b2c0284777", - "020b97cbc58686d365dca1b672cfbd0e116086494ef1852661946e54c795a21c65", - "03066edeeb855ef57deab015d3e995e67af5de916860b2810973ce03a93899b399", - "03072689dacb3668d50022692b93b66c22903020b270ed6a4605d6a6984c33f914", - "0212352da0557db0017ce24ae1951086bc976da3934e6dbc67015c08537502288f", - "022afe915b2275db47b20db0b2531a2891d8410f087214c2720f5f9e942c5e830d", - "020bafa3a2b1c671aa6019bd96e261243222b53e74174ffc2df10fa945aec1ff89", - "0314a329d39aa72ffe8dd1a5da23aceb78e9fca5ed5492f2273fdbe49451dd2e9c", - "031059d6f4585cebd2d127688d30529f18ed62eb15f51aeb1704a08d805a38d9db", - "02289d4722e832e7ccaaed932e605614b5613d23f5816f35ad5e503d8bf479e594", - "0319e1bdc6101fec6ef183cc9e1770c2e6f80f718a432d259b736c32c116b07fea", - "02073b5c415959b33e4ad739ac18a81cea7aee6e583d5e6412814451f7a65b7d5f", - "0314679afb355d69bf943bd12ebbcc00eedd46afe93668d0762f9c2190280f0fe7", - "0319bc6f9cd2954458e05a16451535cb4aedeaf1b8b17fb9007ea1ffbf0a13cc93", - "030d7c4261393ec5989e839ccf8bb486f7ff6c43c0b960d292a1f1a9863ea53371", - "0209c4c2b423e2c98d9add4084ee0903de6e072398fbca191de4a1c024eb3ec0ad", - "0208060eecd74f764457e2532cb7501596db7812217c9c4e2b1fba052c8249ea0d", - "0313227c26cba7f1d2127d81e978ee0c7d45148721c09ba7a5b6a2a72235da81b1", - "030dbed40377ff852ce292ac9b6bf0ac31c4e91b3b7dd9eb78e960fe91b529d66d", - "030a5ea7366ce5f8535002db3336cb331e9ec155335690de96c02d7750335d1e99", - "0302eb320ff4ba95c10af6da352e40e6377168bc26ff376bdb9f8fef70605fde44", - "022f051eb24d6d5e6468540f85302c4393b83cae79e5402080d48f00dc8e4ddc1a", - "021a14c14f5abf84df599e2f929e6729e83c490fe5dad02b552f2d5e99697e676e", - "0220722b0480fa5a534bf0be1c7f25540781a07f5564132f1fc217a2217a322b55", - "030df3f6075b2591ee37c0329fcb0ae136f9ebc10f6695238f5de973f3edd506bb", - "032a7479d88ccd65afb5e5970e7b0de7ad9f52237298366bf2c7735912d5e571f2", - "0326fe04f91a89301f8ba36ae8015c8607b3e5f54ecd9d5df036795ea7c57864c2", - "03044b33e4768dd7f9cb4cdaf60fc4cd1642a5170b1dcdbddb08ada93048b19f33", - "020f42cbea7bdefb1b3818aa8cfd3e51636eb25969d52f35307c7df47c888d229d", - "022278236d7e1f0d5b8aa48fb0298ed3d115e6574ea28ec0d9b27d07ccf792e96d", - "032152d99060ad4f52be74c9eb97d65775755d0a86f93f3bb82292cc2cec269cb1", - "0321e39b171391cfa83040c8edc12eedcd041820aeccc944257df5250f87636449", - "03054c845ba08092f335c91c871aa625bdadf298614f90d1c2cca66ba3046760c7", - "0321588992c1ac99fdaa496845c061fc4b099da1e9e568ef29b7c193d3fe6c8ecb", - "03270012db4601edb1272b319da71789793475b5c824bafb9a0454e4d43a6048f1", - "031cf8d4ade62d31dae7ef74e69c5c49ef6e5c7928d69be7a075599f382404f0db", - "0205267e0f5fe5be8b8809ed685881c2fd947e9646fe5f8a42cb1b7af31e8c2b10", - "0217bdc8eaa7a36f7ee27ad6fc4ff91f58c356dc1928b50c1fe8a11baedeb0605e", - "0227d45f983f1ca18afc566d519a949aef165a400db30e54b690cc5d559e09b987", - "03037fa8d43b34505bfd46af2ee439ba53d0e6d383b84eef76488292c4d5ec8c83", - "021ada39ce1d53afc749158277f8260224dbaec2fcaa60d4de0c780778d6bad9eb", - "031d0a0262d78e4c2c42dd558ede2d6f078a08e93be9d6e7df3fbc9d0fbf2cf3e8", - "02231a401630edd72b78204c94e25eb23678246990b72ca166495bfb77ab641a08", - "03202c89f8e18afd8b3937492b39ec52630c0c85fa29f5bf795be710af2b0db301", - "0204379ae3feb11ee9b4d9fc674f612b1816b88a48506288d5a2836b591c9ba49b", - "032895ee2e82a1a873baba844f270628950b965fb2fcf0d527fd828f38ff3e9e94", - "030aa6291ec5d7fccb9f31905a72bb7d692eaa96c3f0b4548e4b111e6c0d8378f3", - "02089035bc8883c814b3fb68b5e335a2438af5d49beb47de5efb760174ce09ee60", - "032aa9d6d0c506380b09ae91d92b8ab46229767959655bebe9122d30e7939aeaa8", - "022f0e0834310b06a3f8f580bbf5e48a255c53312670fa6e1092208475439ca55c", - "022686a6e565b0103600fc2a2af31a156f79dd41011d28307c0114f8f5a5860e3b", - "02145b2d389da7db3d2e43e91b0c479c73556bb635cf4e6dcee6520deaf1d869a4", - "0207fe8c95958ae9f0cada9ceda3594ab1737f9f1e2be8e08d8b1c6af06c821760", - "021e78758ce0426ed6ebb8b4cde6bb9f9f058bfdd1515b075b4a603b8ad6ef83dc", - "0317836b18e3870d2378335579b4df0269c0b8bba30058198d4e290c7a90f66522", - "022c97566f696f48b54f51670c48be7ab085b591f3b36e3c7a60176badcce4afa4", - "022f2cce8953fcacc9b3825244f073d80ba616d3ed25b0600c66c253d2cc3cdbe5", - "02129b5e0f8a64735ed376ced6a5d6530657ee17c955b923f01d0447763c7424cb", - "031a1f311f3693d503e29af87106c4a61500bc9e15e377cdc681454a761a90eedc", - "0320226014b7d944d668217509c644fa833f8d56c7f8ffde4aac7f998b89709842", - "031f1ae0fc23db57b2221bd5a6756cf57e8291e220f065c8355d7ab0da12d8f0c5", - "020cd6781d4cac2c2c3c9e37703ac25497cec60393b757b174c64710fda24a285f", - "03291e3476232482ddba9f687f69e0fb8df35930c90e3edc5a95c537c4777b3b88", - "032c111074dcfc9b0b650c0636fa8c0b568fd2043c42be5143e0a50198c7df8a31", - "0223962c0404cbe4a8079b027bb52347368139dd211822f2d999d6fb8209a3c308", - "0327cf8437e70237a45f302eef07fe9a1a8686b917324bf1a26fea2fd8f80ae6eb", - "0303a704964097e41bebef328eeb7a00ddb7b0166a0a7a05ce5936175bc8970311", - "03078599399a5271244363552f2d1c569b4853b0ed4415e53057d2a9c496e543a3", - "032e01a9a09d19036ad32805a519faac57b434566418a9ac5cb0e43ebe0cfefe4f", - "030957ab22871ea7afb40e47ca8537c695fe91beb426765848a8d35fb18d8e762a", - "022069fd45a862055a3ba833a29a1bf3e758f13d19d39e7670e22ca76d6efb09c7", - "02042570473af68fe716e491aa503deb80dbe1486201956f076de934e08aaf7a1b", - "031f1b5180d5b14fca47ce521afa576f5442572285dc6afb130e36ced99cbd2668", - "0303d5feb507cd80eb5695cf033eb8c7e1a1fae4bf39cb893aabefe5caa15019e1", - "03278a6cc7cb2a4f858f18457c9971071c812e6bb4cfc6e1a2c276d2d6eb7786d9", - "03205daf78472b61d50f6b9e5dd391387dc347a52c9d4fdbc872ff59c2119689d1", - "0201f84eb6d6f69bd6e648dab128ebaf06a6499900ba5dab5ce76bfd05c71a40fa", - "0318bf9f353be66e0f8f0383fb8a9fb06ee3a65009094641e3a433a28ae0eeb32a", - "032555ceb39cbdc518aeeb0453b8bca868c3241926113b9577f4391dba08f4af1a", - "031f15c2967b69b53e03bf8b7c96168f8a3c5d27474aa75b66f1173275a77c0167", - "0212c3ef187ff24c9f8fde3c9f0ac65af35a874f1ce4febd23b686c3a09ee65427", - "031310af2d52734033c1dc4c7e93a3225172c174d8c19439c74e5675e1e31c3da0", - "0212d4abe852e4d156010a31f63cc28711d99edd1153fbd1f03591d0764dda7bb0", - "031a78f02eb7ccece6e821a78927832515a43b2515df8c4a3f0707e1cbbe6506bb", - "020c96de6d3dcf12b867e7d96aff78522fe0b97d94de1d13d0f2eebfbe12c552fd", - "0328553b08ffeef3a942e3a7c7ce023862b03f2a74c5e2a1935b821ceba0a7dbf1", - "0204a6e9a12bc5bfb2e86ac90db3bea389d9925b3adedb47639c1d684855e0c022", - "030aa8347581ca3016b5cd0da062194ea1f1703787348f17c79ca70446e012f840", - "032821e23d1485724a31ad404d83ba2d3967e955f7a55221e587b73d1890ee7f38", - "0319487181dc6938909362ac5127776145d982e3bd9c57e484e3792456c210fb45", - "0305659d4d1cc7fff1509b1154e8c369f0c80f14a5bfdd0b9bc48253c4b87432c2", - "032977d5fa44d7020c82eb4ed11c15d81bbd4e8554d20add58b6cfb71ab4142c35", - "020a7ddf6a070159461193b6a0b33a6e57e2fb089dfa10c19a23c3a803cc7ad1ea", - "032eacc829894b98d1e03c895d5930994adf909c853139585ef8a06f277775adc2", - "0226155991c32ce68822f7f4ca5c08fd26dbb72736db14722642e089cdbda1bab8", - "021d6fc4ea3e27d5bd3e3a94f1c1e33b3de0fbc5effca05e8e7ed603cdc512f3c6", - "032097953028643ca2b2ad361958824c8721deb18119ab01d13c0373050dc3f592", - "022b69767383873513fb6c65d33a275e615a217e95684864b0915b6ba809671288", - "0301f9b8b137b4fdceb8833832ef16b4e357ada7086ec17b26cd5ac43c012c6d45", - "0317dc3938be7c229156daa40f1857fdcbba7e246eb3c28938bc50ad75d0178084", - "031923a776d67a09c22f0864d8ecd74ea4487feccf1cd45471278508f7f6d45b54", - "022624a2914620aead22d263a2e839934df0203a1076b40efaa1da85ab141e9159", - "0314bc9da396140da9a2bf498b9baa5c97af4366c6e5f53a82cec138ff6faad825", - "032cfe0520d1cba4c9789de11966a91905300c2b4cfc9a840ccf2c099f2dee1805", - "030f81d47e75f010e833edd2738c242dcc8082d118e71c30a87ac2b61feb2373ef", - "0217fd7ff3d8c7ac91694ac91afb8f42946c1286a6bbc167d35286101615def80a", - "0201c780e85f2819d2419de81f3ce9e49fbb90fc2953b666fa69ee7367db173347", - "022b47cf9ae77ee42a2ec1af4733ad9c52c7ce529c9247b30841c1bf17f662d495", - "022b5d91af096eb5903c92546ba591027f0b16e0470c3187b7c520352501c45521", - "020b413e8a770bc1e549f93c5f3cbbf6fe1e78886f2d849a3bcb262ae0d2f7b480", - "03185be2432f631f508373da53088e16affa2b1b35574f4f9b6fedf95f64031010", - "020b4807d26c2caa16358f20156c410c76f9c59fa42772fbf310b89a4e399d6eeb", - "032e4c88d5fb86b0bb72733cd2c47ccde516ca00d053a611903e19df44f591cc1c", - "032b2398009a6cf83fe0cd6246098a3a07f3a36b2fd72d30cc2202db71e1e8a357", - "03126ff0585809e2380fe56bfe252bb83cd1ac805b4dae49cc5dae9ec32b29592c", - "020e34541ba84738f23e6f4592ba56f8fda1fd4f28ec4612129a12455d5c5393ee", - "03113962e4aa0e737836be131d553e4a32740d727f275e378c880bd9986b4d1dd8", - "03014cf78fdc212bf66a657a235d81a62addacf51abcedb236d5df87bbde13b488", - "020c9c26850456f60abd24c69acdfa7e9e46b9dba89f011efdd5f2c06d3ac2cc14", - "021826e564f6d56c68314b0154c851e665f5d7e337a30d1fe0b34ecfe633c204e1", - "020d641428bf98a89a2189f3d4cebe3f78452b9b7c4dc23f109009f2336d77370d", - "0321ec057503c38bd84362dd1f7c2e4384c281254ccc9517313dc8e485f5ee5d05", - "032cab4bbd6650104a3bd510977609d862a52fb2ba205b0e24592964c635a0c56f", - "02145c2864a5bc8d5f6a58d4f2a8f83ea97bf3496ddb0f73214b896cd07f0ef0c6", - "031237bdc632e2a96ad12bf3a13d8e7391001f951fc40128e4aca2a81f199ea667", - "021400f07d34453dc2c1dbb281c7e30008868e22be4cc2d28626f0f413dfc1ed91", - "03043d0895c346f26c45934216e11ff34fda923bad3b9aef4034cd1518a3e433b8", - "0328bd7c4c663d2971d15cce337a87215e92ffd72994a57b73efb39b6745c962c6", - "021ca2b056cc4714c561a9cc0cd71ff9286c40fc4f7fe6cc2bbe0c2e16b0cd2482", - "0324247c32f1ad36330978ca5087e33b73b8924f2579db7da46a577ac4545721cf", - "021260dd73c137e14f32ba7eaafa4f03a2bf2e9e6c6ddd6c99052ab2d6943ecb9a", - "032234266857825e15c8db6efba43e96576d8cf9bdd8c5cd5898da28201e7f2c13", - "03236bee8c033fc133456a76f1978818ba63483012e269230d6c1f2463e90c36c7", - "031cd59a37a778a1d64fd0a7feeaf0b6ef02c9d99a9ca07365af316d291c0e79c2", - "031a89284539b9aafc537384f1db84ee08075a9a24c8c983a73b72a78730f10368", - "022b58cd6b3486e225ff3078bc79e9600941f5095745c5bebac96fb9ea05134f4d", - "032a6c16a8bec5287dbefd82e27f26f064f20000e0c871d634f05f841eae262c4d", - "03128e74e19acf45563cdee1ae5af534f8fad4d379af3eae73e07b8b546f76ea54", - "02301642bf5b3e21a11dc05991bde1075687edf2274dd35e18e2f11e8e5e924726", - "020b898c1fe98a04b09e20fad64ff7c2f8dbfbd4b8d63b99f702270b4db4b45ae3", - "0312e7e8050c34d0b896aecd8c4c804ffbb2fe698ec7489b60b8b501c4928df8b6", - "031fffc6477b085debe38723492ae034bfea843ba99888b381e7f324807aead500", - "020da294f855f974a00b476417434cb4101796a3f5df0a808d0ceeaf95190ae75f", - "0325a390b3b31ab139b99ccc3d63ed9893ab9c805672e0618f471bbc5a5819f8ec", - "0203c36a4747a0a7daee91fe4c65fcb26fd5eb1695e59ca931265770cfd506d724", - "0215ed23a2254d8400e46b21e1b4fafb04d9c64ac0fcf8e93bf8c74a2eda519ec0", - "021be556edbdea8a134af971bacc0562f7d7567e252232de2f8f448205262166a8", - "0305531aaae9348d3699fe413546affd935dc55cc10e35c4fed12172bf4175ce18", - "0317547a2de0430eeaaeb931fc45a542dd59efbd04d22d91410cacf01c638939bc", - "0228ccfb2cc9b10a8dba283ea9e9ae0c9653a69044f945fcf8a359568a225ada78", - "0221c6cc76a0179022c0c09f924fe8920c68e58fe934747b601174bc0a76c219cf", - "02296b09ecba6dd9712edf92324782cbe6dc458681b14bb9861235aacd0c545979", - "0212dc3af478012d4938a6885a175062abee414b1e95ef6aa9fa5bd9899d2702af", - "031d90901005fa7adc47e5b66082e6676348cabe9ab507c42c8dfecdcb9b924dc0", - "030888a2bd79d6c6b2fa6479322747a8df975623a4b9f3c40b29faa3436a9d741a", - "030096e7434ff96450fcaf9291f92ae0d6e27d044998c7d83dd80406c074c84ac0", - "02065ef1380ab11f2ba2e2037dbac1edb061f2d8625d84fd17b6f97e24d4d846e3", - "022d4ba3a35c2345e6d064f3f651c675fde7837315e109a45e055472d224eb2180", - "030a501159a56b89f6de8711d0a7b2aa42693797305d6a1d293c88bc9c577e35d5", - "0306df7302881a35767c1212903e4f7c470cf32074645f47099f3afb1ebacf8080", - "022f95f34e2070501d96da77fda8515b760f91cff51e294520465eab340147b1ec", - "03249fb7bfb03830dd01af473cb0c1c0bc18f3139ce6c1cbd17101d903ebeea587", - "022cf8923a32d55cfb71fc002f9e2f1a30d2e79d3215033829bce981ad86361c9f", - "021f6fa47f2d5e6208c4f1ac16cc9fce1c3c0e70bf079f22c2eb9d982fa3c894d1", - "0311ff25803c83159c9fd77c9e04d543cbbae8a6fda74006dc3cc39272fe846a7d", - "0226aedc08de1a13bca926146ab79b6be43077d4de134ce215de293e1beb9d27a5", - "03226468b833078bc84d4bd637676f78aa153fe96b7d80500c4391b214fc305c03", - "021b56b0624bfd2e00f7ccc1376e1654e012302ed734d4cf15b6db013cac353d69", - "0222199e4d9344c4a3293e4cb33deacf4fafbf49eed8e01dc14a7348be8377f5c9", - "0217b7453c8acd3d9f95998b21fe1ef2c62d0e9cb11f0c26615279659fabb581d8", - "0227a4b653d4641fe4ade83f4e9169a12b30384c99d1d92413258319bd2da82d4f", - "022a325526eb520bcf2148c77d04186f279381ed5eb93cc98f207cc7f6b28e92ad", - "03284aaf2e4294ba6a8075396bfac960e53bfa95ce62e8e3efb625770c57252647", - "021ec976ed7fe89ba328d3f86e66a4f8a7bf8be4e8167732da52492b33f9693696", - "0325f32d1d8773784b99a74696bd8376c9ec9583dc14b0e104776fbf387d5c1475", - "0303c39a0ed4d35e2a2d51ec5ba4e1893687966117f0ea35cf5f9d8e5fbb2bf8cd", - "032727782b04ca582986438593a2c42f4428e4242365e698371b07f1c2bfce4595", - "022060e23d0374d1e3e1d380762e5a3c2e84500466fe063e85e1c2e191eb03bbee", - "0320e84cb2450af93adb282393d3421a08d4c28808c5fef61314bde0f569553d51", - "020a3195cc292749e39c038cac79ff5f84d9610a85e8f27d8323d0ce53ebf9afdb", - "0317bd7904f9608bf2bcde31b35b942e9a7f3a5c5900e9593fc32f26af2f251823", - "02014e44885dc0cd2ce9f3ec29ced0310f38729a550c6684cd3c8735af340443c4", - "0314027bc9442f2784c2261b6fcfac2600bffc28ba9f739019c19a58fbdf088d1e", - "0216280f84eb276d595b1f15a74545f26747be5a0080841abf58cbf576810b4769", - "022e734c9298fe235792f8241eaf33e51f158db3a63cdcf06d142b9729be69bddc", - "03125b7431a0aadcaa3f0b935af1ab60c1736e8b23c32a5464128d219cd30661df", - "032ba66be4f2bfc1659e5a1e66bfd4fe385b7ceb8c3dcd3658a6841a04d2023e04", - "0209542213566669a500aebabae000a6da819014f0efd2fc818ef9d7494fc9b0bf", - "0314463a6d0cfe73cc8d593e9bb018a6c2d5951a639491201d928a306b7cb2622c", - "03274942689efa0369c8b4a70b5d021ae7ad7bcbe0e6a809022c6826a47f5a2db5", - "0319ee0256e360309230e29e838d2cfc82c8cf55c82aadc233655d4180647c18b1", - "020bc285cadc0e124d11fee3776cf5e6f2d4e4e0c809074e448145ced65d82d93f", - "02017bb6805c04649ad1083ed3dc885d9c750dbaabae3898d32b309191fc43d635", - "022c9142c34d8d0e373577cee7ba4289be1d2e0c7bf923446fd2117fdc77464e5d", - "02182a2e223aeef46c0738e21a9b3edc958bf025d3b5a223e999424451f56edfaa", - "0317430b3380f80772834ef360a1dd79331ddc984602c4dc06e6ca3bdbd3bc8517", - "032753cf5435996a834b5bc49a43a04a487674ae90a51e5a727659ef56edd8beff", - "0209c1b840f6095569a6ecbb090749d11f527ee5ed0435ac458f1fb82a2f6091d3", - "03200aa3abb348eb3bcabdf3f6d8c4c4edda9fbc8fee2ee86f0c0b9d8894a72a90", - "02278c87beec0580b0b3e2a9d657a20a905abdd4cfe633331f549c93fcde1efdda", - "032d5a25665c192b4b6d813228b682636b78abc3c2ac70a0b344fd2fd5fd58510e", - "0317eed039447c82f003dfafe81cea002daabe4a2e94abd7f0f6e9491c85ccce9f", - "021b9b60bf07a326647d930db6da4bc76e6ca506a9b3074f37c52e8383949018e1", - "020c4fb10c536c74840c20b36ade8247fb21245e9bc1069f1866d34dd81f982f34", - "021be9ffea348913df53dad233e1ba64d9ebdb2354e352cf840128c4f4fb307c26", - "03294d1ef9a0d5993628a68b8e89d10f00d6acbc44f2089eede0a2265e9178cabb", - "031dca83c45df6612103c70d8e2e86692576f45efae78ef38078e59bee5f65bb9f", - "032613cfed8420df2792aae65f9c1638a8aff5e4e40f29665994d76813bad23866", - "031eea3fe2cb32ef20cc26d2084ea420505099c7a1705231d877bad851b9bf2974", - "02186af67a7fd2671f898d3f26901152fcbcd4f52ddb36e0f818f0cf6b86985d2f", - "031cb68ba8f8b871c64f50e7142bd21749f8f3b229aef00fc137953ac94a945a3e", - "022a1fbf8c7e10ee1d8e07d1e2b175c8880d379f546d4ff89392ce52282a274b80", - "032f90d75032aa7a1c3944188be883b0d58d971d04cafd213fac87a3d6e9fcbc6a", - "021b0132597191e72a1c424fef05677e720a13419206e9b2595646d3987db96a9c", - "031e8308389622ddfeef1a375285b9baa5f3adb494cf0ffbe06b4377fd14222b17", - "022fe6f375ed5dbade08b71fc258948d12d5eb921ce099747df28b2404159fa729", - "021a18ddae5ca1c038383caa4992a5d49eb8a59283fb4ec35fcc02ee8cdd864914", - "020effe501a002437a38269eb377f718137b2d487b18f4e24caed8f7cdcb4f228c", - "0322d2873a9a916b27bb2d6d85e94230e848321141f1b0b0e33b3872f650d1e8b3", - "03063f513dd43b2f93048b1b2b2b427add7a34a8eea5cff670d4272463ba893bbe", - "02297eb2cf8cf365469aac32572202cb2e313d66e027d9ade66fb1f07c208aa986", - "030a437720b46c18f98b4ae2ae17dc0683826c91386ec6280117c08502b1a329fe", - "0325232e2b125e2d8a9c4253c92b1f4d6b13873191f4a2fb59a4fcd1e6ce9d5b33", - "03062ed362ea78010f5a4e98722043d8b7a7db6696468dcb528b1851786acba765", - "0305469db601edd6b1fa2a02911443ee4637329e7d23bf88983efc98c9ea44f446", - "0219469a422e2d800749b2a04e9d7b2a6c79058695e82b01762bc508088272a7c9", - "0215aa4fd8f33fcce3d5867a34d5a62617bc9f6fcab9009a60f07328876f915e24", - "0327a432bd2b84261df683ba39c01cb8a82c230da4c990487415f1232f06054423", - "0321130d8d18575dd0b9a097768c9bac2390cd450119b6d4cd155f38fea22c1a56", - "03225943ebb5e88f60b71efa0f04c334016c5c96c25939004d510c0e1ad7d33321", - "021c04ddd9bf238c29786dd4749687c7487feb7f0732c8e481b8b1af5480d736eb", - "03015c31fe2698ec0e4c27bc6703661e5d23d577f10be49eaab87749e0ad630f7a", - "031166482a80ce366b75e7c253241e258b5a9d15b7da94dffc620df982937552b2", - "03167585af2172d47f0bf6afbad824b066d0154255336557174adf08866ee29c7c", - "0228b5a61eb21581f6025d6ce40b05a6f553669cd1f7b510a732bf4b73d8acdcd6", - "0303c81ab71cbbcdb801f4ab73b86e9f8ccba08f2ef5d9074fdc717a3fcd1555ca", - "030cf13d6237c88eb4f1770199b417ff53de4a35ec5b2ea9af411d7eda8f1332d3", - "021fab8f0fc15210f28dc57fb1b419117c34c94d8bb08209ea2262a8fc7f0a1410", - "0323ef90754de24d87faeccedfe282b08d953789b131752963d6b432dfe66147b9", - "021379e0aa6777177792338d7688981733e8b8017331889b6388d3a92d17055507", - "0302dd05789b0318d915a6f702263f414ed7175befb5e6c839d79294fe984f6360", - "0206496665710d1ed0aab288ad3f7c9230ae131e297ceb8d4462ea8bc7c7d69d75", - "0216f5dfe09c6906dc53feba30e455569d8dcbf88a931a485d3412ba636a2645ff", - "0301ed795cfc808fa3053b2075b5becbaaa9c6c49a2908da9c127081d7e8ded7f6", - "022802af18cd74d0549af3dbcfb40a38c4d20ef73f0ad5b925abbf7d0972f1aa40", - "032c17af81ecca4f6fb6a965f42eeaf91247182607dd635a167371fc1dffffe070", - "0204aa900ff8cc8614913d60f86dc05415931e6f22802d1829cac469f7499da4e2", - "02248a25b184e91c70afae4914f4c4e806fa1b142a6079fd51b3126a91798b5deb", - "0230009c30d7fd786bc400c0030d2a2a13c8da957a47ffec360e3e568f31aed001", - "0314ad05c4630e72637b4a56d18433124c49ca8030fd756902fc379cdcb6446a0d", - "032d4ddb8566c135e3559f7cb02c64d1597c5cfc81d4d629f1902f540886852dc8", - "030b9eec251839c552bb29d9e39340448e53435b277b322a8c6e7f22964d30ce06", - "0301c9d928a0aabb04e2b38ca81ed127d4294c05c0dbd39c35dc6b134f14120056", - "02206058ec0a73de5405aec49d3fc92769aa5792dea9b84c86ca6f1fe5b21be41b", - "0303bc8429fb6cbb1d33943e1418c3521b2584cb88568b52602d1be8ee9d7d3ef9", - "021105a1ae3edc93ea9a964d7887b982cb65dd28657850ad6f8322c983677a0c60", - "022139c9c3c846c3d134d30ad5ac3754d9bdbeccfc73c34d3628f5379d24b859d4", - "0325e64b344d78e8281db939a2f790867b06ea9d1fc95a7c511902aaae0111af06", - "0222dd876ef0dfac15e379322845b8b33ce21eaaa63b114312ce5c992c2808b588", - "032f7d8d67fdce85a2bd82e6731e0f945e11fa4c9bcf2b45a156a210a48705ee3e", - "0202da3b19e9c4cc52565586b29d8e8083f98523f104f9618309cf1ff768a5ac44", - "032de54f7623d32b4844d555ff7ad22a1c7b5bdb1f5311231feca56a03f0b0fb7c", - "0203382301b4f351bc5e9835edd0921dc953400f1ba909ef2a80200d218873401e", - "0323f310a9ab20e11caca36f53f8ae3d3e0ee4e49da7ff8e7929a22645913d50fa", - "0301b720cece25991e10691f77adae0d104f5e051b3e9a4f0df83444660a28d711", - "021d5f517e8405581c2b1bfebefd0dbab59d6fbea1d9e9dde002097a566cd89fac", - "0315d0267a5bc2fbd358e0dac9e3d36da178de0007b93a751c307d128debe23922", - "033026fa0d1b736e4fc2a243d3f994fb2941f5d71b050da6fd26698a19d3d0ee6f", - "0324fc0cdca7d8899347e22b501b696f2bcf0929ae30e788d90113bfe08eb5559e", - "0315f102550b243238170145c64fe13993cae2d326b8eb0194adfc131e080548e8", - "0227928f4b57ca8cf6ef255a21e94f366abc0879c8eb8c075306ebf938a5fa57f2", - "03272979963e06b6d6665c08bad904529586b7e82634f290e8277fba2b5c9547df", - "0225e07020efe65f595f10fe06de77c0d69cf9b0d4497dfcaaaf59d0a099e94ac5", - "0209b77aff625eb6a3ecc8e9667a83c4a0145a1fa4109d5bdf2927704a9d096319", - "02173d0eebace6b5a1b013356a93e2204bcf2cfa80aca3bd92977788ab5ffa02af", - "0321a4c8c9979a9964d1a3af6b0697519823f0542ccb1663d46e40048300b53be5", - "022c6fa06e7594f9501ac26896f7ffc5e201848123386422dd7252400867521f37", - "0200daad20ed1ff5704b1105cfb62d360f5d8a0b931aaa902615d7dec12fa37327", - "031f09acb371062d00294a3536cda98a5e990565f46762c0493ce210aecfcd7cc9", - "020c227daa07f33faaf4c9a08443a7c51b214a004c6d0f7763895341751e223dc5", - "02086fbf688e8e9d28b43ece4dc5a6581aa3589abfcd12d4e2ca1a67b4e817c971", - "031ad5e1d014ca2f0d9d2e4c376e5b63f39899ce05b1f6554e04583d0b3e1df3b4", - "030d798ebace26c90a2281b8732cb9bd85444c09877e463660fee9f350479a2c7b", - "020dc8c9445d3db88cba04a4ab32284cf8020f3bf0bb501c13641275c2d022dc86", - "0207b24d035079692db90dd9dc48c08751b8e7d7a700175bf59d046b51c4619f7a", - "031e3067bf3c536d8695e020662fd7359e52af17d5dfe0c047e4627a9c3dc3be98", - "02076e1f8bd6cf34b45393e375d7bd63467580e21534ac92f8f9fc197dde7e0807", - "022b2c50271b1035a3384debe6fc1f1f86bf5cb61d7be447b2649dbd8b2da059d7", - "020a9c66c5a2b716aabc0afeeceba0c7a95c0231541018fe414b01fad8d382bbb8", - "02083178a7a5983c1a90017a755f7f8098299f5dfa94228de5495e9bb71fd10d46", - "030d3005def727028eb75be4024cf49602f10526bd665c7634e18bd9f41360c27a", - "0320ed04cb281bdb942fed10d91842e84f5224018ba862cbf6d5413b1cedce1c2a", - "0322dccd1b79c068edefff068ca8393edd38ea4f46c38e65c92aaed9a07f00dade", - "0323fb26855954e704ca1bd53c7624a8156aca4b0b28e8a2dff20ed77df89f6261", - "031d463b9df180d2a6990b65389e84cc891b033987cf4ac05f8e8f3ba0d39a95b6", - "03155a3be65b39c580b38cafea4124db5c52c1580bde1f9f7f2cfc8d4b6b5cc589", - "0220137d56133ad256b76e9cd2c09bc6486802e6c28f21ef3d1ec9f38e06e83300", - "022d7341b7ce44c2eac441bea47c5cbbe73d4e6ad4cff17242a5f1241dd9b67eef", - "0321e8df1dfbe94f642d6914f900a5c87fee2849c27ad1e7c458a7bb09056beec7", - "030af84ae89a6086aea8ac9607c323a749c22ec344466c35b11bb57e93558c11d3", - "0306dc003b82d04600908332cca9b68623462d878d3f99d00de63e1bab845aef5e", - "0300fba06c492daf0b09955349d056ab9f351a3b4b7e6cd62af30384ebe3e73b2d", - "022e553eadfbc9b7234dad4bf54e8c308ea786a1f1bbcb7928056e6b9af8fb96cf", - "0223eab58aca9d8c4d9c2290e7c7699aba4dc2631ce3b0d6621b1a3b59c78fdfb9", - "03280248190fe1f04fc4f11f95820008a1cf1978a4901379263b5f25904d5914a5", - "0223ed51992fa146a6844f1ace6a6b1b1acd6d97694d4ba9c09f27d9ad56e071e1", - "021acd5afa69402c6426e0c65f77656cc931db4d833464a4cb1ee53a8c1cb226a1", - "0200c39fe855a2a09632b43b307fc7c191742f65729d8ffee3b16560ab8e182860", - "03100c4a824780d95c1fc0eb050c833c2dc378c7beb62b748f2658ad3ed6f220d4", - "0324edef6f85983a6be6e4dd42747a570464e061f68d782730dce7dcc15d460cbd", - "0222c48edabc645d15e38d34a60b3588f04817278d7e0cda3a4261ae287c807c01", - "0211eac571ed368fb4203c3fd0bb185934fb75d6af900793aa48f004628f556f05", - "031d3fd067ba799923a9322eb74b87598fa41292efdb77b629fc0fee61b704ffb8", - "0322974be19c464087ac69413b9f05ef835446dba6fc23c8c9b5b58b1d62e415c3", - "0321cc9bb042af3201ef2536f6bcd9efeda1663772885d262af62cc0a6959cf482", - "030ab738fbfa27a0036345fe53138201047f28debeb0ee5933d7494410a30c0e42", - "02304c6a000c2ff2ff947bfd7ca5ea24bf22b519f882323721472166eb61e158b8", - "020dbe620d4dd7bc7b79dc2d6abccc2f24d668755515f5519f5b64f9b386d42afd", - "02077e30eee954b5345269b1d3169e1607912b4b191df58b7e3342513ab3b3eb2c", - "02252f6e635450d5eec24cc02f11d33a8b17bf4104c11e82e99a1d40a89b708268", - "02214f723712f7fa4869e8da12d9b65fa15f983ddfe9f1240910ba10b230871986", - "02073460d598a31040bca6dfc45e81d88992959019dccff3a26f8e42cf28c0e896", - "020270d096b5009279db00a8263dbd19c3b6e61e56612c53cdfc2417a909db025e", - "0329cded61b2dca27216b61efd55140b36be2758b8862af6fef157a30110c87466", - "020a94832338bc37fb6f97d37ffe31d1da3ca80814fcc0875eec346487de1891ae", - "030a1d915e96c749bbc15afc93acc1b24525672d097a35d69147503266829cfc31", - "030a1db576d78cd93b0a61112bbb2f6dffb789b0f0cb0c62e10ed2459cfc6966e3", - "021bc389f171e1737796163fdb657b05602b3ac3ef9d0830f28a8d6dc185644bb1", - "0309eeab2b1a657b2ae0b421c9c624c458cdb30efd8e4ba57949723d93fa7ca121", - "0313f4ff19433ae89dd97bc956d6826bdc891a550bd3ef7c48fd85d204147ab03a", - "0327a50fe48df2baa20f53ac772a858b1d00c96248348a8485840fe8ff2fd3cf2b", - "0221267270bd9d9446a41ca83d5381c268b642806314ef89812a87b3644b460a36", - "021bb0e72f1504f08e00456f9565cf01a30a179510f52360dcfade28af9e890f12", - "03063b1596376e1ee334c7b9a5862d65ed0b0cd7edfa787671e24cf33aa09d20e4", - "0310416a0a8ec69f56e9508a2e03d62e2c42ef67045f8fab26f6113369823f517d", - "02144a0cbb8eac8a12957ae2e4680f28fc817b4ac90b944a11066a8289f89ee5be", - "030a6d7a8e23a10ad14619871ba143879cbddc485cf7cbf57577f549c57de7cb4a", - "031957e7e9b94febc4d3b7ce28707dec3dd4c8c6da232e344263763c1f21ab02b3", - "031e66a29a8c29af732a4eba6d648d5cd7eae6254b4a7a14b3e5348a5d430f0c08", - "0207ce2f3af5b4b2e288cefb07fdad7e1687b22ec2a3e9229409f11729d7a05e99", - "02114b011640b0cdf0e4a435909cf63faaa60a415da264c71f7791e0e198921bcd", - "0329ca39f134301076240f20a37307eb0aeb6d2cde84cc78292b1351500b6afb1b", - "0227db0a2c110503227f811fcb079e7c886d75096a43431c7253c7509dc701b414", - "03274d47f15715d8365bc1766e89afb9582b0a6e7f8638dbc0068ec88d433e79fc", - "032d7d909664005b006c1c079d07962a6d5ff65faf4b6617e8555da4fc297a6e75", - "020561d09905e20a580c2bbf7d823ec527de5d87b45b7068d26c8148f53869dadd", - "02065483f070d96b0fdd3afb21b98caf55894fcf23f63671f83ee0027830ba3ac1", - "020d4e9c395e59c2393648c8b3bfa525d684784cd426927df8b4eccd26a234935a", - "0312f41f7527d5b45bf8f0697c20febb4c54e21d5bc19c4b32b2f997d2515606cb", - "02278f7decf2695b3bd7166918f26599b20a859fb88337e91f9451568684b0664e", - "0325f715c4986dc32db113f5215cc474b9ef3c6c61e31258829f89b27fdbac2290", - "030474722299228c4c84d5d367419860c14bce41bb3c7f1f6839fc994842ce1570", - "03219ebe5a14dc11137ebe2dd8b6acab257cfc396eee9241f35c44742d89eec782", - "0227511452a1cecafae17a978082ce7abd0bb870e5dca04892191f478cab54a381", - "0210a834a42795330cafa0f91f3c57b500c9f57097cbc0479257fef221f8598798", - "032a4d8af829f4bcebd5a4a5508dce4477ab61331e75b00818e0508855c4ce7a7b", - "032a781b5791fb9c9c3dcd3fb8552a072666e9f57096137e5f2878f37e036923ef", - "02167851b8518dd0a0cd9d48a158c8bf63fd4773184c0c3f1ea27460d9d73feb1b", - "0227e292f6d290677537c228938801a821c00d190a1edba36d2e90218e09bd7ebc", - "0218b82f6a19d986a1ad0d301f30c1a877098678de54a2a7bc60e18274644ef486", - "0323fbee8f4d13c0509009a88f22ae712740fa3eb0f9b630fe924cb1b4f8e6c8c7", - "02037b427e6f76ca5201607f7354c43e4b5c2bc0e822f9f10fd8be6923c642e311", - "030b5e96ebdeadfc6fb7f919c2c80b12d6bdc7e29c1fff6208e863414fdc048722", - "0226856cdb508d1727a89291701c54845bd5e520821cb7d91bd9ede635a4080671", - "03295edd75630249c5e9cd3d25e9358ebd1401870a12802e503df73bf2940f67e5", - "022baa12d0d7a100d5bdf5ca1fbcbc7beac7ecbe9b70eb1c3c605b6d4ff2e11fd9", - "0322c27889278ad5053aaee2471570b3f29f452114d0c5bae80b5a01d3841a5839", - "0217732a4ef43791d2d699745641f355d09b62ae359f31afd90ca6400fc63470d5", - "022db8a93f22a3b5db0107243c8555b971807c8f981452c7279cbf31c0688cdceb", - "030ee412bd52e423b42d461d8516253c341e7beae897a9fd0df879e1b6bc495aec", - "0310b07eae1e6be15902ecbd312d7211dae88072a301f08a868f803f08c0671a86", - "022ef57a1bd1f3889115bd873ac9fe6f40fb3027a5341a9b0b7effa47c53f19cd0", - "0321fbacaf855eac821f234867a625806b43d304e69fc79259e69ac263cab86550", - "032d826ebdb099489793b3188b7dc0a6fe78f15f3b718c93f365a555522534c5f8", - "03182dd19266c8874e5ef0925a754718c1a4895ae66de4b00cd981278cc4312891", - "030a4cae733d45a5a25ccf6c9fff48c2746752e565c470dc864d78c7042b9e146e", - "032061778754fdaaaa449907f659ba8ace2225b249f6c1357d399d6d4469abe4d5", - "032a9aed38edd6c1c290ff77c5a705958d8abca4e95eaf69b20acc4924919041e8", - "0304de6275aaea6ae6f136ee9849e4489b6f0ac7fd4d57c9623c843482ab7ee799", - "03009ebd7edd4d9412b2df5d9f25144c946d26a5357590f182debb9631736b7329", - "031da0ebddf3c9cefe2e38bacdf958b1db4b134cac71e7105a2fb280fca55c21ca", - "0324dd173d2bc76dc482a3104c01ca64c01ad08b4212290ab3ee5899bdbfae4bfd", - "023017e03021a4bc9ee3407b6c415a9dc051dd5a4f380dc53a45f4158b01f0e4f8", - "0214b55c1bb22cc065cb9f844818db58b9bd60246424e1d2f6b4569f81f50c6d79", - "031773b447114548721ad7e10dcc083fe740c02c622dd07099ac7c4c42f3e069f4", - "02286137b499e9da01c84d560c2d3b1f4fbad795e199a726918dda5d6afa711114", - "020031f1a2ae9e7b25988d6fc20820a7ba6d0dafe9e944af4eae2552dab0ee9236", - "0218613d7d096bc54a4b2725cfdd66eef356db836dc6c198b3eb7434ff8deea909", - "031ef26b9051df91bbba5bb61689cd054788c3aabf925538f45834219ad67b6c54", - "02297909f8e8fdfea23271fd000f2a151e255191a26da8135778bdeacde7cab73d", - "03202051081183e33827b0697a9864170bcd9ea07e21f26a98ccfebee77a5d54c5", - "020c7fde6625af693fbf05c91795753e3807ef2325bf89085b5a32a84b3d7e20b7", - "0203e91580435f788fb6833ec5c4f043c23cba77df2b2cb0352f0f1623cba5ca81", - "031b70bf8f3a2f97df009293d75b6e8a7733cc2fff47eeaa9168b23f3124c7aae8", - "0206bd7025ec06540f5158b11dee6fc34f2103789f9b2c3f8d352b04c0cdb295e6", - "0301c19d7562474519d5cbe98c3f8e7c8db49ebb353c0c8d856f2c9531094b23a5", - "02011f45fcdc539e41092d561fe3dadd301d78a13e1125ea99bb95b3f9f0875885", - "03177f9686c13bc4eb538210737726525dd2ede82e3bc5d43fa23e6f46d988bfda", - "032f42503b7b38547e827e6e17fba9f79ff028a17652d0668116efffd6863b38f3", - "0314e090b4dc5338b9a6463fb088a8095de564becc83ee89d6de7b34fe631332ba", - "021fc65141497249c39235fee7275a2c425b43e229cedc5eede9289c743236fe19", - "0314f6914171b02b0f1f0dadb1f9a796f86c18f3e95a6e16e4f6787d2768f7e9cc", - "03221c97757fac2aa0657824346ffb59ec3856f23dc59c35ea544852fdd80bffaf", - "02173e628b08a56631770c23db153036afc7e477a2a4c739ca236c3451c961e3db", - "03116fe4bc6fd8310d5d82f77a293809a319f7106e19dd1c131540d14dbedb30cc", - "020f821110cea9b78b185b186c324905271e6c5d1a8096de24606ed49b3c641f56", - "0221eacf956d64292c2df3b2b8f68780950241bbe01540dc3d6ba5190337a9a9c2", - "03217e46cad282b358d9defbd91df61da901f0a2695b9e74b860f6923e541427b6", - "0322738e2f7ed230f6d0b196eafc6de49a2c72fa7db9470cc5e26f5a2caa04fb3e", - "0314f0732af14d324a050c72cc08bfdd45e18db835cf300a4cb1a7c494cd3b9ef3", - "0303635ef9900e94e9f58cba1e4d4a42865ca3a5b678a65d9400914a18a141ed04", - "022106cc94e6d19696fdf2655a3717e89b2631dc779978343db4201c4e4aea9695", - "0202c3e2956fbad7a6428ac6881a5dacdffa22cec46773586ba8879e4c97238556", - "031f84e3f1ff43f2de6928ef02ba10a68d4ca1b3f5cac12e683f4bbd253a5afaaa", - "0321492a873b42720961169e4a55074422e08593a17f72d2340b3836785ebb8580", - "032e9debd83afaace9495ff43c6f96139165b634eccd0e88e5f78c16c81991d655", - "021cfb251983752f27575693ba135183102b874b965a7e2b43a1d901801354ded8", - "022812083940270c4b3ea2d9af273a85645e84a66ae61baedf9a6584def6ba0c2b", - "02274472aa1e96b380fdfc06f0e45195d9b8418bbe2a8d34fdc33b88ed47e64167", - "031020828a6da9e9b1415eb24e9ab63ef8e8955a99f331650021a3f76d9a35d759", - "03199dfd1f3fafb3a63bf25bbfba4601b5bbebf87e2fd2f7b15cc30add84ca1da7", - "021a2f21469ca4502d23fb3c78c35805f141dc2861ee5e64d3771d0a69079a4cce", - "03018dafbe7e0fa91d4ebd827bde4c023171cf6fac5e2e95ec2901baef1e184b15", - "0227e88d9e0c3e47488123cd6eb5294da36c19ca2e9f573a962439e247e5f4c2b3", - "0217ceee8a19cb2e8485fccfe34540b814e224788a398300f695b3632979b1adf7", - "0313c2ef421f1e74a384125a8035105c079a63fa2ca3ec38174826c3235be995a7", - "021e3425522652a0bc968d6986d6a5919fd930994d6305dc6ab77b9cdb6df4ffea", - "022c5c2af7bcc0b4335918b563c2396ae07958c081393c007790cb67a357e38be3", - "031c6ca7f988cb1641dcacf0f37bdc671dda095d2313b031a5821a42cc9a901ee8", - "03142b69e73559775258534c70980919263f564093855a56d394a1da58447f6761", - "0208578cf1c5f68d2ccdc702077d8703969ed637a29e513f8e73ba72446653a86a", - "020a22604a4b082207b5a95d637b252760daf9af88c63a6846972bfb9f78133112", - "022d7c0663ed1e78d1ffffc95ca1c0279f90a3bb36a0aa75d02312ccf2234cbc0b", - "021565262f4b000f820724f6c5bce41e4a544e9ac51882ecdb25c2da5297f87cb9", - "0313b285716aa10c6b5ce792deb7171f905c7f4dfa7091effc5862cd4a3aad7f7d", - "030884114879fa401303442aba52f283be928432d709ffb666c60a37e2a2e6c3a1", - "030f92865b8e563dcc4526fa86a2dbb4c4553819c6a71f30b570af002f88716515", - "02030413207bc0ea76427fe7a5774b862dbd86ead52304f250355543e6da4ab836", - "0315f7319af2b17230f188e9247c4a0f267e9b4bd86fdc73ef3314e24f9168307f", - "0306c678a78461b9218a1065179b3d118aefaae6defbb731b5cd98b1b594b7dfd1", - "03283819e6b62920d7fbf0e7a6df2a3e5bbc01effa6bdf907248e98d1a83031367", - "022a241b39a1c592e1e861037e8a137fd3557c866657afcca59f380ee8b8f9efbe", - "031ab04332c806e4d14227729dae75a75d018c7fd0c1e7209b4715216586c1b5f6", - "03137fd0884c9452695b8728cc73bb139e10a5397e7c28e7c5d7cd9e0a1eb53b50", - "031dbf0acbca20c02b0d545e28f39c303a59ee29ee951d5bd1096b56eb1cdb1d76", - "03296f3fb1d4bd89f240774f2f0c246d7ae93decf555fc72ab34465919de0aa765", - "0329e996a9f8547513dfde7c2e8e1900483572b5f9443a26b03006cb17d1ad7e19", - "021b6890ee41027106e71c071a8eb79689767097ea5bf2581886176549129e62b2", - "02121c99c492c7d538b133e2a826b90205c580e8fb0fb350406e6cfb375e49f845", - "021c6622b576b3647ce84221adbd825c1f727e62b1e2784490562d27bbab5c81d1", - "022de46f6d926f254663779cf0b8ea46582f983f9b54bc6783e1bdc994c5eaf7f5", - "020ce19f247719a13995ad7786449c58478d2e591f67d551d64b7b0d20efbef080", - "031a7368034dfed6a8e2ce4ab16c73b2bc0193a4e2d3659c4e21a5a4f3d22ee4ec", - "021c4d0df7380eb06f023cbc405d4d7d6fdd0987a3629d4deb9ed4f2c39282b092", - "0303f4ee2316bf7de512a541f207872321878bab0780e1316911bb27bb2ae6b3d6", - "030a8694fae7908e0803e54a08dafa0d12f72e30ef32ea8476511d3ad6df9cdba3", - "022141dd0d9471390f597fe9cabd254fdb02fc69d895c9e1a50c1605e2c692fe40", - "020d31fafb9011f067e2bf9d4ad9f5ff3deeaa6d355b92282396130c039cb31833", - "03254564d44083667da80feba4310d24ea814ac71922b0bdd82265e3d9da960b03", - "0327a472a100f73861e8d859cffe76e971f5df2794025731443e437834d86d6b8f", - "03095e26de84aad3862f6c5b52916fd18c6617a91284e4db72f14b8fed8853ab39", - "03060dcdf2df03be7071895411d51c33d20ede50caa4f7e440a2494302fb6d9e9e", - "0202e696536c180d80a84fcf5b72f65dbb0580e427041e2a0898a14890aaeba879", - "020b5ffbfd086d0aaa7e8912d89a1f9b454302e44a8aacbf8ee7172b4057611786", - "031bc3c8f568c58a967b2fe7675a796c71ddfca32c7d88509124aa977b1aa6a91a", - "021a722007abc27a9c1611cc7b873cddd86dc7d400c68022dfd54bc17599326336", - "0311fe2da9094b5d955f814dc6cb859bd7a9e2b6cf5646332856897c4dc05703a2", - "0205e333e0f6ff06a05c550e1d4d4e35644d741f12be74219cb59ab3efa856e58b", - "0202a282206174ef041590cb53c343855986a851155a6bdfdb6fadf119905ab1de", - "020fe3f85775c2da8e8bfcd7b59ef5e75b278a9c1f781916059e52964c8f9cb759", - "0220250e640f1b8f4366c09c23714a787e77ae096189a0d0dcfed3af8d68de88af", - "032000faa87cc6feeef1eed0c950b3a487896c435a9bb1dcf38dbfc01fc608f3e2", - "020eec0db7a883c6332f5d465dcab2d5319bf6f1a3c59d536fa10f56e021ea05e9", - "03146aac70a8b27b2cb516293617fc4a955ae12c2ceb69a9fcbfab6425973bbd92", - "0325cd0ed7b1ae4556e9aca69e0793ca8f07645be889e31962de2ba003273d5ce1", - "03023627b9e95ab0bca9f6e4e4eb19820ccb48b7d5dc23ac2c161647304e39a7ec", - "0320533f2b80790aec1da4e291483d3660f917cb1b1cda8df6226c59e5687b74f9", - "02258d4e8fff580c39103f33e0c77604c0aba4a4ebb1e1f575bb2661e1696afe30", - "02160d2d255ddd6f31f56a297b2ba80af4dc819b31e6762b5a65394bc9245c2f17", - "030fb9372f24b351055121dfcdf8146136948b9f782b34f520fff11c8493c9d229", - "03083c1562324a1fb0aaea644573f134cfa71442f0064a714857c105b52d606c8f", - "020c907d993366ee9c179c4c6207ddc8a2570b4daa1a34b0b2edf68ea0324e3dea", - "020b588dee17e094de80fa55353643255a3b9bd6b68c54cd3e9e971cb6872daf2a", - "032ac3544a114193c3bc938bf6407eb3deafcecb93ecde3ff4b05c0c573ce56c43", - "0220f300b3c0efc610e106bb9d90bbbce9aa929ead44c9969a1134da4203fab706", - "03121c86c1c71b77c27aa870e21077b58cf64e9375af4323d737fb360ade21781c", - "0227b39208fa52370a1442b1c19c150f97a0db5f1863aa5870b670a282a94d6536", - "022c98c07fe2f907800e878ca210b440c9dbac95f7dde2fc14e3977b2147d29962", - "021acbc6599f73ae90f44218da095ff6fdf40743d6a90180ba7cff7cfbb3d40ab2", - "0222cea9e444a01d3e842857e4f3b4eee4fac0e6279923e308365dbc40743896c3", - "021690cd00ae2a3801db3ccc626cd77a7452ef65aa2b63a65f9f7030f16784073c", - "03192834d30e4c4ce0e49645b2e177b0187206094dd4e1fc766ebad0f41aeae4df", - "020cf7dca5987165146aa8f8ad747181eab343fa18d12df4c81ef4a9d802c01b74", - "033037fd51db3ee3ec543f4eea7f76dea20f24250f75dfbc9207bec7506f9a8396", - "0325f7b2b991a71b5f9bcd92dd3ce9ade40139b2dfe1ac517d63ab5cb708b3525c", - "0306df625d894efd7da9238f86ef65adac7246e00a4e5d23e19026cba870790cb8", - "03045e15e90c79e43a3c700c3d4cc3b7cee574e0b621ac2524d92f21dcd86ccb9b", - "020d8ea0522dd2ca1e3d49cd2d44f348426ff22ea9da8ff8fb87b8857decbdf42f", - "031c96011dd69647f0da479d23240264bdb2ad0f2a5f507a36050fc6a3d051eaab", - "022d8d88bcb0c93c6d973d15e3fb46aad173209e6ba556c7b4723f2722662e6120", - "032818b1993cbfcc5f1c901971d648af9f405ca6ffc3f68b119ac688a4cf2dbc18", - "02207a0d7fe33ddfee9cc4f6ae96a47d9b964e0c6d37b41852106f19bc468d74ca", - "0324efa827704ff6bbb509673e52f998afe5ed7bf109bd1c19e83c787d302bc857", - "0318559e57d4b4c1e57b558d769a81281346e861ab04dcae4a1bc77881a651ab18", - "0215d69b9b49fbacc4b9f352b7c29dbcd9c561d25237ee95f76d66618ac225d542", - "0318bbf7fca13434eb480d3d3390a54068f7ba7acb35755d13b55cad45b27e3ff5", - "02012c6e62e3b376797f3433e495a4126be110e359ad5cc6cb24163f3f7a1bc620", - "0309b82fca50517a414012312c5f4a74c2a788ddf25428787e6a37c1fae7c3241e", - "022d6a148ed17545fd3c4dd05f3e9c2e46dc8488cb57da10dcc9e359e890fbb755", - "0209a342c871da0fe9c01202d0fd497c4337c0e90267472751e0a22e1dc1845163", - "03193439fd62e045ab87b20ef6fcb35a5d266dfc1964a9a645561f3176b71f40d6", - "0225995df0f8b57e5fa4c9be780acb5a179b447ed5a579cfebca6eeb562304989c", - "0220ea052756f7c33ade6fe4cb809ee322250174e3291ea0b572aabe07d30c4492", - "0328b1e5704b609561ffc58948671530db621ec9e92c204ac470773fee6ea5899c", - "0206aeb61f0524ee7ba8e73092ede320ef5ac3090d393399453ec56cdd0012c263", - "022c36582e8eeeb983a391f782deba5b7f4de5bf458d202e1c67901ad063e1e145", - "032e125bd684379edb78d21c4d4a32ec7986e01e237d1d2759c6d71c3ed5e1aa66", - "032c8314d448548525faa94ae2fffbbcfebdeda3f3493833c4e04f3076b3d0613d", - "032c872355ebbb7995708afb7b5fc75c8cbfb7407ad2f92d6bc75126166f95f34c", - "021720ae6d6c66783c19c9cd2f9440d46a10634088b15946b70ed707022f16b0f5", - "021525b67b33317d864be39da4d221b365330a2a41bfc05e303b0c6056a646b066", - "030d95698b974adb273089f01d84cf6983667aeb6868a01c7777082e0cbaebf240", - "032c93bf50419bf4f0d92c3404a32c197f7119758563cf406c3e79e4be7c63400a", - "032ca1259b9d833f45d1e765b2bdf0f26c420004210dc5cf0fc48f0dd5fda0599c", - "022686550e4e0d46a06fa188b615b93525383ec258f404652d76f44c52c12cc46c", - "03293e9628629576d3d615611659abbfcaa48f7e56dde38b129e7038aed18f89c1", - "02115647aeb6c7090162ea8f91e194644ba8f24064cccba35defc702197205341d", - "0322a8af4dfcc420eab108f9e1342c3d68b1982a0c32d7a7537451ee799ae25d5b", - "0312a56bd41f0e02ee6f99fd4d2def957ddfee4c8d69993414a1cf9c5062a79b49", - "022b89421bdedebf67a74cd3d5e29f54fa19a18899dab590d22981f317aeeee687", - "02184d7fbda316b22b492a3f4db411db065b06d240e36a8a07f597581824963a25", - "0306b1ac3ec62bb9184c44e4a70c88a65c0c17afb4c0d82fb5ee40e005b97d2fa5", - "0302713e20f85bb25e19a43785140b183d82f67748a0b0857de044c9943795c608", - "03103f5128c09cf9cfeff35cfa90337f84ce339972a58442e363dfd0a3d43c6d7b", - "021c8a338eee574730bf6464dbf5330eeaa1fc0983cafa0e5d6f9191b31499cbe1", - "020213674dbc4a32d544b59e06c1c1cdb0a85fb6240448a740d320892f79e42ee0", - "020a2c271d4515d5c4d4fb1a86d6d9a985c258e4cf993515b67557e6a8bafca2a1", - "021a7c2980cb66e0d1f90a7b8f8311ae3803381985d7b14aff933df8cd39585581", - "03219325be0b7b691d974daaef668f9876776526b3941937ca389757db1da59fb0", - "031c2ea03f7e95ee6c6cfeeb90cdb70acc16da5f7467712f5d23be0e2d911615f1", - "0209a9a963b102a9258faa9c3eb149dcfca633a7053cb2cdcf5f2d452d25ac93cd", - "021eb16d1e79cf6a8bb23f89cbedbbb5bc72d59845609de875f0f728f5de841d69", - "0227fc64e7015d5645e9182c009a390c817bbd620aea0669ce893f37d58602e59e", - "02283e771ad4c0fed7225dc689c1c9075754b3cb383bbe0292b6b8574a08dc3d30", - "021f9fdcd5142a080ca3aac51b4a0c6b38a7ce5bc7aab51895b8a8d25ed6ed1ba3", - "020a9354b5fd992a83b3e864d3beaacc723937ee9bf9ce9408016880d2494239e9", - "0312e853c481bfeb3c52c5e0e5d96219b382b96db84c3fa89dc4d42994ba88eb99", - "0226bb2dbfe204459b64eb6786d1afb2f70a9260a9b2fa74b30b2ba72a12df36d9", - "0208868905316151573da0fb53434ba9ac48eccb9390e5392047cbc3c4894c3586", - "031cfd4252c050da9e103d838279ddc677af1702782df77434375148f27af876e5", - "0226cb42d4161b60caf0db04c49b67401c75a59ef013df933ea4c8a06801af9406", - "02205c958393878228e961f54bbfdc346fc02d16d972d14ea0f8565aee98f85eaa", - "022821dc04a7b72b03848abf9202e534edf3003f79f54cf4ff903f006235868169", - "0308ab8576b6cb33f98de725d07d659a35ce4a7b18ca4f983a171d2e7dc257136d", - "020d2732f247f3e5455f625bbc6b1a70e352340b8cbb76dac39697883f0c9b3d9c", - "0312b65741515da5f6a42cdade04593d92c84831ab97f1b1fdb61f8c0dd09cefff", - "0313398b10d1420b883c3c95e25278928037bb9684a7817b7f30ba51c277083ffa", - "021864e99e582664a8dde335b74b20437545ae1b241328e64f1f22d7004782cb1d", - "02275b834cffc0d012f33d09071e0fab97268cb33e8e847a03b1a1615cc90c3f0c", - "031a69feac8ee898ccb4769de98d5f627a73288580ad2c7f8109eb9e2a4f2019ea", - "020c7309af3c7d9d3bd93876777a5c0bb71d86b147bde3f5001f666a46956e0a57", - "0202c6484ec287ce699c8718ecd61fbe805203f341898093936db51bb7ec9bd161", - "0216409d46f35221fb53675b3c14f311d6b827ec100fd4029020d2a73cef97b21a", - "0312422ed045612410b0c71ee520fa22511643484d109be8ff17989129c4d98173", - "0210f38a0123e20d5ee128ac7443530346b942ebb86f12caca89b3fb6f8cca3f9f", - "020f1c889de97fd39613f66c4e8e272b1ec2f55ef54ac3dcd352d99ee350e41f90", - "030cc89bf4a5d0492c2163a0c8d6302c56762c6b6cff30ddbc40fe7a1850d3633e", - "03286669d062ea1e4bbafa4c535d038ac796bfbc2d829230d8f7f32626d9a6e910", - "030730b8d6b956cacc357cd823403dd6651ea1e4521b13d5c0a7879d1d94812474", - "03223f5d414bf7c8ffdb65bbed449a0d535e1e14da48942fc445422d79910af879", - "0228d52b0a48aaff53241a8eada8d8c806ba5b2962c65f9218d5e027595977cdb6", - "031e4c4583b03f462b324cf580f1fdccb565996a915c9fe96085250ef6cdc3ed79", - "030fc6bd6f169f511b80245792eeb69040a111bc4015db73e7645a35f7ac9248a5", - "022c9a72576e7f05b0fad87a46a1bfbe3d5e61cfeac8519873c8fff747959ff948", - "032927f25477f2f8e49bf5b9ed78a09e609a5eade5410fe67fca11a21dcf2d257a", - "0204ddc1462b13ecc06fe3d1d05e42e118debabcaabfbefae8d349c4d941b9ed08", - "0304630f5e317c462144d5a145218f0b9ff62d93062251cf0a6caf1ad1fba4f8af", - "030c555bc837572587c4314fea06b17a211058df53224fbd0ccaf5c868e945694f", - "030604e3981f646638af0d70e4d6ef6fbd61d2e8a07c1c56088531448f83b9fad1", - "031a2abd6a25967efb81574d7a65c227cb87f2479fc2e7c9017cd4ef6c89db2ce7", - "02225d99404da09d70574a220c9d6331b88e0ad9cf520f178a7f122ae93ba04479", - "0205353e93c42b9cee0db82c9659923214b22ac2be19e96f4f0429fc5a027345c0", - "0219ba1701b890e2da3afa07cafbd6ba53aaac0381d0b521216e03faaadf04f6f3", - "03214561ccda40b8a64bab563e52232d0d7948ca62d5b3b06cabe7abe88080e331", - "032e26cbc1da7027c155f6ba68879c03f5750b6033dc3e39a7facf6767e3b0f340", - "020e867382ea41df4a406dc35957d17f597c3054f6e49547fea0f219403c73b1c7", - "02208890c1a6cc404044a05dbe5806ea7e1fae0047c3a48abab2c3298e7d9f736d", - "032a41329c83b5fc6e969f02bd071dd59e4ac169f2cbe6b26c70e0575af38ed078", - "030e4dd1ee808f32ebc569ef4fb9e6b31da91d58b8c437bb645078422242f4cac1", - "02246a065e98e1142a22f7f1f7ab900fc68f47b495154e2d3e2e409973725f64ba", - "020ac8e7ad83449d3708319344e38b8f7088df665e524e832f99b1a3b5d07f10ba", - "03262fd2f782d76d90933103cf30493dbb265a27293ae3399992f0305a44f1f893", - "032e6455302889d5f64d6e98a896869c15a124bc6a5d4ba75f742e0d458a7c538c", - "0306b687faeca3f4a2513aad1466b0fdc893162c126b23d302a6d747a4d8ddfbd9", - "032d6f5aa9e01db6b7d99071a4e6e458e323c26890eb37a179aac3242398d39745", - "021d68c74318344b372440053e71c594f9236c20e6acefd0f671834d8d3a6d1388", - "020ddce58b9fdab380562e1af51287c15b7f74b96009c29ca66c0e1dc0d0dce1db", - "030ccc4138b5ecacf36b1ece1596bf47f9952eb380f4f17125429de6058b6134e0", - "0324f905c1fee9b91d75d8170ace6c746112df3c7ea1239355133b9b7247114e04", - "030ad01b4444a8621b46abf3b2e7689e72ab5689e52ab452576ce19972ce9a54f7", - "03067caf0539db906653085bd3ecbabd1dfb4f2470be2b7f34723fc63e07be1314", - "021c13cf13d274422aa0673c122e3dc9cfa25f53b21a97697502849eaccb9c5e4a", - "0222de3a435db7c4c9b9603a2ea53bdee3558a651a0ec56596331840ed55c1c13c", - "020a95668183d218fe2311ffaffe9e7ce16f150db2039b16f67b5a35e0d05c9eb5", - "030fd0d8cd0ef769400d16a84eaab870bf96dbf6f7b82116d9635fa90012e8f113", - "030f74de74b91fe20ef305bbda8d0e4b0fbcc2e0cb94fa19606617298241a29785", - "021685462e6fb716e78293d87eef8160fee41305cd6f34e1918928389815057757", - "0222fdd281e0d6a19265d2ee8f5af450edf5175c4563c7af5dfe63ca9709d733e6", - "022da4ff0a11cd9c2eb423b0ddf8597b747c6a21b1b545a9c35e50e0b0292e7d7a", - "021e7dd5e3e725be6b66a9f72e68452ae3846d8f9e13b2a676000d2498f517f066", - "021da712bdd177ce7d4e8aa06c2e9e4dd36f45e44e9d591c606fcc6886db79173f", - "022fb13ee0891b633a4ba8691a179979a2a6a4968afc802d0aa7b420c73c243cae", - "0326b7eeedfdf5fe3f34684265bfeb8c90b598567af5c3b9e087ac9f6239d8ce77", - "02077b145b941c4be43f846f81720758fcac1cad5102b8ad940937f834bf33fd9f", - "02084cda3bfcca9e22b59e13b6ad9292e961bb579d17068e8dc3418a7794123b14", - "0223c39294f1b21551f554f96ab4a41f0ff5866e34945c1b4ad86727fee2716882", - "0321469e6a9e9a0bd5254e3525d609293877af1ed440d7bccfad4c366e14a76ace", - "0230178cce01e26f95c777736fae2bb7a8ea823ed5147efc4b5792079bd1d4d10a", - "030b0219975c85c4a5631cd13a80afa469f699771acfaabf3e5e1b0a452f9bb864", - "031a760dbd7e59db059569a800b4f588f0666b574a1c5b4f68b9308b555b63694d", - "020fa6aa54d75148ee1165905285f03cac66f301feeb2673959c125bd2971b5012", - "0202c2e2260c20f5b526fe2c9eab6b689609205d0f88293c1bfdc9d3ef15fb9521", - "021b9e9193feb84e995b4bbe4f8063ff3bc0a58c27c5f33bd6a48476784d1e901d", - "0203c0dde8c39137f3f840a0bb1c241ab8b3ef4077791d3e5aa92131ced23510c7", - "0218786cf7e66c31d03825153959c6a4f6a67fec229dd86be9c07a0b807a711099", - "0323dc5f51f391637a5d0468ad845f9781ca473ede2eec37b0b7b66c5705d63637", - "032b620f162ab3aa4942fd002c365e76fbff48f3c9e1c6f145f8097ab1e7a13bdc", - "0320e2d7e8ea0a33078d5c4600477ad0ae16788fd22996c1ae08b31e5a655ec3ff", - "03076657a2f5fa9fb27a66b3488155f124b57c3b1198e2a8b60f34c383593c9113", - "0218c5053ee59762b8807c48f7e9009f11f82f0eab72a93fc4cbb3ca0dbedc302a", - "032e5cc7bd025f7f32f7a2c6d2b0e22c0edd675eefe637a21db3e26cd6e2190d2a", - "0318202c2040dd3250ec1c0cef4dc2efba589e3696ab59644e44ad79d1722e7740", - "0315459bf3d95882f66e1f6cb2925ed20614a82cd04e4268933e9f8e21bb39cd1b", - "031cda21f5d8248794257b1abe253884f2090eeaaf4c1eec0e20f11010eb5eba2c", - "021668990896b526dae782825c5f79f09c6dfc8957266945f81c844180ad53edba", - "0319a1253eaa77e5997f918b32da23ce40180f77ccb0b4b70fd821321d6fc7feaf", - "022c3217696dfa6b65fb6dc99b23edf696771231de700c5e10e239737769ad9193", - "032926c524da91f8fedfe6bf2a4a2f7b5740e71b1057814f1900f975d491283ff8", - "02131f0224571efc87d6fd5e60e09063617239077c3a874aa16a9fc22618868de6", - "021e524e9b4ec8958035f4e0c11a41d0854d69b5c72b7c1456c097c646096a279e", - "031c99d78bdfbf7cb835db362be02232c49bbb08c951aa9f4f5abdfe1407154c6c", - "0303fb0db6a20210faaf70abdaa3b8653c00cd2a91403b014d047fc407096d2ded", - "030b7858b00dacfcdb1564b64b370100ba04b43bd596d7d2ffd31cc44e8eee2032", - "0228933d53355fd59cb7eab7e5bc95d6fc19719bb7694422a0a8a1365f33644b7a", - "031f7a7f7ebccca017829fe6c8f848df86282e9f6b68449816f02e87d90609243c", - "020c577ace5704906b330296d623ec367a57f78aa3732aebad710c297f93660df6", - "022f4f655382627312a263602bb6c672149d50e733c94a371285f4adb3ea524673", - "0317c852fa895d87f84ad3623c5e571bb6fd285ea95dfdf347e2d8f0e1ad920c29", - "02298ae5aa04b42616160b27ff6813292b3e92dd78a27c77ee99df5b34cf5a93b0", - "031be5d7121a41b1fc178bce8a220fa977987be25785c21873ed185758a6dabcc1", - "0202b7176d3dcf865cabce633e3ce37f9a7bde8ef6a263a9f5c2ff0c2cfe00029b", - "0319e48300b6c1f36db6162f921229c2be56149756694b6d0cbb158e028292bc75", - "0226e57a0ddf86a5a6618db908b005f9bf353f51c7c09b519c24f4d72d6607f38a", - "021062a3250b6827fca175752e580a249b0bfab9ac0a43310accb147e0efd50f62", - "031d3492a50d4107180078434050ecc70d0bd947b7fcdc73945125782baa9bd0c6", - "0314d66bd43ba84b48dbed06622cc06ea3ea2b6684215e08e33c7118c9f79a121f", - "030b576eb60353e309a3da74356609a1271131907f6becd95d128fa58255fb24c9", - "0208bb51b007c401bc7dce4398f3ead5d5690e1f718665c92f5e26ebb8e8d0190d", - "0305f483f6cf7d23094f37a7459b3bfaf17222c6a720f36baf4198baef9f121c31", - "030f305d30303157df4643a765eaf5f385c5e7bc5adc3f776b27a7b217536b4fad", - "021b30c6ce98310fe68f4c41851de21cb97e0c127e7acdae67e29920c35ef24ccf", - "030c86a04992bbf36ba2727e95d58f986ee5eae8d43db03cfb9ed3d8575cc7efdb", - "032518089c9653862296633ec261a705d1841dde4c72bc1aaf753253cf0779bb08", - "031da8c3fdee08dee61997c1f1c06bdeb4e5c11da80a12700fc5ae47c470cf763f", - "0213833998ef9f878a48f4462dbccf9799710bcbba329cded567a63b8092fcf6ae", - "020338b99cd79f6d156960c1b676e7918fc9de0a3474320e91623e37324bc9691c", - "021c530789f89f6a964fbb0d99fcf64df94adccd944040972d114ad08b3bd3fe13", - "0320a9f0499749d63cfbfb7c6c8015d8862d90a6640daa25b9088d7f3e0eb22c51", - "0229a1e8f89a7c7463e33031f617f4162b189d87b717aa92d8b3eda21190eb8897", - "031e34d681b05093f5a04f4b5b37caaedc9389222cb7a8051d9d7eeca339777f16", - "03146d20923ceb7afd32d247d7d5ad55a37dc3811717de617b9aaeb252e97436af", - "0206244487aca4a1bb49747776786d5e6ed89d79741e420117f527381c38234d4e", - "031ffc9478e0c5e1e3daa5a6c946a34610948555af73a96694bda0cd67ae55406b", - "02040bbf341adc5f8e99642af8aaf103decbf56b626d05da84c231e26d6466d5dc", - "0314caea7b4766b9d45e67bc9e794c9e65944d84783d414fd31163419887dbc0ad", - "03064678bfa83d8a49bd3983cb9d6a8ddfef32a393b56b318b51ba9ab8bb1ef88e", - "0200ab245013c45ee4b77c549ad88ee7caf59494aab59f2d9da6df4ba6cc594458", - "020a8b71a73d67f37e9b19a927779f5dd6a178ae762b02ad3c687e38cbd3eed2df", - "03281bf8d01911bf4e815b542642810aaeef5a737ff05a6ede9f10afc14b6e32b8", - "021c52e8fc556d47d61a92c274c74c1818cc0de84e12ad8b6ada72f0f984008525", - "030638cc23e7968f80e8d8dac76ad97085edfda69e560bea908672391379c45eb2", - "032f285b1940b528d6befb450ac8d9ea1ce09a85da1ead1f055356a1b9c086e473", - "03076d4d5bf2a7857eb16387c911cc11516d737e6155e2739a76bacd6102740c46", - "0205cecab989fe8543cb6dff0e4c2fb0405759c58a9c3ecbb7347b265e34c34525", - "0327b36d396d1f6298c66f934e9a2f6596560f37c51fd0be1ac4e9565470fa8845", - "020b23d7b50a38bb8fb21039163895e355b7de8c3c7c6f039a96ec76fc11d8b043", - "02179da701fab5ee8d22d7802c04c7bf1f0d30b9ce706e16dad85c6000f4c9f4d5", - "021f1ee6ae8f06bbb9ffbbd1137e0ceb9aa9e73d3fd89182819dd1857b971d5810", - "020fd9c381f05c6fbe1f83f38ea88520a67842bf5edebbdc5c3dedde63ac449f49", - "031446bea73ccec48cb343f6de589e7dfda3438909d87e5598a2b2f1b5b1aac620", - "0228105dad950f769af190abd62ab24d35976181a4809a6dab41b8ee69ba1e3675", - "0201926875fc9645affca8df0b8f5c7b133bb864b63b5770a0546ccc00c0eca7e2", - "0309517acb1fb9eb5bc92fbf697752080dea4ade1d9bb343c16eacf0b87c246b81", - "03006efd0938310f381627aed57a3825e27180ee369f538a8976c7d99607cdde57", - "021a9adc4154edcf42743808ebba6fbc848eb1b48f708092b2b5f9f81981125d77", - "02299efbf7ee2415d019a810b6ab0eb4dad9d194b7ac6f9d5adf61151ee631f75a", - "031de87e85a57529c315b1fca6299df54322dd3369416ed7a02e58ccfb001fc476", - "03094cf74284f477a2e4fa00a6bfa6c098cd70614de59da9e5610472b2643b0bf4", - "0305da185aad019ed50943f6bb8c71bee9240889e11efe0e7f1a5561eccf77e95f", - "03155df36eca25e646b1a80cf15ff1c070efca057ed600ff8342197bb9942a3f6a", - "03010cc8374d775f48f5e7b782a2709dca56467cfba7a1a54d4343ad5470b346fd", - "0201e6a01e6e8bbabc4c6b2fec85ea1039eec67e07b2c9016f3b2b3883756e1eab", - "022bf1cc7aa0d5536619d492b3ab5eb6211e5f057a25c4845ff5e5f7092c878149", - "032fabc26081bfee72bd0c40151334bc935f19b8a6b19c774b6e6b9a6faaeeb27e", - "0210864e279895ac3a2ad993eb9c2ba1f55e69cab149284c4559a6b22805185390", - "022a756f82950b285b2440b12f159b17926e3ad7ec5f0bf0bf7520d416202e82bc", - "0203290866f04301d3a01df288933b2205a0c441ed07ca9b19262e9a820c1adeb6", - "03248a73fcce786b31a0e2c16dff6005ed5900bfec81543d23d1cde901b2e92c8d", - "0327560fc93d46d5c730bae33d7f21995ec932bfb2696a06cc280edf6267ab5295", - "0323dc109cd0c7d90fc2290c9880e487e4b35555420a6dab59db3d93ef60b3732f", - "032328e65088e1bc730b0fe0eba626d646c6b0a4227bbda41c02dbb5e8c0e8989d", - "022818c6ed5b781f10eeaffad71ee85118aaa14b8045d06d29dbdb935878c13c8d", - "0216f756d2539c352afc3ba6c35fcd0243308207e754b4ce4b481349b4636457a6", - "031affd182f29aa2f044a4ff5ecc813020b3c8d461376bcf8dbfa4cf0b4cda49d0", - "033002b16265d1a8f515683080a987932a081a11a49ae63da96a237f4c31782eb0", - "02134b29565c7f1415d30203ea05ae3155f330f8d6ae580080f6a8a0e8f836b5a0", - "020d04bf2510ed078dfd53f955cf2bab3346ed0222454880b94e68d0e35a9a3bd1", - "0211c481c9bb0ea28fbcb22fea737627c25e26bdb56dc27d69f448a8ca6d68decf", - "020a67d0326b2741a42686302056be9d01c6e657c9392c0af5ca052c4e948c47d2", - "020eb083d03b8a50e5aeeb8e2bb366605a61b05c2ea32eb7e867ef291342125807", - "020b8a40625b1f38b4d7a548bc5f7dd3c0f4b8d52b4537f3c304f2448bce59256a", - "03231995d108cff6c5d03aef486bf6f6cf0a11cd8d6ee11c340cf61e409d5fa821", - "0219fcdb1624c7dcaeea252bfe5a0af1b1234eba1c26413bad9813820dff34459b", - "032e21c2f5c63415cfc911873b846baf74718f33c4699bc9e92707cf5993b90359", - "022375bb3eaaab0b9451ad9926f3379754139e2ed751acdec6f3c1ec6a68490a59", - "0312178f53a1297367075c625eaeba109a606a3a2b2065ed8dbbd4f2c95d85db7d", - "0222775f33044816a15ee4734e662bc1827c668b5163a13a153efc66f00faf7d38", - "032332b9eae445e404975c2b77f853a49a41abf4a5570decb28936a02aff6d1de5", - "031d11941b115d7599ed5fa31a2e65fa776ea04d2e957dcab6209185dd94604cc6", - "030851a8dea8a80d094970792b2c00f43eaef65862e21724223c3cdc21e0e5cc10", - "02302dd1f829940f7701c675385ed0608796fad6aaf005b8b5f681aca65f47e7eb", - "0219165a8b1598aac4c83bc62682e146a0cc4ba16440fa802dccacafe5ddbf36cd", - "0312d2eff8fdf9ef04b6bb74103e2ed29f9b0659f4203967837191c366cc7bc7bb", - "030d167cb65bfb8ce1974747049c3a0521beda50457858ddcd239abb0f67332008", - "032a4238758909995c31e67b70d8bb8cfc02dd37fad2f6bf1bf7846774fcf4b0ac", - "02135534aa067fd404e0fff2939580be86882c3119f58b88c0e030206c484b9fee", - "020cb757df3f009aead37c7df214b24ee2b835c8c0ea8c2858d5287112d58e0d55", - "0202132ca97edf664c8cc63289c8932071658897124d74829190d5cb61bbe50fa0", - "032acc8c563c618f3e15c38459309957ab2c804a8b6826918846a6b3a766541519", - "021a7f712a6ec6d7a1d2be21d354a0e54d16b101d4266d6bd633bfbd5c5494e6b2", - "020fe90947ca8059ab106974a7295fcf54ffc937a6a6dc9e324e92d10d3b88fc65", - "032484ffd484f2f302b6bca55ba92f20158de79e03a983c884f4b6dedf71c1f592", - "031e47193d1b4b34be79ba6c4128dc047ff7b28e16d3283861d21cb1f0a8646685", - "021a19cf7128734081a989f7f0a83a59e8d8d4a5308b60a680e26f2fbc4ef74313", - "02232f34ae9dacda3ae3d99193a2359a3e2544d98cf3edf68c99d2286de51c3a2a", - "0301e77844c5f6633455998f6bd0acd73017ce4e33027b360bfdf3a4476e68cc7a", - "03257528a889485e37a5e27b5919b7a3abbf504afa013a9e8a58da1e6ea16629a1", - "02153cc3b2e1d7c04a739e818a3413ad8bcad6bcf2a77fec8829783e301771982e", - "020e4449078c404435ba0d24e19d01d8e7562bdc71fe9229c91e93387a43d8d5dd", - "031169cb5e941ef434ea8012f59cefc9a0c56bb39b6153f0d4ee52e202b1e9596a", - "03053adb9c59eaf5fbf990ae4182b48555abf7417b7afee29a2f840051c76606e0", - "031b09eb87204c83b51875671a3855dd73e66b38d700d27308dc5283fa543f6c53", - "031defa4b6939ba17471d23198492badd75c649692d5db3b42c6c399d2f321f051", - "032e3bd0488c984d2d600312f0f87addf7603bf268c443befb3ba0e55db74f3994", - "030487099e20cbc77678d4cf6dcbd7f76e3ae453c7f1407f619959347d247621ad", - "021c81121240ead47b78c184ae829cc8b3d8e3b2218bba1980fcb185d216edc49a", - "03257afa49ad02739567c4ad08b62b6505a0259f322463bfa47312cc0e0e2c7438", - "020a8eb7789b40e92fa626d8fa65b0b9e612e50b6f4123ebdfae959ccdba26c852", - "0300cc6cb3a6a8685abfc60586a42d37f060eb6d48202af23de7e5580514372b42", - "030a8b3c4d084e031b010d8595380b5452a608b5ba904bd3c5a1b62e5c2ab39154", - "031088865bbdd008472b6227de845c041a0390951d488bacc3172bec4588828a38", - "03181eddd96f92558f7cf3209eec77e8caecddd3c4d4b955c66977326e1ebea5b7", - "03186a5fb25f9a4eac54a1060b9ca06e1fa600226cc67031181a532ffa76ae496d", - "0205efe888261ae9576bbce15f10623ebdf28f31c8b2377156a574044efa5a200a", - "021b3e8bf976f4dff3141d6d29abd36f164bda5a6e13cc25f1f54479bbbcec9cff", - "032e13b59cdad145ab3c5ab40547ff3c6689293fc829e3ac88c4f8f84a2a75250a", - "02031b314892a0bf98fe573c6731a1970f1421bb26403c3ea37b869c6c0adc6446", - "020b3a30c92064138c801f94ce7b68d504994c17a33504302cb89c2dfba91ab064", - "022b5b9ec9719c99da4763dcc9328bffc51195cf34d0df669e940b73cb57ceade0", - "0227a6d90f5bee64ba14a10e1d88567928dd7a51f5310eaf76ef941a28bedaf15b", - "031acdd3c501833614c352480bfb14a899b2284af41a52bab466c63e436887ac92", - "022ca27d223034cf3386d4a9aaf575ed50a1261d4ab3232c3b00693b85ccb7975b", - "022f6a3320a6f075a0b7dce86e9b9ce75e0c90e845ad3d10ed6d45c5b67b3d09b3", - "0329f0c54f9e868319a8784335769c5ce868ee000fb84e815325311e6323f58a69", - "0307b1168d1d6c5bc62b8220cdeeeb4878c788703cf2623d9d3121c24385ba104f", - "032ff81c1fa43820557aaeb73c240979a570580c00f4bb8daeb93cb1e046fb4de0", - "020b8fc1a2af94bc17e8c5b26956dbd0ba3997da070aa471c5ab03e512a5f31fd0", - "020e2d1ca0f5e69b8196b04fb922fd9d0d05e89703095d35c7b8898daea4298f6f", - "02191d202eea55739fed6449760a251040be5b7143886ba9e6aec99cad54e06b98", - "030c7b698e5e721caaa90abc9a2a91dd1eae686d2fa75cfcefc046d401104ba866", - "0316c564e0dd3d37d21a3b4b504e22fc90cecf51c300c213dce1745d692277cd4b", - "022c9cb51148c58d97b95c17aed81f8838b6f6d79453c62030f15edcb55de81dd1", - "0201330fb596921924fcc27d0b3ab619541de99ce57c7e8e2a5cffc4dc177ff0d1", - "030cdabc51c27168c5b9a1c0909ba74cccf1276c652acc70b8268a051a8eab7fa1", - "031da7fcecb997caffe2f7514e49ac841f88f2c517c6f6e0aac879fefbd41b19ac", - "021b62bcee062abac658c32db457c0bb22d196e73f779c0c9c19626d2435a86ad2", - "0217d5416b1dde4e0afa8415c4859eda529ec54c18611f6a386bd373c9be0f400b", - "021c20754d7711ffe4942ebb2446536b6818f8ad95da16cff12ca124c801ea1eaa", - "032fa8da482310b660c130681a0090b32474b57bc9d69537e8a303f705f74b4c1d", - "022b63138692eef2796e69be7f3e3bbacc75a878047d029df4b0bca4f47aeb55f8", - "03230f9ad36dedd15bdc59806dad0c7a58a97f9380a7cd8e91b2107c1a608dd6bc", - "03068468b95b7e202b5622587181f2c6527d2da204c96f8e36c502198521d4eb71", - "02178de8f93a452d8b95393df513347880589269015d724bc8d8ba555e0421f9e9", - "02137723080df9472df79a07d3f1f57d62390b79a526fd417d8e99d52cf1ea6047", - "021e93df19905cd1198cb84a1f898b04ae8eac3e1ff44930d11abe5218a9cd16ba", - "0221fc8f34fd1e52519013060ad89a22aacc4f8e8ec8e013a02040267b1d49c169", - "020f90f2dd2e574a019c752fd85e9c9fdf548c5738b4a7e920c917e3562fcc72b1", - "022450a937dffc9bfd01a8e7e8522e8fe245c4d9ff900a10d757201ddeba629b6a", - "02249b512cdf76833b19b086c3f4c8e575f3daca67f6d978f4cdc85a636a20ae2c", - "032ecaef5ef7c67e64f6b5d1749d50203618b08466be3d0354bec5d2864a578fe0", - "0300e13ac7c2c63946a4b9415f19c418446e861b8019a1714acdf6d0e507cfdbd7", - "0317e1e88861ac677b36a56d571a39989dd2b1eb60821ea21818960821e161399c", - "0228b825eb32dce0e0a995ebfd588838edc9ae76dbd94899bd70702ece4857848a", - "0216066880746398da4f41a52be980df7f1b6b7dbc6e08e7153b49b8d5b6f904cb", - "0219b613be4b50f70337dd76beb00f7fdf88c9b23f30d2b72ffd58408048640132", - "022e0f47cc0ef8ff04a74499e4f782aa1549bab1538d22f9ef4330beff0adf77ce", - "020dd3de541d20c416da8bbb4f54c0f50bfcc1fc132e52433700b156c44fe88064", - "03146230a22ecc04d0e1d3eea6eb3326126e11b3c3f7b6800122006ea656fc070d", - "021651344fafd8fca4adab2a1fe243b958dc005bad74839dfebd2ff4f2de4888aa", - "03296d847453c84ab18d63637ee97b2adcee99e25d03fb433eb93398ae739a3475", - "0322ffad82a9747eaf66fb1a7e17376ad73c78ed67564dadb2c69b001687a8ee1a", - "020c670bcbbd1e001d6e6db28afa80c891563e27261260c56063bc82b626f60cd0", - "0327c3a94bd0a16756ea26f0b803dd1ba3c25ef0c1d5e2fe65e67a62b496bd3d1c", - "030342598c8c1b29f140b7bea666870a69da7dfb92ec6a06160c42ac2fb7e34ae6", - "020dc69943675c3ef47dc014c7d3c4a61385f10146bf378fd188e6b62cceb1008d", - "02276a7705ea5150a3b495f4048d729a5103e82b2123a7c6c07747d184f18c0f3b", - "0321f6409eb3c04e438ce67ef00be8d599b332a6a738fa877162c07d07b593f5e9", - "0211553a9cb445797cd12b1d8becd2ddca6d56c09c3c3d8ac352016fc7255a5f5d", - "030a772101052b537a330af14b6d46cba3e6519efcd329d3f7af8c3a45959b7ef2", - "022ac132aac64a64802f296e5371585d44c5920ffc1243914bbd6c123af2ff84e2", - "0307381ffa3d873efe401103abc9a901d802a598b4903d1728d5213de7126e3134", - "0317b52745f7c33790dd77d49f5f5a871a2608775d9618b7fe9cee382617dfdaec", - "021a3b6cbf801e0ae981b442c9027336f25b0b98c8f25e49fabeed0d8863b00299", - "031614c34b22b4057a7c9d33bc7da8d135dccfbab77ca9f3ed99a4f1266b56d9ae", - "02161ac9419b2fb87b6a3a7d399d54e1f6cf3ab5c2a39c0fa85fd67650b48e702f", - "0227cce014fb9e2b35576e6dbe9d3d899199c498e2943fd3f7e5f9c243ef63a65f", - "020bf435cc5308f0642ef79b0ded60a1bc5e81f4a60e129f1d39b9e58f8fc07e8d", - "021e9653310308aeb76f7410895f8ad844a2a544deb3aed0ce4dd13d49ff621505", - "021a19463029fb217640f48f11c01b09dd7e2c03e10492b47b8130e745958264d1", - "0301f788acd4904b2c5f84abfa29297c58b86969f14b486668746f6a849ca6237b", - "03057731553d1ea5629040d598567ea5f39716a9d7d26f32fcad2089575a757aac", - "021446acc2a8473c8e34ddf43b515973c657ab68d62a384ae8dfc4f08d7d037c88", - "0215c5f33eb2099bbc2c79055c82d4977501bd93bd559df7f785b6e4cb556adc6e", - "0318035071b0b1692b4e0abf6c87f8ceeb7fa2c3a8f26068e0f5f24cda13cb5bab", - "03083401afc314f2b2000f079c63aafc43ea2b16ea9379e1a75a6021cbd5ed4de4", - "0320063f74380a626c1631ee303a25e10d735edd8cfbcb7d45946702e50621f661", - "0302fe2dc1b89013ed32f617b52a4216e5b74c688a8a8fe2c2d7546ae48e957114", - "031ef2a767546c93bd7134d4cafc727bfc96f3199fa2008a14910f98553de435b1", - "03066ccf70df382e7b05a52ef35e2dda4fea25fcbff7f90a8e75fcb1374f389144", - "030d7846cee2e779e6bc69411b27a5d7099db682873cc64374d8b89e1d00de8d57", - "031eb44f95c8a6eab9fc719a9ff052e38516d41d78e8fb9d76d668c4258868c7c9", - "03037b60f5e1fb3cb60b6dc86a0575f76c2b840728e2182ecb6b42d39b4f257a3f", - "032275c795a4b863040df17f80a42055edf7a89aa313c9c9858c89a11519549afb", - "02031ed3f5623905960240fe2eb9bcdea823e1b05ea35ed1350a4e869b40b23036", - "0316f3279074de631afdfae005b399ce9af861d5cfcc026be324920df4d334e9c8", - "02286b2bb9587d49dbf3fb94d035c3e46484fc13a0e41e7f71701ea12ed274f7ba", - "021f293960536067aae10ef39e25ce86a8cc44bc73d290aaaf76036b44bf4d329b", - "032ef070c0e3dd486598020797f887d34b000367430a4a5ea37c37f5c2903f6cc8", - "020f46a32988616302015f1abc4388a18971da10acdea55f4b3df332c554e886ae", - "021b58c706733abadd8aae2301a760627c79e815894259637ed72852bec1209ac6", - "0203949b3d73d28383b3ceb94faf9d3b99af725c7ef3e9dfb514ad63240c61ad1f", - "021f525e58e9e2dc1ed016893ce5bc125899c7d8b244361cd9190f8a108c264c7d", - "031e13b0b0ab2c1f2869b9876f50f36e8cee6cc2c752992f48c3a4357372068900", - "022f025f668a50c52b1edea4a871149da39987707990c76602de30f01e99d5c75e", - "03185ed6fed60b4dcee4626509bfb2bee633390fcee12050047f7f1ed197d59115", - "02242d7d1da42504ac4f476f291fc87c264d9ac464370f2799284044f5c544d0ff", - "022e9e330d82f851c600c5439331e2485c54dd3bf5f0088c75a0eb54363c5e9af4", - "03144963e12b6f877aa5b2b220452d3f9037c227ca6ac6cf06edd7cfbe9b47e226", - "02253e6caabf0c2907f1ff85f4e03484e6845f988092763f2d1ad6858f55b59347", - "0308936e4734f5fc5deda169eed96310b505d630497c3ae16934ca0480c78124bd", - "0218327cbaefdf8b871c94496c44798559c0feb0afbe64981ee9b80f3ca8f9e3dc", - "021e7fa53fd37514d7771210c80b800e558f7d746ccc410d2af23b193e5020f28a", - "032772f9c470bc3b5c37c821cf439211ab0f75768f5743f9b218e874806f8f755d", - "0206d7c7ceeee9c0e4c769e7f845b16d8dc98293761efb7f316412f9a27ed4ac07", - "02096ad8cd0354038aaba440e533ded20c96733845401620e72a4ad575b361349d", - "03190f202a58532291514f2fb25ceb154c893af1541d5ea54432c89588041abb81", - "03100e900365adbe056e158819cd75dc3c6518802a3f98456419b98369367fd860", - "021202d77a188b888140d7554869bab21fb513669f78e38f540e9701c1dcdbdb5f", - "031e5b933d71fd06e6f079081d1935b628258fac9181e5df5591c5415935c46de2", - "03165c2569aa109c8e5829b615613b93cf7089f77a23a6c71ca31bc9988dc8aeb8", - "0308e30c298d5689f1063519068e6ac04e50039220a7d8615a9dac91c7ddd61628", - "02007a2b778f4f298a746fe34c03ef7a07285a642ea4e9bb065729c961390a1a07", - "0202837ee572cc40a6517970ff67b8daf999b22f6bd727147bea4a1cc571e9e5eb", - "0217a85339dfdbd4defb277b44f440aafaaeaba5b941be5335395598d2aa9c29c3", - "0215b3fac562fb4c69c6694512e1e442bf6752144ce7c743f49a600322e6fc332a", - "0310a6ae0201d5e48a02cf6875c98601a0104c905ac2ee2485656b7dc65244d60a", - "0319a1393b1cd980490faa36c6390dd0a6dcc2de0358804d0b4a413447dab35939", - "03243b15e57f34ff2200a287a0edf027d06db23ccae067aee6a5a76d9a910085ca", - "02115c7215c1e414acb8e85be5045b2e1790e1c4772d71f2a345ac5f72c5f264bf", - "030ac71e7395a4ae152aac29ff367a25746b1eb889dc10c1dbc5ad9c5809d793b5", - "0202b010c762a515189c1126e60d8e56b41e9b8b45b1dd623c4f186a4200627252", - "0303ef75f2a66455050e3447cbcc017d0581bc25d35b8a52acf1a4758263869f7f", - "021f98e06c1d35a8da1cf7cff9a1fa0b6035b5b56adb569a46b2ca1b37942c4a83", - "020a05d1262baed7ad675616e719dfd58ed8a773f79811d2c970e4494a91917b3c", - "032a3d66fb46a29df8d938a6850710c5cb9de7530d09d196c67048e5c429921134", - "0213c68ded7023175ddaf2865fec02989ec193702d0713a7531db209d8d4b64069", - "03254ac0e435eceb100ac02565e1cd1139ee45aaf833131172fc29695bd4bf6ae8", - "021cfce097bf5cc5acd27e4e064c4082337d3abb30f96233cad0cf5ae1a5be5654", - "03258018578b5862814622a37966fab8f574e3b5b13051bbe301fceb3b45d7b974", - "0220fd20d635dfd5ff3c94a76a79a87808ab2b610d5670d91963a23e8b3c969c81", - "022ac0525f6ca6fb0b788dc6e320c3fa96080938c6d6913fe7ae7e5064659bdf88", - "0218e77fce461778315e76753059b694b410e3995843c17e960dec48d0940f2a70", - "0309277a1fe899f885f3dc3fca68e34baec1bf0cc2bff9800ea2c7010daa326fe7", - "021e13fd1abf893c4438bfba949baaf501d718bcd7f1e7fad83e05d64acd9dd80e", - "021df15e988c50a3f2ad047c5660651b4345a2546d9ae75ebf56d1993d4f8934fd", - "031befce4617339c4b582ecfa60d06bffb5d1f5c2ec1d12e476d480eb180c47f49", - "02063c5a327ef5d32bf2b29915d14dcb4110dae5425d113605da8b13ac086f4e27", - "021acef2a663928da530b5959653d204cb5ad2875f7e51f239829da5eba55fd7d6", - "0303ec05ae0dc8ff61b9b1c62119fac47fd112a9aee4f7a773e62efdb7b18f67a2", - "032aaeed38e486363788173cf2028cf47f1fa1112ef84b3dc1dfef1303c07f372b", - "02175747e98537da3411d430e305f10f237d178a809878541dbbcf8a64441aa5ff", - "0211756f30b6d09c53ea93db4f70a527f25a066fd16bc316207b39e7740d0269aa", - "0308ec98beff8b5bdee26dad56937265f341a6ac7067e983b282e0ee12ef001ffd", - "032b04878d449ef84be82afb58e415322baea0e3c80fe76cc2bdd3ecb5e986ae09", - "0324104264afe10bcfe1af3349c69f5eadff91b9a515ba747513f62fd42225a525", - "0227ee462eace80595ec79a634733479b8a562fe3293a1c0f82ea94673fd33098b", - "0214b560f7722de8048a4ac80b4b17e3f5b82a3343d1aa7b1a822bde3e5d81e319", - "03033818c5c004007ea1e0675cf1b68f2f6dc396e4edc2d55857e51266e088e7af", - "0208037034bfeb26a97d9c4384e4826b742507c260101bfe9bd1cf62fb5b0d4860", - "021f5fd3fb2c264cb40245e70847782dd8d30e8392ba8119227523ff2b87aeba8c", - "03290af4cef6d7ce59d29afcca938150789f44492b3f3e3408e1636dc4620b9996", - "021c929d6031779d2b788840e5c06e8de7287229f7139e474280bc9b0f1a1eee03", - "030d193d944f98871c808b6c06fd8869d3cb1789a492be427fa9780363cf488d2c", - "032d5d730149db325fbafaae64f5e8ba01251806d174ff3272784dfe483e7d6e54", - "0311af3dc538bc555052135d80c900a425913c025d2da456ffb7d87b7a6ca25f9f", - "022f98379bcbf02ba6291679b2c2b4d343c3ea385ffc63902a76587b3836bcbc18", - "021049a53f8aab343bee80347ae96835b5e991ed60e8c9394e2b2ac8eec9c483f4", - "030eff033f7b2c98af38ed5a0d46fc1f5dfe3aca725e7596debbf3f4b4a88c6533", - "0223bc6da2e30b5d0f7d39c94d735269f47095aae6f9dcf9723dbca72d1c8794a9", - "0319462edaf61c743d1d1097b2a0fc5ffc82f81ce11750477f7ffa9283f3720f5e", - "0213910c638b88938ae549e81ca91a03d4bd8e164218832b22be1a62a73c8d6bc3", - "020eff9072be01e9208aaa7b252844321a4c7b588b4d77ccf2b18bebc13e03cc95", - "022eaf42eea15489b615bcf942bb3628bfe0fdc35475b1f1511519a26a07b48c77", - "0302648550ed2963373800df5d78b81252193deced01ce625265166ab03d92f471", - "020eca9b2732f45e0292a3a00b563136173252c6404de147f983074f6921779d19", - "02123fed09be92020d51aafdc59632d000a7c6160ba353392a3629898354045b76", - "0309d6e72ec699a13a2172c0f1fe9d4a46b3a7c9db82aaa4294358c877ab01ceb3", - "0209c0bf4b5afa2e41727124726ea51964f6c582e2f3f25394ad7b2254aba0d7fa", - "020bc4f1758f506c6df8ebec88cd08f6cc7b95ad251eb3b9ad8accf580a0673b00", - "021a440e2d907390bc166d20a861708694b1a26fa458c906197f0fe0d7cdd2b1ba", - "0324c93e2ef1a0e96a4437a09c9f67670161f6da9c31d241b58c55180f8a6f4a0c", - "021a6e21f5fe0c8619f91a279da185d23528ef315b699f14e280db08115d3c873d", - "02031acd5e9576326afbfe631c92b20d508666e9b4c42d5d5450ca1353e1b41982", - "031b8efeebe35ad1edc453b72087358dd214b116d6a3d220afae0be74a7999849b", - "021014bfe3d7d91c3f438a87fbe8562816b06423de99b429c94e5c9c7b24f060a8", - "0215bea9f198c8e88fbf95115420df8b2caf4b2d3c0e654bd55651741153f9ce49", - "03034d0db6f2d092084bd28f066be659ba26e6caa64d606766b036464940a6a797", - "022380bd79970bf907ba27bdd8fb6b24c96bbf8d9f1c10fbb9d9198b17bba9ee3e", - "030b0495f387bed77e5d43944c253e58e3e1e7c457878709fd1d5960fe300d3be9", - "03236399e0da10ef1260b0c769ed7b33f2cc4043bf06d7ab4fa68427bab813034f", - "0313f9b96407f94629268976f2e1a272731c2403663b25aa3db553cb680f11c359", - "030e2769a976eb2ea263ac33ea62efd38ff96e415fe60c283db4e8e85f6174a927", - "0308997da229d4974676586dbc124d9f6451e4317302619a68347cff1169a76962", - "02100388a435062531f045c0230f868c3fdbf996403b83fe87a066b0f73ed5a775", - "032176c17bd84f8d55037272caea9cdf5b43a254d3356a5bcea645010303846590", - "0320d22771b785702d2113568c656c2706b591790f43b322168a5cd97077880a68", - "032a6ead412c3a2e3c344f83a9944da3a91f01b7a28c3fb92adfec6be09c85bcd0", - "020d56980338a4f690ab26ec0ae7b625c9eaa7a7c9e60ff41f4ef81c1178046c61", - "0322d0b2e30bbfdfb08f7bb3329bc164f608fc343cca59468126a28c2124fc1624", - "021d71b5af02f7f6b069c9a3f17d336c19acbcfbaf96c87f938bb7e7fa02a993d8", - "0307c17e3cec016ea1d39401b60459ef6c8becab5971999c8e5ee7765d90444028", - "0215c84ba5ff2c93601126fca37a0d6b8023abf897cbfdd9530c4af7570c8442f8", - "032c2253831e803a1d8efd23e783c943383107979c67ee745f88178edf63b2b13d", - "02034983435242b14ff4e76cf8e1d53a313b05c43e24f61b5b9b4a3f54b1666fab", - "0318b65355a4ad005cf85dad5f7c88f48df55bfac2c8be4c93b685d47178c90de6", - "0325dabdf4466ac240e10fa1b5478835390d551081bb9b64116f7692de109272c1", - "030969edb6659443665e7ac6d3b37013316896da03cceeb3c90ecb32218d925ea0", - "0324c6e80aa3243c3f7c597b50583dc9882659a02af9d6891a1c93f17c50477008", - "0202a036c2faca26f933ad262b0b0686352cc623ae4e4961cb8dd59c8ddc5bf509", - "032ea6717aa4abc70317438fb95cc983160ea21fee5692ce2450b49d965b145324", - "0206e362f848d9b0f97b7212c14932f957c23903714b89296f78ac17b5da692ff1", - "031b5deb58652e0674126385686fd48a4403d7c56fd4bcf6a396e74a179aee4618", - "032c8a0663edcde6308e4a3939f24c7a502d2d9873d4a9c4edd96d8f1b8309fe95", - "032bd135b87ce11b7625b252bedaaa377919497f5739679725c2f4ef18476bab6f", - "0317722392728cbe55ef42eb4ded544a61fa63c278f3beba415af8c907ad0a63e2", - "030896072b4b30e95c7bce77c98354de421acd2c9aeed9d63c4b4591e4606ea5eb", - "0223ebaed4b0762d2ffb7c432e922bbb6a9e0fa749d3622f64a771aa71d0f37454", - "03253e4ee260e06d1a2ffc88bdf351396e3ee0a5244bf1f822f76a2659e1cdbdff", - "0320e3b3c335ec3eb63910dc9d4f5e85feae7d38d2cbb4da942eb2741fb6aefca9", - "03003e239e9eb6b0a6476a2c3f7f07b16bdaeb3cd4749a8ef21fdf7cd851ac9293", - "0223a7c1459c4c201767817799ffc2d27cca1822a597a0783c2395a1e98fe0acb1", - "03147ccf8182333e5a9a35621284d64078b4cf81ff31e28e55bea87b333e896e46", - "021da6d9c4443b9bb69e6e6c744e4f809e21bf8ea5f889ff58b9ea5422d62bbfb6", - "021108a2b94d1afd3cb0c86d8e743ad88b6526960e8d726ec5f7e6d8127d23704c", - "022a4bd7051b1a88e70c4f0474ed91236c17ea02d39e35dcbcac1a26e195cb01cd", - "0221fab8cd90c56c30c8efd6641147cecc74a606e21fc0ae65a8b350979910ed6a", - "0225c6abf6fa7266586cfb8d8bf2bef46315f1e9a75d7e4084604fb503235e058c", - "032a1c1dcf79b44ada5206e51cff4a297730b5e700fa638d08a67b4cb1c68c952f", - "0309c8fb2d84863c738dde2ec179789ce8ff56d5288b2aea4b3dae587b8d5bf50c", - "0314bc45edc69bb6db04dc7f2534508abb791a7c9e8728acf42020505f61e5661c", - "0304f3bb817faf20b4d6c73af6a054af39ead049559e276d98b80c09593dd8284e", - "020b91a9de2bb4ba5aabe4d1d3ea7b1e183b486b141c78ca4fe19eaccf734b2b68", - "03008c3a26ead0182d013339071639efa353b8ef8094119ac4187482dfb4982eeb", - "021577fefded9670fd59233dcdb0f7783b35d5f67b9df8ec6b0d99211fd332700c", - "031aae44a09706d047a20a4bc9825eb8d66cebf285cd01abd82b812bc0a1a3fec2", - "0310adfd0aabb55534d20d4f0b4960082a28a94e777385107c57a415c14472c599", - "03157e3a9968ad16df63f146a0b1f00c60612a2f8a8040420880f8a77da8ff3c0b", - "031fbba5dec96c0496cfae28edd3f6db013f0188935b6d32e73263611006286bc9", - "0214210446269aff0f3e44ba1a115a98420d5a279f335e5c4554596bce7e80c1a0", - "0226bfdae7b14b4caa8e158f3d3750093f0ab61a6f1a5b59c18772ce83b9bb3a98", - "022d7c74f25372d615d87d0c0d587fab322a235811f64b1190d50064d8a5276aea", - "02212547b15dac4cc52236be4ed9303b0394c799333ad5b6c47098274a54a554dd", - "030432e8f29d3ed8a119140f69a150f10007248a38e1dc151a4ad52c8bca59b698", - "0223a17d385ffe11638d198459284326f182bc01453723968f3bcc74606ef952dd", - "0305bdc198d7ab6f57512e4e5b1a133132935a3d47cd6c8edae29734e4041db510", - "021c815a54e474fa0bc21d34e2e04c69cdf9f177d85e75452a84e007077a3ee4d5", - "022f65ed06404770cdc25bfe28eaa73ab403d2190b10e87d22f38d7d30c622098b", - "02147fec2ad14169f5e4569c81e750d322495abbe30b9184fde611ced24b6389c1", - "020c96a7d063d5b143e237d65659bfaf5cd5f200d4c4a04d29a9bec097e9b9c432", - "03187b88920f3f0ec5c612cd7995256c75ae41bfe1f30c48f305401e3cb2b52db0", - "02195965e801bf61b4249b2a8e876ca7c780efdfb79a94d3c5f500c5c9b254c91c", - "022c326e936a36150838ec07fbc8bf47ce6829b50703351cae777d67f96eed2fbc", - "03154395a8d4a76f1356ef21930a43a39e97049d9c2ab4d3e5bf1c9b0aefc0bbd8", - "02030acc5eb433be6aaab59247fd575789ea88ced99d5aeb806db5fc85315608fa", - "03266675b77f9b1a1669f1901a73a9533f0a1b98ddec0db1b537b667371286fe92", - "0214a1c2048a18e6cb2b6fcccc2bfacd5f0b2c8c7f0c5a3f19e59bec9b4a6f54db", - "032e97472eff9e8d62dbd905341f5612d91d6242d57605109f442f5515427ba668", - "0310be6d7734faa32a54217cc673a499da042c82924b3bc49f922dc9a88ee333a6", - "03058b8c3abb7d6c6738e6ec0b87f80b58f141ff3603ffaa389c63d3e839960a9b", - "02057c49c49df1891e6e6b93b01df1e07d9cf9a785286fc0f9b64adeeafcd5e958", - "032a7126027dee256485386be3f027ed58da9fa36cadd276f5fa692045587347db", - "0225290d727f50bb1bcfbec4c9aa15caed6b13fca187babdbeeba742dcf9d3c72c", - "0214bb1561e3a4627b4777a6419cb2ac125c15aa8888ff9b0ecb18187de2d55fb5", - "032680c2fd5eebfbcc865b377fd362069b71b82fab966b1fa643a215c11c1b4475", - "0322448b7b1ba374bb29a5ee2f583724ce5861d0d05fa9904126db41b03f780b0f", - "02290f7b175118cffdcd1f3fdde10d5fe19938e19fc9d7f6b9482283a573a73e40", - "020a2b956067fd7a656cf75297725c4ea78a599956f7dcdc9ae2d1b6e0e5e5671f", - "032236cba9c510a652782a656882cdc9989e6ac68ce9e6ec4d4d8ed2f2676b576a", - "02001eb07bcfd38eed0a11d6a063bb8b3130c65c76f4aae61d1ad1ec1a4a305196", - "02285a78f8e43c73468dcaa190943a5b6aa0de27d06f5f87c719acb183c7c6a011", - "032ea40fd917a3d02ba43d1655f5912f508db6349fa344e5c183c57949c495efd4", - "032837e6cf883f33a9176ba35ba03d7fe0c164e6e3194636614196d6e8d1fac283", - "032550f9c6aa3138828493a5380f2f4858b7e065c54603b361c1c0820383e6b1f4", - "02018f40cee24c9752415c84777a5838a18f1b57e203d3c66770782558a1ab9512", - "03039d3cc15b43bf7195f080a9c9e774774f67513b142575636dba819377b35b87", - "0318ed0443ba6ab569d072f5ab21c051930d1c090fb3bae9a12013b44ea1727cf7", - "02236e0cb8b00a26cdcc63761f74f4944e03c6a2bad31d22c80a45f2a7709476c9", - "0222823fb2899164bedceb17ad6734d2b88e6fd3690ead79fc8b833f12b485b251", - "0202041a3d4ca3e38746cc3a98507af851841ed4f604a02a796b85cbb3adbd5150", - "0311e98da4cff946319bc741b01eb1e43e368da5751829dc17ef40a071b1ed6be0", - "022a8dc6202f3b9e47f589f5c87ddb9aa4bd36e66d1b6838a496e5ad263f4ebcb6", - "02207af018270c6576f47ece89bb118536b2bd7574f80b0bb8f415174293c2521a", - "020f3119243a86f248ef98e4ac80dff52a7f4007f5f802eaf36220562727b197e6", - "030da411698529e4fb9125b667bc70a23ead83a8747a23632b72533a99a7273b73", - "020c035653f7aaab0af23b173a2eb0779a0961f9c408fd29f0cd2b4bb208c798ce", - "02229de495ee64dfa5c20db64bab7a2bb8c7282998ad47177b2fc9bf7cb526d78f", - "02083307f78c3cb78f610d8c8c0cb074b6377003d06fa989022729b896e6c2deb2", - "032cf1f5af7a2ff13db84d97f57b09199dc6360b4823bef4e9c7ed753a4090710e", - "0311315e551de7ded9c478d7529ac2a43749f9f820c2ccca78353117c6de38dda3", - "022702adc093e7217f2b2d24f18fd05bc6db08fd69672a2ea013bdac2b0bdf62dd", - "0327c58c8798ddcd5e6b2f477864185ba9b72485ff3d5a1a044669b5e557a880bf", - "02232bcc62c0538c9208639d05ff9da1697fa44af5ea19c65e23483e37a7f4b785", - "0328708520b7f4390707b0ce461907c214e04c1f524b9e1fd1b224890c47062fa3", - "031b52b3c963cfb189687fda9fa36eadc0ea83a990eadc9b471ccb905b1044e32e", - "020c6e4fec13419bb1afc566c369e2730171d831e06b4419b0abdf5668cac545da", - "0206076385457eb846dd5e855a1c5651ec945454d1451602dd1b0064c3a8ebde5c", - "021505b6abf0c62b8d5c8ce7cead9b2336b5df36e44e1f4fb3515828a75dd04c22", - "0218e353ece0d59681ad1e52ca11271e67e6d9fcaf6dca4be89351cbe207912923", - "0320f93d30b760ed9b98775d4ff66f2eaa4d2814ca027707d11d918e07b42cc869", - "0202e785646289033134af8ccfa5494c20971ef7cbb264331e4c87e44b66a8b95d", - "032f1135638f33e0f3a31b538e301400b32b6da7ff686568f4f7164a23495c19d3", - "0309797be93671e9a721492608fcdb1c16c081f3965bd9cfe56167983bedd04f47", - "032c18b34a52742584ef347e902b18ee7436715889dac8550c8aca2d83cc8289ef", - "022cf0f56c451463792d0554ef755e27b86afc563877111aa4cde40a2898fe9f59", - "022fa337ac93b8fdc484d35c40a1c27c46b85ca68e583da975bb72da6b966bde7b", - "0207f0a8606f6fd66ffc3121316362b66721f1666bab192822568848839e9d038b", - "0306b77ec761f53a014b9a0b3165dcdc36e3c3b5fa0b65e0815a7787b1ecd84318", - "021b677e2ab50242f3eb414fd588ed95e87ca3d3f4a4b63fe031ffe8d5099410e2", - "030853dbea751764021311c46a5c820c5923cd53547f5f93ae1c6cbe2cd67d65ab", - "020a9a1fc2542cfef39d1bd7cd1939b5fbd9007c6c17421bad641413c2f9e94f1d", - "02261bd0c4980c00ec748d7a23bc4727e9362222a151f337a379c29e0286de9c37", - "03151e3c47411f9a56c1dee793a5fea4e71700ba87a812c1d66e7ac565dd69c12d", - "0220062b2bed41e68f2d4ecf8104ac3279daea38aa3c2d5cc9bcd3ac34e17f2448", - "0206a7e1566741ad7135655c0775eb1fa833b557d9e45575e827d88e530d4c4ea0", - "031dcfd298606720d217549abc133d232a3ce3cdec720f795ea30b960bf6a494a1", - "021f6e9237b285341ea0e1639b0d393e86adab4c7feb7f1606896da00ea17769a0", - "03256c823fa931d254f8282c4078334ec57c25e6f54cd81f485616ec165e8498bf", - "0307bb11c86efa2b65c3879600dd5ba7050681880ee8e42e096457c091ddea2f4d", - "020b29e1b7373d98ad0f30b7e311a1d9bab678696fb5f6ab280dfff3d6ce7041e6", - "02291e860d14e20480ff75591f939ed0c238da9282aed4cfbdd73b0642707e429f", - "031d5dc066c851167c8e3e36c631c28001e00f0f30e3b713081260ab2b48f8454d", - "03257c4f3ba4d698b0e89ff7ab74f23126435dca3df82dfe703fdbf04c9ed51541", - "020c3c9846eb451d011e0fbf4fb486c4e2c764c9dafe03a342ab1ff0947ea7a671", - "0316a0fad57886fae1e87e5d2e53b630cdfa9e584fe3ee50923551739eb56c42bb", - "030aacdcb5ece7f123a4515b95e2f05fedb0ee93d069f882530a822e24b22a9dcb", - "02209d23bf98a346bd54982a19822848ac7277ee40c4dda2b4d3cb89193100db7d", - "0202eb38b8e049a200e344b6a63474c916cb1cf6b990ba8191fed2ceb5bc5bae39", - "0230431f2485b6b884a87a28be60396b0e22ddb023bf3efac5945cc83f05d8bc6e", - "0319ca54a7b0512811fb6ae0ffa5dea7c3956cca480c46ef1bfbbd6958aee8bd31", - "0311701a84a9889272dc23173b99c30704e8ac73c9e884a1bbe03fbdefba41f364", - "021dd8b9957775e139a8f604de5aed91d62c37cf248e044481033a6da0f605314a", - "032a108191d5a4fe23da3d80a889264811c3c94b8b3b39965e156bf335ff3fb854", - "0328ea5fd9a813bd135cf393cc2a5d078141464df293e8bd14a9f2af8b56a1d530", - "030d8c05a9e35a93ad471fb27ac9a53791d93508fafa2d6824136098b0c435780e", - "032c5ead7ba23bec1a44e7506ad9e8552d3dd1de8bae992e7be3c730eb3adb66ed", - "031f8303bd88a85c795363425429137d9e4f075cc2591c385a0120a36f33856ac8", - "030972128481ac33f12e09d00a9b73d98412baa485b1659325a3acc2dee3f797aa", - "020351148ffe3927a35acb937b658e175140018c3799f0d9f8028c76f0806432b2", - "032cff50ec167cfccf8608dd66154257573e9e055e302c947a57edbdb2a6f07c6d", - "031b768a737b3e5d72440dbf1b6a776d8dae114ccaa11c682c0d14f19339932515", - "031c6d927b949bf0eed84e3d22d6e6e572d00cc9aa2ffa4228703538f5ffaf8508", - "02241ea9505a2dc98e8f71cc19ab6404f139859514d92e220118f0a9365f50776b", - "0224a72f180c3032d4db358db19c0f8bb6b99ce8d457e2215c68255a66932dac98", - "020062ad64859319de66b7cd908bc67d9408970de0b3a24a7726d4bc7f422fc0db", - "0315a9466a4efeeb771ca3792862389f64c13c0689d7e293e39c69d0ebebafb428", - "030ba9ce03d19ea42a878ed752e7f79f14a49a8f2e4ce68358f63124e437197a7d", - "03136a9f8c6399fd2c05faa7fb01fc51fd85dc3029fb3931c58676c1ef20b3753b", - "0215a59f3c93456d0d424f3cca2ec3e360eee5c1992fc0782138bcb7b6b8506e64", - "0217036e823952fa3bfc55784901139cbde95090dd07cd19e2517f882bd7909beb", - "02025221e3ee07a82c4c97acabd4cee0a7289fed9c1a7bf9c4e744c2b820db74e5", - "03278313c68bde6bd74187e4b60fe691045d1a62c3cd9a78c6cde81e6a0511afa4", - "020d19917ceb8b3c830f117f7ae53c3e5fe97dbe337e3e8f6db2c0107741ecae6f", - "022c443a3f817a2bd15392bb9d0cda156b7781b82a8a7460704b6693c8d2bf6e94", - "022144973e3b79ea455c0a3160d989a88bfb398f9ac1ca92e992617ec328f1341a", - "0318644daea8b4c8f171b2b4ff3173aa9bd019f94177e5e5f78662e307e7a7a036", - "0230281b872a2752d6085afd86141f46b735ac334d27b1bf1a9365a2cf034399eb", - "0321bcc1ea67af90890c30e16ce350303c1f7e79f3ed6d5b912e6b081915c87c2a", - "021879b2d7b571c804a7334d6ec984a131e608fc9ff206b91057718b0823db8219", - "03058619c88085fbbd6212e29bb45071f0992bfbabb0402bf9aa23c19ac17bf5ec", - "02127108ede6e5e3afed9230051c5d2bda77c84ffea2d209021f2b66e6d3269933", - "032825a7ae2dd7eeff4181b76bb98b991fa1443654355c1a10f593595f1ae5eea1", - "02004dbb229fb99a3de095976a3cf2688bbb4d35c402cc0ce9e241d20b1f416f63", - "03162be9d6c5d94261ff94cbf09f5c9fb5cca2849707505570a22a2a77747b3a93", - "022813ef5e65a50705e22193dbdeaa0a7710ad0d1131fd937a68ab25e46c93cd63", - "0228150548817ad4a32df4509554209a895d9c470f5f938c5ab56bdd6997874799", - "021095b198d12809f1672018d3e71c7496ec31a172e38ee018ad95e65be9da3898", - "0302cad3946aa34a537e20d357e5a9063284e3ed2e9f60ded72b8e3604b5d01692", - "022e0732d403c9ac608da1f0c14704dd5faa4261f83a90fda64df05473da9fc204", - "031056ef19eac4045d87a96d676a4e0f164e4b4e813f302aef7a210e9a6ac9d9a4", - "032a9b0b3ca8b530d0d842e5d7675d4e26d63449e3810bed892646ed1789f1eab9", - "022fa899f8d311e72dd32d23370e5fa1e63891601baf8c0d01c8de8354b8bd0840", - "022db1dc428ed29e9193093559a3bbf6198078b717f4ec389b08aa62db7a7b031b", - "021ccfe59c7536640e474b0df5bf489beac512368d8c63a898bbafc669d617b3e0", - "020e6a1ae6c735c79d01b215eeaec604b1a328969efe898fc7e85e508c2dd88297", - "0320da469bb2a74a6ae2086a029d808f0618928ad6f6e0818f549108f1e5d39d50", - "020ffc9502ade8b2a7b859f778ae44bc64982f5dbaf5fd1a4dcf8783c62eb683f8", - "0226befb4db313f94cb207c32a750819fbb12346582828b8e5a08b6c3510273c99", - "022353f0b8e604eb48cfc92f5c9ef0da7bc4ca18ca32d52a34b156f2b831ef1a95", - "02054181bf65867e4e31e0c71b825122c0d9f0c15d1fc69b549a9f401fa8d5e6b1", - "021f7791b055a4f069189fe9c43cde7cbf820e15545f72296a5ac988fbca69ab64", - "022e210b99b1ebd430aec06c7905d64e492215c8bcac019e1d88f3d14c4ac1dd94", - "022b7dc27abb8be108310f8d237e28c22095fe94b582a7b9711fb6dfdfab101bb3", - "031ea560c0ac64db8ad27c90f419446a0c855c6c6536d89b9b87702ef5fffc844d", - "03158cb45f193ef6887693f980e35f9797e7fe0f0a6c0b4acda93f7b9d2e9c04f3", - "030ba7a920caa2c639d46169d6425769cf57a045cf634c20e06baefabbc28feb4e", - "032fd13ada0c7a8af176f4975250a5c91476e9a6780483d8a585de38086cfbbd74", - "021ce95e11bd9d6c225002de2b7190ba2662c0e08bc4db9749a3b24f5ab9e75be6", - "021a44791a10b423ba98db4fcc25ee95dc9b5a881a3bb145e2151579ece825debc", - "03114db65848838c9765b7d7581cf184fe7f78c62151a53b9551c5c6fd68f4790c", - "030e8bd0931727d89716aa02f52dd0142ae361f8f04f39d9df5dc45377e16619c9", - "021b625cbf889b7432d905a26211feb72b71b1eb0c24521e71507ce4c63151c92b", - "03162c23862f6d97960b730b9540291a877a97013ba37c39fc96ddb2e5e0b80ed8", - "032f416e3683c3978bfc26b8576b4195fc93507918ddc8605596310b19559dbca4", - "021aed9c8b30ecb633c002ac8131c419dfcd25644aeb47bea6cb77e943238af150", - "0225315119fd56ef5057bea5e4d8eeb8b8ce9184b0faf702fa7d108513255e1cdc", - "022f21f243246f6148b0e6fe9507b0bd4c3cfa29f6664841abef5ba285439f21e7", - "0207bfca122d2f1c6fe1573c1088e391ddf8e576de72743c8141f5bc19050576f8", - "0220dfdfeb3c10e2097ed7c16b6a1e96d47d1a1c3cf767524ca233211ea663175a", - "0206254f967ec9df0cb3a316ddb78f88833efea64f8db789445c72a975685a6607", - "02051495ecabcd5e034973631557490d17b14d6b3145e03168bda9f70cbc6c8026", - "031d0630fc805c4ab48e5221473d837fa769c9b8d3e81866a43d9ed0f7304fccca", - "020b3ab5a13c8022ea7d6f432505822f918fb28abff4ecfcacfcb253985be25a3c", - "0227ebaa1cc6b8ae0207525acb7cd03763c2c7516f1d224908aad986e2cff52c3b", - "030d6438eee6c0e71075a888afcdeca52bdd0149e3c4a48f17f9c1400f6c3e2395", - "0212fd7f06fe6007f7ef9ae8d83f05dbed5db8f289220884eb83a3f561d12b5835", - "030dd5f799b6be07038b510e3885be9cc525036bd715ccdf69d1c3c687659d9ffe", - "02074386222a8f582868f3739db50fbd96066344ae799541e8959179962667c83a", - "0316b52fcaf4a9f58ba695e6e1851fefbcf0220b25bb00f9409dc0582e85efd526", - "03169e4478f3e503df762646ebbb4250bebe34543350549f2b9510e776e1f226c2", - "020f886bbbbde529bea8bf326c2fd80679f70efebf742f9fca4d9356dfa7b88873", - "031a39178d714e73fedd36274e904341587bfa0555cb6a354bb7f5e9502134b5be", - "031963daf674be67a79c3c5056b2d917e86bb5dc707982ea3eddfac623415f5b05", - "0319bb5488591da07ee73d8803503076f917e1688cd2f90ca88034f334693d9b0b", - "022ed898eb630017904bcdbe67643614cf54f8929a53fac8fb013bcae2ff960d3e", - "020b95b8d747167b16abaf3e58014d8697a495d6b9ca261c81e110380282babd92", - "021dceead024b10013655660248f3fbba79bcdf9a8dbe5a95f6edd5bfd1b992e74", - "0305997365d74ff3220e5fff3bfb7106cec2b1e7c4ce554474c08b67e630fab3a0", - "032eab746fde5278c9d57f09a9640443785f1b4bdfb9b0b8f3aaa92525b43e8042", - "022e7556955e87ca77f587957c7a0b04f4ba039e7289f23ea0bd60dee7c62e26ab", - "0328571f400a2fa3f48a73c9515c2046c579cfd642ad13d2542e6a049105767e40", - "032c03c7f88d4f8aa45b0a0583ce302d750e17f0d20db511d1386b142715eb97c7", - "0314cc8877a0e40e7983d17f3b4a24ab08da9269138b4ee506f161275abe819499", - "031774028602dbda320ceb49b42103f917ca9a4a365f6e2d3e5ccf315bd01e9353", - "032dcabb91b4996a532403d5974d31dd31355e4b15a7e4e1edff4f75fd31d54f3b", - "0312e69a3bde65c4621dcbc153b45b15a60bb466c35cb6fd91261f71bff530663a", - "030d223b182997ad84492aa27eefdada4883bb5b4b3343fd6ea90c7e99aa32486e", - "03061e99d12fd4bcf0c7ab68e134650f47a7f0732ab0e9d6343b02e01c15c51a83", - "032027ce22c457887a1c4af5946363e93edf18d46940f333a745f43ea6f0d70a5a", - "030b5f11e02c794e5b97363304157899eca3c293de2f63372b5fe1a6157740918a", - "03109118c5b1211b4aead646255d9f7a7bc4947ebde5a76584fd3c640fa08c4803", - "03110e3eafbc9c820e8f07544aa75fb1251958a2e4a49113dded80d93d5856735a", - "0223d08a7d3ea4c7c1b7b5269c83fd44cece6dbd4332a02f12637feebef980499c", - "022309d677d5fa0138da0a65d60cd22f4c313d1483a859df3e75429646dae2b71e", - "020d3d5d38d24c76cb1c8aff48c0a4946987df7a05365e18c6f6f468ec7ac8e89d", - "021f49d816d7b4562f7106b3e3d4e0da60bb045a5daf5d3cde4c1047b37b453488", - "022a42c816e23afd389c643b1979896a776815f0d7b8b3dc7fbc68583ee19a38e5", - "020bb6d66fd62bae65db837a83eb6eae4badfb05b0b3adda98f4022e4f0f008302", - "032f0598d257af4068f5031dfcc2f0981cc3261e328753661732f00cd20b7ea33a", - "0206d0704a4ddd0c7c4bd6c5fa42c523809935ac24c8072ca72aa77e0258af810b", - "0216ab85b3e529cf953242afb098d772d567a913cada92a8515f46cc4866aa6421", - "021ed7a89c69a1be733a3dd2a712bc33abd9d4513a21c4365f88594aec455e2670", - "031b535c0a287ef8803e859b8e6e928305d4d2b8954f6d051e19bf193459322aed", - "031e40fbecd3d0262495f78deb00f4a1dd5c45e485b520ff702ee54e242815c87d", - "02008e3767d70843c6b7eefa9015719974e7d8cbeb14341b0692af91e6df8a7761", - "021ccf19c0dada02611c7d8c01d421a20318cc554a4eae81ea90f9357cdac724ba", - "032dd56227737258b66e86564ce37645a9ff31fcebde1a2eefa3a98c9e8ef97beb", - "020f73129e1d629d02565f734b7f849bc6d6e590d8c18cb2d6d19d8adf39343b39", - "020f152b39893f4726e76c13e6fd9ba23172c943451f416f4e8b8b803174031d16", - "0206bade65a5fa369793678908cebc9d65dbf1fec7c41249ae1a0da61c60d5d81b", - "020ccacc08a2ef3eb848d2509aa0b81c9e25083f6709b4288be4c5355574a8c584", - "0311a583f632b7cb69288f69a2c5e13f75e5a07ac3ec679e188c6aae80ae76c7dc", - "02062df6020945ca34df453983037dda4c75a56cd7d7bc7a069c24b56136072fc9", - "0224ad7a8a44f8dc2a8ef45ecb6ac320387d80f20128fc370167affa039fc98728", - "0302778865380753f317359c8af8a9e9601156a07b4666ff996e9a2202de65a698", - "020a2589c1b5ee99f07ac077ac1658e464653ce315b44a07daa293ffc0767f7781", - "0213ae929a42cca2ef7fa4a0ecd46530deadb8b636fa8d2da34d38a4ed3df5699b", - "0317c375428e89fcad944e8c2a45943b52c98225c3b7e03d4978242e83dd0a5348", - "032ef6e61ad9aee3470d6fc47c4ef7339e4378f76cce602e6f614aa6c295bbf9b0", - "031c0e3cc634423c27e2cb50cbea23233257f8e51cd3922c3ec626537b38ca54fd", - "0319b848ca42c09cc9a1604123481e4ebe8f5650c24b759da36e26b7e6714f9453", - "03229ac11f8b170c173753c0f2acb8e179d1f3bfb1be188a9f0e5f835fe761aaf5", - "020a746eb224291e789ea9298c3bae6f4f189852312470920d4581cdb06c6dee51", - "021140a376b273511aefa00fdf824280f9614224e9a3598f64c83568eb6bf74ab3", - "0219870940d99adbb126b6edfc27e94577f6cb1b58596ba3f6833aa65de8a2c96f", - "022857c65d424e8046aa5c5351ffe6ece6902e75608a268ada4d34181256cb55bd", - "020ffa30327d4c393421baecfd1f81aea694cabbcf7fbb1052af8a084353d1786a", - "0309efdad081b298161797ce5da2cc668018c9cd9b9e25917bbde8fe5b98ee81ca", - "021c20c831f8c1083c8f51602fc0c900df59d6600d681a9e4401123e71029030f4", - "032994e30ca2c634c3bc18f06d87815a620d11cac8b6cba574022935da073fa9a6", - "030981eb6eb54975c478f385d9b15e70e68fed1a00a83e41dd77e9d414c1a8d602", - "0210c8097f115030dfe91b70c5fff62d39bebe6be27e07123e3235061e60ae4449", - "0220eacd3619c8daaa614136aa6651762aee42c1ce22fed9647d10900109007761", - "020cee429e3ba873ed65405afdff7dd6cf23e0c4d87da939ced693f25c7ac2829a", - "0324eda906daa47078c0dcf00a652adce4bda46f40764ac8d577577b4ac8f8b98f", - "0222e62919ae2169c83934f55a247342992cf8d9562d7f6937e5b83d13c61debcf", - "021210ca0a3c52cee67ea9b74ccd50cc9851dae28de88356c960edeb473182cf29", - "02071d28aa0db8736358e343774026326fd200e1b0970b00509acc9e34045c131f", - "02209fb10e1a514d99f0d69f20572d7aea2cb733c74f8e201ffb5e502e7afdd00f", - "0303e0bb0767e3e8bc6e84011a6606c05f576a9777f7356baa54066b14b3bd2452", - "032c4532bc4c1eca2c7029c312d7209f4304e2b626e4299a5e6fe7de8d1a4a7fdc", - "030f3abea2b5415b06e988e3e0051bf7e13d982d6d2c2fe1e14c36de91d11e2dce", - "021656f6f5a850cb7a79ff17a3f7d0951f5465ccd7a5d785908a53b3a27d3da29c", - "0314d8c095f5f6b7f831f1be15b11bbde14482778cc46bb1a3a1804853db5cf0a5", - "020905633c0aa642a148496626878942825d6f0b7ac2e3d755866a8675b4dd6f1c", - "020f98a47d87f6d63d2196cf05df13e5ef5448a9d000c4665869861ae3af572c10", - "022a1d684df8c0bfb20580baaf8c626536a5626a52a1be270af05a9431bfb5f967", - "030d595bb464ecca16e15664cbda8f15aa4ebc9eb406875d2fbf985650c2b93594", - "0223e9a68b515a6f2c8741aa6d3b099d5d840d436ddf43ffe3296876c089a281c6", - "03063a4f95c5fa8e916b375f01354a5d24df8cbe8013c17ca2448ee523770000be", - "0225a77a4b4a61dab83b3875284d881f3a7da5583b23e0e73b13d88e85494f8940", - "02274aaed0e12e934e8a8de2d9c36a1ab453b9d34dd8a6c2c510a90e7786271eba", - "031e2105014161a96176b0af3955bc675275b874b04d87a774d16c9e5aaf812cc8", - "0206278011c2ba92b7dca26419e1ca41b6f72503d194d504d49820344fd1d9776c", - "021c97ce68d1735f10c3bc0d5e9a017b045cb6657b2386be795bd12b71c67284f8", - "021db8282321cebed6ae0fe69c24b6eef19cf2759e451e5335f1880812b8b569f2", - "020632f8501e427d45d90dd6dbaafb45266742d55287d86bcbd4d2b592cbd6f913", - "022975037682213912561e7dc50ad86745d8add0766b1ab98aa98b9f8b79f9b3a0", - "030c3db5c9e83d132e0319c6984c6650c018a84427d693bd71c1cddefa5a84299f", - "03157170e025c996c0d404fb82f95d2458e13f8d2230d93c7e141da4dc0856f348", - "022afdf387b026d1b10576c59125089b9b68f0a2c948853a2a8eaa175ebc478275", - "02164009ffcc2a0b9a811b7dcf337de400927513d9dd8419242d31b3827c221f3c", - "02299d38cec72932389bac2443d75d2ad3ef7c536ac0324431d08f9c051989f146", - "0329362bdc4ec4d33b0fac898fdd86f8b97906011153f9151c800fc4a4ff6a907a", - "0208ae6cb9a3afae19889447a00c192ac9728386a483c8eb87521d7661dc6598f7", - "0205710384fa8ebac2f6d4313a7d80ef41099cf8bc8172f64afcedae179fd6baf6", - "0304832b8b15ffb3683c16f45b5aa05370cb3475eb2cbf1193de07dbab9608e3c9", - "030514f8b776b14d4c5d1527db22caf9ccc3215372542e809ff93f2b49f9778138", - "022d35dad660027af3e043b9bf3f3bfc1ccde67a056046e949ce327730ff78a1d4", - "0206becb6766c09b2461f2e0d93c4d96e6d25cbd99f7f6455a18e067a49458eb4a", - "02194ec2200763c4c467e38a74d4644b720c9c2a435068b9da3c796162d24da99a", - "03295d8ac499925272fc11f9f7045accc879b37b8f95a282fc04b43da54261e934", - "02050dff8409a92ab76c434cb2cc58fe08df34fb6c8195f4c78e1ee40f6e2c0ca2", - "032bf05e6ec4bd3acd93541ab5b3ddee776f127ab1680d722cf8c01eb6b65beb46", - "020cfdc37932e6277f5f74c32c833f8fa74cf8e99cd0a300ba6199683ec4ada486", - "02184c42a4d8c584cf36847bb89280a629a6d8a392a3f5d1b09e529edda435514b", - "0319c14d0b1b89a045edc555e713849bf0ff2f98f06216ccde1f6b79e5d491ee76", - "022bee0ef8618d7c193494c00a2a3f34a812871c46b8eba0f0b71a63e1d39a69c8", - "032f67dd3e0a27ba6e5689d97e70cc8528826581841501016a644cedfabaab9c28", - "031a0c4f778adaa9613024de8ca428d08882706afed511b551446b66aecde9a2a5", - "022fc6b18d85c5fe99d0da5d5975815e279de2b06c17f5f34c5a4437808cf33ff4", - "031c58eb219dbf50da40f53f6c8969d75b52f04a5fc7a55759c5f1e41e20fa6b19", - "031a096f5ffc1798edd8e6d2550e74a5d8a26c4f5909811eddad20e3350383f26e", - "03023d55ade874a1b589f6027bc134f7ac3ea10b67d91bb5cefb434e6a7c2a7751", - "0302a202b92164030f330426509ab85873147e813a45f303bf13236e5dcf5062e1", - "030e5a76090cbe1882786fe0c927fff007e6218a412dc4c870b0bac24b5d850283", - "022bce292d4f1e2b9d75d6bf923c401fa1ddd83fba13ba16f38a81c29d8a81549f", - "0219b39f1061613ee98ce2169bdb446470832fd8fe2465fb85814a37272f51aa6c", - "0309666c0cd2892e0a318cff786b777bdebaeec6920d073c811ad636675049ac64", - "020c7f016cb71a001a9f412024ca332f9988029986317d039e478f9f60efb8a033", - "0212781362f91579c66d2d31f38e92152b665f69140acfc6f85275a7b01ceb92a0", - "031b1a2cb940b856505d39af2159c370af751f2707af541c337a186e24015727ee", - "030a4d5a94f60fc87213bfb63c08babeb4f7c84003b8aa32df81e2b02cbfe1befc", - "020abeb0710ae7b73e202d44c620578d940fe4eeabb2c6ef5d503cf6d46e81e264", - "0218c0bce36f4fc52396b8a571ad9eb9ba7dd454a7244ea8583bf8a7085b5dce30", - "032a3c8ad3613367d6a6b320dc3a6efb71a975a7584a8e9b15bd84dd845eda1ec8", - "02169fdc95373ee1250e7901ea5675cabe786672a7d413129c0305317220d8dec4", - "021d2f570d7d48a1787a24c41f89b36287cc1295058b6fd6c2f276cadfc8600983", - "030606c8b61b2781192cbd0b30448b923a7ae60b03f0b5784b7bab5c67470fb1f3", - "030a73f84537a798383182937b03b6a80c0697001d274c9435d6cb24f96a9e50ea", - "031da7fabf21571cb2b4833b6e57ba2e595480a04e05582cf862c3e92adb21023f", - "021f7809d34dc164d71a2924c9b72c754ee01ae13a56c08bb904aa5ee3085fff39", - "022cd2a29176447ca8b6c8e52372eac549c9a4cbbb6b7ffdfca116433d800ad3cb", - "03251fb47fb85b182f301a591e3c0ccd2b3b1edb05db49299851dab35a839496d6", - "0200eef798c6fa251dc3349c90738ca72cc08afbb9f2f35119598297d1c0557b34", - "022e7d0d8d540487d15ca61325d756cc10175f8eb2c41e726e6cb4dfb88c59f5ed", - "020dba74495aae754c7a5aee6034b434fa55baa89dce1fa7ed84ff1d662b48512a", - "031e6cc8e053222c0baefc51539609f4f9e95575dc3a5c79c7e808fca059811cb9", - "030bc2a1f047d9833b7da299adbb8a9e059dff54f9778247db684c16993b59f04b", - "0212daea614d5734650761b315086a2f66f8fc8e017fba99e2032e7ef6505a052f", - "030d73ca73066a91a629c689e6e3dd0106fbf9dc59e21d4c0ec8e5914730e10d59", - "02217257b494739372cebe9f03de97a9baad35f885681ac4accd4835c1985dda86", - "03273a1eed9585dfae5f91589e26b1a29adf27194ed718953aac9c333c96d9c570", - "03065ae1a6de9299728dc4bee22974c466ebb48c1c4d98049fddce229790c52ffb", - "030497fb193fd4af0d56a661ff90d297fe8eba1955a43273a4771eb5e95918fe9c", - "03066bc174ea86040f96edc96193b5de8266cf786c35392706d42d5df3c777d84f", - "0302ea2b642db818442217948fd4463f16cc885209e24fb24079992131b1db34bc", - "032d117ee6f5a021318b6fe2019db902bfd2ad0da6ca5a96c7fc7ec6e5a6ab86c6", - "03273a5be27d62bb9f371d10dee59d5836fe5052344fcc8ca371853341ec86e960", - "02120795475471cd5db2ed66e6871b01073fe825f02fc017d203194356fe15f59a", - "020e6afe45d208d9f5d4ebd7f155d49e2f79fc5c28cc7b4bde23e4955a7c49a4d2", - "0201f3e325218287618be4fae508e52e1e6d9cef22f63e5160c99d79cac3a06e1e", - "031455e9068c8eaafa57c8154858c4a6bf5f5a9144e5aae85df2dc38fbf1a97b58", - "030e67f8ba90444ebaeddf83491104bf8952ae16adc8bf57f80e1d31c21baa99b5", - "020e98e8d0b505c18517bcb1122c979af5d80383ed4d98345aa548f5f71a943fae", - "02241fac5cf65c9246a03aeb7ba194f346285ce43b8ab9cba44c23fcf28bb7ebb2", - "020a35836b7cd999f94d153c834e0e49382228c303ed6078ae97d2b69d2c1d0d06", - "0310a314e590738197842efca87d841201f97f2532ebb544e32288e3ba1cfc4895", - "0211804e8a37dafe8093e07fc40c37ac0e1281f45abed0d4c2b26511dac6b6ebc7", - "02176368efd32d109a54914caffd578317d302f06b201e8941cec2b8c9b343f584", - "030dec93c745fa97de5ba4d54062841a4e9623d43167599b2bf30ef4a5b4391e5f", - "030176e793c0e5e2a99566a98b391183b4d00b9edd62bf8c2094266d7abba78a01", - "022078b227aa9c9ec32ddef4d295971d0234cde7768cb6de81caf9b9aabf9b5fc5", - "02120e2da290b17d525f435e8eb8562690adfee7335c16ad38d09acd24e001fc83", - "0310e226ab3e40784900fdea1b33d4b605a13533765b13f9e8458d8c30f2dc6eaf", - "030e3ccf5fdbd9e1154300670ab23172ae826ae4e1d4d58d0343377906563afc01", - "0200509b6bff59ebbb3ca2e5e1bad2ae9be4f6ec93f1c6510686af0fe4cc0d84e5", - "022cd94e56e4053bb2af3d4910c5b9b33ffdbb501eb2f8ebccd3231ffc19b9b931", - "020564be63023ccf9c39e6e1917a255bb5690eea8f513a1514f2e1ba9458d40426", - "0317e0c35181c8aac8e1c7aa56347fb381a9b342de0c74134fe1c6fb6ab14b3d9c", - "020521e4d458afcbfb1116e13a0b2611d636d04ccd2945bc7acd556e92a2159003", - "021aeea364014987b6c517dd46f6404a021394779d2b3ea196f7caa166e8d03164", - "030ace9ca2e846765a5a4a50764812c393eb2de06bd4e9b03e89d5bb0a40fdd5f7", - "032e7df54168bb52f2d4952864781b7fbab2ea629f5d205782d155542e87c3856c", - "0319198ea38a5e77531d104aca27b63725d923dde2f42ec80008b1f2e6970c0944", - "022730cfabada27d9774b0bd7c7608d230d3889823255a42d7a7c8f2a1f9b08380", - "021363a820137a714233244a965779aa4379bc2cdb540861a3dd854a0a9cb4bb2c", - "03152c50a8110e59874a97eb030213ff4227e6107e08a3ba2d1feab8e5a702e2ba", - "022e8821663083db822f34831f6a2baba87b2b068371f0b98829f42f83dc6207a8", - "03229ceeb8ff6567b366558ed9868ac93bdd82c772b47f1a030ff255eed1fcf1b5", - "022f1a450a20e9e0b1b820aa625c6326c5cdf55ffca0743c30569496982e9712d1", - "0324956ef2aceeed2102fa1b46dc6f1c582125e0b0174decb5e2a3f973d6496479", - "020e01dbf31ef4a9fee910f57ae1a41da5fa12a60ce991eca75f8961d8a741be72", - "031996d9ec2a26b6daa44d9366b23319693f2d2177cdfca2ca2d189f5708785fda", - "022c38089fae753660028928def906d0425ba7f528a909e05cf2c97e1703024df9", - "032264bfb2ef9b3db299be94ae3de04afa44e776115fad7a48ba51a0efa139c07b", - "021ae1157ca6afb56b4f9cf8f56eccab9965b82c9cbe8e6c116264d7935e8d8f6c", - "0322caaccfb4378b67607c7a1a5ad9992dbbb0e934d6387c0a4c43f1c48a4943fd", - "032401bbc18a2ae60d25b1236dade415909b1ae2090aaea4a54b918567c408f601", - "021fdc5b66cbdc6158e2f159cb76cf8838012c2e986dbe0bb8245b049e996a462f", - "02093d0fadbc52e13f08de31ad0011db07d3fe79216d7ed0bddd39d397b26a2587", - "0315b43284a469fb9cb5acf842a05ffe541c8d70866b7bfc86ed193f9e66e7b958", - "021d94b28d5ffe4605a8bf159a9ce99ee5559aebe6a65ca80179b7491dafe8396d", - "0324f83ad929956f8262f40a8da4edac31f02b1c39a4e91151fdf4a5105e974033", - "03236d3fe91c4d4414af826f5bcc4a988a84e1f7773ff84993a039870c9ef4f3ee", - "0300ecde93f53ba67937683c827325b17fc95ba83ce9adeccf9b6cb6d32a6a96a4", - "020e781ab1e5e12d5c9b43f699030a3b1e47c507e2cadb753407f6cebce2a20747", - "0201ee6750054e62deb74ccfab67078cb8ea01c084011d57b781ac6563a2cab94c", - "030c3d9862b3a9c1e6713efa929162cfd686d52e1b7353b2754708a38e80eee52d", - "0228eca721096a867bdf251be6ee4f23031b4ababf34eb96d485ecd0ca53f1f1c5", - "020d197657c269479e258429310bdeae77f4bfdac0866048ea3ca71e5e005a54e7", - "0227380d45813b1de3d386cb5d3414348cc023483a3503881b8b44f6e7c44c8fbd", - "022545f88046487b66f33d37e2bd51c1fc6818c6c977415f2a9c4088ec1bf38c67", - "03140e4f3c8533f0317d32dbc194b37989561f7128d9a107a65be44985228cefa4", - "032b8a3cd5a10ae247197597f095035faa747afd1c1f3efb242a6d291f98e25fcd", - "032702aaafb9624d6559751f462fd113041ef0e1d6564b676d76cbbf31941cc70a", - "020d3ff663a5d554bc3621eba7d3bccfa30af87a21429d937b3cd71006a7254531", - "022db123fa7b51ead2029be321a585e1ffffe14807e5d2d1f7fd4befb8156a01b1", - "03040f175256f556666795664d0c116f32c6ab27680436e33a24ade12f75bcce93", - "032fb5fd7e4ee274e94a85c8763db6d571a6be184b78aaf6e955665b76396fd7c0", - "022ceaaa69ce5ac70cf1e1a7c082577cb1a2dcfeab308ce157404f96b97077e381", - "020697684c99e00a2aef174454238713c4535be9f1610a12f399d1702d2a7f0bdf", - "031403b49a561322025ea7efe497cc8cb4a6639daf2ba449e5d31bf5d0ec48b114", - "031bce5504f9610ab1c0e5e59f07ae05c1fe98299aedf380a687f5196b19d37d63", - "0327fc83524325552f4587e4f218f9d0d70c41ee0ca5eeec020da78a48ec9f5f45", - "0229445f1139da156c62994c51a5aa13751b5e5e1bef21fe94533fe407a5d7c650", - "021329fbfbede10bafa4c5a13eaaa52cf41a67ad9dcf6ecdbc5cd66230bafc20a6", - "020db8d858eed620338bdd02c44f1af1470d0a7587ec87057e9a4c2bcd674297fa", - "02190f1686a9f9b2a3a40f940842a56f461fa1ba2f9570b392040aa75e2eb946ce", - "022634dad57085a05143473561fefb6c6ec1b82cc2dbee625ecf93277b89f43e1e", - "03288a045f4f1a644cbacf466623caa556bddd9ef0ed0a6717c001e02e660e5386", - "020c33866abb09282a8e4cd894b2ae11d82d692f8d935c9347f792f3f806dbd116", - "020f03ba0e19efc1e2348a616555272056bd8aacd00c7cc89a6564e5ab7a9fb86c", - "0306c52a0cc6fddaa03e532547df26a4524728f23cbe8340a79bd7fb0957934980", - "021ae414d43e09f95acc334d39b9f52712fdad39a83b2976b92b22dcdd2546038d", - "032229fc0a6581f2af773d2af3c70951deee76398ba8fa874ce12db6fefe381db7", - "02199fd8c1c11330c8ec1712e5601458d6a15c8fa1f44030737f19516222570a69", - "0226835426053729011ebcc15961a3d40e627424efbcc1b446a96c5a1964bb59b8", - "02071db5cd02fb179b69a3db1aed80858c45a4ab17624b24123b190d6902c0ef84", - "0308b5bf4257b7803c48b293e46fdf2d78ce87af8ac8984cac4c95dbadcef50e2c", - "0207df1e5af1a19ba9f90b2f85b095e8c190d47a56ab69a8792ee3555b147bdfdc", - "02060f2c193cc63419967959c8f87face9e297b49cf71e5ae8f41c7d4abd24c2b5", - "032c559137ba4f7e464ae72d3bd5f723647a29be4306aac46b7a8e0808bb7652c0", - "031cfb09a3d464ce6a3a97492fd350adbaa1c53e87bc010ef02f0c4070db403ef8", - "0230178ef2fe75f4145254538b28e5e26c866f27d2ed871b887851dbc5618c4c8e", - "02200c2365c855456b5fe78f3a3a17a2d1605027ba3496ae6ecc45c6e2f9cece38", - "022f11517f65fd63c9ec79a7d73fb9a12f179018bc038b3c31a9f6a78493610ff5", - "030733e969f30bce64bee6ba28bc7643c258581e4bd0c3204e0465e78be883eea6", - "0206dc32c3814be48dcd18e9bfe81b7396ea1c02f5866b7a26c0bd44bc619d8b19", - "0326ee634b4ae7b9eba6eeef80ddb687a63b16e839b4d90eb7df95ac3b76a95212", - "020b884418c6d707783e1cb150c6ef51ec40abed42b199c393922909bdb5b52681", - "022fb1150cf0844e959f7a228fcad78dd943496a38e8113762a63dbf274dba8979", - "0211f04791e44506560aee7493851a4db09d820fdae24977e3e77f9e951126521d", - "020297c788545c1b113da39c3f957bb836e3ecd44504e446aca4d752f52a046186", - "021498ea46591ecf2eaf7dea9861cd7159e1dcb69f99a4f95db14c4784d2c9b27a", - "022d0014fa94718fba60ada09e32bcb75108b0d28c167d09aaef9882a0a5f01ac5", - "0323dc2df3eeeb5064967e465f97c9f85649e3dc7ee1ed9809f976248343b0ee93", - "032aaa398507b4ccf0543c4f415401bb30f1dbc37c684e7377c3dbea203d5ff35b", - "032416419d2f4a75a32c1ad5f6680b694da690da8f08c1e7ac40fea688d0204a23", - "0210d49eeea5fea01ecba40fea735cd28992a0edae6edc14ebb49f90876d6c45ee", - "02220bf5553f6cc2129da6aef2e8a42a0aeda5ed5b6f71c32aafc82ee8fb0e6e03", - "0323668bd98c7e27293b9210cb2f36c103b1079abb53798b007d47bdb3b08e8135", - "031e8b14131c2768a8f7d410acba1a476a7607fac336a61e116c5670c57d0700d0", - "0202878a3bf257cdc05f4ba2d1fa6cf19342cd210f77890cbb1af36c23466a0096", - "032ce0442ee73b62baaea4d44ef1017c5346b4bb990a23345300d2823b93e35840", - "03185579100ebb314b2fb22822828eef22fe4839832424dd32070f52870f8f4833", - "032aa4b2d9789431c39ceacc58c1ac943d9d2e56eaceaf4d7823c2edcb0e8691b7", - "02193c32c2ac8fe2c5901a6d3ec821f90bc94a5c37db6920885be99321e8d359fd", - "021e123516775f4764ea33c50ccc1e7a63a8a068c1e5a97f63a6cf338fc2e9f590", - "02147811895e5585c1e2f4771930dc950759145d3a270af95031821a199f488ac7", - "030463c51634db1fc10e4f5eebb342450719dcca85169e6cc0f7eedebadf1a9744", - "0323350f6115dee5fa0d6e57f1c9909c37c354f561649c9e549e0a5e6b243b5c34", - "0207e74dba7534974fef81c8c5f0ece37f39459b4f7dd99be98ad30a62c71e7c0a", - "02029c6eec8a8850990cbe0684cae22a47208f5972d604a066ea7d0ed4b39177c7", - "032c0315595493430b6831221b7f0e0d340103ac57c439ff084477e3c88a9674bb", - "02019528aaa7487600b70750436a39c21a7081e1660c1320d68c4addd385b6e791", - "03047c34bffb5f82035c6ae17d51d6789c55e6e0fd689bd25bea064a3cda453e77", - "0309dec9557f5ed3fe3c1eb1681ceed7c5fe2b469ab6e2d615e4da8618070c7c7a", - "0309119aaf186abb1a11a2adf0b681523ca7884afa117de37658d7ca9c279ac2d1", - "03054293f264bab005ce0efcdd2c7b4d6a5a3e3ada8dc1348d7bf29e879d372fa0", - "02222c7085af41657173252731e825c82ea2d3a91790370b3971fdb715115a4057", - "022e7ca1b11a26decee40611d2b817f2e1637062c188ebed2a1df9f7a35dd13659", - "020601ccfcd4b079df0ed8e8033387f27003e132574f339371f85c8b1dbffc642e", - "022e2644d9e054f9f32f48ea7b03ba6ff917367249cee4b24715dd054d2cfa69ae", - "030e86bbc0397c4f8c3a889f444ce715d3578fa0519cfbe91f8931262ed57411ec", - "022f12af2ac5bdfe575c332f5e8171b8dd75386581b0bc07bc2b7bff2abbef34c3", - "020e911b0cfe73de9f4a6fb01553d4baea4ffa9e1414e504b1dc0fb81663e7c211", - "0309e4959f515b0d6bd9188b10b22947f565f20f7a51f2466c334f17d99c6bacec", - "030d961653e11f4e3593428908081f543f7c3b4a10ae7df064246de702b0742a17", - "030f7156302e9ca59aa034f121e2ad7fb25125edba5da938006aaeeaee994f453e", - "031f9a6b2f65fe98f5262ee33c4352f4d48cff0eceafe68c4432b5a8281765d37b", - "0225662a39e91cabe95eab50ddfb4002082ce2e2ddd92d02b76554d0e6ddee889a", - "02071d1020e5765a52fb9844f788a4fbc8d49d1b166d8d89c1f3469ec535322b83", - "031bdfd55259cff18eaf985c0f79346f3f6e8a17ac8f6e85a6630e46f7bc12800a", - "021298d46b60b66b46ce922bae746174557fcffc09e8fed38b89254be0b181328a", - "020350d3e1dc20712ea952cc01a91d29615aefa63664e6fd106c8f07def25125dd", - "020a7cd105e6c3ad187aa1b8684f0dd6539f575fb81058716e78cc54ce105453ba", - "03108bb41c74eb27ca8b48e5163fbff397d4db21bf52e719e4d03f50de5c1a48aa", - "0215f317f25f1e3f6d6f8fb48b39d87daeb801bc0ab4d5d8105406ba27dacb5e7d", - "0211c13595d4b15cb863b21c5be8cac7505976bdb312c0d9487a8fc452a2b0de64", - "021d89896d50091bcb4a9690a0bd0ad64957c29cfdf2dce8ed6bc5dd9feeeb4cd7", - "0230034af8a9019e0ec8b7f5ed9ee3ca565461380f1f81ba4464be50d3dbba7e7d", - "030b89cdcfafc3ccadc58b57c70af14927cc1a98e206853955c2431567ee4b0f0f", - "0224a67e36579ea120aeb82333c3ae3c2f991330a77ab815ec43e2d9fed352d830", - "0322b1fbfe3271e2e123383b344860873190f7deaaeee11bbf440a904ae44b237a", - "02062a6369323dbedb78a251350b33a0315bf3a57753e78673da9681a3dedcb21c", - "02297eb028079f4b9ddbbc7146c82727aeed2b39598dfa59dd3046370383f30132", - "020393262a0cbc53f03e3a157f6a1ed068d8b6858c53e8659d656a1aff9c5f8253", - "032dc4708c6afb321f86967f6731c23b47d0fbb790c3cd4f734ac562271d4f69f9", - "030569916f138c71d8287d5ad35c62aafd6779ecbac8d9cef535cadd069c8ee97a", - "030aebcc5c2619c4e38ddcfa4e8b10c464ab27cec2e20f46275cb832a3efc7f1b3", - "03088d0700ec36b0889f81ffa1d06456133a4e42814a42e8fca38376bda806c570", - "0208d49dcef0bf7ac6ce9fda573c9c5ee8c69668321ea50b795991c3911e2efc5c", - "03298f1fa95dfbd8e7a688a5cc34c9ac9fce655d8b335fb7b106d231902ef742d8", - "0223b288fc04a67471049356d172425e9e38e5a2e1461d1da7dc75b6cf5821998d", - "02080e5ade16bdf5ac3872295d64699dfe25e8059ecc18abad695bc06e2909c95e", - "031d58ae872dc45fc976ba2f72ae4613beccbadb0d263989d44ce4e0346fdcc301", - "032ff731bfa8c72702d1b826c7aedb2f2e6af1455ecada609e037d77614e8f4275", - "030738e0f0e7d383d05d14043729293c5b73f01aea74fb85188f736690baaa546d", - "02265cd3b5fc59be368fd71629534edbbdaf73f738295ac88b0e368f209de1b0c8", - "032ec71aa237b45ed8be586946665ddacb940ec41098e472a6b3a7aa1a8ffd1c1e", - "022b12c63e9b99ca6441c0a9ebb367938af9089e369b78ca99485a17340c6f7ca8", - "0302abfebe069ffdd9b55edbb682e7807d00bf26fa42b46b2bea989d618f66e689", - "021a3a752759a431ef0528aeba8b5220aa7583c430862cc130b40edb4dc6b2dd15", - "032428d7c6067a13ce7cad6d6d66a97c4d3c629144db19715b71d8837a65872ac6", - "0222f51ef1af43278f315c7e80aff3b55e85d196fd8dccc1f0809b883ab8bc7a45", - "02113a2e264a20eb6a289c49b74ff673071652cfd7e8bde2388367b4fe57d0cd9e", - "020e76486a41a3f3eaac8280d8957864d7f393e411c7cbe16a922d0152b2cfda05", - "03180610120c3ace33c76db93783c68d9315a0bae48e99ca25d6dda4c9e4cc5ff9", - "0211076208c48ce8b66e7d352ccc98b1f298ffd0d625ef4fee6621e685ec9f9f3a", - "0305c7acccd2ec2fb2e64de02feca6b25f72b7e16a6f2d05cd2037efd3cd098c04", - "021cc03b9c785149a1b8e29fda0b53a77c7d384ccf45c0aabed3744b61a30831ad", - "0321760db91fe6ba0542a0751a642ea27f859a01bf6fa77019654d6577dc3cbded", - "0302e10fd5c411fb61078c423d8016c3f79160e6217519536f9f1e1c9448140b1f", - "030901bf3d2d51dd2b08d186dae0221ca664df68b9acd6cf876214631ae5e21b77", - "020fec7eb0331dc8ed5b2867beef5088a21ff0f26d4f980fde4d59c48d4588a9b4", - "02213618b1c7989d22c22c978802a308c26e0d4f3ea1174ca69912f939fbed63ca", - "022c91f0fde3863239693407669aada8e772f70bb70549233f56ad0f139cb6ea15", - "022934ae0defa725f6f2deba8c070dc94f9b413c5e1b6b1f4a29c8e197fce811f6", - "031ba88a300a3a83d84b7560b2dc5465b8058fea0735f2019397660ae851c9b689", - "022947fb4e541723f890411e90c9fb4a513f849b7bfc4e358ed43b155e88d11235", - "03117afc146662905f0aff9553ae6f17f5faf1b8257ac2ace9f97a1559187d273e", - "02165a4c22986d07d31b38497410e30a45d7dfa48b5574ab891731bfbf066cfc59", - "0218a39e4911234824c04312963d2cb7360ca371fc3feebf1ce655c6d78be1c53d", - "021636860627bc0496fccac4335e5522735cdfc7f041fc1b45e0434fab332c465b", - "022da29a34260bc864b4ef7e05929a831ea62b16d363deb0c78c0b4f61235a7048", - "032e0b650f486c31347cd0aa54743b139075bdab6969c0ed1e814d9fae10ce285f", - "03040f9fd82dffc39d5935717795d9f063841629f1367b24aac8818f053d897d3c", - "021047d451aa730b1f22e446af284bdf7571f0b856546106a695ab724afdeeee67", - "0313e06b1e295e7009f821c2166418b72a9e1470104dce60ad2e65dd96e5b79670", - "022a50ba700a55d648bdde0625e473418da088fcff0c9b9311bc1f38f9316f07a0", - "0325bf4e73662d717e8a907e1c1a526018abb612575e73cdc8deee44f1ce3f4865", - "031c9a7e0c66f3699c3facd49b8d9f4651f404af965e448b4d05a130bcc7b04ef5", - "030e1113a782613739c5d2e99e423b368f8dc9e726e83e6209612d3cbbdc32a440", - "032e6af6edcf64fc138c5f5af2d0203800bb17b35a1a258072e66178c35a6aac94", - "0208bbe05ea51b865555ec9e4afcf667905f21369b12cefec3a626483c88b75abf", - "0209d5aed27d54e4b19820f2c21c360d8b3432a126e35e9cdd5317d8028f559ddc", - "020c034100e2d48e5a1e932947334d9ae6d9aa4b95146b306c0144f27a5a9178c1", - "0324263afe6a4510124e97a9015dcd5e0eb59627b1847c56083425b7ae4772da15", - "0327e8d9fb0b3224544344bc7e811eb25670093fde2befb1afd8303d2d6dab9951", - "021c1abfa27ecd97830e60cdccc352c0486226e508b4aa1075ce2c13f506ae21b2", - "030a85807036b1687f0af8510d3fcb67e0c12bfb9a89d0f6c2dceb8538da66d2bb", - "030311be8d761573571f59e93470dd705219e617d4372f2f1ad2910217a0e52f71", - "0307e24b751da15b563057465af59d544917d96f6281b998449faf6a144efe565a", - "03086c3bf82da1cdf8d829dfdec33035a96f0daf940447411ee04e0f30840bc134", - "022efeb759f310e5af346abc629a12b022ee694c9896897ca1ac1f38453009c8b0", - "0208ca3500be1c332d3816ba417b075f8dfab2c63fd9b71a19d4844504ef12394a", - "03142f20835005d984ae17ac85b91d050b5a6c91a28d95bfc78964b0730a91cdfc", - "030ec976a353bc1fd8c60a120b7fa100171bfc4cd2a52fe28b80bface4cd39133a", - "03196e9a44da8a25061aa09ab396f88914f1bcba6ebf645d0e648073f8bdaf68ff", - "030f43b45c28dbdff7e37c77e9001f2dbe683ea966342af949358f10c2e21bc875", - "031d529b472e2b08181d456f4c5b5e93a4c57240614ee876d82eeb8325db6d896c", - "0325139f424e315f290e524f1764b64980204545932bec76afd66bca994db597b0", - "032ce254aeb9917ab024783573fdd09a79733a427750a3c71d4328b803f6be846d", - "02175fdbb2d4cdd6cb0fdd846754add870cccf415776f939bcb42e2823c93398a6", - "031f1f51ec9e9f873a2bf59248ec65298962bd5c5962cb653925d653e9a9c56481", - "0307a092177048f30fbf294399ad27f235574cc52c4671e63e0ef7879e53f3d856", - "0208c7b2144dc7360f4fc7dde5a16aef615f502175177a913d6bb5a1feec0dd114", - "032f7e82458c07d893d2b87810b6a2109e565e4b188bfd60ebc3ed2aae890ae4cf", - "02193930e5dbb6e0a25f8f70b7caf74197f300cd04dbd02822ed0981f4c444b6f1", - "0220b4e452ef50132cbc23bdde370bbd617579dc85cf17b5c689c4cb0ab41788aa", - "0315ccae326b740849733190f95470c4290367da99a6bddd223b869f4f3d39c0f0", - "0327b49236a8d69ed48c6178c373a049778f451b5fda2e761fba0747c52e4f3b5b", - "0323770473524f01d2d34f9b0dc79dc78234b2ee98901a41cb756f149540f8b6fb", - "03300fd4d41da80b48b484db844120c33f75a2b29df63ab9d412213f506fc529cb", - "0303165307894afed7f083cc3466deb3451055482a70eaedd003f16d4445dc5568", - "020d2dd3921b5c61118e390851086412970e2338582b3319eb0ce7f032e59c80f2", - "031f4eea643fcd42686b2127b63add56e6878704763c6c5de4be2095932044e954", - "03205c4d9eab52cac070fc0af6df32776dcf22951ffb90ce9986cb035d9767d35d", - "030a98ea88a65a16b7e00854e2a8ce5bc4161f3d8ee8ca817c1d3f6196103dc348", - "0202b94481b84f4ddfbc0af766903c0928cf6066674fe3d8c0bc99c50df2aefce6", - "022b84f8d5c41ed69c2ce3c4c7af8f4d875f2a03592423de24c5694a4db3a42362", - "0327a639d040dcfd3d63ca1a71efdb1a8586c7ae7640755ddd36c9b1c46ae8bd70", - "022bbb6276cc959b1a403bc267356d4e47709aa49ebe8aff37d5196318e71a5c45", - "03051c5eb5c09edc8768da8160b9a4150376d0a084e0da3f7241469d2e9f90a511", - "021d104560aa1b4bd5ed39b020c9fffc51bfd56bae0719ff46df37d07ba5b0d8fe", - "021372dc64d7b1a0a74df016a1d32ea7191edf63e66321e876f52ea80c65b985a0", - "0207e2aee5aa0939f69d1c52884daf077bb3db55ff9c0ec6281f7e7b07dd472dee", - "030594389b2b6b6c22cceec1b2cad5304b409003a9cccb76ef0f26aa045d7aebc4", - "020a8c8f7a1c74ef12200ffe6b5647707eb0f4b3ec1441a2bfc2c70dc72cf92850", - "0323a44b88df7f64516a8bd2f0bd373906c32668856c50cb2c59cb55d4af1f3b78", - "031d37e7d3bfbda752911632313a259d3f5fd34bdc85eea16bec3837954ade5c6e", - "032116fdf4ccc117c004913d50b2964315e1db2946d06ef74753f5e54a5207e001", - "021a08a2ca30b8873ed7039018824362f0fb2c0fe04d537482db5dbf6617db3b1c", - "020525be45fade45cca203bd9f068f154e0caefcd717ef52d34af27c6064d61cb4", - "0325d2a46f1a21c15151ce9ba8c43d3ea43b4b8961ed854e9c7c587a3c626cb478", - "031c7543d30373eea452d163ad76e14b9ab7c2f7b3de2cb7c815b77bec59921dc4", - "021ff9135082b56c4446c45690d326a6d58e79d02a514a51b6f12911819742c4bf", - "030ee58ad4ce4dd59de74bc34544b986e1161e0fb6feffaf2533df7748a5449da3", - "02192126f7d48a4427fc652b1e870c9c14b7a4b3ac576c53f2d78549b12026cc43", - "0328c8b5555936cbd53ce2362127fca616edd3fd772871f0c8f13f81cca2968d14", - "0221cb5c18d57a87e990996bbb461a2d231cbe27232efe0b7185dbc589c6cdff78", - "0206310247f2b3456fc3b118e42153c225f988e2472f044bb72258cc5cb1a9d520", - "0319c89a1e827a028e8a775dbe119e3785553c8c6614869a3698ce7b4545273820", - "03217b6c700e04dcdda303f029affde078856cf1993d94190206426caad689e1dd", - "0320854f4ed0c9ea86f5df4877e56a0bd79ee725b12b691b21b3a08f7b4c6de6d3", - "021dbb3652b001fc671a5fed8fb49405099da780d194340d9490f4dd172909e118", - "032f1093311f76d84f07835766647d449a9a062671f2621f7996df58c049f575ba", - "020c5dcf2cddc442916809fec65b6ba6907732325770dba1b0d30b6bac53ee8221", - "0223d068a5f96d71d7dd164ec0a6810f9a894fbe103aed30b06914b038b57eefd2", - "032549cca4e66d18b8743c94804a69dc58ef4bbb4d0eb6bce88a0392f8a8322b9c", - "03190696b67ccbcbb3da728bcb57d4bd165c9ca69934488f97307ba161e3750e05", - "031c1b786c7166ecb0adddca0459004b135ab994d2f898686343316c4e1b58d399", - "030b8aec391c874e84b668fbddc5e0db95ad4c03729251042a599ebe38be1a739e", - "032225904f35ab27f74bb68047f986527dd274aa14f338b7dd232a63e86f3a4161", - "031fd094a6c8a7138ba97451cc0ce58cd750bc7db8ae1cebc3e4ced70f44a0eb56", - "022580fc638001f34af40641d996dcf3cf1a6ce94e0fa5bf9b5ed2a041367bb74d", - "0221d84bf6141bbc34ddfafb5c6f240d79c810822cc33f5c8f1c6380baab4d3a1e", - "032f1a90fdb7076dc20e7eef642c50f8830a5e37ef893c0d497017962df7140e64", - "021bd92634c043c7e3a31d7d71197d6f4b053d4cf93828e5ddd74569703869ebc1", - "03039aee95a8538795cd49c95a2b4963352cc7da12fd6f6fd50ee127d84376491f", - "021beac392e0c3470efa3237056e5352ff4798ff7d14cb6a6c84492500686f6072", - "0219fef2b9e796e71561f0d5e9993645db07e38799ef5a249e4f775c2fb5feb97f", - "021686416cde9528c46444e7792e2f9d75e48a7a14e85a0e494d3e816eeb77d02f", - "032665b1acf58794894364ef9aa7b442cf16c41a9ab685d0a914258bd679afaf53", - "03029d90cdf39306da408e2bd4f3f3e53550ee2e729011ad689e02c9f9387f449c", - "022647adb91d13a1c23a9d603613f844a10a3bcdf83a5caedeeb1dd6e665dd0f6b", - "03009ffd58c7bdc54253b0da00663401bbb5ab74df2ce2a31a88938d422929238a", - "0228b8592e304131708d5c3bc4501ebc2668fcfacd0bb9385eb014f75313421dc9", - "0228ad259722e9b4f13696be0221f5b3d75c8ce8d13e7f000f471e3bf1c5a3f02f", - "022bb458cd53e481335f098ea72ce3ea792a09615c9f98e8115b809f6be85991e0", - "02228832d02649a0ac402204360093d10e4a1a23176cd18f51d6b5d6230f29f054", - "032a24c7be5b547ea824b9e77ed8353c9f57e5b30418b157e8a807e49865db09ac", - "022ea84a02d78424c87b136e99dec7e435a840dea6926ec3022ac6826e1f2bc568", - "022cfffcf81fecc91aabd8c74344008d7fb04dd2902bd3fe202d181499505c18a2", - "0307a2f638912f26d55552fcbdb1fec8fa33422f5a53a42aa013a691187320e7c5", - "0226567bed2fcc4e8765b497a739410d209b08fd4e7307904d59aec31a2340ae04", - "0225b1d698516ce8faa32d18cb2063e8be945eabd7df65d3bf9b7528a6bbd96ba5", - "02126580a2e94fdfc56a0e45f9d8a0e7f627f48d08b0c6b5cd3188cc034e6638c4", - "021a0ab0977531dcf466fe154f994537b8df98ebf328a21d5f0c962cc08a81b814", - "022a3ac5511c1d73ac17d2f5c303429c65680cc1a43294eaa1d2b00b5c696c547e", - "032820b8b23551f5c0de82bd26c7ce031c78850b032f240c4885b322e20fb3320c", - "0319e342e172440698a82a699c44cc1324d618dac62df621bd6f12026d9b7ad0e3", - "021a15ea3fbee67ad8546c9fc0faba5c1f7d5f9d331dbfae309e890e3951c70da7", - "02070b0cba39c5048c37b7325b074f30bf083b85a8e32d9a5c7f4f9e1001880fde", - "032d3dc720ea9f58a30d040cbd5ef69c543b63d397c5a724ef8a14dc9f2f3fa564", - "032d21d9fca19748c3ca3d6dd8044b2651ed6ca3857fec22a9b49a47a91ca622ec", - "032f99c969c0a9765b82078c9991be3301ced339cb1bc9c8f664d41ced38f6d46c", - "020f49bbeded7d33f99c6d94198dfdb9dd311a02716be5246b6e3a2d168ae8fa0a", - "03256304645505ff227e1103281324221fd01efce0f8a9f3e4a2aa97ee231c87e7", - "0204057c971919d95155b3331952a8633d1553f8fcad722204e046c421c61652c1", - "022e87d31b1885269b65f143998fd6ba7babc585e387421a44e0cf6655982d3b29", - "0229f09c35745f069162355572d459a094e5f360950f8f514be7fa62e51062fd0e", - "030bd1bceebe6be3328fd5bf6731e594fbb3798fe0f65858c26a5f46efb7ffc381", - "0325eb267b5eca1e51bcb96ca6d1ce52c28ce2ca0267e0a386eeb2e9e6051939da", - "0328937f511211ac4ba11acf2fb991ea172292ce9975d687fb2102942e80b0e37c", - "020581fbc29487d1cb07a9069bc58fa849ec7aa096fe9d8454ee6596097cfa2eaf", - "0324d15a1b3d3a073b380429297b4c7656f3c6e5d46323d09999985828926fecb5", - "0209603d7e9fd756de33b32dd11b2a0e98b1de2ecc6d9030d72d7f31bbd39a5c7c", - "0230337ae18e0c7e8656399915e494c63e46d3826eb4797f14b767ca68328156ed", - "020197e1dd9d8d68bf4d34a09d746860a0727367c88c98091e63c63ad0a698385e", - "03077d2068fbc0c183a7dae6df36dfe9b9ff336e0820170be44e4a45004187aefe", - "021f18691db1826b94c0990997e0905ba920a78f7898280fa3253195e9f9c76f52", - "021d1d83dc742832e90800c49d2b5d1ca2d551b9ef82dbd6e70e6cc0145a557134", - "020af01c3e2d580ef1676d093f07b6b4662977b50e1727605ce4ab0be7fb647be9", - "030a86e016db984fbc93eb6c78a2a69835cf58ab7b656585c316498b2bef8dc5fa", - "02234b6938d5bd13822420b4688d7903a672cdb85a70299e7ba08b58aed753c75e", - "022270ac214a82e200c4b726c2002f43765e99e53b4ad32512f55158a1848a2276", - "031103fd26e82c15f57ccacb6c1f3474ba0fde1805879fc3d7110cae0f7732064d", - "032dbefd0522439de9af65fe37b284c71ab040f053c9d0b26cc3cfe966b394d11b", - "030a3d3070596d38921fe6b23bc17b7cdfa83837224eeadae5c48a6eaf1db5b8d0", - "0315aea6acc057b2ee9e3acd7d39b6c3c45de4455bfbc98dbd161a3cf0a6617a48", - "02066e9760af3edd97602aa4475d6115b056a9ff6f88df95127b5a94a29b5c6c28", - "030d7e9914a8809d234e305d62853763e8b520b69cd560dc5ab08265980ad1701c", - "02152974321bd52d5a1e2368ae41eae4d1365495d135f34e0018894325814c3c0e", - "021f80b6e749b953e324d6cc659c31914043b47e4fee9f005d859f696a457238cd", - "021973fb272d6da56b182261c79b80254f70a1a3de82adc83434a1b96123a83725", - "03117579c6ab3a635edbbc1942e2e1124f6274e9f7640ee3746f559fb064d3e72d", - "02272efa91698d389a45a214f4ac692bccc691554dbe3d9c614560b50fab5ed552", - "030e8fd4a7329c96529d404f42e4a4e2fc1cf19aaa854797cbc11f57d7e501e1c0", - "02128860302d0755d981eb628833c84c157e508e686ecf0f5308aa2def8fba5108", - "0328917709a8a816f4760998d8bf2b11f0e8efe8e6338e86ca61601af86095964b", - "030327a1381eeb20a5628eab3e908c1230be2fa5e8281b5ba2faf32cff528c1cad", - "022fa0b6db07ef772cdd926806ef76995d84d18edb2d75991a400e5ef80d2d005a", - "032c968454c21834f042152e7fc419583b5913291d26237239a0f68fe32063b9cc", - "02128dca66c75534f9b5e812a6a302fdfb0fe4a8a7c46e8518d66e2a9f9544842f", - "021fede57ad1fef28ac955436551f5877fe23d25f05bad3b91ad57dc2ce0fe9d9c", - "0214f6d9b6d8c0c67436f0acb69549a6253b711ca700ec42c44e89cd0caf4374db", - "022559309874b0272b0dee68d7d575a84e7c3396655bde6bf2918e0c5ac0f155c6", - "022eb1dcb91add87fce4c22240f1c5c9e08c9d70a079fde3e0d6da276f65c83543", - "0201c43204aa6c4cdcc7b6ac9ba4fcfee1f72dc3d9dfd651748f90efa4945f9476", - "022ea8c3f0c5863dba071a845a2764bc01057dc3be5112973a5276f028d1097a8f", - "032e338df07f89edde2695ebe0606c9cbe8b66b109931d7dd71d7ad24591f48f21", - "0214568a769ddf6fdb20501e658cacb1d7929095e095a78433309657eec230505c", - "0217017735dba00dbeab38af0c3c3976a38744e75b0f3e23d40277735b15c518ed", - "030989982bf4715c096fbd5d9fc9d3aba899446f5c7f32b7bd26d517755c2dbc81", - "0214b76ee21caa242244eecb511f24bb03ae7ec70a5f6db5d51b815f20cd42706e", - "03222993d968eca357f8c031c59b55d4c78ad60e06fd84bb53417db20369d19bbb", - "021e2b542b4ea7901c302031555f3736d0f545f22594f45ae68f9e846b15e7f199", - "021565b67bdcd3144b2b8344971d0791c8b3747d22b276d9d96d275b16cd5cb1f5", - "020ac145869df1db5469919cd90917253725405c1382fd2e1633e5ea052a649b55", - "0315b2017e9d5721877912189c4df13654d4198aefc149660955929ec0cab000d4", - "031d1e7d03b881e4261171af92408a3fa1763d5af344cde4ff5c6112e0d2ad1166", - "0305085edf2d0510c6b088ee7f874f12f30f75ceb7f6f2c432b4e954dcd94a7209", - "0201c20ffd65ce142c14755d18b0f6c802c4b8b5764be792f12529d415f0919259", - "03060ceb4e60f5735ea9fe4fdaa3b9160d10421da830324ee09ecca0be168289dd", - "020dffc9655b9804e2ebffc26375e578aa026378178ac1602aa2d10c603d2b95cf", - "022bc48a66ff1753dd4e6af51f26f1ce9961efee91bcdb6206d51b1db265261577", - "03099346474b3a6b80ef802f7e8f275ff741bb12abe0cb706845461f5e76cf362b", - "031d63861c632e9b9aa8acb4c744b95f9e4b51a2419a3f11022af0f619877e8243", - "020aaac7edbc4e6320c7b0287d2a599f4b68da691bea8f16aca239486fe5276baa", - "0222da8ba88ec9040807e9bf6d2d8df7c018f822260eb9e2aecc88729da8f51c49", - "022766c15abd7c11ea1efb97f155d3fc6f052b6a3082fb58308cf2ec9fae2281af", - "020ee01a27c521fe0239f1d404c941043e38ad1acea4eb5b53bc54708ed5271813", - "032db9fb9cf84e424012f4eb9c5ece693322d4183e740190142c94bc7402fc414e", - "03121e04316ac866653e2dc7283f707f1f1dc15c0c8662cb6c55ab27755a099fa9", - "021c20dc6ea9ace0d17316e8f8b106749ac51bca9fec2cb3a12e270c14c1e8f01d", - "032cc0bcb8c498f47a03374df49a3e549b1c9b120628bbc62123f77f7cad419e60", - "020e67ad39de69e986f3a2832be86fbfeb796690b6542254497c8c4e15866409a5", - "0300eb0cbe8aaa77afb1397707b0d5cf2bf8073f8a4145219b8124b089943fd33a", - "030d3f1489c07ac8208373760f8c153488042d9731f3074d6219d24ddce9543c1d", - "03205e6a0abdee7a52c6e772aacf7e1875b02fca6f0bc1d65227215f061879c1cf", - "030bf9d00ab5e2c027172c4121f7fbb07667bbf6dc3d4087b0a16b1247b7fbbff6", - "03178c2b4c258d5537c5bd8f72344d9b9155fd10ae20336fb042dbbe43cb3c6fe3", - "0327784f25e86cc96eab6e0e0448ac4d80eb78878c7143dc7c3786dddaeb56032a", - "02116b0018d689ccd418490e23571fa36c84df6dcf14f14afae011c444280f0596", - "03150ebb9c783c93244de67c4079c560d7469b8d199a9052ad60b1352b965f1f4c", - "0207dcd68af17c3327a522532b0c9c8802b1c9c1f9188ccdf20e3f5eb3542bc3cc", - "020d7ca27a007d1cbf2a4804968c0f869f73a71890802695ef13ef2917d84b812a", - "0202b75370665dbb70ce799ab776c1a966d932c14b3302107eb6d97d7fdc05618d", - "0318b4116b7bb2ad324e8d0069e038057789503ce0d77bf01e7ecf1cc68590e635", - "0218e4ff0c861b0f1248208719817e5e7ca3638c67aaae8232bf6aa27b8116eed8", - "032761be2cc37ef5f5bdd847a9051fb34b9531f1a867ddc017be4a15b3d22ce426", - "0319e36a412b4def5436b06b42beb48040d1c2152c2aeea1948590d29469d9af1e", - "030d4d6f82fea61f5b576d35f13d8ab69b7fb2bb965893f7c1ab359a4dd128a919", - "030464ca260aadec7cdf96b43504530f623869e71ed66d1d1e41a0c6a750f845cb", - "030bca76b5eb096b4f48053a9318a073ca7298967d1d7831c0409315f868e0a937", - "03055c6924f6baa0366655f942ec57013bfe36c289bcbffad6659d6d737afeb7ae", - "022952b4c5734247280d6e88d710275e482b10a420f5dca50508bcb7cee6a1d7ae", - "020c25297614a930a820c947af2e47a93f3b33a2260bca765466fc8ff9f99c9616", - "031d424b4acca785adb8e25cda6f6c4ebe9bf1a2b0126dce29c477fda9339e3956", - "020a721a7c3488cd19f5599c54891367fc1e370ff5a8236fd2cbe54af9e78411cb", - "0214028b7343f91909badd01530c4ffd9829ccc735330f6f928d123e5aa6d1012c", - "031fc3b5790796d18e981e81f055f7bafc00e574efd21b934faf1a22598db5b82f", - "0229fa7c0b27f9ca16e1afd17668c486c52f3bd858bb1f530a69682868973aba0f", - "0316b5134e608778abd03165514d4c68a9048cbad1ad1a42d6fd7bbd30b62cbc96", - "022e4b524d0182bf0802046eb72410c3faaceefebb9c030db3dad95bb47d8410dd", - "031112139d3bea520c2a57659d96de3f153aa8a2189565ec047ce570f02ece2e3f", - "02163e058247117b0c37d841ecea45462907f111e117eadd7d7a48a49def99e7dd", - "0323f8e720a105086f23384222a31480a21cd28817aca77872caf3694f57276a8c", - "030e082b96aa59eae13efc3d6fddc7f3620d9eb38a92f4158cd0133cf2690d7948", - "021cdcd6d134ee1d44d7bf188bc92be6b25ebc5061e75f7cc3d7e65e1cf41c6720", - "0315f3ceb7f80d3f437b8b505a183f919f3b8c747259b5e262aa778ab189c43712", - "030a2214fa7fce5c7439708553ada564872fec2687e405b123e334177d30db725a", - "030e2ff752f928ed45814ddbcdefe141724832575b0019f51275e873ff12c43213", - "031a976635d62b7f7ed0cbb6d48ba2976bb1e26094e20db57efdece8d3e1fb9d9f", - "022ef2ca9b22e020d69e39b5d354470f07b27024be2d1a19218f905b1df560ab82", - "032507820f810c029d12518454084a1e5a8ecd6d42164bac29ce4bbab25c0e143b", - "031b9b21d942ef66ed40912b792b8a474e47282f297bc5addc2e1c64b3b556e739", - "021d2a5e8528d3b585998e5e7ba082e187347d7cf697e808d42bf591f7f2c11703", - "0325aed705422786078f0ce360faf4c2c7ca62116bd93c21c6b5c168a63f06ecfa", - "032eb5c30cdb1927d7924ee0510e1bfb852ea1b95dc79bc35c2b241db0454830f4", - "0310a154c525bfad6af14856bd82e6b74c3f127228351a810ee17a043d843fe6ad", - "021d062cce0a6baa5ff6a0a042ca875a5184fd11ff5e49f690441e8b60c3cf3521", - "03217a8f00a8fbd1d5394f17cc9f95ae726bddfc97527baceff88861cdd551e13f", - "0228a68c4a81556027f3c95e949f40efbf7ec977bf3ea571fdd95ba74aa08c4459", - "022db3c9b03e3bc5dad441b4e92dd977f0eb3a050b649914b5dcfa17301e3dc427", - "0314805d4db47bc896e017deaf2ef74ab98044e16c41c9aa512d5832fbac603a40", - "031b5590402c982260e9db33c125d9792dc79722b024f8769e5bfe5381afd916cb", - "022874dc8df4629c776b2122d3e840d782d69df6a115d246ae118bf4a4c33135df", - "02087f2d57ddf770b66d9a806929259827f99c3e2cd3e8246b26b064ab9234dc30", - "03260f825e334fb4e8d3597bcc1cf52e218ec7ae801e9c20cbe67cd2b04ad5af65", - "030c0727e67e6d980418a089b5d0d6b45f9f8e60b0aee87ffa96d4585084f73226", - "031fc4dbdeb9130ed97901332d5e81fd6761515bffdee75e7abdbb3b7e8893ae66", - "0325f2db99e232223782659d7206c4028190ee9ba6e0f7b249d907d6e886305612", - "02230d8a783ce7f87cb39cb575b0f362338019d3690a11c93c55f315bf71bd06c4", - "0326df7202daa0221cdf9e2744c9bd6fb02397ac2eca14b337c6b5fd157b6eabad", - "03012a962a7a8c79d465277c0d96bdf64d2c1e2e419406329bef52ff244837a94c", - "0206135727e508b57442cca13ca2e8eba06d1e76b1706b79b582683eddb3d83d08", - "020d392f4323cc9bb457fda3f8ac10e0f9e81f0e16b8d467d0af2b93410269974f", - "032bc03d058cdf9f1031c53b530c962208da009ce7c5ff86741275b3479f8f1719", - "0328e8d8cdcd7c3a7fb947972f9068f13a5fcd6466312f2bca955fd990d192909b", - "0300db39cce3051df9d4a4fb46be4c1dae4cba10c3f46807eb3b69d1fcdee7b03e", - "0305c099bfbfbc4656dca529bfccf67227ad9b5f26a20be14c23e83e73cd284859", - "032dfbe5b9087b271eda36d06e37c3f38377e65bf8338d396b2187fd3ed2e25c4c", - "0319df0d1cd6936160b46c059d25ea4a0178a57582bf35a0b87ba40200041847c5", - "03250376ab8f64c294b4279891f363cf4836fbcc0dccd94967278f5d79d2831adf", - "032c93c4779200422e990223bed5421e293c9da52f12247461a998015fce2b9046", - "030ba288bbf220effdce8f1bbf5e208601701d0140c75a647c4e2c70ad8f0a745d", - "03061036c66bb85ab093eedc02acfb92dfd2378b4a022a9c9888ac6db986062f98", - "0310702ebdb1970ea767401141960abad38fb7549465e8a976391e484595ca1dea", - "0224588c5c284ece5538b8a9cc032b9ca5a2626bc382083866769e2b05469d5e58", - "020319c0c0660ea77d0a3770d9f07ab0f36b4be537ae1d4f113c8b1b1e2db5ca87", - "0305c4dba1ac1528958457d91e5b94f4ef1f7d047e8e106234d89132fce9cbe86c", - "020d4e91a2eb12fc6e30bb61cf07e1593dd8b42d0dab2125e02530b44cd33b00d5", - "023048881e5a8efe1eebb72d9461b9ee8d96b8ec6c39ffcbc4ae82faa2e1736ad1", - "030a17f26426f8f1b9ea3118017c7231c943d8eb7d838d03f3e872bef8b3e56f25", - "0224a08bf9882eee9d209bd83804b006b79bc2e96b0f18d0b364122617ce0c59cd", - "02200e4097097bef41767da80c2f9c78fdb948fa366857dfa1b9c0d0fa7b7c599d", - "020880aca356d5c6184effe288348d8ea4cd6f4e85150991e064ca85d96170bc99", - "03207c66fec5af9ac702757f2b9a39044ff1f945288094ddf3f2b79122ef160b0f", - "020c271642901aea6083ce48a31ea8220aaada0b4682c678f7876fc03a35078a40", - "021c760e6f3d3cb84d96790d08bf35aa803c66e43ae7013495823ee645447fd5fa", - "0308d810e30c82f4b66cea75807641ba716e088ea08b3fae49f527ea8555a311e2", - "032dce159dde45f0862897a033415677bcfb6a3d8b59946df706250a85c2d10736", - "0305dede9a649920732581df972ca7a686891ffc486e2371d63538a524b3afd9e2", - "0225c44bfec2282de2434ba8b4037f56e569e0d0f3531fd2e9d85f3386a2dd7991", - "021a5771d72d34e45114e6b2659ba7dcad7ac4392ac11c48f75e1178ccf37e2be0", - "022b4c79389d8a48ad0ff001666bd09d7cb400af17dbf14ccf966e8be8db6495ac", - "03172da6d89722c11672dd02b4e57932adbc401aa3c651b590aad7347755beced0", - "020d604b458c125269048f8be676f9a2d065c0665ee34b72c94338e3292e04aaa2", - "021c80278d77645681a2c3f114a64cadf5056cb65bf0241013adbfb017ce5446be", - "0309924f90670e2cc781223c14526d5ee9bf7dcce28f09f0f7a39d175334c1b5bd", - "021af67473eb6244c5879ee232e20d6f19e68043d9f0ce5fa07b7cb582664a6b9c", - "030e752b0df05f53fc35394b3f15374ddf92d9e4893ed48e41a6ef6a433e92f220", - "032f70e81892932b20b403d47c986d8d3d08d4e6339551f0dbc435cc7e36889b5f", - "021332a694bbe2451076a2da0672bfedb30c58b2f1c62bedc99eafaca1d8af638f", - "03142f7e99dad7545c2121cbb24312eefd6d38853c6db33080db3655e17d4aeb91", - "0314e63117e3c7f94f9371ba17895e27778cd2b9e0bb5806465f4d2a239cf53eb4", - "021d1a49bfd8e8c1b9ceedbf07f8b929219e5f2fcdf4c953f1bd7181733d938c5e", - "022423ab05cb2019232351f59db976c4272642e2afa495f30f3909d7696eac6add", - "020baa4bff2170fde9cdd32c2c93ee9f8164dcc7eb6696a8ee6d5d34f3da149b31", - "021f25de69b2118d8934270d057f8ec0140441ef9116f958b9fe4fbfca95f1a9ba", - "02232f1010e811e059aa680f1b89f9af0f6b47762240a127c77048aafc7bceb2c6", - "032c519446ccaaa453bd9bab7b549ef208efa4aa25080dd9d9cc8b8c4285f4644c", - "020f744460f8d46de38dc6a70a37ecd313136688e1689f2dd65bdcb2ce18d3398a", - "0200c3d95a50a132b64a6826bdcf6d1d49bee4f1d6ea65cb522fb1692158c673e5", - "021f8df2453d0570ada79bdce17cfe33b4cc9e8e64578bd728d745a33d44aa32a3", - "0208da0d695e1409b5a60459c3c52e6363adda920fd10a9c381eff515c4e14a4a5", - "020d792f051add57425715d0d34103a252375909b0163c15895b52520d3ba83951", - "0327ddba16985a924d77ed2fc85f3ae138977d346afd17c8a3e77da3c7474a1a3b", - "0213c0de57b132e4c68c7b633ba4b022d18e2089e7b53ea8a6e2d0ff105bec73d8", - "0325243aed30c62e2757fd7069b178074d155089dc00a6aa7371a50e6257a2c490", - "0324511f295db5124c4bc460d29ac8518b056cf340087aca936b5207b5f9f24beb", - "030bf5f975375e011817da49ef677707a65e3963d9a5e1293f7c7d02ebe009424f", - "031442332580ae12db1726569ae1674ee0a5dcf53607e36505656ed957ed9e4247", - "02266531848f88d47375397013cea8e0ca7358a28cb3b571b38ba393b418a7398e", - "032e9fcbdc30b81ec1e343622ef10da76e6709c7bf8d1458647ae06481286a3554", - "0315fcf1136c7ac3ab9e8fdf24990776ffe632b5c2a21a197c908e73d6a83341c3", - "0322c85a3dc4a4f672c8fa91bcb8f8342454f2bed63348aa4a18085569a1833fa4", - "0228a76f38d4a38732ac97a9b89f0aa217f30f8fca82b499d47031a54ae16726ac", - "0321ec3775dfe0dfabc8a6500c4e4df302b9f05957b5e9d527b04f47d3b02180ab", - "03265c0c468637fb44b7c61125cbb31fec1311a2c68ce81b488c7ff2cae68c97f1", - "031d05695bffc2af34278d8d00da1df4a00299cccca3d2af7e3a6fb648286f1e6f", - "031430f0a2eb79db98a563c492a28ae593226492f11103958bba7596b25fe50810", - "0321b4c9bfe2139c97d976666b1ecdc9fb679167e91801076c275e36f413052caa", - "020747577089fcf37f8faeadc76887a320cbb15739c073a76f10acfa7a2bd1d59b", - "021231fc9c490bc2fa0f1b3c4fc12b8eb6d41beb0a9c4317d0943e39942fbf0676", - "030eb5f152362a53ceeccba69e8001453c23b81a2ae232932411ec145e885d2f3d", - "0300b80626cbace4f3fad52d0905cca274d768a331b6ca52e56eb418598a4dd19b", - "0316427e47b60f4b6c2b970c004632e74b437c6032d39c7ce6b98983d7ddb861c1", - "02071e47ea2571ad4390800b1637e80c8592e79cde25d55cc3e9aef9ba148386c8", - "021bedfe8189ffcc709b38aed33db97d7624059189b3806b72e8e28dd8af97c692", - "0210125cb13b694602ed2c351e29064a012c5db2712988f02f8cabf39a24c2b43b", - "02022ae506d74786c2a7321d1b4db13daab32a2643e18857dc6d4343e4f14a08c9", - "0222986b6414b30133b870e421c96cbc509d4d780f4527b4e76507c1183f92e224", - "031c5ef177fff11e3f64e2187a093674ca4804ee4ff254242273c018ccc0f1b031", - "031979eea8c96da117de0b93b8f3a694bd2db23ea7e480e78fb66ee4b439c09d29", - "022a81cca01fbc520407cf433b459d08940c1f95f9c2aaba96742531f5f62a9d4e", - "020123a27af177f73ec31d1b487ca44c107c0d7deedf5bc276507b35e8a17fdd27", - "022c38c00e4a294ab89d79bc725002286e200808e3107367a78024aeb07ad5a9ac", - "030ab466711123d13943260445105fa683faddfa1ce08f59a2ff39476343f5cab4", - "03160073ac005bc5a2e85c705fe81a0bb57be4a0d74ddc9223895bff32baa1ce5b", - "03106c920087f906ea0efd716c5f5574a47a1934035124769e10a6bcb5c6e0e691", - "0302b163269048ec67ce31ab5c5e532b5aebf740c106e33587fb91559b622ab7ce", - "031780143f11fd8a1eb5df05ecef75e3c050db6d6e7216460082762a1c09f3f00c", - "032b1f0eec6233bec839644b65a05a7ffde9342e4ecd9cc27e3eaf84e5038fa9b2", - "031e7606c1feb30460afd156ed8b9bcc13d6abc68d499109eba606c467dbbc9020", - "03093b7e01491613b55768eb54c3858cb52e425e685d5c50e63044729cd725c75c", - "022828714d7554c24ea82d8d3894a7ba9e7db475ee881ba505c294710b50e4fbe4", - "031b67e4f55b5a0b1a35d5c704b904efafc41534104dca9ee8186181f79fd723b1", - "031a8b26e36b01c98ae23b72d677396901a324d8bcb086fd63a86c81de6a6171a3", - "03090a1a939b9e7f74ab3f80d359f169b44ec55c7cb74763b8563523d5f351c387", - "0318a3a6834258b331c5f5adf3c6cc9d867115ed53f77b6b29ae107edd8565edfc", - "0325a57c4c925f743f2d5f21e4e9c5992e5b858fc5b097a305167b494e9313b7b3", - "031e408c6b14a12d5b8a718fed7aaf718c0f6ec1de7f3bc3256237af3a695af620", - "031242d2b979235cb1d25d5d2de64a2448aa5b9be3e61680d5876b90cef581e8d5", - "021d01cb451d075f057b4d951f653ade15b3a3457212129aafd7e7c8a3c0f211ea", - "021020ca4a32e7e9bc3213d26fa767f1b7c4f29887561ae561cb40166029429c4f", - "0329967088d60888b7a2b72f8373e5e616e395fafc9729263d9a87a13f2b13fae4", - "021c61730706ede70e9f757ee2226a0b9c0b8034c854211c82a8199afd18109781", - "032d4157f5b750f103220da8bb22f7c692245fb637ac27d4612218c49cf65c7a31", - "022e01165450adde960d6566a4122f40183225137de48c1b6603166b28d65c1555", - "022236050abb4393964a90e8ccdb79be35e8e3b474bd3cea96d8ebab86581dd159", - "022bbdbc3316852715869cd5724d9aa31b079835142e2404a81c095f1c725cf78a", - "0328441aeb7303814c2f8ef440377a518b3f7a8ef86720546349baeb4cf24dedc4", - "0225ee9e33f0f69fd9cfc280131495368c32c43e370096f513a9628a95bfd153d8", - "0314946b911bee310b9703a340d8efb5ffd0dd438fd58c35fa0341415f0b87cdda", - "032b46d7add91640667579dd9d5b39a89b4699d1e7514e6744cc43e6cb9e0402ca", - "032f88f4a17e2084155ea92c27b64ef0c22417859eb242ebdf8db80e9602855259", - "0226d5d3bb8b3bdcf229dd676ebfccfd3ecda66fcf519131c53b1c71fafad21e15", - "03285cd4b223a39f976e16999baa039940d5357781856c1f707dea05f09fb922ab", - "0206b44558f566b56a3bfbf929b5f595ede2dd5a4581c9b40af06878507c76fb99", - "02302a45edc5d55a143fc7598d668b7101887f3ef822f09e6efa911107bafecff9", - "031dbd3d2a26f25fef9302d8d1a9b85ddb058a04e25b97e4bf0207dfb0d4d0b66b", - "020f0eb8054c2a1cb8b1b1af5c8bef8e1259dde5e268a353a9d6b3b8dece0c4608", - "020a03b79445ad00ca4f36373d6027a2836f17ff0be021da6960716de374e66760", - "030eba04cd64e03f82fe0f848c7464fe67855059c89b93f2215e20179488ff2c4a", - "0210dc4fb3e616c6887086d3c784fd22c4cdda53b53566b363d42dc66bf7180bbb", - "031ee408bfc4919c44124345831dd4d1fb16e0fe760136076d996a5daeb39e72cf", - "0222376103390f99089f3c77c3cecc982dbdd868839d7b64be1300248dfb2c34e8", - "02167fd9a37ce90cf08ac61e99bb52d8f388f7f429eabbaf08a956c83f2e23c4bf", - "02181d7b740489320f7c6eb1db65ec016541b5c201d58a048e952e2b70b8f286c9", - "0200044e5ea0f180a454ec281d9013857e8686bcc83465b6956c74068195e5ce71", - "0328914ae991f37914337eb6f83400d1b387663fb1d43e134307434d25a6e6ca4a", - "02253e5c2dc8f89b19e5550b6cf83224b914f9af906387edc2aa139e4ce70a4ab8", - "03302a09a8e56a0c64d31e4cc5c0c0a7642a020bea75955816565e26b87a87e51f", - "022fd976a65113fbaeb9bc4e619f51b6e477f8cdeea3d9c1c77355b00e786e768f", - "032be7e78584fafa358df823f4e65d9d7c53d7630c0676da41704cbd0b45ba9d51", - "030a3d5d150beff10466f5c21b684bc5c5ba49e11b17cf1651d16c1fedb0883fc0", - "031f92faebd194f16d947c474c766cfa74874fb1b824e3f1a08bfaa057f752cc34", - "0213072300c2235220b9f535a8235d7a05231edc90e22199a97d1e3c3fd92ee49c", - "020eb48c4fb96927d052ab525879ec5ed5e9cacbca1737b00a0ec480142cdc8141", - "031e86df9e78da27cdee562953b9aac2556e45d732c14de2b6df80701ca11a1914", - "022a200f8574a4b9d2798e37920168bdde7f8988c9e8de23665e9eb8435113374f", - "021e446699b01f8f35c841177001f904319bc47a43240c97e8201292db08b4c3b1", - "0210d19ca42b9907df426c5ebd3bc3f7d0a21ab5e288269ee9ff0f02e2ee3b2328", - "0207512a6fe3f1a77ebe6c37c1d37b9b64aa7972109f338bb67f63a508e5f23281", - "021836bd17c6e39947cefb8bc67ec7dbf14e95d3653c1875efacb55acc6b3b1894", - "0204b5c4e4603b0c87aed8d3a56a2d97971ba63414ada7c4837ff1f8e9723270a2", - "0313eb9c2dec2dfd6b4ab0ad01695c6d5dde156a9d5f866272e02129a05e220928", - "02113a67ff1587ac7b4efd94a09ec7221bb49e14eec53f46afa5e4f1ae8f0424d4", - "0215999f65b96ea18e46d7a8b61503e1c06185159c64beddac83da4d38cd87d94d", - "030644dc86f718416c57ebd626c51574124a0928545e325db14e79c2940000b1b8", - "020ef03436d22744acda62fe53e1b9f97035d91319b474f7111beb782a13a1028d", - "0203b2699986305cd2721138badcce2a2bce949f8b0b8e8c07374c3353b58fa95d", - "02237f84cf059fa7e8b8cd4f793bf14f1a4fed1b7524d3bbc33bd7556562655409", - "0219054910666ea39157fe6d6fb485cb18a6516bc72676f17ab7f2676df865d362", - "022e389ba03db76adb7c5189fd210f1241c3c43ec841873ebc3cdea786a474adf0", - "0224e265d9e41ade5908845dcbff43a643e6825b05111e766aa39cf35a6b0dc9a2", - "03187445acc3dcf3ddeefdd2a86794c107f0b01e8fe7a0bda25530a13c46fec768", - "03102793733f24ba86ec8a18c66e7483778f8d9d9fbb7649c4993a6f326dba96ac", - "0326d149834b539886df6fe1d6b8aa7b7ccf2cf9718720167439bd3dbec5d41827", - "0216df5673cfb7495b7144b39e0b3948c6acb2ec134c76d092bc9bedf196da005d", - "02149e6ef032e03d5b6c32027585bbf9dccbe754f219a809fcb49f7dd66a0aa11c", - "0201e285994bba2b4df74e129577eb5ddcf6311f86270749b9a68fcce4379623af", - "02005137aa0626ac8b4bc8f5ca283ff41fb73490bfb65acb3778f377f03e7d76c7", - "020e72dbc24b4ec96894699d951353edb3c1ed078cf2433bbe965bc27c3a2e534b", - "0208571edd860d286688dbb3397e71e9d2d63f0b5f92f2159db55f85961344b842", - "0216ab77300484618aec83a099680e08f3ae0719256f314e872c816f2ca40ceb08", - "02089dcf2d66283eb039b6b3fc4e1d9c2a6f613062ecb8fc4c5890bd2aeb8d0604", - "03025b60c6f290f6aada5e14b721baf348f56fe86f7f7c58c9728a21cd78b56ae9", - "0224427b2640ea7d35a86f291ea5907de54a99d5eeae1471991c587032e89ce1e6", - "030f26b3fe7d0bfd42535ab51e7a0af41064d07921f4d782c0683d415180dbe843", - "022f943c333bb623e25534435df223bb30d911a9220a12fbf8668a39f72ff8b787", - "021502683e10bcbebae59c92209b90e6c773aa1db372b1f533dbd1da5e9d05da6e", - "02068e9405faed77d1539b8a2ef3899ffcc4aae723d7484e47446572961969a551", - "0319f51e50f9da2b6abf0b3ae6c5c9c1db4742b576502c583cee5990374a1dc9f5", - "032ef543034382efe2e8eff3273f6db822d56a8eebee608e1ba08fbbcddeb89b1f", - "02022066687111d8a9cc3b0941bad16c2203eb1ea716b39ba3810b3ff5b77a744d", - "0229c234ae1b896c17af6e9233c870ef3af6b115b7f8caac1a13430e7ed16e357f", - "032096d068dd99c8edbed78194eae0604eb84b78acba30537b98aeb8f94393597f", - "0322a01c43174bfeaeb8372451add5576f9d3b7a301177e97792d6cd6c4404178f", - "0326502dcea75dd1f4e55313066de3abceab686d59ea24d93ba0b84960ca484580", - "032ccc8023300f7478824e6fbdf203809e58d3cc4e7000bdc3efca0c49c3d6e1f3", - "0205dc9095e471de7eb79b2a24eb3921bc8c8ce9e4d7b4618624160061b3adfeb9", - "021c51d013e4c151f3a036a6b0a9049eedcfcbafd1abaff6ca83b19a55d46e21d5", - "02130fe2735cffe92a78497e2178c40260061025979c59edef3e74afd0b877f1c4", - "021a98b4d6155426733dd6186dd0a5ba5367365c365d9c2cba54b6524a57ef99e1", - "0222ba4f7a64cff205ad06dad5cd645e0167ccdee870e622f83464af63079d5189", - "030fe7b4959c198e66a383a952cd639c34e1e0f8d423828b2cd49d38662f29655b", - "031fedb417e9ab5fc7d97ddf802102d9efc1cafd6d63600b753817b61d0bf31c35", - "0217764cb03044e4b6c393e5c2f3eb68938c147cbcc68896b32df9ad588df91dc8", - "022c7fd82a28bd356105eff584b5b18d0817757783f522c193ce8a374bd62c4d6e", - "0201db0afcc7c13e7bc788d7dfb2d0ea07582b49fb448f6e7464d10a80e241db1e", - "0320ecc3d3458d7e9dad575f4b9a097f56d5de8e318524b7c1bfae1e094e22af8d", - "0214629d6c9bcf76985e54f765973df8df725e602cd1af00030b7f71b0cce38c7a", - "031ff753ceae0a5f4371a6003321342ce4fed040b139d809fda67ad05d7cf8cd68", - "022a0d8f6b23a4dfed7e9b6f1bd5613e8ae89d8961d395f56494574e71f64356d7", - "032b1ba7150e3af1d396c454c1adc970c88070387a99b7d8d5d9a7bd1952613ff3", - "02120d4db30e6fed553d9950b74abe42caac9423222545dbeb6d36de70289db610", - "031a43deac5f20e1a1046043ffd6b8188022bc395cf53996ae3629a3164209ecd2", - "03287dd09a5abb00cae0f82979208dd15813123fefac72dcf38ee433db3e7dd175", - "031f1d1b0763207d6abfdf88a8d723255ccd73df8722375bae81b83a74e9b8f290", - "0216bc64919c649a1692e59354206ff9f1140070d1026819aa640cdff75e51c7c5", - "03179c5d75c2959720c71289c790ec792844f88160a13c567b3c84b095fbeb6b1b", - "03261f6c7b8ef78bb7d5fecf21d22546b47cfefcdba53f011d3060cdfd37cc754f", - "0301fa64d68b0908547794ce4eb421d53334da3bebf3915230ecf0c733f6c330c7", - "02115730be09aacf446dba18e98d41c7c070013029ae07bd2c304d21756c0393ea", - "020ed17e8af8a59d0c46e2a8ba94dbd88b42aad0f37f9bd66e832080b223eca85b", - "03279f65415849d830b42c800f65be5f87890e4b0a75b1780a271419cae9387fa8", - "0228b4a86ec212bd7520ab4c243bb11e1ffc7c127f5d96d166a8b018d67df833a5", - "031a28a947dc734cf1805f1f42d1fa59440ac8e35d97636d4bf5ecbdb0ec8e5471", - "0225a489acba8a37be68e07886b9ee9affa6c6f65b55b44f8af818e4f7702cc6fb", - "022595acfc38d4d28bf84f2a0fb78d83c0ca0dc7054fc22dfbdadbc968e982d08c", - "032bc6b84d43ad12034baa1838f6da3915123cc7d928d942dfd555b8d629f5bd9f", - "021bb62de9fe1d1fea6e9d07cbc27e7f5515aa8d0dbbb025e506789855d8f1863d", - "02256dd44c41d01c0d9b589bd47e7f0d0256c337243c163875e3fda64f4cdcc2b0", - "031854c0ec9506d86c47a63170fe23b8143f5477975d26f6474befd857dccdea54", - "021cdc5b54ac8c79c1e4a09aee2d4bbf66fd3e6da2db6542e28397e1587e421abc", - "022465f2d2c3fa262d277a8e1ea4c5ec0cf7ba618c21204540a16ac50fe5e4e983", - "0300140d50655b44ee68adf1fab81f4973ec210a14a4b49858b367a1e105da4b24", - "022eddfae8332cf9d814f3a7b70b2a712e2e6876160a976d16e77cdc4ce3d38980", - "02081c6d0d42745ad08b75889c6a087e2298e2a09642a171ee666995acf5506bd2", - "0201dcf8377980b9f7737745cfe255e457281f8a0be8208ed4469195e482b18319", - "0201a392628f2ffb98ab8a277a6e2f1cbf2802ee7907f03a2bdc868b94af4d0469", - "021da407a45778fedc586b0afdca3224953f698d2ebbbe5c5d78a6418544047ea5", - "022ade270a44b77920a6961a7cf4531a1607be1503eac026adbd8cfe30fcbc53c8", - "021529123141b32c0812f84724a8c850650c1b2da5c01b4815d8f7b066fd9e39a3", - "030ec8eae723dcf0a8766b1b8ce279ffbbb28c13e870b720b5289bb6da37024ead", - "022acfc5874ce1b6235806ad0e737f87b0046eda8ead40a6e8d5fcda746523e47a", - "031848dcf44201451272c682ee6eb87c33bc793805cbe7a3851d00f9732483cf3b", - "021adffbf8608ad8ce34ccf06ff112188b344b50fadfebeab62c36f31dc62ce20e", - "0303e2b9d51c50c32044f7aa8d6a771a3d959e3d221722f4e99d32307eb144b356", - "03049db6274e7242c25b4bd40cd222c54d7ac97bc8882890d1e762c02a1a64608b", - "02073147f8b9e38b3e9d976c0c3a025450439ec1b7acfd0e4ffe816062d110a6dd", - "0203d5e1d91ad8c9aa41cb6c930299815a3ce6257a6f5404a915077be8b1316a9f", - "02228732b38a72962b817031a0b9bbd681fdd1c065a570769be971bdbaa3b9444e", - "031e796f91093389c3e0d946f25b34bdeab3e0c4b14600d8657eed234db8652183", - "02065f82bbe9a367989f549936d694170687117a9ee15afd0a1fed915fcda9961b", - "02084ab0377354a98d0e4e954da22f8a3424a22fdbfacef97fd6ad3d93c1e1ada9", - "022b42617996013edf1caa22a73540cf5b67e0cb51509a8496e843217f5a716e76", - "02120eafd197ab4112f1143f16cac61206937389d374c9b334ff6539c1f5cd7b61", - "0317dac9599699b55cee6f47d4cae4692f5b44a99feffccc43228ebfa0e56a262a", - "033010881aa0f7ea4a2d3b61bb3492ca780101d8d07aefa6dc311cb5dcd5328901", - "021fc624e60bdde3e93983b5dd9fd3c1a3f30179713c825533529b876dfca81cce", - "020fc9af37335531457807c76b4ab49fdcf2e1a26d753cc9eb6389a3b6eccbc610", - "032e3f3239c14f18ed984231e9f8b0e4ad1a27f6605a4f871af452a9b12d9ce4d4", - "031d70005a34e22264e2409225a9da3822c8a29384c9c11b852d5ca70840e8be9a", - "0227fe4ce595326267391d658b989f4e62e5d134b0c9c59a455d6617ab50aa00a2", - "0323398b85379e4dc0559c407c441fd3c570589a1a8ef8b6be10476c6f19d00368", - "0206bcc63f252f2509fcc57406c8ef15466d313e99d893d9e9aff7a2a1e008ec12", - "03203f20de36b824426d4df7c4c14fe51d94b97264c4c5e09a445e677dbc6b6570", - "022a8392ab81c5d41c356771c3410ef48857a6831a210f36fd1529956c48c28603", - "0222c31275c5a05aa6b3ab7000da4c9548d91da512d14564c5ec913eaff9cb1f2e", - "031267296c3a80b20e84b0f04279f40131a3cba1691dc126d02179b4fe290ba780", - "03198c584da7fdc3d9795b3e33995d502a53e698ec2bb2df38141479df576f2f6b", - "030fff59656bc0748138c2672d4d531b61260aaaeaa631995fbbec1a1b313fbe88", - "03281bec5b3a57557f89a961189242e212758fb996250901a0f8574e5da6fb6942", - "02139e3eeccf31231700a3af388f186b99b21485cf07e034f20e2ec3fcbd9a0c3a", - "032c194a3ce9b757db316ff78e89acdebbfe959cac3828d737dbb5aef712f2074f", - "020f3ad6da1d424f00621ef59742d4bf0d7a17fa43284c446019633c9b065d4474", - "021bf1ba489124cf1453c44b12d8aeddb5adf155706caea4aec575edd85a063335", - "02205111e4cd66a241325eea1fd9a63b5614a50142ea0ef31387bf44b268020a53", - "021c1daf7cf54d3904c257b70325e1f87f914910e2da1eee20b985df0dcff44740", - "0305f83a9e5dc90a5c33983bd1d05d3fa50f703af917d9985116ccdcb97545cb2e", - "0227d419ad050c0627b6c67f2a2fcb845dbc0f9e9ca4255a7990e79c12091de840", - "030df27c0591c44d27cdef09db31619cdf01c149c641b3951a167075c6915660c7", - "02142e7e0262b430f42dc8e5bf3d1ca18ee5caefe6bf925627dc75b44d90efe7dc", - "030218f231a613de3b6e3af6ac07ab0b0861111e368bc10d6fe7a219931f93880b", - "0302870a09cda77c1bf27aed3e2c476e9c5dbc918cf0423a81e4c3030389d3f69f", - "0228152fa16312ba727580aee4bb51c4242bce16cc0d2f93173c9b291d5950c127", - "0218a9f82e3b53ca63c750e7fbb7edb43d6ec0c616ee3ea068a574494d3059ab8b", - "0318f2248f9387af7181b1ce842dee48126389ef549109c7f94dda0a6507202cc3", - "031a320c096b268f6dab14546df811b94c18f2511abd80e3daf8a085b0f018883c", - "03110470a22442777744a097be824b2bc91ad449a5955a5f13d158e10890a7632c", - "032af57e9c67e77fa5ea177f91346903cf6a8d6f062c9fc4aa7135fb0cf20a26c8", - "031ffb1d24bcb9ababbf58fe4dd68c7e3fdde090a28ca10dd3e248e8817770a5f8", - "022de22e34a660b0ebfbc98cd574a8f6d091a42bd955258cf96a2d63fabdb559aa", - "020ae091aaa349433e7725ecca4333b26c188c9a2c2fac7f5af73cdc5b59cb4f0a", - "03138293e42ee32b3314566b95a4befca83f9bc9860a69f8933c61ddb410a74794", - "02039e6e22cfe3851c8e731332ae68cdd448926368b71f4c4437b56352d32806dd", - "020bea913ae85d8b9fddd53d912e247ad1b37a9365a3385b255659cecac13ba7d8", - "032019a090a581a1260f139ffbd5cb7cab09c514ed2c884af66ea8cfa1cdd50e7b", - "022c54a653de10516bee8144051e852f524fe24b67603f58aaec818b5b6a9bc965", - "0322c8fe5c40995e43261a87f5dc5dca6906fba61a696397d6b19f83d41814f942", - "030ee4805b76960d3c8459a369678ceab7e43bf94aba4153958fb474127dedc90b", - "030b4a699bb3d734c32229aac653e4fae5bf520e2fe8ac24c8c80ce010a7fbc496", - "021dd0e7d273538159a1846cb14045f63e62e0b9e54cc6b9250235f36c6019841a", - "03117db41b5c3da9f232c64b344bf68597d8714905e4c85d24658164506d4f2656", - "032aba8fe7ea2d3b54a2fdaf39ed7995329fe1ee6a19090f9c3dafaf91106a0026", - "022cc41fb7ddb817f63042e60646c49827acfc31efecf9180609c64dfce8e5e88f", - "032b7577a681f54a56d3848286c7ace16da9b1a7c0db2db1cb9b314547f014abfd", - "022516cc334a5950cf7e24877c81d0afad16d7e2ceeaeabe9ac1970d8fe389888e", - "02257e1ee00263a4c80989fcc2fec604ec645402f72fb9a6a3ea91de6e2e3e2983", - "032d7d69bc612ed7995218af43b0f865318f65f09340150aa0dad5b8acac1170b0", - "02070852aef851042e4de9ebbc495e2be8b8cda9ad92549063e7f4c4f4f23f47c8", - "022dce6e255f913be0cbd1f5eecc6056fc9696f19d1fc99ed180c2307dc745a492", - "02298546bf5b2a906d1f83e121f83104591652b6c0c040ba642ae857dfe2a9fa8a", - "02139f8c0f6cce5efdfa8bb4846cbef2c725c0481a39342785685e22d3d079cbb8", - "022fe8766ee8abf7d3505a9b92c03e8640d668ed6577bbe57bd2ef7265bfe415e0", - "031b67266a5adfffae7c4666656384abd5851b3ec4cb6e2a44c44561b9e0fc37e8", - "032c420b910344596914ec732d1cb98ca703b940fa35e4dad28cb0ef51741f176b", - "031bedf4bc72b5124f0e760ede1832c2a5d78afe18d2db1da6c399f7beedbb2fc6", - "022b3f30ff5e832dc60c75620dc6cdfc01e8d76237b54af0a518ed7d409366afc8", - "0200a2f3a6c98a2e2922cc704d81ac57121434ee7a5600e1cef2bd05679f3f052d", - "03235d050b64ae440d414fd7941691af5722857773d9ed1c94f298e7d8c75c6dda", - "0304ee14e9c605a43e18a64c845e8f7a62858b2fd757d00a26ad1dc6bedd893e0e", - "0325d641284631145d28b21d661641ab361cfa9dcbe17d170f17446398fc992273", - "03058a506dc1062a2b176480963639517c8d665bf4172ea5b31f81aa202bfa24bc", - "021f4d425d41f91a4fdfe28f37e21052905901f40a111b87e86aac17ae8935715b", - "03112753457e1b8b9b4bd00da7d3d52427c0220209811242c7c29c250133b5c995", - "0310600f10259af48bffe93a7c94fc6b0e9507594553e16b3f7b333de7c4c275e7", - "031f4befbb92344c572bb0e69741cde766f80f2c634a02248daa604cb7f234431e", - "0202e5414280670fd31728dd185c5b44720b17bde7aac239b9ae1bae97e3be772f", - "0328a76fdd42c3740555c15b991693c3af03bb0fad9d781bd06c8fd6ed479c076d", - "032b9210ae50a0d03d323ad7f05524e4a5b084520e7ba83a3b0a27eb1e5d6b3e49", - "021309a14ae030ee860e2e359ee919e7502754dbd76c1626be5ae44ad493b1183b", - "032434930d03f6847b7b0b8f1fa8d9e6e5a55f7ec2178f3f943da82d5dea46da39", - "02084ada2dcdd00ac69d3eeda035d76b31059f12145db9ead396c2905549eddadb", - "030afc75deafbe061938063b16ad5bc9b907c0a7f9ee47dde30bc9439aec308488", - "022b7fe9c6a3c874065a1c6ced1e87f091e3a8e4f49b42ac3f1f9a242edef3bcac", - "0206b5d84f76f55b2b9a557d8fcb178ae150acea5969aa7934b9fa523d728f20d3", - "021aa55f46fe05606033b7ff6ef39cfb5ab675671547580130a12ef2167ec326dd", - "0223dac70565f1b073ff7dd5cec9795bb1a701aa137d7a12a69ccdf4103efb1226", - "032c7f23562b3b2b9ddc49e6f1d974d547e82bce62288fed359a2355c4fa0632c6", - "030bf7ea1c75b3fb95b635e1a588f0c5f70e7150e431a55b90ab9652de4089b7b9", - "021d5c9a89abe303640ce0ac1cb7462cfc49310d924c2772be5ef9c6ea3ec1e4e6", - "031acbd2d8d7670dad49867a326c3d83771e532ac098ca22b9fb2ce995031b3f0c", - "021d180e525a7a404f031b5a99b9b7b38facdc56a00e5f106a73239980c50cee1e", - "0205093c19c347cd7af3417c31e653a75989cb1e28ed3a3749e2c8faca48ad966b", - "032e76c5653fbfa7f7697bc830e6b9984c2491217cb935923ab472fae5e3ab6f21", - "020d1270530e1e3bd23b5ac6de5ddd3f2777a6fccb3294a6f03f1eeb139e3c8510", - "03140d162524928027ac09f06144bb52a7cdf7a9a4c2c37105e53d6a86dfd5151c", - "020c3c1dd9840e12d036a4b165dddcbcf6390de45d3c1ca508ce63b3b95b5c7483", - "02207c2f27e6504581757b620dfb6f26b2bff27ac939087ad04e09c2d5f3c29670", - "022c34697a20a2d5477bbd89e579d3eca9c78435dc211867da503b17a62a338d4e", - "020d3bf876dbbef3d99c56b187c16c16e96cdf5378d9428d91ec4cef0a0a1ea55d", - "030eef3708da9526a624624f521fa9ec7661764c8c8f4e28fa8be9f8fb1e3b6180", - "0202273988e62d735f8ef8c58e23e82dbde097cb591ddec715df3178607a72c296", - "030d392668f9fcf98008d7b543500c919f110dda2e1e2a97352de3efb3a2cee37f", - "0219e07f4cfc074aec129e2e775f0a86637b5449ca7e7b1026bb020b3555305e0e", - "0316723596798714a8b12e522e1c25c77d37b938de1316e1f67532e57fe08f6d49", - "0227071e6e8a973b095755954f75add7deb69eb55e2d0e2baf4bf3a91a251d6c7a", - "020bf8b993932777885942a4674996dffe6398a4f6dd97319d798676562491ba21", - "0302508e2aed7d2173a145b3b074a4a96e681b2c927e29d281bf22b5aa450e0f0a", - "020bfd26e65d9e3ecd2977d3835ec79f4c25be12523f504c591ea06943b80b364c", - "03215c7930fc87d4fabc0fb7b9c17a85afb9d567bfdad8b76ce63a5d325e89a498", - "0224a9cd7896d6c38552fc43dda225ff65b7bd2dc8bf2f790c28a11d58135a6c92", - "0205e582e9c2858275f8ac981a582eb31d6180090125f04c526da04f37f103e57b", - "0322c9090c90ef776bcf1bc841181c93c6f0c0cd43ee230cd0d3c97f7917a7b777", - "030741914f9f7338f4eb2c2a609bd4e68957da7a87565d05ef26d892990f166b4d", - "03170f8626e29300d721f1d3c8290eb5d713e96b1b66bed3fca21fa082b1bcb0ad", - "031f82c7ad961d85e2ef5ebba932b0259ff89aafb206c5ca83a74c7ebb1970744b", - "021c9d3553684beaff6fe48a529fe5031b38ff87cfae6d882472764da5e16a449b", - "031af88ba829968b1cc4aeefa6b53a797fac6c1ac6e39154ca6fee85cc6cf22600", - "0200c8493dfb1136a5fe6b5b188a045189e6d76c2695294b0ecd1d5f8ef1328b23", - "0308b7e3b001aaa52c50221448bb9d55d53c3316e046adc55ba937f1f691b3cff3", - "0317e1ae6c453d56804a4ee33f293c64f91583e592fc949789a1fb6355f2d015bc", - "032753afd5fd0101ac068ce9191e6b544511b0a57531999489e4171d1e2514ae77", - "0230470e60c5171964a5c38121f75e20acc6cc7bc7aeaf649fda197c8fd46da45f", - "030f354ee83be475f83922d4537ccfe18d36bd23d6a7e6453950a8ed13f5249b26", - "0300d461cea40ab4c9431eefdee22deda878dc50e3b2ea3d1f53018a4fc4ee15ef", - "032fccfa15f901bb581a63723345fd4c5f42849c5c14279c628ce024be6a83affe", - "022d9383dc8c7b27412e221e03e291ae0bb9fb2bf4da995f977642019766e43906", - "02286ca87f1f327ddb08d644f7081feaaac1acda985348163af4fb50b5c255858e", - "031e5acf0dbc8e7b1366c31ca0bb24f81dec0fdf809317c6d7524c17751482c9df", - "022bc5c2d3f9cf1832cd1920972f4aaf270b41d6d5d49625a85bd3de3b9753e0ba", - "032e6fe03f5dc0c95e11f1c71d2124171c85c77ca6d1d512945807d65bf11e394c", - "020731fa78ddc86fe3eb3083a5577caf8d82daf2f981307f6e677b271cc0df870c", - "022c7f9c02e092080e688a243dd8585180fdc219a815b95b927d76d01ad34816f4", - "020ca3c1a316f488fa646fa1db985a79a6307c1a14a2514fb18c5e678ecbdefb2e", - "031bfe2e60590d8c54ef57a30442d297de8de6a05051d89e687afb6db1b0d43f3c", - "031f477a9a2e5350a0bcf6a131b3bc95aecd074fce8b56b55271d23e37bd495c0f", - "0325d99cb9962a75c5700eab11492bf6b0a8220066e2aaf47a9a5a2c0830149809", - "0228ac29bcb837550e7884c5414ba2beb3061e9a7bd50a088429809113e14145a9", - "021d3080bcd4999b9d46ba1f0f38d0ce1b8f39afc1f5738e33bbda9033b1a3d3a2", - "0318f41312a0f909da96f06acdb4e358fdd45780884c448812e13bf2858ccd2810", - "022a6663eba8ebe53dcb5821b683a5df54a22c73745cb0a074e892cf812853ba02", - "0204ea5b5412906afd395c79e8b32c9a7de284857aae374111f14349dd96ad8969", - "020a581490277de15a808a8eaf087242a3b720eb13c54672f6ef88b6632e48199b", - "03243bd9da1146542a12f9562fb8c6ae731e950da50278615fee9f357250b8f113", - "031ccbac83c9510097fdf1457508cd11bd349817de1b6cf27acadebc8546e0a1ac", - "032b37d8d4e8efb1846df9709e5db0a2df21b3aea53d75e4fb24e07ae1e29070ad", - "022064c9153ed5713dea532d1b26c9ceef539d506e67c8632d902557bfedfb1773", - "021d087587e0a89ea9f95af37ea00a31ea04728fda281fc73fa9dd3ba0bd077b04", - "0214e4aca7eda428463be11081470e210d2aa3ddd115e9a537332974472d73f135", - "0327d0a78b1ebe8c3db9600997e3c8d33b7a2f100107a49d70facaffd3598aa49c", - "03220c3386253c842d24564450f4f63d73a3129a170a7a79d644b241c11afcdb16", - "030dab9dcb7e5fe84c9615984d2019046f3657d81d0db3886d67ed31347b7e7f3e", - "022813243b6bc1aaa09a080cea1e53ed534919368e1e94ef00861d879f503a00ca", - "0213f6a4ce9527a72756a8df92fad741f3db06a1b92db02f3148138d66cec0232d", - "022e5df36ed50462c4b1fb2956c92021de2a1d0c2f23e41db382dba319f67fa5f2", - "03183840f723ca875c651baca0cb711f7107c69681568fc80b99a5b341af9b1a14", - "031e3696a7f761f3e312ba35bfc37e8f08916248de9a1183a4f224c524e9770127", - "03170dee7b766fc4af3a3cf0613a4230f7840b238f2215a41bdbddb39d5b3bf3a6", - "0209848ee4f26fa0a573515cd2b2180937710414dbb8016579afa96d4dceceab5c", - "0200cfbad9d9eedbbfe98298bdc32359989404e8fac7023ca0ef599937ed759952", - "032e9ea6b330a803e1c21c914550971e057dde85f99be392e22d0be04e640ebd26", - "0326bfcf16273453f34d6d99278a2360e7e7f378d859d73656d30236ab2bfc1aba", - "021b335f0c44e33877b48981117d69c997a55d375182f01fb8d0ae9fe49e403671", - "0209f73bfabd4bc458bc755beb3d6de74e57e474d58e01327fc463ead793b7ad42", - "030b031b9aacb6fc68780163f2fc3b2e4c8bb1444b6be85b19baf27cddec8539fb", - "020b467a84774f48176fc80528d95f49b1b7819a2450f2ae31b597658d3c4cafb5", - "03010f5288c9ff645670495890db7e802494ae2bda33d1e669896b0dadb1b5c9d9", - "022def77104b8d4dd2d5fa26f95798cf2d3635eb3167ba20d51c551930300f11e9", - "022e36e5765f3a9b58f0004f5e6b9bc3bab0cb6ecc2e6b12790c8359ac70147962", - "021397e1f7323db7badbd60e52045a1f1f276ff18089dea833af76f0c03f658757", - "0214394916caaf6ecb8665abd3170fdcee0ff917ef0c90519bb714dc31adf4c2ba", - "022588bb4ede0b9fdd2acf7a2716e91babc71ded6f2b73815e1b4ea520924d4aa8", - "022698e0e97c45453a8e827519c482e96baf76cd71fc707d25d80a8bd82b643e31", - "031e884a0d88ba9162528bfba816616a564660e8c53813491dd2ca838a9c26e915", - "03169aa4483e749a32519e6c28398f97df1565da82d1b2ebd22177358bee120890", - "0214a50d149eea07cc17f89d11a1973f3a071e625548f79c3a44929df849ff803d", - "02034f3d144da203e52819523ce5ee40f6e43e7b2834643e046efab55f65957af4", - "0213fca186776e3ebe37094bc707e71bac474cb9ff6feba6e7c9a2053ac1d5473a", - "03061815f98ca172f6057d46c258fa282ce63b9406f8c3ece7c50e91fb95904d25", - "0229d6f30e13b47626a4101d71f3c6c73aaf7e4cad01c51283086b1745de392138", - "032c1b13c66b8938c4d3a88bc951e4012492c76f9ca89e37265651b7b8d46e952b", - "032f10611f570b3e4ecf81d078cabd7ec4b0c51b8c47a594a8a2a6c1e43d7a425c", - "0322b181f026f8eb7bc88ef935a6eed775c36b19c03220e651aec2d3cb29537489", - "02109a6a9ac7a5b65f803e2dae4db29bb72d1d1675ea50135c0ed5b721fb96bdaf", - "031a2238f59026007c5b5e62c9af733b072fe0cce5c75041af7742a9f7e09e79cd", - "032c8c7d3549e41f97baea616883663f80f9c9944002140ab7242b07ed929f0091", - "0302f10ca1197f7c098a1dcea42fd5236832ed05d89f3f6be67647385f4f289e23", - "022d7b4ce1f510930e84c30b989b652226e7092ef9be0639de9f0bd4ad60e85bdb", - "0314f4f7c37e71446fdb73d6ac90fd0043439c314a9674e1395528083e8851219e", - "032ce2b9e0bdfe3a091c54163c3aa8dfcd8c3b7609a066142baf2f2eb842af6c5c", - "032c20adb01354414145dc5d32d07a93319f32f630e6e7ee0c12ada7f4bdf1dc6b", - "03285119a68a7d73a7c2be30df5017ec596fef3dc9ef2aae94f22864ce99659cc9", - "031ea5db2f35daddab0b720fdfa08e59b9440b66e9d9425785e66066fc395ed23c", - "0321b0f369939fb1b96ebc412d4e5b27aedec4854601ee1e0371e42be2be031f5e", - "021a145b05d26def7d4ddc8748b1dcc67925743da1b0ff51cd6c2142b09cbd6f3c", - "02220b340c61531fa2bcd164badb3c8bd0694e333302063164db3dabefb5771f50", - "020d811be405d5e7fab3824cffe2fc53636a8718fd8d4c53a865c85e1f84677e3a", - "02036f7e11a22ceb45198da92a9671eb26c33c48f99501da87299a952cf842c822", - "03239ec453b5999def780030fdbf74f15e6afeb23e299cb3062f8ce8e849f55be5", - "0203de6e96e1ea53f3fe3373ca508aacae680685a1034677901df55ec540118757", - "032f62ab9b22f728d92ae8e077319c2f6a1293db2b18bc029c26b6e42df23b0544", - "02174de0f08dc09c3d1db3139b7177004618205b51502ba1fb78c548d1c1e652fb", - "031ce3f76678fddc07b23536b32410fb7885502419335440d9f61ffae2509a29fb", - "03252eeef18b669eacac3ea75161dd6e42a3505eea407ea7b59ddfad9d0eac2c7a", - "032eba359df47605a5d166384f409a582de4fbf9fe125d56879dc8bad7db1ebb99", - "020f70e3c3354ede37fb326849617dd33e47e1140df6f34ff7807651c36847c2ef", - "03177eefb75c9e79989cd524566b3c6af88dd21533527c375d7e4e9707c9b1b68f", - "0307025d9a60e3c1d26a792e7c22522110212f492498fe4283b4fb287bc9939fad", - "0329d7a52dc1c0c0e78a76b0f47f7fcc984fcbf7848a6a2565ce732c11382a170c", - "03030d0a869414afe4a57fec233506869b11cf594d232dae9760f2ed8688dfb78f", - "032c59da410d47cc147c8f6036415e441a28431730811546a8fa2a3bd58c4a9949", - "021d86111a88f7fbd0488e538f31603d37db738188e3b2e362577659364a675873", - "0313981c0d20ee937752645211bcce157c049cd0b16ab6679a997680a03e179161", - "03225949ea1c93c98b0748e30434008fd080c174e8a924d8a3f050888869f7ae35", - "021f57c3854c7e37c1dfe75e3a9434047da5029c2f261adf79dd449f1f2b3309dd", - "032bcdde665160d184ad257552d3918bb32af410bc212f2082141f24652ec9e55c", - "020b7278388562cf530526a5e7325d6f64dd81f6a012fa4e0bfc448cdeec3cb7c2", - "03298bbc8ca15bce47558924ccd98726ddab4d019f106356bbc0f6696de7d5b931", - "0211c7e164c21b336c93cc7efb276fd8cca4ee8a136d4479c3b7f5b635c442fd58", - "021b9211ed5e199c083862890d4ce5b9ec2d1647801ae3923ad37984da3fe89173", - "0227eef9a1e0d93eff4bb37fbd6390beea0a970ae2b5f775aea59530985cc6c12e", - "021493e41303ba338467162cf8e91f3c4282891c116a09185bc5aa77ccb2b6b212", - "0226a576ef39ba10837f867ac55543da4e5518daa31a164a3c31443a28141a9c41", - "02292c19575c53166c90d1fde9d28218a0e3a29dc5d772e0a080e3cad9fb34ece8", - "0310d3a1efee0b19c3dd849a64f0e461fe38b1e23c744143f836886c376fd5098f", - "031e508a0959b11fa654eebf952d5e88ee1ff047f0d123d26ccdc300a67222dbd0", - "0303a082e292e0a7235138514e698371a930b291853a4349277a412febfb53fb61", - "031fd6d2959504caba829091eb395bfab42d882bc73adf85d7168a9ef1b9f27649", - "0219bae15344a9ee7a9ff571a3d425bc6d32c7bc87cc9726c45d615f44a6fb0127", - "031f942d93ba916ceebf179b4db1c1e8d8206315b5de087ad079dc43545767b22b", - "0309d4b5d3d850c38f89b94466dc4a0cb3740fecfa5e9d2d6440f5de20016f67cf", - "031c778ce44f859018a65a39e87d3b4cc2da762b17219b15fa5562148084c010ba", - "02170fa3e35a2c112619fc3436a234347933d457abd14fe50f0865b234e5a8ed8a", - "030f8b9bc24724561e0d4d36e2804aa18abe0b8a779be34b192aa1023a7327f2c6", - "021ea51cd317194df0d98126011d4dda994f12028eca13a9dbec63fb58a3cd43b9", - "03222db87e3539683b947437ae8e56bc9308edde1abe3447b941e2c7e382e2a804", - "032f3fb740daa95145ff1eb447f2d3741da9d00b128eb8d68bb13e4569a4764639", - "0213de76e85236ce70a40721539a923177e375870e831064dba3e0e547c4977e74", - "030ea9c0844d6bb1c72f7bde1b8e95bf5cb57b203d75b2854bccd73e80819c32a1", - "0326650b1255014ad8f33cbf62b56d1408b58961eeb490fe5975aa136fbb8e0a54", - "02103e70f24d9ff1e7b1536e7a48fa4171654c713d30acbaa73e940e157b8edea4", - "020680c398b39c014765b1a3359d6594da18820cd92d156441bf4d5a2c8cebf2c8", - "032cde24ef642223dd7ba77f12c35d00ad5bec14d6ef16687264f48667775cf23a", - "0319c606ea2e3a96af7f15667f56e9b8ea19318bec08280a1a8b5bbbf2cfb3315e", - "0228a1cecf18f43ca05e85fc62b9883172e0cc3e21401bfa7361fae3a3412ca186", - "031eab148c7f9d8f6ace5e1729c55fc396f7352af176bef8ff6f969cd80dc3d590", - "022d65596fe754c5837e224c2122011b106ddcf075942836f98fbfdc43c40c6663", - "032760191464e81c61cea66987c1881ae477f4b737ef8b0b8ba46f404bf799b2e5", - "0302177cc1d329db547c4379dc0c96f8262a69e8fb8ff081ba8ed952c4b48a8198", - "032d7c7b8126aae63767ecfc4fe3cc42cf06f7fbc680db047fe5ea9009eb70b64e", - "0221bfcaff4932cb127b119e8e8a35d1ee1b2750a0295a042ef3409545ff41c36d", - "030db8617f1124c19b4811441719b0f29da41f90b4167620382f78d9873f50f668", - "0204cb91a0dc60f2b312814610690cebb96944169ade7df3a39ca73814e4c6577f", - "022a48227360186c1c189832ab3e23e3d6c74de8718c5b693f9f5dfc95c13cbb18", - "02038ac0866b531977263735b3e05d1ea21bea4e4b16471c549d5cb12b665529bf", - "02004d9627d1bc09df3630002326d79b320a09624e0a58d5e7fb35185dd052be2c", - "020b52459e0730ae92045bc57175fe724649f32e07c9e316ec14d5b2b5e1d28fcc", - "020ce6efe21527faffe42e8ad77f35b529ab4c582231928964260169f0d028cb08", - "0202d27b96f382d3efd6077c2d4c774779f4e56b6c50ef823024336ab97ae65eac", - "032f09a055194c4d92b590ae16b584e889ef9aead3bd00efc539a7553a30a8cbd1", - "02204c5774cbc3c0423061398f06768bc83437a315bc5b3b17aaf05d406e91fdaf", - "022ec81bc6f48a2909ab22b56a3b0ee562e3c5867d3d94289126c88c612d281728", - "021ed5a0113caee29f502a4f6ac7c32ffa82c2d3416dd9d00421df7c1456b35ab5", - "02143082f892b44c3ce3f1eb1894dc0aeffa8745d3abe88c13556596cbc962f643", - "020aadaa2bda1d3c2895ebc28c6d5e321153c7b4bc2e368c0e5b2d7217858d973a", - "022291d8d67b59c4190b2af191274c3ce61a93606bf8cf783b801720a83fe0fc9d", - "02209c800c8981aad82c7b16e4273b1a8ba67c01b7234a355aed3a6a1129777fce", - "0308358efab2a94b4074730b39622371e19f5e91c9f10da82895da1c44f85cbbb0", - "03227513f5ad7be4be0848c05def47939762ea55c2ea3517355fac21c4d15f3184", - "03010d19bc35226fd76a97fc14df71fa648885275e2534dd563fba1c16913c12f0", - "021dd8f55da91bac1e208223c4f95ff4700a89f99f82f18333d4e42ffdef41ceec", - "022f59cd017b0066e73bb680090529915ab5630ab669c048bdc1a3342c29493d68", - "021ea7f3cfce91d5dba24c795c3a56592a7962ac2122d8d175147c7c924b3994d9", - "0215baf7ea5603951a769cb6b39778e65a5f4743918a53f5997aee1578c605ade0", - "0210381a21149cd519f0e66349ab209534bbaf0c1c08cf6d64f8891f001d62350d", - "03111293fb124590360e2315d4549b62bf1a354ead8a1d68131aed42577c3bfcdf", - "03232ec13c881c9262d9978de386e99c9b2535a99bbf035882c00d0a80b9efb244", - "032ca4841467cdff9aa2ed26e00838f08870ae5e217dd176ea2c36412d39fda606", - "0315eeb765577751735a05e08e955dcf4b495ed9e474b666314c52c14df16ca8c7", - "02275a80bf4264dd1c78c6295c5a990ff30f1c177207e0878c30cd2356cd98093e", - "022c17e7b342be8fc8482c30a785854283b4ca9bff71dbe4c7ca8c25053dd45663", - "03124e454144304050d08e9b0e754213154a061e8c8a0b5493a2e7157132e6b44a", - "03246cfb9602a1b910698e77ae031b4615be64bcc16d4d17e181a5f667b6698f8e", - "0323b686662e61f69de95f31e0df61797fa3febf13c6aec546b50c8708bb055042", - "0220746f42b8b16640dc2126a86632ce8ab0ce250cdaab0e6d4aaa29abf46b4a7c", - "02096a5b101554c5f89445f981d6ad424e95fca4bd2a407d58652cdd3f8287e1e3", - "03301c8436a2f1ac4a70e062334d255b85dbd8b81b66b40c28677a50d925753434", - "03158372ef61837ba97bc4a7133f8b3691cae7c5e02ad8df4319d4e31ae6331401", - "021b024842b0884b21471a58013a411f5f8c34a7f3c7b9eb7e6a6a30631041f3a0", - "03027c0d943a86b2c5d36a618d1deaa914378102728a9035001fe5d162cc27ce71", - "0309452ba6659c602e4827e173ae5e324ca0eb48c1658afe9b1d024af7d0090f8c", - "0310b8f9e92e04584c0a642e22a0b13a2f1718a10fd604c56cd9d943575e77f425", - "021742b1b8039680e2295dac6173120f6ed2cb5a2976df748691e45ae40bfe9415", - "031d15e8542ef02951e419d4f9716ea39c67822727e36c2947ca72df088c882615", - "0206008f44b8e7dc2655bc8b8fa5fc1ac5a9307bee74aa8b06820feb735a1f73fa", - "03066d6655c07e857f348d39d9805b5978224004bf4edcc4079993ea35d34b550e", - "0222997ac4bb56b6c19027e4692db9368287fe1f95786c5cb42f961b1c4732b510", - "0212fb69130c1d8e2fde4b359fa410172bea37031f4629a71e4e68b3e0ada49d28", - "032539d5b63aa7d72cb8d77db5a8275c9a94f919559409b6cc816e382b5d011857", - "032a14c952e9a4d424fa90ee686e7c7b2c43c7d8e82e74d50fffab3965d7ed2062", - "0309b55e2b6729932da3c8e538ff503e6519106ea31fcf905865aa272a26264060", - "03028fcb77ba54419ae900baea14a770e7a3e7b445bdd64d4138b3131467cfbb3b", - "03033681f452390813631f6d8e1630b2b6c5de77ac340bee15f1e8eb15707e2d47", - "032f89c9f1b360db9ecb9ff7a000ea076f173834a99d0ca63acb2742085bb8ca5d", - "020a12261ef4a4439d4a9738377a7528d329196ba7a279fa412c420beb14f571b9", - "0325602989483c8cd0969a9d7b49157927e2a90c28686f3119ac54447a00d8c453", - "0218e95e6236c8bb59825c320d4bdb3d4cc2c6e1ed5edcf31b5cbe9c5d8e9e8635", - "022f91b8ad41baa5f24a337e97f5eb84c8dbc4388b012f6f7641d2f1f9f158f4a3", - "021078de570568ce8664409604bb1233b648b7e4ccf2a67fad6cf6c76c20eef29d", - "0302997e5cabae598c4f8101df8e0f90275f1c08be8f88a8e811dd31a1f55c5e5a", - "0206ad9b361deb71032a25ab09de840a870cbd0e67b1f0c4103b85aefd5404f40a", - "021a553782d48fb76f19d623ff91abef564355fd5c1ce39af71324d8f092fe8f92", - "02154659df27f99d82a392746b5335ae970b939b37fbf272549378151500f4687e", - "03016126755974be3c27d6aad1223f302622c3693b591c8a35db8d764a95319caf", - "0207098161acd3b79ecb29657bc8671f85a4e3ddcd5da6e2c7febc24f389d758fa", - "022d62d1ea28a156e90623b739ea4265bd27ce853fdf1c8ffb718fc6c1f224051c", - "0327692295482356686106d77b12a7dc3dbec9c1f64defee09da340e53cd57d796", - "02070715eadb8fcc325bb7de2cdc5cb1254674c6f1834bc2ca2abd9b1fd2b878dc", - "020296cc004d5185cc4f128e5e5a16383200bafd4c3e5a5e3fb9c323dfe3e07753", - "03183551b6040a7875b731eea979c41c9422e051c5a7e388a1d3a1bd41d2ac36fc", - "03024373116c997f4483d4fbb3f74465fbcb579f398e79dd514c11d53d98a55fd3", - "02012b3fa601ff2044f0e855bb43500692b43e085abb0546bf0e5a984121379c1d", - "032c02c21c3072c19953006e4f5b4f9999c370e53edbb01342bc438d120c671c4b", - "020a0b81591d08e5be1bc6cd97203b1b4e55005d81cb65cf5e6aa9ef2b41711810", - "0316e554ec0218659418806871d001b1503b815b749428453a3c25f9b3ac89e9e5", - "02178d518725d7653d52e6d9f206d7f38ff73792c79343a198c22c320a47852774", - "02131a635e89329b4c1b440c4a17f3dd233db8ea314d1a203db466b2a79aa6c56c", - "021d25d03ac04ca97a7c92ff4797f8ac4bd8461da2c8dbc29cce079e74e58a319e", - "030af1d7fbf40c4bd630469e942565a0cc3104aa26dca486ff943ebb02b50d83c9", - "031fee9ef9e44da61bb02f97131d6820ad0c5207a5ad5448570c6f76036e580f5f", - "0306d4e8cdc3bb0a1879763182d1156f8a8b11eb1e9805fb11bf5acd926a38d554", - "032ae47b9b2bd7d7519d369b28740d38ab18bdcc757995cdb76f8993fab4fd44eb", - "031c2dc91a99ad6554926b40f9acd8d553e8f1b033750bfc4a478771f802d45fb0", - "0223b3d46fb8f2e66f9fc872f255ba8b902364aca52bd7d49f8a5a6a3427b6693d", - "021e5dc1f176b61f3057e2dfe952fb4e9d55a82d61929547718fd814aa44f1b93d", - "0312e1d6325c641b780b2579a05fb804cc71b3060b1a25916a3835b327ea588798", - "021c68bc3c8b4abaa503f546b2674390ca90a1c1336bd89a10e0762354c4f7d600", - "0310d276d891724889678eb5778b96b49b509dcc1f914801a587f31ddd66bbaf9e", - "0218c74ec9db9e7cdd4e2bdc9450e01b59d3d1d192d6485f59e2c66152b87db330", - "032e2afab9af0f25cbb596aadf6c8e246fc8687c5df304cc0c3631db9878271740", - "0306398278ff9f5da2847eeddb9bc6f91ff1c740188dc6138666c266b86dd2880f", - "0208026ad3655cd10c042d2cb709af3fe20f20450a0a72688f9d152bf7afe17e45", - "0319c7548870807829009b96cf4a6ecc31ef8bccbbe19f530a4c6267006277d412", - "03094c8b2d759cbf8715b3dfc60b8d293910564468653291dc45759ac2935edb49", - "0320c4040cf9ad855f4f4994e3cb3767ea1925aabd484077c0a6d6929a122c95d3", - "03022321c9a13b263d5a4de560d6c016450b8d31df3ed80208a6e38e9b04858c32", - "0322941be642a54b9dbc8be7c42f36f50193e92ea57b7abf81051bcbf3ae58e160", - "020ea5a81ea85ea9ef03de2ac5ff7adff59871836457ab2f38262ddc54af81d4ff", - "0215831eb3b966b3350dc852c0a3ac1428f428a0431949496e7c0d500f1cb88332", - "02006e853d7ef113ef75acd8ad7352e55a873144ce7f8cfab6aeae59b82d99bd8e", - "0213de4ba298e357556fbb2bac3dda19b1e8fc6543ee5309ed2d2b8ca0f18d3192", - "020c1e57b5b84f704794f7c061a59eaf73f38fc1d49630dd5a6774bbb686e86632", - "030c4976d6226d7cdf6d744828accb122e16f54d3bc1b447fc717b7ca391413a49", - "0225289be9932b903e3ae939a41a93e37b2a22d17f4a2660ff416673bcf6c92d44", - "0224d5ac06b23a7f388ceff1eb92cd6226ce5629663380bdcda033f437063b038f", - "032f00be1ecc3d34763194b1989e0153d635df94e692f8c3483a7b876b568875f1", - "0225b1debe6f8dc44e9d3af2bdc6e527420704101c39ec20f1f072331298c471cc", - "03006e0b8a4742535cdcd58980319b6ebfdde6281615b7cfe0249cc017361ff89c", - "0204df3331a12bf857b9f399b19c5652d5c7af43bc548b9f8d4312ffb47288fa68", - "031cc697cd75a60d977c05597f48446eedee8fc21c2ffc7efbb930e82dcebcfafb", - "030a39ff03a350492e3e667adcd936864e53260f3a2e2d0774af31607df0de92fe", - "02131de5c59701f0ad7316fb0b7f1444e1cc3009b39530a0d92e0bccc9c19808b3", - "022a10d67b2e2515117c903ce11b2b6af802236e373a06b83c435cb1e472bf2892", - "031d1e6e83f93ec2b5302261e1e69c8bc42ead95582aac16f5b29fccca92e66194", - "02118a961d3a920d29b750f5e007d71fc1fc26de0c394b5b40e4e949e77a57f5a5", - "0329f28fc3c73e7b69cf23789fc6ff5e8c30be6d7c78104ced3a1027b6e5421ca9", - "0316d893873f6b7613cd832fac86da4339a4b282aea6a9d325beb3d00f2c9c7656", - "020ba2e0d9ade1e2ee6c9bcb96ab601e80357150784bb506db8bd53e159891a47e", - "030d9112713ff97fd310bc9660ae417d161890b70e6e931c32a362e24eb3be7c6e", - "03108c3a392d190216bf505f47b910c1302c5d35c9fee237bd0e4062db1b22b54b", - "0300e147f01f683297653f112f199bc91cd1c7cb7ec0a9b949fd121df4f3cac783", - "02298fb33a18ac89e46765d261c3aaa891d5e6ea4611864b1f90b7c89b79465a06", - "030b26e35043bf95cec4d9e336a283d2c96081d42f42c3b91b5b2f99372286add3", - "03130b4a5c746bd03270471972d3f459624a23a4eba52178259a1f9356e0616044", - "0313caf98e11ae690d49ac0f9f6295ba9d30c1402550f58e4630c17385d5e315b4", - "0304a02bed6193aa29cc8b6a34bd60483936fae123f8483090331ffcb37b827a2a", - "0218ae0cc00a751683e3a5ab42ed4696334beb7aa8734b2dfe7a5e8b4539932235", - "0222a8968a5bc33b2814f3600a354adfce87407528e28af5c73228b339b8ccbc28", - "021596dea7e7e1c1ce4597eadc4d4622a51626e4ef3df304feb2f4535a37c8a083", - "02230ec4b0c54998a8c78bca16536fbbad96d09ad8a5ab1ea9189cc18e3f268e9d", - "030d26a083835f637871b8b39a1eb71e8e70e15e340f34d6c357bb5055189ed4ff", - "021b82f2abdf01796e1bd0e39cbc17f7a2537ba33ee953fc3053cc47ae83bf8866", - "031ab51ebc409fe55a023e2e3a27522c5f4bee8dd878767c67b649e37b6cd07052", - "022cd52d751c972a00c9ca6c9391f223cd69cff0ac532660269e66b3ae93fa7193", - "020ce6d97e65abe42ad0c55ee6080941960b4de8622be0b2f0b46ed19e784f86d6", - "0317fbadf32acc3c7996f1244d1858f8b51e7b1bb7c3c9f46f0231f4f2cca6cbea", - "021c5e7c235bdb80c158cf04780cf0a00a11398c082033d2c214ac8fa022dbcf5b", - "03048f0c11dea96397204c9940168ec726e93b8103afd9c99c5dd35c8612b93ccc", - "022c26b02ab0ebccd2f6a531a668cf8c85bb55403531507dc2b40e763da5cd373e", - "030e9b681ecc4c70322f623b3100d867d5abb3175a6c8657380c3bd4cb744b8eca", - "03134c15190915120a5dd0815b1f9a4977120f26d030033dd96b2fe1b2c3916381", - "032f39f199a90622096bd6b0d700fe3b7ef479ed0edd37a97895bfdcb85825a818", - "0215013a803af5fb344e7ae805dfb11791a6f6145ad13eb1d433329dda4a04eb18", - "031d2c6a709c54c48021de39de4b78592324e4aed98159b6ce4025957c3042c84b", - "032c5662d2ba63beed555ba2c7d13a27a90eed25b6a3f60a3651600d61b601ed8f", - "0323c6e56227be53a2c969cf91c8717d81e5fa4903c79d34d278d0edafbdc08ad4", - "020d015b83417f58a2dbcdab386d1cda3da75c8a44787739615f14a1233177189e", - "020c2425cdc219bdab27949ad030f973f3f54757ffcd5702650394e90449b57182", - "03041bb8317ca1c858a75ff61125282db74385dbd3e056079ec541a549c5849cf7", - "032841e33cb9b375622a2b27c9d8ccfa800afbb841b612fbc2ff7e3f76e4dd26b0", - "032ad77e9f38383b0523815614142e5331af8068e851f5f5ddd24473744c20c5d8", - "031e0a4d9f47ae49caad5d61fdce8fb16dc0b22e0dbbc12e13773f43975e6eadc4", - "0204f8b6397c39d878e65dc35fdead366c59a1841cd10a464fb8a733e95ebe577d", - "0216db571c42de016ff020af52755986c15a408ffb518092057ca4588d6283bcde", - "0321fbfd751265869f87943e5d6e4465fe4274c4d6711b82abf645eecf17a9075f", - "021466a9c911be5470755492ec839243d90444ff1ede2fc012b5f5eb66397950e8", - "0207770e1f58c30fa43a4a6f147cbdbabf0fd47fc20c8adf4b64188d330bc635e6", - "030833bd0faa781e2cd12ad98e379ac36bf53a978b8fdc1c933b372fba0ee27c80", - "0329ada2174a2d8a8f711e059c463fa0706ca3a9750ddb6837b0ddba5c963599f3", - "0329d4adc595ecd410c0eea0402549ac7af27b88aed244fad7c5a281844ee2fc3e", - "021860c37a3a742c9d4c0bfc633961f1f32b8878689a34a688abe322d4bbe6bfd0", - "0227f87e5b972d6a67b0e33c7927617db47a74d5b7a4dfa3e886a13ee9acb16566", - "0305f1563c7d6714c112585235e88c6c546e01fe8f2864eee79a86451417caa7b4", - "032a7e907bbdd723aeb854e551a7cc66856376f2555d8b6dcd1b5a0a371b5364a1", - "021e399a2eb27b5f4266101396485ab146364b6e69ea0c2dc75bcd57f05da7552f", - "0225564a926f56167cf2ee367c7e66783f1d9cb1076e167d62f22d08bf862e9273", - "0210817c5507d686f9e42295c8c41cbf9b229a67385ab935d47fca1ded7d7ce204", - "0219f1cd0ab6aa9c8f0783f085690b125906e0fad976d852c81fba95fe9dd10b09", - "021073fa7a4ce0b5d44f71d918f52103e0cbc2b7c2be0f27a4c44b284dd359fc25", - "03047571e3176d321a4d852ddc53364c2ffe90970a2de1e8abc8995c4df21a38ba", - "032e9f233e0e93e54813752c53c6c376f7cd53ae4071788231d4127ec268318fbc", - "0209bba65f7e1b91295cc7990f86fd7beaa195edce3b2b3f638fb497bee56d2fc8", - "022500ae3de225dac808b2befdae847b51ade087ede4eeed46260f1517b3f62a03", - "021385dbb679752c723fdd1ae3ee58db8b765e7bf92d750f209c1e4cbabaf92187", - "022fac28a625a9942db4231a705079bea0d824965e111fa522e512515f7ba71b58", - "022dda003001b3ce8a4d4bc556b40e0de76d07c6a61799380e2cbbbcda4cb5aa12", - "0212f7f5d2bdbb55f79cf9384480e4866cac1857284312fbbbe0653ac6299ee865", - "022ab913b48f36cbad03f3dab1f9f998901791892cd5b72ded942d3d08a1861d2b", - "031f8fbde6faf2f6468f4474d5f62b6e5a86c865089f9602d4b6d2af6c06711328", - "020c10464dd9a6cda76eff8e1d165eab7fa2c5fd699e6d95ed4a86e251ff3d4e54", - "02278b457362d91ea6d92822621f557bea10699ebc12fd437552a7cb28a371427d", - "030cd42fc4dcfed7df934cf6432939b17811db8806b88424115afc77928054caf0", - "021295cebdfff01015c8d0f67538006367d47aac18197b1e53f84d117e6b1ac3ee", - "030ac8dd3b25099937d97873ced406766e0ee38a07874ef179467802e705e757c1", - "022358d30b71c6da6481210f6627a7622a98090c4bff71493fdd12fff2a98136ec", - "031a4ac2332c91ab208f974085623d9b216fb4c1f59eb8fc0eb1961eedcad2bac6", - "022fdd5062f87032d70ba5759dea70d0d79117d49d63479f80cae47229641614d2", - "031444be77d3be12852fc09b5ee9fdc215f4a04758039bc5c2b5b4be29936b7659", - "0216278bc6ef74c65a5d6290f985002a3f9a0aa172148f5c6a424fc81a1ffc56dc", - "021f9ab4cdecc72fe44d79678b7e23b269d36a0f92e4ecab389e6457b82fb3cfa7", - "0302666c4cba81451ccc89b27e2f5e9100996f18561e6f184001c57c581b9e4bda", - "03170054ee8db76a98c5f319ea573f4c476e9145db7f422bf8f0b7c965ba5d372e", - "02289df45a36f8f0a14070150784eb25b24d41d0845137d929576a209f5218bdd4", - "030c8b36b8f470d9178694c710d38507ec0297d81b8b3f9b7bf9bf1fdba805ea4f", - "032b20f6b14ebe5c86747f5b99059fa44c533f25f794132fdb6aa2c86ac5f61cf0", - "030e8afe14c9dd5ea5b33a6b73267acd12a0fcf6aa010a311bb7577a5f6593c0ae", - "031e10e7a4528d657b17e2a3b58153a26f72a598c5beb457be95a7a8076051f8d0", - "020faa7294639992fd57b605bbfa4617cf7d35dc38dace004e4ed3325ada3dce83", - "0222392ff687d6525d98944fce9fad1251f2f03f42f3d569f4dd28a0cf4f545c59", - "02273c78c1459625e137e3428a1e8298d171697f5591dfe4ebb69f1de82e47db0b", - "0313f50937c45a8121425a7dfdadebe7849833ab0a862a1927cff29e049e73933d", - "021c3134ebc2daf4dc3fd9ed4fce947dcb9184b1f872ddaa6793f55c3a20236938", - "02086e07ee0ea167cedb15ff1a43f8e548609f6dedcf6bb0d5896f35c945d75961", - "031fefdf43f182b277a0b2e6a4b6688636a2dfd1c76c7c30dd7c23df2dba1300f2", - "0221a2370add2fdc4adca095cff876e92cc37998464526ff8a297d98ece6d8ad1a", - "022631996299311eece6654f989f1474de2a8cd553ff78ef3d0acad73037e521b3", - "022b9f0e606767790e52ee0bdb7684400a2373eb478ce941b5322d4f9f5bedb81f", - "032a9c95861d1f7e3cfec0b0b54781aef6dbd6086c966e93967e3325e91ff37c9f", - "030528fbf0d03957544c13db67aaa8b002614e68d22891cba798027828c75432d6", - "0225c393c9c036b8bb21ec65a6625a2600a9c389b2047edfed60ca0a30684e6bd1", - "0318356f213b7833c702c86658875d3c8483e7e382e6b611b46faf5e5cb07b8691", - "031fb5112a94e749262bf39090bb98a6f37e392bdd37166ae76a8addf1575fdb9f", - "03020c9913746e7ac644c346902158c2c9138f436bd081d5ca482e11569484aa5e", - "0304d5e38b815217559a476e1930ce56778d3989c4b9402370e48cf07887b65982", - "0321dfab4a0be2dd84517bc950c65dd3c3fe415d20f582450190f3a5ec1ee071de", - "021a2424473e3187c0abe9632992da00430b9aba51437ee57e98cfa32e07d9cbe3", - "031bc1f66583bb0341e45777ef539658705e427565ee408d7bc03cd195abb59ba7", - "02041c5de30df6bda1d2d4f258e89f7cd67c7623eb2db12507a17d049fd2230672", - "03251b77595c300a2e16378aa4a330a13a39ed03d062e43297b404a2bf0a5b727d", - "032f06267f2ba835ff1afd6897af93cd050a02467e727817ad61c92d5e39da2e3c", - "0206ac45b60589aa705f254982d928f1cbd2388e7553a4e4c56d3cf05b94b8a6de", - "0320f5e3961c21fc371f482c15da875e9440a84cbc91d1218ac579a672cfae3696", - "022ae0ae22aa79bfd4e84ab539eb10c792ff01861076889cd5be4ecf05adab625a", - "03002f44779c81d8b491294725c99105a108c9ca10cdcdc51fe4a62b58713cf336", - "0320b43630e37fe7c98f1c93a32d464a21d1d72113515d4b75706bdbb017975ead", - "0304443132a149f3393a191c3fefa9cda281dbe0a4ec107b9b17adb2ccef9e75c0", - "03126180f1fc0cfa512a5db33e220fe8cd9b1c83a79f1402a2df23b11477a485b2", - "030ff825ad79b3e07d49665fa3cff68d0d03e7be15bef87d2e83fb5c7e64d9d109", - "022437173fd15ca27e0a04f17c6ead6ff0858a65b2c898da077ca8221f5e151d80", - "02301fc8f2f8731232a46e71fb7b61680bbc36b344a8d4d2aae687f489c1f5b237", - "0207cd14e6576ca77e8764e8b7a773f337571cfbdf70d8a9c0e7584166e1f0e2c4", - "03067caf9ae1be12b73205919b867ac39db08ab518451222e4185a1a44fa3c7231", - "021d938503191290d037189f80b78f2aca86cb476e23103d589a4a2295b5171044", - "02014c5255bf7e1113d05c486d3cf2a2b1b87eddae7a8b4842c46c7452a33cae2c", - "02285cf458a9eefb3112ab358da954ec7d64ec417c200a6ea3f4aa450094d80916", - "031794756fafd3f0233aa788000a6d3ac4e84032b572e03b885cbe7287660f6c86", - "022d6bb0665ea35bb5ee1ae29984ceb7b9df39342f154e65f14ad9bf5b0c6b5079", - "032cfe9c890ef9796e7d72e91b6ab2e352b11ba488a69b5bd4ead2c477ab999dce", - "03018a14cfeee3089ef1d33e11efee021d48d418ea3d645b8ae5ccc4ca4ab625b2", - "030fa4a2c5b6f0dec5a808663d2ad95a21e274ce2af203e00591c6c14c283608fc", - "03192fcdef379d01d211b6d637cad71e9f5bbf327b8742fbb87e7f06f9d4179bd2", - "0204d0c9b2e8ba4c7024864cfc71e7f7816489f70d35faf66219e787aa618d7b19", - "0319d737481f34cd53ec4fa31c71150e61f5d6eac18ef76ed2309690f5c1230e49", - "0214ae704c16136a35f5b91ec558952773a583bb62b0188c5f85cba30a68584acc", - "02032bf8e0d488dbe301b0d2dc2ad86cd2b66b7605888feddf3cfc0c25f3dd555e", - "032a0776446ca72af7395d746013b6c70b35979c76c449821e8206a659e79d83e9", - "0207f1dc427d3fc59c589be3a3f0488346097cc17b79a397489b1f51f714302c71", - "0211bf6f45a1c618e454822e799dac12457ec1d6eb991c1ae7af5a088ab4fc65f4", - "02042d33887a91db00d1fe48c3e0a031d44a0bd18437d074cb6fde0b1e405b85ba", - "0314cf7b083d9c3e49dd0d52de556ef3c821fe5db55468f527ff1bb1b55c75fa5a", - "03163dfb86632296e30e015262c4de663a2056a1d2f5c929b5539aa95c2ad97f77", - "032e0433e393dc4c3445debf1f46840563660e6979e819f084951c256312d30ae7", - "03197c03194b04a0e5ae7a2f668c2f52a8abdc4c802c00806ff58991f78c37775e", - "032624db4a1968e83c1f87e59f7adbd242e49bf73f49f7818eeb9ab67ee13ab9dd", - "032825319dbd7354e214ce3eeddd9ff8c6923c6b4416babdf9a52c59df738d2530", - "02165167b63886f40d28bf875152c803c57335b1a042c59c4e95e71d4228a172f3", - "030bb7826b1686177f5a3dedc43d234b7e652252c6565a4840c2c8e1d4de6feb94", - "022913d89a64922859716eec22a0d3b88a306e3347936108cc07668b8c372d62f4", - "032d92a899225b92c6310f77aa2157881cc17a5eaed85395aa7ea059d4ad4fd9aa", - "0209b8d75722c363b15851cff926897d3b5ed711a3e132027fe2e28158516e3ec5", - "032c1c2c1f248c9dbd763dc11ed4220ad5f77a7e472c1cec5f75c65380a36ec4ec", - "022e95257c8a80eedf65b794f658bf9d7065015ab15bfdc70cf74a8502e18a07cc", - "022c8954ce5a85bfe465c0be106e0cad0d3f810109cf1a2fd22ab95e3339637958", - "0329b9c6f4db7512ad4d3bcb7bef5c81181e948bfb5ae30fb983e6c66609393dfa", - "020a53483cd8494bc6b8afe9fc880a799ba30f7762a3b02798de5a7562bd6a2b77", - "02168e222fafb36be05f4bc9de9aa77da96eab21feaf095611a0b44539024156cf", - "0215e028848fdf382b841bc6e48a4e8be0cbb80f4a452978027af2cf900a0ef3f8", - "0303d8b7715fbb76946acd050f0596b1f1174a7712b13e0fd36e2138f4205c8764", - "020366c3f3c4180caf641ee150f4d19c5642790441348af571b7a252fcacf09275", - "030fb0492e6235f0b01fea3093dfc09745cf3fc71f70e77c5fb8a1a07f51a0abf1", - "0300e140578a0ed9c658aa47f6511568e049c6273e860aaba28d24fcbd6ad8f6c8", - "03155d8b7640eeb07d4fe66f28bf6fd57f1b34635f5483494baa92ed92b54c8320", - "0222a48bc3c735effc58ddf1de410130bb3f12884e115a27fff7b3574f4d2b7acf", - "021fd1e0f9ea62693031a91cff3a4825412c8f4463d81610d7dd6d2c866057072b", - "0216f9da7126d99efeccefff8fc968769c5df8ce9b6b77b2c08972d61cb26f8f12", - "031491c1713b4b598cbdcfa46d119e543964ed6ecf9419441bfac096e30925b9ff", - "021854d95c81c482504b02a4837bc479f00ee2586248e2c7a2db25b2159a4216ab", - "02136fcf4f738a9d3d39a30a43dfbc556d371840c2c2732e4fa4301af3d5bf5a87", - "020024b278dd95c759279a502ecb4ca748aa8aa69a06151ce2862ddb957ea9d267", - "02192b2639b0a8d42a246ca16a5ff792075d984a680fbccc99dbebb149781ee28c", - "0229d87c5dd47d72357f9ed09a46a9789767c904b29744067523fc0850ee401415", - "0219c5c28e5d45ca10d0d584d843e5c57a48624b36921a1816cd48af2b8f8b6648", - "021c870939c981c49da944f88f2dff1e4c96344225bac6f7cb7c75779158c2de86", - "032782e9f0a9fb7747bb151b435ec0132b5d217a28b38aae62e199526f8a65b9b5", - "03074c5488e5cf03dcdca994cad99e2e7c4fcdb0058cc8089d9373c01c0032cd28", - "0210238876a8c65d7cea316d35ed95c03401c06480c4d98dde26cdf94fd49428e0", - "030b481920ebfbbfa421755dacf75e660c6a04a8327b58988d87d3a3f497c8525d", - "0311698795c81fa59dc9ced8d13f432d434817bf1057bdd79bd4e659573a5e3124", - "0227995822c7bfbfebfece7d9c8e14b4b34741623e03e58c02135431a1fd91c717", - "020e67531f0ab46d1757506a248b9bdd207a3b42bf50d554f307d83394b7f07ed4", - "03112a4efd56cead6af7952540d398d2485dd659c1f915999cde3594f1854fddf7", - "0324664afc7f3fcfe8060394064cba3b26a879eec1f8437043b4176ddaed4db86b", - "022dd1d8d9c0edc77c074182b70b0e281fee1063110ea196c9547333fe0fb3cca2", - "0322cb26a5df080b3cb67e619e4fd2bcccbfc4fbb80c54442400ad3ede047233ca", - "020f2fac95acbe1d4ca07e83176a34184bc55e5d6ba8fcf9da055fcb8572b61eb0", - "03057a0e8749374d4a22eff3c7a579eabb51e1d561376583ba1d479567be215ab1", - "0312c2b67af33858854d4bb0902ced7c89c0985fb3a97b36bf35a7da8d0b909b72", - "0326dbb2c242a787615f2d864753d83c342a8edb1903251b941db8eecf403f6bd1", - "020d2cb81b285b08888b984bc1830537da2e78200a734ed3bd36b7637a6907450c", - "0313ac5c2d2c183aaa3ba7701865e060c26d3dc8e9939a946587b7dd8a273bbdd1", - "030d5d0554baec30ab661ebf6e5aa478292ba3720ddd0613d8a6c14ae38b7ade68", - "0204d995d64ba23c202c01ec21f3e88b0ad790b1c4e57d15a5464762f5c771f8b1", - "022d6c414f5db89db1d0eaa8d36ba54b93a90428030f83b8a74b15029bb5428fbc", - "022ab1a930c1941b8a35192568303d19f65fe5fec75babd3e1b05cf16997bbd9f4", - "0217a154cfaca6ce715f193738ec3fb73c2ced1f6a28f5feed7b6a57cc99c2ccf4", - "031b973a58596eae6d3bb22a86a2a85cfdd7be52821cb1086c350291387ee263bd", - "031f8b15a82cabc0e51463d0243ed119d7e66743212514293e9cf66d99e98b6222", - "0226ce8e60c05e1d127828c7251e6ecbfda99ff8d3e8a72532981c9a29197f5f51", - "02099c7bb2dc7f152683a30c4d4a176b7f306e6116cb3358abb452d170cba453b9", - "031b33439ce11d32ae26371e49b7b1199e5db2432a847ac0a5c5848c1ba8c9d986", - "0200daf8dd8e93f30029ca9ccd5da2c662b53e05e450b38c02b2b1095aaab83793", - "0319adedd4dde36b68ac84650e29cc97fa65f1f78d86efa3084c66888e5e7e92fc", - "031019b8cf50217f7d6eec4307fb28f553f5a26f95a9d4fa819894dfe83d0b9b9b", - "0210f808fe87d3eed5b308c3c16040c311233bdaddf1642a5c0a043748979232f8", - "0303a478b01a949fae266a99ad4e4ebd848b12ad4948c28734db7f59edf9019caa", - "0323a445ca07801d9640a5b64f01625fae104221f7cae38c21577e4a2e4e6d19e5", - "031e636006b5bc4e03c4a777667fc97c61cac3961bf0b6b1de93e0cca1cec89d62", - "031ad040ba3ee748472e6cd7701073b985927e6251d107653f3eed2c3104bf0157", - "031abcd5584b62af84b10fe2402487d79dc2759577c35f7830eb2555d83d440053", - "0313953848cd1261f261f3ea3882261106271f7ad28311ffff8f885d4f62f50f0e", - "031e6ad9f89e0d558d9e6e1105581877999cafe856c2b9db29b27281e89a60a44e", - "021ba4307ffdf9358e4acef9664cc449190f4c577a0ccc78c4584e055b2cf8c820", - "0209dcbf5e4c44b726a5b3323bc1ddac05fac700d8f7f10de6acc72eacb7a6bdee", - "021eb57530b84e03bbc98fc8cecd7f71145c6c3c63b2dbeddd61195878296b4875", - "022a58c25f0999514e0d7c7e6e84c2be402e606dceda0f9712bfcbd391bf12874c", - "0209e7152861ce8abcab5a17c5bb550d384ce99acdc1589150e6c5509d2173380b", - "0326b6cac163d782fdd0ff22e477811a703f78c1c799b571c0e5e5d62505c19337", - "020679dffa52a0fb9f8f8726797264a7704675196316f5e8ba83c874c7e088815a", - "0327c54850941fe3a088f175ec1535f242339b0bff2518d6915aa9f5181e68d2a2", - "021301aa41ddd6bbfaf7fe9a28ee1a895b8cdf04d0ccf6ca24ee4ff099f45a5562", - "02074fb1d65d2e35303d2e9fcfa2f19e1d2de12f2e39aaa99a9f98891be4f84581", - "032be573c63946e0cf9ae289edb9c4905366777ef74be1ffc2bda1a7d690ada4fe", - "022ab3b74d9d0a4b4578a0cb87e4a847a307a1ceb5bdfe1f3ba9b1f78397bf4c33", - "0301aba2427fe7ce26aa7d1b6512b47d0630c79b163a455255a0a0e381db56ad27", - "030f2c352416e5776602a1aac8effdb96c1f11605b9e15bd178901b543eb182b45", - "03172f1e6fb7f92f53137afcd0cf02a8693f47bc145d688c6b28941fa1667f59ba", - "021119d680c205e337aab3227df44460463b7482d6f22f9b9f60f39317e1fbf868", - "0329c37ab09759f808fb6ded4bd745a51eab90f04693b63e4b39d0e54f244ab3bf", - "0207e1be29416d149152284255bccf8f3758fc8e18c04eb40880b22fc5a60facb6", - "0207b216b30dad3c055616d3f3ff1c4db529d61aa817c48d3a3964136ed2f53149", - "030f4226a06710e00fb4790ceb3ff78143602b0c12423983c62b427f838dd903f9", - "021c42925a6772dac3b9184fa200bb2d34fab0bda9474150b57974382ecef3317d", - "021d048394fd2b7c5e1f3a5dd3d691cd38046fcdf3a189c6816e6c98bbbb6ba6ab", - "0222a33c23c43c3cbc84b6d66de4dd7c0e35b7f882120813f20f4dd339ea821e44", - "030689570e7cd48a0ec5a2ba7b178ab6c8c36858304b293db9d0b26a3f910945a5", - "0311fa21e92e01b20e08e9f30bb5e8c78121b92a38feefcb45a0a48dff40b9c66d", - "020b9a57d419f3d2b993afd356b1b613168e86985478621bb90614b4c57c4e3c47", - "03167e66c5467e5c821e02429b75a10768a89f751f739718f87cf94d2a00357256", - "020e3ad450a5b495c86e10a15bca7289dc9f1c2ec4c614c4fe394d80599d788ad5", - "0326fe81f7084d4907e2204696f6612e934b6a3dd3e272dce29f6fe7d322d8c67f", - "0200bc62e8b0010db0f94bbf5e9111cb2f8f42454dff9c60879c999647f3f6da0c", - "032d23e8b0f177cda0eaefbd75af83a01f9f39c661eff9acb7e17f161d45cfac89", - "021caba048d3de6f31ad668da7174fbb497b685aa28fe9af7113bc30147f7463eb", - "020eeff2e7f95b2b878ef4c823d9b59d55f02d22478812d8f4502e9363a5f5d172", - "022ef381f1018a3ed495062ca4617802fb9b2c8a1cf05d4a701e85ffca42b1dd48", - "032a0c23475a1f19f42f1f2633b6c13d10460d1c011d6c33a4db3ffd41945d9df3", - "02020c60340bd16f55310d57573a4f270740cd594b96778c92ea32f5eb0f5d9656", - "02052a6f5ac8336c8183dc1ef3d5e174e567dcb361406401b0497c5d63936f0e1d", - "0327bdf3662aed27872aeb49972e3118650b2837e097f0886c657301b711d6342f", - "021f2fafffd28fc6b98502abd418a9bf0cc98736944191bb32e58f04ddf5a999c6", - "021079edcb59124c5efa8165eb05b477a03071567bbe70ce974dbb6fb332ce187f", - "0319b833162f65b2924bdbba42f756ff46c392007c219b1ff42f6169808a56904e", - "03086ed068b76081b00a4af4fab71c998beb84ecfd368a70d8ddf6c80e0d20ce00", - "022b48371a0a3577b033c3812516198d12e25f3e35bd66911fdb48ec2fe936c77c", - "031cac2a505816e1c0f2742c97d2a46d1a5e86bbd7b4056532e61909d3ab8e91ca", - "0318e08c2402bfc4b2453224c96b7ea8e25fcc1043a1318e40e97397c20342e916", - "03024ca780e4080195ad08942d5e925f0fc30f8a0c1fb4dc59b7c70e633ecb0e61", - "030d9ee21431317d70cfc96e18388f89ea26613bed8f49cee81864ba27c4aefe86", - "02070b9e0437bc8362df57858b0d3a22c578e4496380472eef46472a5811692cd8", - "03266954c4588221f059023a4c05a9120d95dff28e42cd4bf20fa338978eac6cfe", - "022275ef60102dd35d3e946dd0d3675515a93c79f0dafe7869be8ab4c12eacaa6a", - "032afbded522a6d11315404f7621ca94eb9a92e57a7b2f3d5bab311ed739510d0f", - "0226836e66e9ee2dfaab4766f8502452f6496555cfe7a4ece298ab15c25baf0ab4", - "0305468776c279c8018535c1b4676fc6796469a87a8abc7c6a2dcd26980f0161a1", - "032f7b6edcf247b5b98c20dfc69de3055dfa530eda1cd6654854b190ee0cc54cbf", - "0200268512f0c180a1a21d364c6943a63851e4a3eaa564be41cdc9bbad7e85744a", - "0201faff3cab1d48f59748c4458d84f612603bd53da1b014fcacd7bbdacced2073", - "0202b322ddca5da1dc99cd36bc5ed89a9de4fe2b30e8b6525e6f26fc8e17780d6a", - "03119b1a139d5640143e01533ff8655f34113e3e48e8dd1d3f980f34eeb99a3110", - "020d39aae71f756fd87262858ca1b0d6fff31f9ef5593545b27c4be6e0e1d1ec40", - "030319700b6bba2631c8d4eb643876136ca0c8a03b742cbc13f9dd25f580c79941", - "020d784d2589fa040d09a330e6e3ffa4a18ea365112d2ff9f0f95aed916d3e2834", - "02157f93d5b4352069598e96c1252cec3fd4ba90ff40e31bc79446080e14b71f84", - "031c013c9241bdfdde52c146266f3414ae00de0ba445194c63293899987ba6e92a", - "02122183586f42b8aaef6da8a42678066629e6718d7783156c9952e24f6a7137e0", - "032bd4fcd24c19648de571c0963fe238474277f494474d963246b053aaf4c33af9", - "022a7ca2ad5e0f92d7c66cddd1d2cf6e60a6c39d1406b9d8d66f9ee3ad3d412c04", - "0219b49552f22ecf07bcc57e73cca96ca8f3411057489c39a5dfddd8bc45cb9052", - "0207c43a298b6387bf7bfb8ef1e49d69ffb3b6299116f42559b23a562bf4491a4b", - "0308382fea42cba461719df076aedfe4bd254ed315b55d4847cf23f1c82d075d66", - "020bc513f75a6857a9b3f5839ff951f59034f5edf50bab522025f352af18264d16", - "0229543667cb5635d7244376e8d8d0eff664ef201ae4766b96589c362d2e949ea2", - "020e76ed9d01fc12939bcf46ef1574de30c4a4b4a426039e98594de0ef093e6d67", - "03154882cc353040a0cb689e56d8bb8210da80b4e21abccf8ccfa3723cceffb3fa", - "0322b7f4c5e8d31e51edc48bd30ee2ca4e10c1381d539a2a5e1b7c876a68310aed", - "021187f591482ba2f219b0ecaee4ff924dc7916bb4385d3ed410a75a73abbc3214", - "0329fbb942fe07b3538bac84e1f525b594f32b29f6f187576fdc121f4345942cf1", - "0209e7f15023b8a540412973538b52d9ea731053522b0a8db8c27a4b7408a92b3a", - "02185593f0eef532e91aa5d55171014a4484915363cbc4b1dc90bfcdf7e1052212", - "0226e0345b6402a8244134ccb3b161e04e213de347fa4d6119036bdfaafcd0315d", - "032bf1f6662fd364eb44891021763640df508d51be9b7f71290b6278381c0453f0", - "03241ba12191e2889bf81f57fa854152d1d27f9a4cd2c7be0e4b05a5bc7c279dca", - "02076a8d9465fc6c6d3d60c64c2e75bf63985102cff6a7f107c7edf5a9277ed792", - "021ad05ba0035a33ba3c2b523e716cc280b982a03bf0d73e9664b17bd90900dfa8", - "03206e59ce923ebed3063e67f54f125e20f446bd48c6b78bb92bc2c40f64d0a3de", - "0311c6dc292fe5a4d6a372cd19338456224ce4eadf85ff814c1198b32293b2ef78", - "0220b003bf8e8334fd9fa6830185948088486cddab6ee81fd4f881f6692d7aed5d", - "02242ca95888f8b055b0cd633e135c88ecfc0106d97486c33f447e95f28733804e", - "02249d51207be183649d252cd66c137831a6b0bc85e438026daa05d1dea1daab21", - "030add2769eee893478279a3ce18f5b2c28bdf7e1ea2d479bd70d3659f6ccdb46f", - "020917a4ea8d5be9db9c44b8de67aef524523b8aa468638f543ba9f5384b05598a", - "020f78d0a93594cc54c45923cd067871ef3e38af9f5809632d8ffa918104746da8", - "0222d5e32fe529035369f3aa0dab58158db8b350186aa124e4092f81faf9644aab", - "022f95683e5d36cbb09a1aad6fddf3bb31c2e51b2c708816381c643bc11222a918", - "031d0f4abe8b5e08adf7a1a5d6066200bc143fe0da9fc1d2c62d881f97650b6776", - "030bd47b35bf894558bc95b818a35418f5c934eed3ab7591a0c24387b0b55adc2f", - "0301fb53222c9721f10ecc9fe8e476da828911fc8e7637dcc810012bb7e71f0426", - "03135966b6e770d5e31faed4dcb756c2eac1f8e09b9f279e30cb4e9e8408a049db", - "022c874fda9b5a519a77cc1b8c774304ffb26a83d964cb25b06410bfed56bd6395", - "022ba6dc969ac56c9dd4c7e264d51d9e0ab0be86024508b343f98dbb0024f0f72f", - "0305fbf8dc9090c9914148246585d0cb8abfa428c50b4fa0de218f4db08dee4fc8", - "03233108aa06b12cf8caa6dfcfb17ae6629aee11731b18879ae28a6e7c7c33dee2", - "030e622379ff8d99154a291e77fc7688d83b618cf1ba8fa6a9a365914b6e26ad39", - "031e167a5b6a1bdc7dd28e1684d38c1f72b7d14e613d390cfde7bdbabe0b0425cc", - "02253965ea07c2798de12f52b5ce0dc0e04acaf4cc693326e20001aeac60d40b0c", - "0307f91d98d43a9e08fb35bfb7b53d084836018ec0c68b57ce67db6d6498139259", - "030b5295b03bc1546191d7edacb6e2cd82d2c1701a16a35b4f2b606ed060112a5d", - "022a926daf56b6c499d43ea4632d9d4fbe257b2b09ff272a8e8a4d048b3a51c884", - "022a4da7e2cb1cc8134a09b1c701e49e8f1418d7564db99d37f7654db160007e1c", - "030ea593d303df8f65a45aa791f97aa6a5f1ebf0e8b418ba6538c87b870455ee4c", - "0217a28fa3f5833625c51604c148b67a044d6870405c4ffb842a2a0257124d8c5f", - "021567946612f380f3bfff6d06f7b8cabe48b904035b210cf807b750ca24c8f2df", - "021c60ed031aa7d5a163f71cb79537e445a78813868a1d04bb88a9c1ebbb30e7a5", - "022857786c85ae54ad29f9aa3b6373be262a353262c58a01c143a072bbaf751634", - "0327979bea8dd9c45f7b2798761311ef5b3c57fa3faa1f79115d8cf8b4e835828c", - "032c5e3763450110a3fbcdd960db63e79855b159f7fb25852e01a205c2ea833b1f", - "022ec3f61de6c8993972e354f797e77e2be6ed083e9c1c5ad7c4a331271c8818eb", - "032eff1130519550b8151dcf2ced55ee6600e19bceef40407604832af0b41ba148", - "0307eb652e28cfe6922c855d3e393362ac214cd5c57bc26a49e315464463cc7657", - "0202ed59be1aaae369e938853c966364320d1b9d2aff7d56116c4738804a1334bd", - "02068932961d6c8a4b1a545effb7548272ee36b4ec52c16722061b0eb53ff9295d", - "021728b5fcac62a18ce56038cbe1fa8c50043e13f4ec3d6d50b44c01851f645a5d", - "0308eb12eb1fd3ce271fd07909b74b9128ff1b1d1310255edf2ceb231c97afb5d2", - "030c48b3e8da880cd0073ec7436773d5c977b8dd487536cfe0912aef89f137ba3e", - "03163f8dd1e1c3b97bb48b4f99b847f6e573ddd1765fadf52d3b83b619bc1ac761", - "0209763822ffe71eb61f58b08eced08cd41a8741e04e0ee9243ffb9a80e443fae9", - "031e96e5a48cc425683611565cdb6224ba6ebe9f459c4be5cad2b936d4370b82e5", - "022ddfa569582ea50a67d955849d9a89b3421f48e2813efb6d6d97169eaf73bd3f", - "030dcfab8e2939cfaa1a4e84d68d0200bcd8097b07ac94f5aeb7bdbf66a4ed7b94", - "022e60ecc144df0a6f9887ba22548a1dbea66837bcbb690f23de9e456d263a2c21", - "0214f2d3676f41fbcf9dd07d54619850d36c55069d98cf6965f123cbefab97a191", - "022039eb43a7f1e6ef0158ba7225c95533711301b883af97e9fcc5173adf73ab03", - "03084b56c446dfaed66af068592d9b07b42fd6fa57ea58e64d80e680dac9a0608e", - "032298c91c90e7d1aec60d266cfddc8af28e5c1ac6810c3f2a78ca1e91132f85c0", - "021f1451fb4d48ce98ede915dcb82f43f89fc72b7874a9a7b59e91229847f84d06", - "020db1628c58e17161c6f8ed76f57b7d235a77b3664671105694c2e0e5f63e78ef", - "02144978463a559e2cfd73b226a7f0db98f212f23a9d97aa09bbc12ea99c5e3999", - "022a41c4dc735072776e545388857df86722b2a813cf6c9f1fb6a6715dfda6c310", - "0320993ba24b53160806a621522645af3ffc6190f88445f37165ebf02b4fd84220", - "02042d1afa1eef66babbc746e6c4cfb5f6e15f8c5198e12e4f0f532d10cbfbcf27", - "032f6f318db2ff835fbbcbb2aa04a9a8153e91bf771859031723364b1c7a895aa7", - "021a128e6922c82d31de42abbbe814f835fd2362b3aeab47f51bb79dbedeef63e9", - "0206e808b66559834710a18ffb0a6920acf1029422aac74d7d69c09409edfa2a8c", - "031e2f4b87d9e7c3bafbb2317f5dc0436e84e7f0fb9ddec63efe1e638ab3949a05", - "020db409a68821d0befe9fe1082fbffdaf103afe9328ec82ec2a3650f3176b015a", - "021e966b06419368d8368658e52c45003c39ad59401e0bd1ac6b1dea84556c66c5", - "030e8fdd702b4397c47734c62b7f27390877a05503211e527ff9f1120983f140bf", - "03123f621fe3b81c191f47cda51655a2ff752d388dd2297fd94042932c0a548f83", - "03032aa1928ea3e981397231df0d4abd613390ff87eec6cf1d1bfc35bef322ad49", - "0221c4e20aec1732f328353e990ce739cecb85b7302cc275903aaa6827504f69f5", - "03117a88add338ce6550f834831316f94b130a9d92375af838783229b177e45ded", - "030a71ed4c3ec87a0342a5d164532aeccb0e2f71c259df98adc64b0066096c1c5f", - "0329d6fafcec96a70e69be0c2846a3811ca90bd51b1c430c31ed6f0e1d3e4d2829", - "030c8a04b42426203ef7310f1ababa2c1359dd6aee61806955d5329cb6a0e8501c", - "02135aa0774d9231b43db2962252c848ec9c6d2a77b06750e6129ba0f47a8949a4", - "0325ea9ed2ac617e4fcab02442a7f28b8e3cacdc7ae83f09f0fd56ecd053b77888", - "03169a821319be9165df54ef93823471920757f5ce54b7b04f18d31206d1029aec", - "0210b73fdd9ffd1d6456670006760e4a217272795ac2a43cb920835966903127b6", - "020e307610421a88069035c2b9f7d797678ff00e740d0303debe9d5d8166e5f81d", - "0202c95c3d7ab100d3558ed53f3e07db58e1edde4a17f4ab1844b8d08a435e28f2", - "03298c120fd5e6d92fdae8ce8ea8bfa54ceca463236488d102ec4b72c0e67279b6", - "021d2274cba001a94fbc55452a91d5a9a88cc7cccb1fcdca1530b4a30962dee560", - "030e286dab65b2fd62365e8973099918d578004faabb2e82b134e4ca098c084069", - "0328a70f7d46af04dddfbd609aa7834d40f2000f76c1b8a49160a8c02a1611a30b", - "0301c19e2fa84d764ce3690f3a94c0e8ce03c4d36963b2f3fe5b538357a5317cf2", - "030e39db0e037d1adce69def6dbc9f7c1e458ed210abef12bc03370f332dfd916d", - "020b134518949662af0e5dd7e82084450647fecd2577b5c20a3e4851c556b78e3a", - "030690d382487de52b934da147767779aea93464b2bd08e1310266d752496cd8d5", - "032db991dcc4bd2a3808ccebca970d1d9f6a1b3f942df5956a1e0c477286066a34", - "0227aacbb7d3704d3e693beeaab810c1e05130e4e5b11234a9be7383873e148513", - "020b53c823b8e192296e9283e15d1cdfa81e32fef9e4885e56cc196540aa81824a", - "023030a44420967179aed66e6aa859f87d7e9a473be7dfa57482ac69380cdaa9df", - "03206c0d4bef7fe9ccaceea869ce5b639921be518c6deea6ef35c4996817d38ebd", - "022b80ad733f04ba2b13ddb425c6a692ffee61503828e941b3b835b6d6e9af3672", - "02161b37e12748ae301e3734746b40c5e704bbeac490c9f6bfa4aba27e4d379ee0", - "021036de59016589179a23f5e61becb0099717eca31270aaf0970c37a4117203aa", - "02064b3665472ddb330e17721c86751bb546ba248465f616f87b6a1c01107d7893", - "022e735dcb6180f5bc76afd3e25476db93f578bfe9ca352bfa3221594ed3b4f55c", - "020b3b04b93fe780ebbdfbae4378ffa85c92e967a2160491a39b0346a7c3f535a6", - "0208259d376fa7fe65703a4cc02c0a4b6729bb3e1a264e9cf77fd96d525fcad91e", - "0201f32df87c8a6572542c131026ef525975f987494bdb527107302b9a7073e958", - "02027fae2f6f38b9ed26d9dc49fbe67d9625495b93cec63b221f2dd9bd41ff4fdb", - "021ca2622b840c86a743446d0dc117bfc47bab519e85690a88a50cdb31b6c96c35", - "020d9baca8a87b0856aa128e47705f7a7a410a4df3c23cb23bc8863f88339faaff", - "0209122b814983103dd57a2a26a5529b650dd4077084634e3f7b2839dc7f4dc39e", - "03135b55118ed98193f5c75566d2f47344a36b369751723619b1b92e10821ad657", - "031341b0e13dadea97bc8af735ba689dc26f24d22e90296eea8d8bb2fa0a97a3dc", - "030e12f73fdfaad48876a7960df5955e4e07ac2909b84987b1a6e78a9d75ab3545", - "020b19ce67903e2bb511931009df318f2c50c0ca4f34edfd9eb1c69ad1a8448f85", - "02245640b90ab6c76a9a0ed269a89e629d50d63a191bf4012466c726f4857403bb", - "0209a8448437af412c487e04dcf296465d0525d49214993059d84d7489afcff0a6", - "031876ba7230a3539a2ea12ed6ae372c3e07d289b196fd77ad359cccc6fc16dcd4", - "0313a387a6bb9cd0a6cc00cd583bbfc58215cdca48c5265441afef5aac1e75826c", - "02239580590d3fd37478fa8c11ef7035766c11adcce0a0a7a856b8320f1a509a4c", - "021faab4dfac8bf85581ccf284c3ecd1bfe0b3806e5db93f2756d808a09a9b1fc2", - "030bc93556d2859aa69045c083e563d50d22b714835e3c152c46c4cdc4b1540055", - "021dd1813a8d969acf5b80bc32a7cda7c9f008ca29782ae97a215b5a71725e9f84", - "02130d653ae5e85cb1acfaea0d40502631da347644681fcb3080960962ea79c14a", - "02195f2d475b683a4744e958828c2b8690823b2d0afcfc475967efdba132b94031", - "0209d1d3ddaa7f7663e31c4c6aff2c692755353eea63bd2a0ee29d728186c903be", - "021f95b68ab801aaab533121d7a340002ec032840bf218fba907fe3457b87ad636", - "0205c0ec9dfd57cb1bd0caf769ccc611b81f558870363abdce86bae5d695a531a8", - "0212e05407747818547dafb3ed8b060b931a3e64997118712e21baafc94be99df7", - "032fea7117aeaad6d0d6bbd278614d9a26254cefad6baa0e2c5ce838c60735e82e", - "020bf1ee7a1a1a05cdc8303a3d14547e11b2d8f03ed523fe513d4afc72bfbb4c7b", - "02178be1142659c28b787f8601af0b027670223ed5264d03acd372d67c8a864d7b", - "0310226d493c8bee97607695c0c668eeed9f6ef9c1ecdc2ce4c5fd7b67cddd5107", - "0201513718c4617593e05031ea9bd266d0e6512452007e5287fb7a475fc89e1d18", - "021c71b7ddbfa5377aae852a2722776b4249bfa09e0ec1f4eb1550a34f30bf78e1", - "020c9057038d1a9f1d7fd506e66638e46f0c52387326a8540e0e0edc307c0ee2e8", - "0209d8dd0191fe3a23fdb46f545eaac010d3a4f183b505730fbdb5563101ab70e3", - "0305c31eeaf3e87002ccba90b12b519b3e845a7f212be3cb243093843010db5f9d", - "020f871366fee705955e03e560bf875b801c6f8073b9d79a5dd9f7f7ef99470a13", - "021c5530120b0d2587f3e0dbd9d8b955d4e56631eab5dcbc8ff10717e871e5a853", - "022e41e333d359ad208657177eb3e38703022247736c67ab9b747c3f72131e0541", - "020b6ce9cfa5ed1a0ee36aff9d322a529abbdef176a97de9e497f0caa35961dd4b", - "03189f44e967d6b473ad613a17bb1c87c05cb7727b6bbca084cab37b2c8aa83413", - "02102576130b56ab0c5ff12045f00e9d3d678873dc0f02e0c6ba5d2d8a565ded6f", - "021dfb453bc4799143c61213092220e3b90b1de0582602320e0f086e7d7283bdd7", - "02264e339398d8e27bb39ca478ab95814bf7d0d50d28388f4a617d98140aad84e2", - "02204eef72c5455a2fb96f18aca46010ccc7a081f1b0d047e0c7c7ccde3240dd2a", - "02157bc01a8761997771da9a96efdc1323b6bf581311f601395448b3f75d7056d8", - "03262752d34fef3d4ce79ae6f4bc02492b8084631a816141e52dce37f591860ce8", - "0200dc106903a04922427b7d31d949f2e9fc6d9b3dce094ae204c81f4f26216db3", - "021fc1e37a674693179437cb4eefc1f60da1b4e1effe78241d02eb7d9b11e2330d", - "032ae946853e95cd5dd02e64b7b901df5024394f0e3931fb803c68124e751d0fdd", - "0202837bb02b53190b3904b9cbd0f8ca970a73365d1652d6023b1269511c6c7524", - "0323f8a91c875e26e4d4b9c4ed0a76c0f8abb1448d84114ef6384b0d5b03f833fd", - "021a06d11e6117caa73665c215e1c56699a441b3ba4b156e037bf6016ac9d850f3", - "03075ee85079fc5b8a191ad992bc96e9c4030b11888b4058d8cd4227a5045a2271", - "0203349223364c6f6790834cf143919dd1ee6b26684906ad6b9d99a0d2eea2f403", - "02305770fcde7013f62b8c82349c01bdac20be39404165e96edac0f4f4d006ab8e", - "030e0c5864d4391af8fb3d8bea92af2c28097f5e6b28b46c64cdfbe5abedf3ba42", - "0226e78edc76823bbf6221b28e497618197256f0370234bf8c6ec3faf9055b026e", - "0317efc9f33a1ca3f1e82e408d58a645180f37992ca8e50214bf35154169ba7ff6", - "02039e239ee732c7d7a8b0bbeac65e75607482263f4e2582b9e6ec4bdc992a1861", - "032b15c1f3f85bd34049629a548d9de3eac706c2144663f9ff89af2e6f1792153d", - "02291fc91130620c1e68e5cd26b71b5b603ed2b1e363a83fece80745522aadf09f", - "022d12cd4414c59af8695bdd6d52f355bd1e7e528200fa8a7e5e29a3887f0f0b79", - "0219ae296f6f3fdfb7f5a49e6783aba2fe2520f36127be565e90273c975e22c02d", - "030acc514094456c84741c696166c4248883f1b9e838d958204deb37e899af9425", - "0215006ff52f5e4cb2f7d3c1588051d3788626042c772a6368d141d2e2092f829d", - "03219e6a90a45c683f06530895d07f1916535bced6f29851536cd28ea964ae1173", - "02154c68423da2b563f50b52af8d4b46f365ba29ebcb8643895770d720ab121150", - "020f9608fcb26a0d7b9e325d832f381cad2caf928df98bdc887ff27314e9b5b64d", - "022831b045462ed00987e5952e9ff91cf1c9dcbccb8a635d73592a85ab057221fb", - "0320b6db179b38eb4d48d5e6c26847d65e4b570c751f33c79f86751d5408633492", - "031f1cb85d94a9f008703ea9cdf63629054ad86a4e5853e0905fc498c5d27eb41c", - "032737ce20e1fa15901a5ae4fd74b6692f0d852c92fcdcf4691031a61591b3c91d", - "021bbd641eac13b4c2f7d74af4f9f61b874425c2551d7f4e4186106e5d216927d3", - "02175b91ada4dcb1753322ab882f3fc46f6c8bb4d513a84fe2783099a6e8a03952", - "0202568bd7299ba4c1fa6163d43e2e93d31dff103ebd143428738b72270dcbb9a3", - "030090bd9c0167431b3302286c43f0c99f793880ddc2339ec4462618a8054fc3d0", - "031002a2d2d882e3fc59bd9a2ed479ab2af727a42865ce966b4b4fc93bca1e84c5", - "031d6327ef9e4b2c1913d21ff31dcdc8bdeedbaf851c65f0ae3597046f82e9cd01", - "030d334ac72d070041192c9d0e38d64e30793c1620beb8cd7412d565b8ea7b355f", - "03091247870cef59685ddb4389635ffd9859b46ab1246a6faf96dcf2b3b4eb0223", - "020a024907f3ae935798bead56dea4253392fb4192262b5ded57809f4be1ad5973", - "02035abd76c79b43dccb954e017f0f27da745107a4981e7cb423da4340a7a46111", - "031d1919899407420d535ea4cd46d3b3d7fda82d71b2747d00f0958ec8fd93a74d", - "0302e033c77ed7aa9051c58d7a137892d249dd262598e6ce8f4ec3fdf27840d5aa", - "03205b00dcc7a9e7ce4200cf036a072ebe67eceda13660db491c275359af799856", - "030d87e1241479b8eb3bb4215151d003447396ca3e4f3cd77e87998339a56a34d9", - "0212e9b6581c3d2f34aa23a980f94d0999a5e42f01457dba9d3cf3908a8de02646", - "0215170a03e7513c25457e7b9dfc2dda413e3f1e6c9bf60d17555562342607b5b1", - "0224ebdeeb809d198f34991b398eae7f12f6c2c83cd267a6aa88aefb8009ad3841", - "0214eb53ad9c9b3336d13164643c629dc1e8c8b3dc2d95ed80f49ef0caadbf60c8", - "02039830676ddf322ec4fad60200516b3492574fdd5a92989ad045699c835cac2d", - "03111632eb27b5d3c621b544bbdd47374a1b804fee8789c8c1ff1d6fd3e057b19f", - "0217c98077abf93edd2d7b669f3de05d3c6c959beec7d7f26e569f551a097675a1", - "03032fb32c3224db4f812a7c8d2589efc12f5acd9feb78fa3551646acd200abc94", - "032fb8f107a184b26cd18053e254287aab832922e0d26ce3242668acbc6ed8d3f8", - "030d084d3b8a92d16b0603930ed08aaf4839cf34dd37311c7b91b20afc3b815deb", - "02099399e8f57d7be8279ca183b6814288712b35885ad96234c2ac9922909fca49", - "031e31fb73fd03c448e97b754d3b876bf3c3758da529fa30118bacfe7e727dc2b8", - "020ed5b8086326b1f600818190fedfc5f776d6b7e3d3cea40d70d130ce77a6e914", - "03055ce893b7bcc97173de6f781e6e6333755287fd0eb57fae991ef087e870c1c7", - "031acd9e32450ce90483be2383f3b3c14dd7fadb335ca2dca299699e617b104a66", - "020dbb8efb719d4c82174eecf4506dec4ddbf15dac1657fcd4559ea8067160e55c", - "0208eb93037c9d7bfce62cb30ecc5b8f77b3d6c1057e332cf6ad42147e850d3ab1", - "0218cee5cf9982d9c415e9c649a2fc04b67020bfa9980db136c3b67d4821ed2397", - "03061699b8624cb0b678245eef7d95ec7446fc8d60144a97df390ecdc647c7adb4", - "0222627185f7ef206b49a5964568e1494c5d85c025c2cce21d122ad29dfd6667c6", - "0216b4a3aa56cf3c0d8910e9150efdb24653f1bc5ddc9e101c3f5f81b7604b2afe", - "0225fe9ed9489f1a0aca8ed476f49bdd75c5c8ed3cd4e8fc5213c707244eb79cec", - "032aebc0d7de7ec20ebe22bb1aaf583749adb95cdf1c902cc44eef419e983f8d73", - "0212982108d8c3beb2e2ccf3858cd840b157c3a4ebec77b92ecc1ae01e1ff27a14", - "0314da1466803b4c39e6171367eb31ec753bd781a5a7c3f3c88a630eece4075905", - "022264ec0b9fc5cce4c80d4611b02f4345cd3a4cda91e1a2f5194b5313d42114be", - "03274334989a0e5a7d298f8bd232ae20385ffe4e56ad6c1b22a9d0ada3930f16e1", - "020d4ae06a4c35f31030bfdc740d71e9aa80fd21f66d2f68e7259931ac6cee811b", - "03000e6a816c73b0eef7d578aa1c7878d4e6a851161e64584734253978456d53e6", - "02148803b03b61bdf76b987fd2da212c56d0af160224aaf1504fca2ee14451f0b7", - "03169bd341792771eecc54f8270a62fa5511b1c4b4876c0cedac345465ba7dda51", - "03298248d6796021d5b8e5d539a1c8c0618f75d20c8befa4501d78b9cf8a24045a", - "021e5054c1afbf4b8c4246182a75945261cbc9a9f97a3b116de82d2373c52cb66d", - "03122b57693d0d04c5d89dcd7bf04405bbd77580a9481b8b5f43ec9b1b8879265e", - "0218052887d2f7e0685ce49d107e4f82bb1b146025bc71f3d694aa0b222c3a2fd4", - "030a9f6ba401b32edd96e9f87e62caa3ceb0775c30613397711120f0ccb01083c6", - "03229834360360454bf50fb25180a60c024d39055474a7fb87c60b31c7138f444b", - "03154e3e183be8039e49d46eec387cd689498f3048a19a734f547b6bdc536e4217", - "022eabefb34e8925d5f1952b577a7e08e835c90a7b56e86b280184b9a048899a20", - "021b022087f98e44751e93bdcf8701637e7158df6b4afeed58ed6f7313cee0cb25", - "030f48e063e90d3cd753384c4195621599f0bdc22be3a870748c3e72440b73c63d", - "022408135d728a3333f912e1f0ebdb8204d22d94b254e07e7945277af4db44c3c3", - "020377e5d859bd28990f72da5013ce8dcbfbd59e860820b84817518e8f9c38efc2", - "0218dca94f39799fdb0849d41d169b3944db9235767b031359d1737018591a4939", - "03261a6fa741144d5c41149dc1b2030a7eea22c3ffc16a96322def164d2d8cc3cb", - "031417b9ea7d829456358480c3f385898eb9f78987d19b09c512f0c0aa040d1c43", - "020ac6ff80224f1978a5c4840276feb8a8d831c56b76097727a52aa4a6b0685c34", - "0202f685d75c5725a3f4cf9acc429c61e34da0eaa541ab9f5f4191c483219d756a", - "02287ba7bfbfae43166c8a736cbdb1d4c62c69da2a4d09184ab8a6f0a2e2bef28b", - "0312c2c3c140c853d9465b9927c6f689583e98a095ae2ad55097ff062071465d9c", - "030ac79bdcaa96bb0b3ba72364f4dd56c2f49a8f628f267ad205725a4159233c8b", - "030b5d879b8f14e774624bbaaae8251fff6f636e4941e66ac3043090b343b90c52", - "0300069eee2e91a7a88b419132b00dbc073bc994762ee23be577ab095607d71222", - "022e01e56c8be8dfde36b51cccba7898ad70785d387f0dba2159ea7c02f7a76aea", - "021220bda179b1617fd7fb545ddf81f19bb08a2b0525d3a9e38c1e38624a499d98", - "02046bbf70d8507d3fd7d35e20e240a26e00f3cb049ef0a991d35a2e9e2f77d5d9", - "022807847f6cfec4ff54a0f05077927c91c7d3d15bb2084ae4ff22782f3d06224e", - "020e81905612909991e246abdb2a284e8aafdcc126b8045c6e965404f9b5d8b9f3", - "020fca136883e964cad3f19e38e17dc47e3ec39cf21201468e5b287758986514f7", - "030c17a9660756202fa5d0360b7bc96fdd58b66f25102539d97d5971b0c3308ec8", - "0326e666b59eba81239dee84e12d06cbccf8877bf7a5c0a7ae1bb8d41e6153a8c5", - "0320e97d85bf2b66c5044419ab159d71a2c373bcc3985c85c821a7e6532a92d758", - "030cc4aa9022aa4e77281f7a79be1e7be0db01ed89950c1a89d0f2f9620beb3f3f", - "0219fcdde3bb4df5471b4576e02ea91ac135e0aa0a64b9662b63445723cb9de985", - "032d663a727c1732b204e9023bae0034851dfae49edb36cf646bb09ab830ad51bc", - "0304ad67fc49b272f4ea1a9606bd6e1d0085c25e6484719f4bb739bf324f6a3bed", - "031a1f79d8907f28c75fd74dd56fffc2149da78fba81e030eb372034d517cf3db3", - "0214a6c4c75cb91c5b828bc8d1bcb69258e86c8a9eb9b3404f327659bb51b6680a", - "030d7dc78140b08d47131f9fabc36371cc8013fee11520d1aee101428d4a8c378c", - "02076ced854add04daa41726eb664fe2cd232224efedad633025a8b4a6e0e13585", - "031767c1a30da6b69f8060be7797a3159c57a130f077a470829e0c2362ed4d8fde", - "0208328b52581e18ec812e158e3dc7d1080d4bafdd6245c0955325e8d46662cd53", - "032735edac2dbd8175ad0f71dd2c887da2ab7dacc55542ee37b708bedd23567e23", - "030c5e6230b7ba3552251694e77529a0fb69ee9ac3f3ce610433fedf0c78b45ca2", - "0311ede0d038497cfc547454b99ba7b32f1ce487f399f291de1a894dfba481e974", - "030a03e601e224ce5f57c809661555acc38b349f357ae3b278ce9f155e49e81d28", - "031acee484fbd3f5831d6beeb16279478cfd652c26be047cb9b6f8d18bdfebb240", - "022c4a8c03e7683ca88de5a5d86c39e388e6d656f22830440f46b10a87915bfaaf", - "022cb2deb5664b96fc3a8a1e60fcd37e289a0e71cad835b0eb25959d2146d528d5", - "0309d460b9c7f5b892134444db966586f1a934b7cb6a6a61b8b725af13b73d677e", - "023009f4a53256cec39d5f71df7a648fefa43cd14e6305d4a816d75806cdaed568", - "030ff6b4dc529181f3111cc905efcb85647e772ce99da81c9524504d52f75f876f", - "022fcef3f1fc3cbe3092d5c29e1de367ccdc1c5898c33d1fff813cc71a0c1030bc", - "0215890188e468a9ddec1d344fae0c70ef743c1b390962d49e5ca6f07d19a903df", - "0312404e7af855eb54ce927df63db9af02899d983bb330018eb0c44791fb409a01", - "030618bc70bb09225c2b0a5e26d0f21742d5d0379e3a5bf2456d98bac79bed7988", - "0300273beed1e6dd459f8be9b132a825115c53c73795c1014b80725a740d544249", - "022e15da2f714c9deed7034fdd9284b8db7237ddc76b8248f7cfe805231c04d47f", - "0327438d460cef55ea06edccb9cf9a4139e574a404ab6cb14fd4a93ff037f2e7b3", - "032f24f4cf830c2f7d9d604ba14b60c0c5d93595f8006a5070aa0309fac38b2d0d", - "02151ac6b909df643cb5a1ff13dc0562ee79a1148ead3d415021384e991c7e42cd", - "0226b39c19676f589f7071fd8c493d586959f285f27d12664fb22c4162cc577f07", - "022d901743950b2b8bdf63602df05f44a912c2ab1a278b80c731fc7e416fc3f36f", - "0223e4206bcf8b148b927e88391162fe3f56e082ad4c783d925b3cf9e44cd3533b", - "020948edaa50d3891aefd8a2acc4f19ab0623bf25e3b4be929fa572d26179ce77b", - "030aad4cff4a721f0ade1a0b84b651e363a80d5958055ac75dcbf4b9ec72406c23", - "0323dcde173864e7d6047d17dd3105fbea1b5f508e906248a408c7b6972ca22b8b", - "031c621be24a300b5fd92cf6a92052c2787e9e5c9a6baecbec8ef37d27374932bb", - "02265f054e019801b6585824e15ef811d722f074619ce52322232444ce9f9e4fa6", - "0224e9f7d0704c757375d7bc24ab667b7dd60b4e3945ba274343e0085a3c289df3", - "02052eac224edbbfb504b89c5c0d9e0fda36e2bfe4687de6aca9c9cb6a5a26eb33", - "0215fe95ba1e4435989c50a9d4ba5e13789afc6e4ee08343662218dad088de9e7e", - "03114473fe1c032108d2989bd230928dc9982ecad7dfc3136729c1caecae24d1e8", - "020aaf24d5a2b4b3f2c30b2e643da48ae94a64de496bae9d571e74f015c49a56cd", - "022ba418ae8ad9a6529f45046158ad1950133a62ca55f9caa5348735e1ff18c88b", - "031afb8bbdbfdfc5ae7d8a70bc7b72a0cba00ab1262109a14a12372b7c04a34754", - "0214bcfaaba2609f40b4651f7b1c26d900a1edfeaf9bf8216834c8faaedca81b48", - "031c494cb497f4f850bd373be0d069443164951d87c326498d634c070b6f1a29e7", - "032bcff970474b0b773c2b9ce16cd0f3ccf3783ccb0badd5c1e4cea762701f5de9", - "032e93447ca6c4a48786176f0a4ac722a2e0d58282c0def896a57c2b4d9b95683c", - "020d9ec4b3b8a5bc969c4d6882a8fdbd01bd72c99ff4e4c2db71f252e55331ad82", - "02117584bebba9e60870326427529de4adbec84286f67f1a62f7ccc140fe9dcc1b", - "022f72287ba05778a919f8de9c0ddc6ceb5e4d0c312cb4c5f9adf754922c8d2eb1", - "020b56a8ef866e779c9011e14d64d689be81fcae6bb24f3672630d2968df0bd628", - "020b4ec3ad3b91219e46c94be372b5c03a595c587701272c8629eb47681cf5a2af", - "03080f5b42ebb0908bf740c2b65ab02cba891dd3160305966b70f1f239cd63e3ff", - "02245349f4b44e17198f2501a4e53e1cf2d5980c1f6f627dfb05bcad84bd4d34c2", - "0307756ad3aece0c58171d89e24dddc83b87c17a4ac0a578e2d4a118b87f16bf72", - "021139a7d35e98ad21e933c7b07cbc5fdc1d80484d6f64292e7c1ef112ec0fa8c1", - "022e3a4cb6932b3c0a0fd66f7dd52daf9afa70feb18ac637570e405510dad777dc", - "03165f419f3397002ed6edcaa94fe112e6f1a93ff97384ce4931a42a7bd06c3f7a", - "022461d26caa27559184c0ce3c730555e172d5b15ad97612cf1f82fb32ca8e5ee7", - "031b58e0ce24387786d35e122188e91a0b1d3df61aba086ee15ec276eb40122900", - "031f8b22db84a97c700f1efe13e5675facf5956efd05837b5917562081ace41a09", - "0224cb2e5dffeac96dc76f548042d6ce6bac7f2861c326aabd64bdc7491588f58d", - "030a636feb2237dd008ee5bd25a2d1c68eca06341d1ac1e6a909da1549608045bc", - "020f61a656b5e5c9a318446235e5de4e077feccd5bffeb24f7b31ddc87596c42ba", - "0220aae51fe745d75ad215d5dd52c95deacfeb00df073f063f3f2867e30d64b0bd", - "0208731dad7767f6f9291b344a69cd7cab06b0e9b0123af6334a7f8988e85fc050", - "021bb82237f90d08256ef2d9c2eac207c9e6ac75fdc4c938ca79f87cc4e00627ad", - "0203c1e6f78c966e4478490186d1402dfdfc8270677cf5691cdf008517e75d20aa", - "0314b44cfb6a9bbbf3675582a3bbbe6dfcabd9bbdb2d479e41dc65ace77d5da8c2", - "0307beb2d767e5153ff54feebb8a102e83ff64b3d687f485775efb4443bf8f9756", - "0206bfb41b4ad6009c0d74e47fa45302187cd73d8ffcd9f231d620680f2a523e09", - "030935cf4604fdc41754c5a0f7852ac604bd70b8b5ed111c3221cd9a1eb7c51d6f", - "03284328958b172915b802fec55e7e8328527b75e44d6d4b4b571ee7f602d8e159", - "0309a617cdbc69cd4dbcfc810ba31fa32cfa483add51ecc80bc8ab636573a959e4", - "0322c3bf5e9f3c09916fc54fc02d444e5c8b3f07210ca0bb72b4a6ba02a46ed7d2", - "02081b3db6783a5544652610eda8d291c690b5d9c2964e80bedd3427258207f743", - "022cbb0c3f6a0d70cc067163366bfab884eb474a023dbe62419bd3540834cb81a6", - "032142a79cc77b3e937fc11551392c29e579d91b1835aca924a2d5af7e89ca549d", - "0205618b5706b38587b719d2be1541e3c1f3d8273e9aa2e2c8512245602bcbf947", - "030a7999ae410470952d4aae0c96afe163774ff99156893f07179743054c5c9457", - "030c444e1049829d2f7fd8954d91b722d9309a20c995ce8bc8c07b8e85f66fa718", - "020bf256221e7cb95ed187d0208be25553bb2d492c15d69897aea87473bd0dc06c", - "0314037697d47c7b0e0da6a303f950a047de7dccc5f5747b70da31a4d92db2231c", - "0314c84d9be62a1422d42536178675848988d2f022e8d7dc0662d4b289c535367e", - "020e7387c0a58dfc5a53107a4bc2c771889d2c25a5687e6b178c43005ff49e4903", - "022a849ba6f9db7bc76500d2edcd43413a6b3b94fa18faaf6676b7aadeb4ff9b0e", - "032b2327003c3b0c3fb477a1a7831acee6b93af7267f01c87739fa4813afac28f4", - "022410a89e5d155103407a668767b15d06ffcce067014014c2ce8a70eef1dbd579", - "020258268463cc5420adccdad1f368ce59489e55988783c4a9bfbe0318fa243356", - "021576827d915390f2156a638f623e67e2d4198db1d8507c457cb2319cca75fd9b", - "030b25fdbefb2a6595ee94c6dae17c488183209a5e104c95f7639ee13d7da4942c", - "03239cfc9195d1dde6b6b466348586ba32546eab5bee3afff5fa245f267dfcca7a", - "0310dadcb5cff629a224fc00c9d70b47391c5163eb1b69368ed708592ddbb18fda", - "0224ab15a2ad2e9040da01749a336e0777e5fa62e3464bf32ccb174c4b923eb982", - "0327402818d506c49b1dcf0f0cbf09e895a4e4b2ddb7fea3a802bb79447e099248", - "0210d1f4ec54f1dbcea5b59d5190745baee8a9003f7a2b0ccdac3f44058f8c442d", - "0329810020f2b676b4af5f84c5633013e1a26aad7851655f75ab459fdadb54a255", - "020234e61a1bba70cbc38bd6a95ebb460accfd4bebecdd274e5ebfe1f8e9e2e962", - "020e1d0bea1c569ac66212a53883ad007ce5165654f00420526d8da78360ad695e", - "0324ac370fc6c6df669a8c7734c52d6e8132258a902c9e5f4e981525562b89f8b7", - "0306978bc5a6e2b1addf96a9aea72ada6571021d8d9afc5963c3706575b1a18219", - "021b90e093958158477c9dca58f510d125b5560b3c4ebfd93183934fb2438aec7d", - "0202eee65de22263b01eca67e3d74c9c21f826ba30d9ddafd39ad953387a99f125", - "02258a3679bf0d1bc16a537acef9c15c223b39fe0e5dfb485dd80f04675ef25b1a", - "031b81de05a0f33d41301c489891bf128e25aef52bd8b1bd7bdb7ce99de5eb410a", - "02288577e955ae9730bc8897d6a888e4ad222832ea112b65c831407d1b49443a74", - "022fa583a407db55bf11d2cc357dac2a17555a4ac0d75581e4c859126241243749", - "022acb951d57dbcc52b89815d048f53a5e21e2b47e79fadb268ed15939f4cc90c3", - "0307bcc09d301f36bd05709d1420cc38605d50686f975321f538406597075a9f7a", - "0211228596246dfccea66b5959c3e67c1cdb2e89685d8536a3beebd96e75354650", - "032369d778e4fff26ddc94b7baec0d6d9aca9f75f3b124e16b72555732de978aa2", - "0318ef9196905770fcbc62f9b170d8533438e710734264bb789996dab386714d20", - "0325da9bd79f66c55df9781a2ec28a16cec8db3b7d28f70773037738cbfc96f6f3", - "03151ba4bdd1b93aea21511dccd00ac123ceac1b8ab91c2371ba46e113745a3d30", - "0209f43b05e85f1563ae09a18db7ca7596d061ad441338e72e1e94af5ea81cf1de", - "03114083e3bd4802e67364d867219bd6da5c0a74b4086fb017369fad39be127e3d", - "0229edc5e7ac465d87c8c386807de2fa774561fd39a547afce147e52ede03bc30a", - "03103ad6b7d2bd94199b760f67e0f85ebe4a61cb57e8160b1316c1d9a3db9a00a8", - "0207e2dcc691c5c6d32726a0ef1e39d85d12f79cd043a4ea9a0c0462f33d69883f", - "02014cff9bae41db08da700cf531c42e9331745b9a5cd5c9aec2e1ac1ef168de3c", - "0209ba51ab1ff1128da86bde22c737c8796871c84bdbfecd7c384a90f581f284a8", - "020cafd30d5a440f135f370ee629f9301e9b819318ce2b2432c1de669d699d3e6d", - "02109f11d897207dee66b03517500201928b55b4da32d681dc673669c72cb22d5c", - "0325fd2d18348e8242073f16323151f5486cb482e7285544cc7fe07d0cf2580555", - "021b7628b24a72092e2fb0bfb03039c89acbace04349b07a8c7875bc86e6697603", - "020d79df565505c9c059be83489b1cab2699c798e27816a8b6142db464ca5c649b", - "020dbea83017c2a6ecf9cde03a9137afa32db53e7d736c992fc6f13b6546fbdc9c", - "0324a4b326e419e05b08add392aae9c05888f95f4082a88c38c0a91e7d0dddeeb7", - "031a584db7b7e9f1b04e9319991181e02784872ec86046e40fae40e5e038d9f07d", - "030073f063e3f7b6aa069d59b8f8bf154b6b4a9b3118d4d99ede3bdbf0ef9244f8", - "031ba06586d5ed6113fb3995bd871150dd55ab96befc876c555a1c6f3178c2327c", - "0311baf9eb6cc6fdd66b57108388fa8f53552f2b9d345419b41e4a112e7a761602", - "02283fb9342db42fdff5910428b6cb42e2e8c09e09bf971595384d26da3099b131", - "0226bebfe84a3b020be972f317ce461d83041b0aae86e6ca57d0eae5b0a5128fdc", - "020cd049cb80e54484352c874eb6431e4d9c621813239b624f666d14b7f7d34934", - "0323515204d0e320f070e04540f5a572dc9153341b834bbdc0b38859ab407e1a6f", - "02206a8ed5872242f58dffc8f8ada02be2a242f03e707078d9432a6718e4c0750b", - "0305484f50eb3f123b699dcf8d1a9536f395ac0d8edfa1247bb3cd2c7a5e33a2b7", - "032af47b259628df097ff450a15cd7a4105cd760c2a9a096aad624c91508655514", - "031285e689849ce14aec5a69c4a5ee8fc5a75ea533820e69c682388c2f178b6df9", - "0211e6c396e2717f85353ac52c86c7fe1e212a74d0f5c9aeb66580bbe40c4ed72d", - "031e29a997f89cb58e2cc6e1c84880ccf0f9100a3cb759e16c22e258c89bcac128", - "02088cec49d6ddb208a843c2a044ba9ef9f217ac040495afaf16b00d9ab3907d58", - "02014616719e7f2a8ca9a670b0faaf51d2695e6bbdfefe6ddee06a096b59b3f69c", - "0303fe72c0132f27af827e42a4c0405054f09f33430f6b5526920303219a329c3c", - "031f6d14b5d671b5ad9a8be0e860ed5a96d2b680b0cab6c4b3c678af8c9d58b09c", - "030e99a4c79588bbc035d5887081a6d013d5c1ca9ada39f8ffe80a35666bdab1fe", - "032b7fc92b287875677941bb7623af532801d1f6c53df064cf07893bb77b062d08", - "031f528e320dcb3434837a78e6d9ef16023b754021d425908fed02c0089fce973f", - "030f47a61da1379dbcb1e41beb91e68bc9b38bb45d3c00cdd82eee266196eb9e96", - "031ed72c6e6a04c73e364049f00182952610aea372d531fd226a8983d888edfdc0", - "021d7edfe764746fde9ed72ed17eaf8b41cb52f4b2691bdb6653aa006d146bdb7a", - "022b2d10046b684aa9fd733ef1fefa3e4a78dc0eaf3390e41147de3b8ca76da4d3", - "032bce84b6a423fe7e62d6bb6803ba913abd182148093af5ea40dfb5c19b651c23", - "032f12a0a14a81507d7d83fba0794f1ceef6d4917e242da7f3789ad8ce4bf85b32", - "02245ff7430ab48987623fa1fb2bed0b478728936538080fe78f77167f22e7fb8b", - "030e6f36dbd7d4b95205d758aa915b0c36cbfe98d95d88a79dde61e2b4dc6f0108", - "0203a0e2aa35f2a0e8079f3ea9fa0fbfacadc57c112506b7274f11c043b3d790c2", - "021f5c42f4daad60ebd0a819a25180eec4a936b638a204d059f2282699503d8826", - "031df31bca47bb96f36ad170d655bd96c2a09f93c4b8a816f07456376452262f3e", - "020f04c9ac6cc44dde7b606d55efd82407db274f4a7b1c6c3ba5437a142ed6527c", - "03172ac522c7cd5b85d741398c5d30cc63fe29e2d8a5c5d3f9ab0983366ed122f5", - "03101503b128b715ced762d675ca29fc802a66c47979b196fcde0b7b10e49c8a9c", - "03106238550d458ac6dacff2970e0060a5daca7277fa818bd7b0785e6104223768", - "0309f574b52f445bae5832b6c6e2430494f85128d6f0313df790c9a2f3e1207dc8", - "0213ad84957ac44050274aab69e31afb66910d81444fde024bf162771abc6a5c40", - "021f5ac5867f2201ae958cc36edcb871aa899faed550a5506a9581182c55573284", - "032b95c8673cf8240e63ef525d0ed8d8e84a21a599cf61cf7a571d164536efd3c0", - "021f7146410db72146098d81ff82896d5abea732e038b3818b27b43de034557d9f", - "0213dad2c5f01961f5718867ed863740bb7cf7128a96ccb9e2b86d96c2dccfdbce", - "032e51f5f23b51950b2bd0aabaf5c730471fa98f94490953c334ab6e0aa0f8c231", - "02090e3fe821f6ebd3613f434b85160e9f016e67b43a5ba53788ed5a9e665eaf8b", - "02234ee0110702f97bffa2d137ef8a75bb5ed31a8267db1d1d528845d2af471ebb", - "03244b58ac42c00d2760069fcb90ab56e4199939f692e3bd9be070af54b41adda3", - "0324d4cc51b792ed8fabb9a1973a510b5b46dba81d596354f759799f882610fd7c", - "032225588a81391cdcedcd59e02b562776a9764af641c5e7b5a8a7f05c7b0df732", - "0327813fafbcf84422594eb4904a7b13766e2fd038218b87a71e16cee1bbe62f69", - "031790d230a9f81aac49cf86256ab7aff659c0e5f41885611c766174dd4564d08d", - "020ca3a3d5c31ceb52c513de4efe0a2bf63a7f366396927dd5f4a4d96bcb8436c1", - "022e5f684db1202248018502613700db14f685f99869a1522edd9455c5b54b440a", - "0208ef436b610ebbec08af14c88ff49c869b0deee4b1617cffc6024c1f2a92eb7e", - "0302179645b841bf90d669abc670ddd4e96232a5836a76d2fe6c0f30b7c7640b73", - "0311d417decb0171ecb56d56715be23cc0ed767ab9abbcaf0e3c0f650b111c10d6", - "030c071b0646c46cefbd952d76d8530b8970c5919c68263912c1e948b82659380a", - "031478f4b6caf90b6dbafafa921065d0dbbd6502f738006dfd3e175a1fb4f9edb8", - "022b365c49921c03158d4a95bb281e2a06e0b4e6ac5840d3741bf4f2ad12639205", - "02211b4c24f2f62ac5fab553e83ea93e503379bdfe28623d3e41a64bff27393a8b", - "020b90fc6aa01085c550da46230871d8071c3ee089646ff115e36b2f15120c8110", - "031031e76ccbc0a372cd1359e26a2757eaef3bdef8b89e2f4ca020ef200b7d3530", - "0200a93230750cba12ef9a0c1d78834c3a5962b62c0db0d538b5fa86f57e3ca9e6", - "021f3479871ce79681080b6a3f1f8d6986670dc603fd509555b93c4aad86f56fd9", - "032256037326a74c8c1cddc1680acb1203d58157bc7131f77272f6930068b98478", - "03196e0aac3de518e6aa1dae69651ce2c7d02272f64b1cff0ade680228705bba04", - "02011eecdd292460b19b4946493381434fe1a620acf806fd62dbabed8bcd722565", - "032aaafcdfdbb0e0321bc3ebf47f15956f28552f0d867d26ff169c7500e65148fc", - "03070db9e9f275ad6fb7369063e87490352d996b7c2c98528c89da161bf53a2d7b", - "02168a97430783884bea3316a39b1c4459a115799c8ddfe61e411d5a3bb2b9c516", - "031bfb04a2ef239210a807513885c78e84869d67424ed29396dc055c5928fe52c3", - "031d6e55321d8f33d3d98ef4c5fbe490eef7cde33861a740a17f0a0a47374651cf", - "031e8c04cbf5f31a6932bd9c950da8855f0c0a84c29a1f484d855c73d4df63d6ca", - "03243e8721d3c2cf4caf5fcc4e2f601f4cb8d91138d5f1ee0615476478ec8a5ee6", - "02200a433eff20b201515301d612596bb96a1735e24b64ed1133688ea548f604bd", - "032313c2d2e995d033bb1dffe9bee6cd4d48c1192d52eea2f5e76d1179aeb347a6", - "03069bf2364a5b83b9df5f167eb2176736a083a0cdc0513f9e4b474cbc530a8a36", - "0325db8a9714228222304c65511fcc053c98a71570fc0c087a135873d6795a366a", - "031a6cbf7ec90b7e7afa5d731428f997f13811a9f9a7a8c47f09a16f10f1a95cd7", - "0323c3d1460fd062383d1220761d0f0e880ce99bfac810d919da0a217ce125973d", - "0225a749812857f917e7b0d11f5b3c9c9b07349c9b10f4afc00934bdf012adc68a", - "020b0c4884253c4243489e2a5c5dbc7350be9ff9fa0da7b1dbcedb4b647f75d677", - "031d521183b3c9c052823faace7beeeb2336202e47d29bfaa38460a43dae935ada", - "0216fd200e3ff1a10aa3bc007d2526a9138c6fc3c629d9fd6592efb98eaacbb935", - "0312ffd9f62ff0ff2042e60ed200b5d7247243faf1994bf42bb797535df1274de5", - "0201a7c5c0c3e0328cabfcb489b23b4a17f33248621ab7becaaafe8fe0bc041ce8", - "030cd40dd4d485158f32e745d3e0303667580e8d9b31a1a2f5bfaac32763df544f", - "020dad79c7121011e1776894b7e66ad9743e1fb8730d89a829daf4fb01b632ff92", - "0307f227326624fc19ac2f6bc5eda82d4cc2362b8637bf421066d0f61716fc2395", - "0218b8a4a496b57d20e04c52e1a45953fc475a34a00e7d08405c548357f4f81f58", - "02048abd1ab11bb2e4baef40e6ab77e6eceb16f91f094462502a0cf31414e7c446", - "020683d08658528af787902f2c515f9eacbbbbee96547bc045efed40d0d11c694d", - "0315842e247baa1b1024e68827886745b2ed3775ff36141aad0df823fa513c2803", - "020c2fea213e621ff789fb2cfbc7c9542a3e131f8f60a691add30fc3d53055a2ff", - "03297f2e50adc95725022b24d31da562fba91fac691872f19fc24029044071d7e6", - "030c96ce044c35741b624ee8af7cb58b93f337fc40742b8d1d12c2af76764babfc", - "0214ec9e6e031ff990746253cbbd254f7d6a849f664a0472c7fb5d0ff6d7ed413c", - "032c737e54d008a4c2960f0a0ed847e765fef5efe7ba63016b1c09efb6361f2e57", - "0301098414f55356707b86ed747024fcdb0f40b2111662db59712821cb2005c1d0", - "02095dc5a4caf7e3b6cce4e3b62659f56671f16e9944d141433483fc065748c902", - "020bdeb64cc1be06aa074ae72ba67d9f4babb2840d089aed040034bfc6a8680a6a", - "021f3b8064d533f2bbe2eeeaddaf2c20f766c25fe22b0fa99a1a987bf08dde8afc", - "022905fac234505bc00572376277e1582c6e3d35efe47f83f8f6317223af7c2c66", - "0321de650bdc6f1400ce312087c53ba6a6b55f504d92b6bd59bc31191e47a8b085", - "0215f6f64445d06fe4c7be1efe31e749c43a4bce3e75c8fc95bc1f1e322d438a26", - "0229c7c84e97cccdcaf46885908f49e8ef62669255391ee599ce6ff02dcdf7551f", - "0310a077d8d6aebd99c18aa00fde32c555fb4a8bd472753189c5b2b3f3859dae4d", - "0300f062e43452a78fd3f1ff2f7be04f51a63b5b6e2954dce1d9437774c73b905c", - "0316bc85d23df8f947db6f1f6fdb687f2b214cf142d80ee03afdfd865433d15fad", - "03260cd1fcbcacc4f497885bbd1e0b915ce67a021c4bd73abaee8157bd0ff11c9d", - "031f4893083635b18c382018fdedc404bb98e01d7038b0d54b363e8018b6453475", - "022ac7ec18400a72f4e005ba2c3c7d48248a1aae9378ab59d4dd049ff8b1e7b3a3", - "03275045ba256a13bfd30550b8e5ac5b81e755eb1ec21cd19b38467e20fde0907b", - "03139b38ef3c2b6f8cb5e816e8f686040bc8e0242ecf3080b6938c939a8375925d", - "031a5ff9bb680b2038b7357761bccee9f80d8a0e77acd06d59cc9aea67e3db2014", - "021e9278ac57013ed7b4ff4c339bc4d5b7381632cea5239e6ae771ee95e3c98a35", - "0218a1171ac29378bc4613a28447471324ab7a3e0e668d4f2ad111c63f0ec32403", - "0303e4df922cb82f13a2bec1e18b872a4bd105774de93a12521638116b04ffab95", - "0301c4e1f2221baba0e42890c47e3931e0732237c94d555e7651a07771eacdcd46", - "032617c71723fe563e1b2bde08596e59eea5afd4a2113823cb98cf9c1542293318", - "022d7fd0d9aa19e21b0b7d6701ed330cfc10d6984b4e7528e39b69bca87d721c40", - "0300dbbd903874cfb8709df7a0f3b8e187e417aa8034942e89e6a1c7e1dd5e861e", - "020197152edd9f67a0a6f1f0f294f144151aa18de672c6a85bf306301185495d07", - "02067b0be7b99b7520b23f7fcbf3afde1f19836d417bd562ec1db48895906aaebb", - "0207cbaebd2597cd82622eddd413bd6c4c07c86e73af445aecbd957fcdf6820c4f", - "022cbf78e36fec12cf8b4eda6738ea69b34e5ac95d930368f8f3517103485edb53", - "031114304b90003bce178ee03a2c7dfb4e91717b66439469670cf47c8d86e3b342", - "0205a697ea315f49d294461e0f32c84789397a7200bde51c64b2c5f837ce967bf6", - "03174d41efd7a74ea69b8eadf6fb259300188676d49eeb5e9dca0dc4bca6263e45", - "02183094a6ee5f0b0f8322280be09392a85e6c02a0627f4ffca508271e40abb0f2", - "032281d379833253500f8041313554309903129a13c32a08c1e4e9494cc8c47fbd", - "0307ac81062a2137df4ae670d6698f48a409d7656cdb7b022eb3ecb26d1eec9ff4", - "031fd114adf439445052486d8638774a364777cb186f70419915615adec6057762", - "021e0c32047f8b77eed9cc760fcde478358bb30063ddba9cfd821bb63c54cebae3", - "031edc03a081b31ab30a4d418ea994b0042a11025b3a174775ee17a1a64b3bbeac", - "032977bf5215685beacb6ff8710aa2a18f8930c7df893c0c7eb8d65734edbee972", - "023052b0ec724f98b38443d2b3ad032a00d93f928b292cb6eaf4ffc87950ee6f30", - "02144c103a07b87245aabca539d65495c4ac2ea9edeedd3c9130a2266ab85398c4", - "020f1df4356f67ef59a6b1861478d56c87affacf8f2ac440f47cbc6deb3e585671", - "0212771dcecbb61c13f1512d498653a083d52784702accb031497143ceccb89c85", - "0203ba620a909e1bc954adac882429869faddf9821ddc66764b13d21cb12ce4332", - "03100c9b07c1c193c6c185751f9adf0bb6ebb277c987c09e20ac6ce1e9fd4af225", - "022467adc86db6bfdb35f9410b1a51acf16c87f51dd381582f0ffcb6c1a9678cee", - "021faa69fc89f3d283b38aad5779a7b680c26d8dd1e5b1aa38698ba10b04a73ee3", - "020c66f6abf6e7a3b1a7d2c4f27f410afc2a7e7afb842cdddf7ef4f8444ce57286", - "0302fdd0268e29e072afa06495cbb32e0673fa8caba86d8788be8a28f6e11dc33a", - "020404f368324799eb98b100824bb1be8d2ae593f347598ae356d4234669a104c7", - "020c006a4692d2face9f7373f792eb39742f50d269f23058073c1fc38a5dc6ddf4", - "02139973a4f76dec5e91ce0fafe0e21c0de683997fc6cb714f9540e52dd9712ff6", - "020158705c97f38de5ac07b1ae279671d60af90e6e763f16139ad87fbfa4aca3f4", - "0229ba3dfaed68705f170b726431964c7979862c787b8e17c81e13a004ff289810", - "030d086d43034f03d8ca53e571eed131524f950802f905b6c5d182736844b8ed29", - "03003f0a1bed62b6d147eb7d04de41efa7fe68f06974108aef905a2ab61809bbe3", - "03127d1923945e984b2ab796f33443eb45dee844b18df6ccf25ff47d228ca07ce4", - "0329848ee325ba8428a59d4e9cb3e7285b6b44fd80920aa8682d778d61117bfcb8", - "0303f93babd606b4018534f69549fb2334be260010bc5e951af64fbb15547b750a", - "020419f2cbc31fbbecab30db4baccba58045c171e3aee9372c738487159cb47ae2", - "0228accf6db20843f22b03163ddd541f75dc60415449ecd5394e4b551c976773d6", - "032c3bf5d7099281b6f5e00a3eeade9aa05ae1078a38cdcf0a5dde2e2cf54176cb", - "03049e4326803fc97e94b0e0e34b03cc6a0c3352c7cb6043dd21b8f6483a819d20", - "0213737e05c2f563406b59ee0fa310003a3992d0237cb95caaaf5dfd680c7eb910", - "03065bc8057537345a41a8902b9446ba002fdb8e2b7e869e7c2a127e168d9dfd55", - "032438293dbe3edfdcff870d8081c5945303f7cff5da74062a90abcaa50e672465", - "030232e17f89acf11e5adb7b17a7776e2059437c248a76ea0b2c5b46d9e5c786a9", - "0314a75a3f782c411e3b4ea9f0ab3e5384dce240ee41d46e09b503935b3d0ea455", - "0329c337c46b58134e4b0e57a64734e347bb43e5761cf69c1a93398a6a1e012a5c", - "030a9099f1cff7dc13e568ad185a6dc641697f2886e2b5d1ccf959728c629abca0", - "021e0f701b264158609916fc467b990e76dd0342b259f4517986aa1ef0b6609ab7", - "0314ecb36ea87315fc1fe0a926b5b1e99fa3e20efedd3cbcb26b6c451113857c25", - "02185b97d5d103ab58796e21614d4ed6bc6dce1a47e512a93bcc6d626740383d5c", - "0211e3680f30f4bfc7b8c9799b8d28867577c8f97c5134df85e4782cbd38de8fa2", - "03060a82995ab8a09330f3d18f776afbc5487e2a1b4f4c542ccd89f03bc4360b2e", - "031434eb878560ce2348ed6782ffe037962ee8c07dac0be18c49f15f832db4e20e", - "020207a56617ff919dfe27f66f7f84c537f10e005580ece9c7e11f247d416570f5", - "030a4aa8d2b08bcbb1e12575b802fd03b4c3b364d28c0602914d77d5f969e86493", - "0312908a8d1bd06c32c299876c7ed258a9ec70f6d729cabad14e922b00d796cc97", - "031c94b9474a733256c3908934bb33b6878e857f8a62893678d6e61a8fe6f4a255", - "02042d3e34ffa800d77fbfca5c7e118ba93bf598c9dced99aac8e0e5369406b257", - "03155752ccecabe49cec2db82f308a4da1573308d99f13c955bd2a48dbfb32cc1a", - "0321474ea7308f854c59f02a7c1235ee721d4d7fc82024c3306daa484aff5f713f", - "020137dccadd324378f241e5f004c332ebb28a095023353f28a7dd2594da7a6272", - "0218043c561a36849f49fc29bd824d938d863da89a30fad42d2c059953411e5f4b", - "0210dfac2d99734fb7fd65cbbca4c7ef096db3c426d1d4589d77de78e29fef9431", - "03265c1d1643859f767134684f2ddb164b552ebad83cd83b715c422256a303c599", - "0224da96b08210fb1b39a34c4f305ed9aaed93b5261d3b50c4e8f726d3cbaedd3f", - "030eea31c7fb759148cdc4a311530312efabd9866419919aac965613ac77428648", - "030b738ba90789382065e68c3045e570764984ec96109bc0b59fca42c512683bfc", - "02002ebd52e0fee4efa0993089d37f707ae76dc9a99329fea50ed194b82b3095d7", - "02118b4acae7a7a3a5b3cfab716bc319e20f7def20bef8f317f824e170ba123bd7", - "0223de9ee66a41709f8ef641794ae42cbf779a7f9916d2c0135d72f78d719fc46f", - "020c3f976130ba67f17f9589ff098d7a6c3a55547183db072161ab9e067e88e2dc", - "02118d5bc4e95466f89c43aaf3691b70424cdf1b717853a25012a2c030e046f641", - "0212a9c27bf6cbedb4b2df7b052aaeacba87fecadaa10b2c3b1b9b6cdb6b1493c9", - "0300e6137266637802482eab445fe98377bda04980780168824429044493c56bec", - "02202a4eed742dca26a063c865fdc8d21a406b418272db51332dfaec02d4e226d0", - "03259316fa50ecb086f95fc0346fa8e2a4414ae0d6315d92bfd6b2fb5392c40a0a", - "032defb5515a3c5d41dcd83f636d1be8eaea2cfdc7fbda91c1c1763ce8298ebb8e", - "031ff62ffcadd6407c411158ed4fc9db75f2b023f143f83db5904be2f26be903f1", - "032ea40b1029573e44c1f2f52b69fcc22efa99ac4e98819bd74f6b533677eb9312", - "0312b5e87ac04273d1db2682a3cf6dd77bbcf658024daa7c25589a4fa8df4cd775", - "021333b8056babfdaa8c6f518f7f9c4bea64595b0645a66f4efd8813b341d8f49d", - "031b355e18045fdce5409ada6afb10ce91e0121a52f71b205350d8b040e8d723d6", - "0210936a923fdacad11e464f3530801db31e87ec2c0f1fee5035145fc7f423f781", - "0308a4c5eb94a8b43355a82b6998f6d8c0c2307eba5024914453a014f0bad8e500", - "032c00db40465cac169288fff071cb05a5c66ee5eac20d6263586079778a22c241", - "030fef0c58abc0b6df97ba8dab1cd62c550b66a177b28d263d24629537d150c701", - "022cd7c19eb3e4e68b2800f41d1668806cb79040acdbdcfdcf4771452f28e7a15d", - "0204f52d4f9689764f289aa95031424e0b4720fd81b0a380ce1b8e9073c43221e5", - "020e23ba1751d9660778fe5dfc93c5743b7b7425e81f181c57b1c2dced4ba9b92f", - "020755ad18f648f0853d5db3b97ee2a76f3cb2dd30993aeb2b3948356023299a5b", - "0201618b4aa454901a9ec259d3bd45c31f5a2fee0164469a663446a52a4a2841a2", - "031334281c706df08623616e0742e8e347e31b4741bb3d2385340fe8537150ce0d", - "0229cfb76b2752f322634c259f355baf9c8bd46562ba20585753770bea5aa8e343", - "0208586da1b0f0dc5fa4c0cc081698c761d6db8c4fcb6a6d47ce48c9b696606ce9", - "0318ece146df9445ab28598e60695445c5aed80e00b5f872361e2aaa5edc6c7bb9", - "02109c1152a97d31233b69c6be2398661c4915c2ec4127873356b6f7b18133225b", - "032c93b244e47150357c0e6c9402b41524ffd5432bba960d76352453956b9cc337", - "02202b42b536a9d23546d2cddd0f9035159ae9d5bb7ffe841f929a84d0a296dfa2", - "033056eb4e9d3348ea39b1d0fe58477c0d690d194eef9ca4f1439e82d188de8d20", - "031fa32adabf73820cab9768ceb664da5daa246a57a7069440976a68263e2a38c5", - "022c2aff8d98e10dff12bde666fed6953b4d342d543adad4d3cef829c3c4071af0", - "0218bc3a7b239fff972410d4a5e2e59dd4c4a047cca9618e1a752e2382ac7dafb2", - "020ab8abaafd854e09191784eb1bbcac2897530fea4d88b56e5c4f90a8417df2f0", - "020e4a51318862ce77aa5e3263f2a5189187aebc9aa5eb602e9344ff5db0cf730e", - "030f02ff4fed8a39aebf512568c8a2c0b40c88f413026f5b0e7f5285eaccfd49f3", - "03168f3f486cd5349f1e71522da32d5a6d90c5de2e2e4881ec95965f0e0ae97d5b", - "031a0a9a28ae217cfed40ecf62a6881d5396b3d9fb298e95bf8b3e6bd4aa0f9d63", - "02046de38b2edbf4525d5cee8c82ee1c36351bc618cc2a05aa2dfc2356a98c1aa6", - "0221172cb247842e7b5a9414287f568d25473480d14ee6049ceb251ee6b630510a", - "02250f01dd84c3e4418ce782a7d21c7550976529179a8002b7b72d7ce5606999bf", - "030f1ca479725136c39d94961828cec4a67236a8b38c041b6abe1727af93f302e3", - "032f84416337577e490b99f9b3843486afd80fc5cc8e0d30d45e58e71b15e03ec7", - "030e9e1b47f4829ad4ec9f1ebc9da2f3ca652ef14c35a94395c2d24354ab9b6be8", - "02036b98956586d17dd4fb555d9bae9cc261bdbe1e639809b3202411888a7e029f", - "032cee18f1072c500c44bfe362ba2527efaf732531161eaf75d79a63673b0827fd", - "0206189728786cffd81a4cf41aab35a122f24ef3459f77d14c6bd0e0e170fed6e7", - "020752b61dee1d3fb6872acb384999aaac37dfb51c3d66a205737ab7cfd59933bb", - "0328dd590298a5e2ae34a7e9db9fa0847b59d3423ecb689e3e6847b76b3400c3ec", - "020e69be19f0a3ab3b9fd0f1b578bb53503bce793d5db7b6257daea47abf477a2f", - "020d1807a2c1ea13dfdac6196d3dea3e235e5796b6d71a109e89a7d542464ad1cc", - "021b39227bb48c91053291b99953195ae852cd769580ad3eb9eccd6888334cda43", - "030fc20226f7cad0172670bb59a4890837cbbbc4895e188e7bf9fe034ef7948b4d", - "0228fd259c1119668498942feb8afa188382836be43a8b2e50b4ce82b5133d7b5a", - "030ecaf8f06c8fa3b10d08c6707045f3774eec2c006a828ef08057ec6af6aafc60", - "032efa40d5696f531a6fbae469201f5bc12d70f5b3305000ad9812555e23608eb8", - "020ca08f107e32dbc5a8a660263dcaaf7727b34ffa9e0fdc4c2efed217926b1144", - "032389b648348d863fe6804cfb45fd7491812ba02e83b81298d3b3b1ade6554df9", - "0301e1fde82233c09051d9323cbd792cbff25c7fe8563fa6a8fc2430cd5daf7d86", - "03079c3aa7a715438ad79e8981e1a7c7589028e77c1be39da0e08648d9deec74fb", - "031d316f749bf978a396cc9386749df921a7529446ec807ff40243b21a84a05d1a", - "020eb80fd0e9df5667bbce236aa4ea091e6ad31d5a85bf7b05d1c3f75f7fa13f04", - "0223300a646ca56539df12478250d48933a3e50551409e731adb4caf1464e75f92", - "0218b4bb91de2b3aaa12e8ea97a9edc930397dc5e83d7d4a9c9e694d5ed33050ee", - "021c358d956bb83baf5234dd510ef3c2d3bd9fcff0dab832e539ced09b690490b8", - "0200839701bc4c29153fbf340e4cc1c4eeb735c9dc7749743e8abbd5e3609a5008", - "0318feed3077a58675a0908ec9cb435ff9fb9ee61424853ad7128e47dfc6aad08d", - "021ebebeaaa262f914cba27805fe0d25787a3fa853c64dffa2e5baf9d3e4f88759", - "032a54cef047345a53dbb28229fedf8fe5fc8bfb172a33a935b07d9105ab9125fc", - "03106d4058fc68621b848bddecdc116d6240217dbfe70221b1a0f5eadbc5766cae", - "02023ce2264ff3bf963f74e2e9dc1235d825a16bfceb73b4ad41feb2a7fd8a4f16", - "030361493cfb1250e24ce5f4b591713a45d3eeef45a0a60c3add71a26c20801dd7", - "0223a34790fb91eb58c42afa3946c8b02447d45912a6ebd5f0b79af7c002d3d6cd", - "032a17ce8a7bdae734b345551bdb945f0e002f40ca5fad0c46c95cffb5a90c4948", - "02108dedade912a113b7b5f860765b60a7798ef07b481d2007ba6a5427be17b8fd", - "032ab164bced4755d4d90d5e2da432161fb2d1a8a715c3272f7d8c4620ba9932be", - "03123915695b3baac0d2a297b287e474a1e492b65bcb4fad8314a758de0df840e9", - "02099ebce4a1c768f45c894f1d89aeec9fbb01bfddc78b89d98cc917f1d84f3ca4", - "021536fc31816d42030701b3aa2630fee2b70fbcf02eb99fcd92708256c2edd80f", - "022e69617a9e5539b4f55350689b3023042d08c3bad25fd6b48cda5792b2eb979b", - "02169ff4ba070001d0acdb18f3a78abc0b2b640ab1046c9dabdf71ab5625222678", - "03236d92229054e59f134e05d88355a40180b7d4064f917c9f5b27c53eea9bfd0f", - "0220d5df1e7e72536650bf9c885e5c951efc463a6d4ea77afe50eabf5dc674eccf", - "03080e70e4c145be4c886aa4d7617a621bafa455e7086e262c07a88cadab0a915f", - "02133a65f56099eb5df64cb0a976bc78cc55edfd0873c3710ee3d01531cd72c176", - "032a854ee37e55c2f29f495da07a68df4f5d618da2ab7351c3931b18055cbcbdfc", - "0312b6d38f95ec5fc84bb8c251115f7fde1636b765ad002346a25bf22d3086f640", - "03034dca18b0cb34b647ae06a5ebe890b5b0320c1b7ae2feed11a357a0ecd0d152", - "032e1110437c690b561dfe8ff1f880476184e57d2fcb4f0593f5f1440fb0f3b91d", - "022e616d24550b78e1de91dd6649942f6a7d437d760b820f8c1d252570bde67bb7", - "030ad210df09f18b59bd18eac2d32e9abc751a0c938ab1f7fd8c081bb804a0b8db", - "030907bb7389c407859227f90ef76a206b74d4e0aa03af7787647d8dcf07fedf57", - "0324ed5d8e464dbddb3502a72cbf94a08328f845bc453ac3ebaa4d3045285fa935", - "020b9d168edb3991f6dd9b0f733c40b640a56ec278dcd8c6e361d3eabc16bec08d", - "0322e4f4cde3f5e4d90995864593c3964cace8fcd09cfa7c9f52808cca5814f6de", - "0209dc7781ad13aa706349ac458aa2f2a1df29a6e099037413fdf8d9a2065a4f33", - "0227b0d96bd4d4a7a8b05b55c25aa2dda84f613320e58c5d2faac37c7551fa6803", - "03126ce0a2c52611643e5c9c16b8baf7f081ffae0fd534de32d4920a1a4eba4483", - "020b1b932f7eed34dd9c4c8df989d27109785b7e6da9ea5a6240d733bb2d470440", - "032f208de285f38d4fb6f08b515797b5bade787d689acbf427589032a18b168bb2", - "0322de4348b1d0247bcada66b90f2dc4ee0ce0bb654a2aa24c08e9acd6f27770ef", - "0215248a0b0c4acadf8fc9eeaa773a54dafa7a37f7db003b1d2a5411594d16a328", - "0220bcd196397a04c2616daac26a43ac5867aa7dd25b5137386db51a3c530d81b8", - "032bdfc91a32f0eddb0aea61ea50a350a4bacf857c075b54f78774b82775760bc3", - "032cf5dfde00664c1fef97252c63f9e92a410d6ec4aa11bb481eb306c8cd7a9d1e", - "031e4ca2bbb684edbabee3f033aadcd7d590fc1667e1d1fbb1167993ae9269b0fb", - "031000d1a4751a27e049cc83800938bcfd4b11ecd6cfcd1bc072883a09232033f9", - "030ff8f49166921a122527aed10db52856a7879c1a3b4558cedb0801d5a6e2f4b9", - "031c484cabc3038324fb19983d0acf25377996f4da6796fc36e18071f9a155314a", - "032340e358daca36603971024f4f851fef1eaf9c681f63379e0e5209bc3af2de78", - "032656a2cca9768d9c2d0f52c637e323e716ef4941c6e014c13b88d26f0fd644c7", - "020918e6060541440965b081a9f45c3b823abbbb61c3dd3d630148c593cf16a2df", - "021259a19974805511f88f29f8ff795f6243476764c752fec986765312d5dc7933", - "0226a9ae2e4485b94ad38a5b2317566e90282204e7a89ff1b50c3c12e9b0b34159", - "03093d8f93d904df76bc8c2e8aa4d43a2d34f06b3935867a979f26a6b48a970208", - "03055a6b66fe043687ab33035318fd834cc15f4de7efc4ee2b393b8a38190565a2", - "0323f7a9fafb864f391afee36d2bfcaeda080079db89e9e60f3d8bdf7010ccf4b1", - "022f97ca0cdefdc1e1031322ba68a55f380c65aa8c39d95b63c53a3d64af603bbd", - "020e17c5fa4565dca3c4244cb417ce18350cf2200a0fcc18c3a28bfb13374b4731", - "02076f50a2758fa4f86ef630fa18ba152eebcc89a3f6e0b19abcdcb00046e905da", - "020763caf84e4836433e28f6cdf88bc2a062711ef864c9d1472cc87b0101fa8a16", - "0312f81843ae03bdea3908908000a7a769e0f35cbe6137def881fe11b50d3cec6c", - "0220a44aa0fb0ef59e039a879a1bbace7e42fd49873d8a20c39a3b6cf2585803c6", - "021bdac1d4c22218ef5e2b9dd3fd73a7ff71d7df479d91cdab55532fdbfe4029a0", - "020ac6dedb72a25b358fe70367d5e1f6057cf7c419fcdb751c84cbeb5595ee08a8", - "021b38185626080015565fd4ec8334d92f4c8db6a49883655c3cc494d5c8d7a3f4", - "030bad417f38e15c6420addf7a09405f16ed9c6c6cb1039749c9a2c103d8842d71", - "0325b1e6c98fc7e9f46122045429b47723fabdf3a328379e86d540b1c0d8ee303a", - "032230156ae1bf1914841b3ea8acf20a0808e32ebf024b7c5e9da784553492de9c", - "0225e0e23b5f1550af9c4c3fc06697c142804fc27a29efc10461c8e96704ce77b5", - "0322ad6ae26e383415064a35c9ad1a6f95fb52aff3bd0b13efba62d17dc486e2ad", - "03193aed84dad04e124e55ad815c638373a69ba21979e32fde6a4e3bffac04e99b", - "030210e61680895dd3e20797c1cd69bca3720f7619940bc477a97397a6a42568b3", - "032e68a5b712aff6da0a1d9b97a12e60f9245d6d196dd829e89c95613c36142890", - "022c436291b3df056ecf87a902a7d1d5c99105d4c541919cdfd199928381c76018", - "0206370295d8553cebfb1a46ef26547ba9b08a19c80e490164d980348370b85516", - "0315eeeb968093fa0ba28790411f6cc2201d25c986be24dc3a77fb27efcfeaeb67", - "021b0d0e1cb7df6e9317b3441ac852e8ef47fda68b1e1fefcdca55d67671a615d5", - "021824c24eed324ad29c939b51f00b2d3fe1d83cc7a02d83e12c3e0fb1209f9d02", - "021c1ef838d33f92dac0052d014acf7d063ac856cd2d084dcb11aac80a8db22f15", - "0217a3202520153d6c64da8182c0a0d0025ad0a0d9360dac1fd52a2d4317df37b1", - "030577b583d2da59616ce5dface886b59c8c3b501a1ca5fe500982bd1df1478b2a", - "031a776f98581c0bac6f4057a26fd772aa43221b5d602e0f26e61cbdc71e315bb5", - "022ce96bda007f582ec8c85e6150d82329e574c9ea71e956dc9d5358e2dd0af76c", - "0206895d30056ff90475e4c43f5789e5fd7c78402351c20d1647a35c7e78295265", - "022018c5892af7efe96f8674be914289d5030f7f257cddd8d5be1bacee58550b32", - "03010a262af00950bb254fc127ca378a80c5f5007ac9243f0c9b1f648538fb6ff9", - "031f081057683e2248c9e3b4a944ee893c8b5f8df094e9d5615dd981af967b4465", - "020b88a4a952ff2e1280d097d94687d668624da19ada35109215c3f1194225d0ac", - "0319b4ff431880d371a3cbb5f952c1559db75e74f09556ad073b7aa2a15322b34a", - "0207d036ee52607723adc71819b2a23af49b6056d1e0cf3a82cbc8949c51c53447", - "022912e2865151920976f91369493964bdc8f95d0ceee4367225544ca32b956d33", - "030dd5c692d2d9bce7a94b6c50aa7f9627e46f51b778a9f7b607ac67b251e83ea8", - "022687f4d15be1261597d30f239259966ec622190e5a43bfcd8d423e4a64598a2d", - "021eb925083e1a9b538b422894e5a4b5d563837277382e398bf157852ef0c439a2", - "0212af99ef9e408169de977dc3373813896c82ed6918e3a02b29e81fd0765579a6", - "031860531cbf6819d0732e8d5d09d7e197f916e162de6673432b461cc31c6c7f1f", - "031798bb6a724440c9cb925e41a5ca4006704df29dcc22308c54cfc3c63cb11103", - "03091fcc4282640ca4123832ee85e6396834f7b34aca419f4f9821a52d28c8156e", - "0308a015fa7c43e342e0bc19c10b07c9d7160a1a0c39921c2509a4917f11838c32", - "020073a22f78e778ea6ade8eb8386b5d1423ab5e273532995c3a6a91df07e1d6a7", - "030643e480a571925b6f1b92de9a45649d1c456b4d9251414a91f2378b484d086b", - "03096112ca5252e308a08a387a1723d1ac7c6baa24764546d4dd9d0f9caa1fb714", - "020502ab4b4dee92c027d2bdc76b8efa61f7465979164857d8f5f9a21e73d7c3c6", - "020f7d84d41d32158d35c83f04297586efbc493c2595103ff31fdaedcd521db36f", - "031bd279d7cac47a1ce2225543020053d9ff820fc57dd1ffb4df7b26915b540ba4", - "0200f18bc3f1e061e85923aaee672abd6113d2851b5879e5441a5db9690c0079e5", - "03298112a2d903fb202968849dba5bbdd5a431979b559994a85c786e00cc25d336", - "021a6b4492592c22ac1d671034025d6618618cb5ab44a8469f57ce8cc0dc5bfec3", - "032944817cc9a81187c3e5c112f856438ff8747ebf40810a5f6f05e4fd0daa05aa", - "032186ca23c0a01dcbfdf0a7dfb172881a06603ba9ba8ca0dd7d4c2fb4f506180f", - "02124911d80c42acaf20ada53f3b4aba940f0ad9643b40b1ab41eac2a33577d519", - "0321d655bca2053a2d5ab3ffda637b429606f74b043e3889901c55c1294c7c4395", - "021b135afd2ecf35122ac05f948d35c8b945dbf5d9485db75942e8c229dcddf587", - "03109873602a830030b01b2d3e42d218a8074535e492f8d977bdd94003c9e1074d", - "030d241ab93f53a5175bac7611cdd5917757792a3478baeffdc60ac3291da0f14a", - "0219028055489ab924d6b0a880c06039a9546d8d9945064eb6cb7361bf1b0becc0", - "03105b0367074e918d55bf73057b1611ab08f038cc86c549b645fe41049d5b4680", - "0308c9beb6be2f022484a15b8810843a912f01b7bf161f1de2963c47faa2d61708", - "020500c81f97fd616bc8866f7db1cd19c30c17c9c1eaba04e344aa66dc6f6e6fda", - "032f9880c43b1aec92785f7543dc69c49dfb5085f3516618bced6df8891d8bfedb", - "030cebfdc6715f03cc86ba04708c254e8cf1126d2434bc7c6e2d8f20b1fc267c4b", - "03239fe648f04bbe2cb7d04b4abe0826791eb65a68b7264575af2a221b48b5d247", - "0229d240aabddf1f3bc0d08d834d9d0812b74cd710dd7fb77887ed0448b9ab0440", - "021e09d882fbb6a69ad125721f553c70180f3291b5c26f4e9d9224e54cee59d7cf", - "0311790b94af4465e598bed56e5a461bc8bbc49a62cbc024c34c2b0004cf596c32", - "03151c0ffd674e0978802add159e40812d5af395296d9457bdac59eb8f773f1a25", - "0204fc04e4d7379267de62a6726542fa44eef0eb653cf80f5898c0f748309193f2", - "0218443622686b6f030b4699591b3253b597efc127f69251e1d981361a93b8c53a", - "0200a3f632e4798ee194d41d61810c65b5423bb80f95cf12ec2146252d71229945", - "020a2102b996108c37003eb282cbc4d9c0555997935f494c74132bc3d9b5da95bd", - "0229653096be8aa2e5b3346df7e7bdfaff74fa35fef4cf5a4cc646bc4940f3f11c", - "030b78292c55cd8cd32a42eb78083785f611dc8960ba8385273031dd07e09720a8", - "0218c61fd0187122c30357b75dff6f8473c5ce060645961660c2349365ff79375e", - "03082ee0d8ed755cabb3246b8128626308607643d5924523d2e530772ecf3b29df", - "020efbcf9937e28e194ad52e9d897fb43535dcb76d6eef31031c87ab9234b69203", - "02021544f5da907c6a75243868a7bb8b44172483fdbfa300728392637464ec0742", - "02136fa0c13d7af208423f64e75c11f59b0969748de33627db75730eb15d3373e9", - "021e06730bf41904714b23a9adfb1ee721bbb4cd34720e9263046e25c27b83aaff", - "03129344853d96920168e063c5fef0eec866b8f96ced9512f2886a55dd8ffd23f1", - "022eeddd5664dbfe15aedd61e865b84e34f6a51819382d63baf834c19fb2f69e4a", - "02178be9b5fdb53ccabecfd06e68fd9f206f76cca3a98e71b4cceb83752f5ec7d7", - "0319fd4bb53cc7c8c3f0eee345dabea5ea24240e14bed99ee03b94095948687663", - "032d65e31c75ff9538c27f62e281c32fe885a29d7c19ff4b0933a25c43cdc7d0c6", - "021041db74552d6377301cfd3f354433c438675914e9c385e9e42f82ff20a405f6", - "0201939f9f1d6af7a59a8858522990ff4f00433ac932470b0fb1bee8933347da2b", - "020a751273080e00233c43eb0f70bba8d1aa077df9a1b7278968679a67237437e8", - "0225491559023004162696699ee0d57666b937136ece1564750e41a2dbe548b353", - "03299e18a17d0e29818825e9f0c790d65f028ab35d449776ac65411b71ea4136f4", - "0230374ccdc41afd32819e1f92c3fea369f83b7e89faf0c58adac9e1dfd39bea1c", - "0216ae4d1bdd81afe2fb3ecce821e69292855846b325c8fe0f218572ef48464eeb", - "020c8c619f467356bdb4e44823f19e5247ce33c3d7cca247f58fb61d474e253247", - "02247189e2a321b8910a01afcacf621501c99999f6cd683f630639dd06ef4dd2d7", - "02059b0fbd01d49480bc768a1782277b65f8882be27855a7921437dd3365b4d5be", - "031f7cfa706dcec8e117a762e20002512c7392db6911eae05d224de57e56c9cb96", - "031a49ec90c23e2e8d6f27dca2ca87dd9482e3c1370513bad3d5f9eeef37248759", - "031b2adf148bf8fe41b67cab9d470e83f9f9d551b6ae04d7ab718ffa71180dae1e", - "0306f04cb5b140596ab405f3619ad7df572cb517fe039641e29d68233eaadc4427", - "02224fbbea7de277f41334053baf9b6de6c9cf47731d0b713f23e0dd517425310a", - "0228154e1b4b1e3258b3542b98e70f30394208c0fc2b04701b7f4123f5f1d3057d", - "0205c9640614a34bdb5daa43f143236754fe511b070227e929eb1f11cbb3e3787f", - "021ba9f386c6c85319803909ece6d22431cf3155c0f29d04137586592bc88d20af", - "031b00a01bfad355b6d35f64719e2065333a1f3c0fad096c715a5c58eedb4afd7e", - "031e7df7efe35af61ca4543da6022d700afa073c76a0046fbf7967cc29690d81a3", - "021017c0fb0be36b1cd579f21565cea1dbe04930ee53568f3611913622668b56fe", - "02006a287bf8443582bee1ba70a4b75e51f71512c64320b689a898e2cfbda8815b", - "0309890ffd423455ab835ddc6505d8446e61341ca6c87a391432c640b6992b188b", - "032c48d1ce13fcbf9d35a4bb4847ac98b62ee31d6dc390dd6cf5f32b74509dfb1e", - "02137fdbbf64802c34ec858b6d8c1d5da9c15220d918384cbeffcfe58431256c33", - "0324665c7476be666c7ba8dfb5173a528ee0da33bebb1447c34b44fcabcace2cab", - "020dcb2d75e252639c7e0d0c1cc7655f142c220876f5afec71bae8c0f49e05e5f7", - "032310059cebff70c7ecd634a24d42b24d1af7b3c9ae9e81839db6d13dd29bfa56", - "03163254ea672c1e56b2600a703fbfbb37301d2df2ca5afa0d74aaf8a861be13db", - "02135b63990eeb29672b901078596ebbd0449d5a56390c8210d260719483387fd3", - "0318ebf4bfeb04feacc09e7d737a67af09854ba3958985b7ab0a77b7045c6e33f0", - "0221d2f4c4cffc622af34c25c94f7796d3d6fedb963ad0dd60ce4ad08c00f0dfda", - "0202c30630449d156e48c9a46c868411a2a8dbbf0f3a7d084d3822626648ea4027", - "0206d269fa7c6b4e3ecd41eb0fd785d0695aa49d65f855926eec8b04098d6bfcbf", - "030cbfa78658b89d6cf491275b4e40fd940d056322d9219fae0398669019ec20b5", - "022e69db9292164bcbec65c2e564b7632483bd741d9e2e4c10788251a4336f65ce", - "022f1d0845f98de43552692c3aa95e27d2b77c4bd7f6ce02c4231f8ad941e21d9f", - "0225e93a6dc1b56b3fcab6c6521bb18cb312d8730439c20ab5a855daa09f2601fd", - "0203ee461908fb0f2ac3eedeaf05e6292c4828e1ede9774ec182e419cbb1ccd0f6", - "021526c6ef7d9117ad6d917eab1c0e07a04b2e6763da2dd390b34d8ee6b6a848d0", - "03185af0e21372c092584265fc3ab1651ad9e19ea2fedcd8ac218149594d5f713b", - "021013ce8545f0eec3a19f8aa9d53b2d673f29f97bb642ce1ea9dcb7b7fc8303be", - "020a5652b585adc9f843435d1cf2dae727aa086c1d5a74fd0a445045855bfae42d", - "021a015e03da8c5b1ef7e368350ca63c2fcdc7eca71fd03941e9c255109e307ade", - "02056f32b356e7f68ef956c8fabea8076560ded8720583bd941b747ef68f87d703", - "020ce2758d68201b37d555d098091b3e8da269c10e5c5920b38246092389af6e13", - "0222d1aab598f60cecdd651180096ae965e3bd7dd36185fadc028ccda2a28d4064", - "0302394b0c8b84c972bfd5a5a9348ecc8d2fc76cda3bf63cdff09cf1cdf8345815", - "03015e4257f127583dbd73ced5a19cc6d691da80e567a4a06c3ca258c6fa0081c2", - "022a762055b37618d45a1508f50afbf425ae413284a31b57c54d92fa8e58594007", - "031fc89023b65ae0fdabe0d191e0b8642cf00ebb4e687816e198d77ade01a00332", - "031b1510dca956c655a5403831dde2d316b1129719148d5a1283b360f4c821f4a1", - "021be67d5b3fd20de33fb1fab9a8adb85b3aa3a91a3edcec7937ea32a12887ca1d", - "022db8c054b1e35ad591e809f05b0416483eee0067755032a8f219f2a1548f0006", - "0309ee90fb71cd3026fd515bc19aa00c6080e14c9867f44ea055807f349fe261f4", - "031ae86080defce07c0b8bd30dce1f1d8e7817a82385f2a0766df3f32754f81e0b", - "030243a693b16b9a9fc4b51330f8a4c2d79e8098ff1433f8b6bc09fef3746b9338", - "022c7c5103ef59d8f6cf905352d43adccb18d8506a656a53aee3f3170981cc56c6", - "02232559015948dc5cbb88195e338a29bf5934bd078d6532a5fe991b9cd3b81dc0", - "0303ed88872acb0c969b9319ee9ec84cf64dcd74be3fb166510902802384d3d321", - "021c3d797cec019e0633108c16ec9e74c204fc8ff19a8e9fc4d02372b3383db387", - "0323703436b3dac142f04d5f0239982413070ff7a14373f8bf6b8e45e2303941e1", - "030aaf3ff2c57e3953a7df9cad7c4bba209a9f056d8f05a193ff74e69b5397661f", - "02101494b2f4dcbf60027e6b5946e370ed5e6d949cb8b859ee93faa9acbd4d34be", - "0203304959e47c8531afdbca86a6a800ea36865b3e0e88259cda953f662c41deb5", - "02159b47181d5c037162df3ae7b118bf971815b202484c7301dd938b0a5cd4c113", - "032a30f5dbfa279cf5ab4526e972d310af0ca904f165a142175047a234c32a0d17", - "0316b0d0ae743928c6a61d1f2f5ec600b14819e4e2b5818cb8404434f41129fa42", - "030723474a8b80a66c23cb79e034d27f6a859d0e3117ce12e42937d4e2b3b6293d", - "0225024cf4f89ca7d395d50812e3215a228f91256657637f71aebcae62bedb40fb", - "02032727bbfb3e50b39ae8e5c5b42dcafcb3f40de603217c16396da2eb2a4b2682", - "030d2d2f335e29eb07e92e2584c791d78f805111ad083ea06fe8dc98a346dba463", - "0203d55a4d1cc4bad92b474eb70a302c0b77c0c4e8a6c897b53e91cdf5561e0e97", - "02258c095e1b171b642080d32b4ce6260bc6e27be3d2be82d34e121014d9dcd796", - "032c52ad327f247155107e2b6f233eb7c6738c8b11f48d7e758cf6fa466be574d4", - "03010686b4678667318614974f31b4d10896371035e2a3fc14fd2f2e262961c01d", - "021c4b72395cb680e2f214eb617d98c265bc3440d3a97b63e9bc7d92f102f0d724", - "0205c8d0518abe69384ef52de1f849a3a5a2acb0387cf4c4948a3b9feb6689a537", - "0307794cc4935adacae9ffb3efaba6c86402f1951bb08516beadf43f2cda6d5630", - "020a3910b1a5683fdf65f2e0bc2a076d18b55b29548d6090199d3957b2895e3c53", - "022a586ad5e1350648d8b88692094d661efefdc2645af5c50ad58523def8e67dab", - "03102a6f3cd4e3bc58eaadf8b2855d7adf63a4ea1f92e90f7035650a91a169aae2", - "021d0633c0e4d92d117f6c9b1c166e56da78955a255df689e326268289ca185724", - "020f8ae9eba6c4e6279150ed5897d43216c32e39b489a2945548a4ffb4676e7611", - "021fcbb639a51f60dbef5145e5327a1c810ebe9e58244f3b3ddf1274945d749f08", - "031e169f0b085ac9d8d3a454735d3717d755f885aeabc056f98324814f1ef04738", - "031b54bc2b87911afa179360b0063ade83698bd2426f7184ec47d0d2158f877dc5", - "0310b18c9236eebc99a0904a79bc8297cd85dc6709f256e7d07abec605a6088a36", - "0229bb9ef01f76bceb23e9888a065a44bd97d05238228a3448901ca8925239a276", - "022e0a1d096b6474371ea2bf6b96ac3749f0d81d4c2f3e78dfe179286963e4986a", - "021c92f32ffa976be332a12a1c3f77f2045660e8a7b0f4493510759b1395ec2a05", - "021650f5a27e07cf0316974a90a2a2c2920d971a31e599efe80037189b59dcde15", - "03093c8f053ed1240dec4d2c6d66386e33338831f1c6ce51c09879aefe7a223f42", - "030374e90bc41267c4aee7b791260b76cd4548b5339481199798a8140027cb8031", - "0316af0b189d4fefa9da02b5fb2fb170d47e7b2141e4d467e3cc3cf54c313cfcc9", - "02196c77bb99de6e4368d50ec3c30edd47526fbd3d06fd8c78eeba30d93e8e45b8", - "03069b2e30e486761f28b5de4213e36a668c7bf9dc3f4727e363ceb2d4ec582d67", - "0210878f75d6ae1480582ea4c9be6f4c1efcdcf3c77eef1cf07cf47ceafdb96161", - "0218ccb8fe3f51c27f7279937e239e4674223522dcff81f247f467351679e029c4", - "03055b961fe7663820a53db07e819a34b4dba4d1fc3078233e536ea04a2d4097ab", - "032623f41d49c8c5b9aeb70689045bb8b16f69212d8ae2d069ee071231303959a1", - "0225cb7232367fab12afc0ee04776dde783f89b99f6b8e45582427ddaf26aadd3c", - "021c3ab9b83e8d39f3a8fe8fd5e1077c445ce95fceff2d124600119019d4a1f3b3", - "0224b88217ba2a2ea529e2c0b1fbe272c2c5468230f8089ff3f5349731317ecdd7", - "032769227e8e83d344e591323ca4a16f499389aa6c115902a2cea3fbb45946f850", - "0226a86804c56c4f6689f967f010331b17306cb2fd83270b86a4c4e5c627771c16", - "032725178c9249d35cf9227ea9f575154d897687f3eae0fec5abb42813e459d68f", - "03271e93f4ea7a93a457898d156f008b867cffb1517320515fdccbdc0f7e5a6593", - "0309baa80a1eccdaf10accd53d1e07903c44ba8ca59ca29706a6ffdf91a1216b18", - "022a85366dd7b389774b197d5ee0f1facaa9ea35d8eb23029282117d8b90cdc9d3", - "020cb749ba836de7fc9288e7148615184612390799fc59d95ac61d57b9637c3f7e", - "03218b8c4c54a3f7e081ae48442a1038f7cb62d1b39bcd4af6e98e6b8096e8db2d", - "031ea89d417738e2762d5de56e856282092b44fb7e8510650c705b0524a1b53f4c", - "03013750776dc7b53d4b3e03c0be8d645422e9e6b83e29c6647dde3b950bf779bf", - "03121d6a7e7bbfdf97513feb65f48a77ead836e62a468e214bb0febe6262ddadc9", - "030774d18a8924067198efc2bf2a318f4f001409f38ac3f35966d12a0a35d19d7c", - "03123657d2e5629817e29d314da0f69de4db584f3d6a6fc648649a8c8adfd99cb8", - "032b3dfe80feb8189993d23f8b5d572313f4200af0928b05fed6f223c15e8fda38", - "0313695ec2fbc3a2ae4e4131b6fe89d91f3fa10843f643efbfbbd9553f28424f12", - "0218b46be837dc9c16af96b13a5b492c6d4a84df815f1842bebfd091f4f757c5bb", - "031d3df9fcfd4af5963f1ad66b983df28d05461b0671f9e67045946de238a730d2", - "0315c5abe6ab4092c67859a3036bd26710e508b9e69010c07f346d8482df839533", - "0319ee36ab5d8292fb250c47d77021d2db4af71b57227b272543db95c4bd1ef658", - "02023766962ec652b55b3fa02958a08c17efa212f6c0ac5bda1ffbdcaad4b23beb", - "0226fc564772c60508cbf40dd01d518ec891b7472568e62f800a48253a5dc85aa3", - "021a6545765e8d298d2f1930289471da488463b91a76b29e4b53e10540e35f100f", - "0317611fd433d2a4bf4e3489866a4dc5d2626a01b62e6728142131e5b0a7978d08", - "02127a076511c5b957fca99d84a6f086016269a16039873f1746ab460bc6dacd8c", - "03118f6f587a2a3a5a562f1d8d61a401ddbdeb2dc37d4f5467e476433f3a6d33c6", - "020b925e7fb972d8516facf0f28059aacec84238baa4b516be24b8aae38a1dee90", - "03238b132f169ac75c266663b498a556bf8e07e07979e3a57d0060ab9f8efbb8db", - "0328b6b7b285e726f10ef97a6e13be04099dc23549ee0406be60643c91205e2bd1", - "031ce2e4f31dc9e6d618703e37054964893bc997622807756b7fcf2b2788a59396", - "030ea1cf80d257cfe906da4bd1a5f29ef43846f63667b3398225f523060299e442", - "0328c53d6719dc85d712f36a90097d93cd79027986eebce4c7eb263cc013948823", - "0316b1739653b7f61c538c2b62308372515a04fb15ae946cbbd9561aba54daf04a", - "0208f0dcac9b40acbd8a6d31f5bab6f4b8b52e5ccbe315b05fcb9fc28f1b1fc2f9", - "02039cc4a68702085da0053aed8d2075147f866a275d13422f281ae77bac95ac83", - "0307d08e7b557eb0414cbfb73fc8a950e73d541db5476c9507f6d127145ecee532", - "032e1b84fff619ee19d23db401fabc17d819c331ef4b9c641d2795dcf956529b96", - "0207973f112cce2b72bab529a50165d50b88b23c2bebd349000613bbed1001cddc", - "020567eddef4afaa930de25fe98c65d6ebe9c37d374fed27b5726bb8e29bc6fa8b", - "0211a0acb4bffeaba347a0ab09a925cc2a7f3760a175b198eb46644110a8405192", - "032c00a1cbebc48fdb87ca019bff2cfe5d19267d7341b8252309921671fb3946bd", - "031c5b91db3228333d5959a2e8e935953a5023a5b78cfdd25bb0b2a5a42fdf42ae", - "031b693add561fbdee0baf84483a66a92d99d1157c075a9acdbd880868c9df787c", - "031252971a2d4ce29633ae4e80d55d478085e404154ecbf0a4d90e0c9d9eb7b49a", - "0225d6e3cb18051842ee3e366c1db84fab853d0fbea13a6da4fec93853dd6ae46a", - "0217940e4683edb5829431a218637d2b2a6b3201b2a9201e36b91e4976a8edf416", - "021d5ecd138160efd4201d8d35af9b389b75a654839b88473bb8af75a7db985c37", - "031144a2250217fff00355ede9f94a2224a367262fbdc7cd5c9e112ca3ee789a89", - "032fe6f06699aba0a414139b2d413ba58056fba52b2793a495b28414c0de1b1b4e", - "03104ff5f09aa8961d4740a4e483641089704e86632e072f4334538f9408c678ed", - "0313fb969b7ac7b604057acc861b17fd03958619eabad82484160c7f29a9cb51eb", - "03303316a856a10a3ac74731b375cbb282af7ba24b555b42a454aa12e46ac313bc", - "030e9afab852a8cad4ff942ca58662f1f49447ee4aead2938835106683e862c27e", - "021865f268f4edb41543382d5d670da3224a90d4b9c5b620cf6203a3773f69ca42", - "022e4c7caa1baa54edac6dc277749b9669e9305046b97c38e464e52f9fad1dd49b", - "032d31540bf05a50d855a8a199839e14100cf5fe6c6561db54aab7bff5ff194c84", - "031e944ea01653168b02d33cd87c3443a10264dfe1cbfc00e3cd23a240401970fc", - "032d6235a017bbf8cdccb3dd41c210e319783954a4ad601cf0538992db4fd8eb24", - "032c54976c7fd1ddcc14c2a9a2fcdf3ea0bf1f6f75dce821a5366920544f408dbf", - "031af3f5c46395ae0155d559e6f77d980c73cfd01d73756ca58c1920f19ba70a0a", - "022416b23fa22bd530f6fa5dbf1df7be2acd4f8200b4c4b39fb9458620cb318658", - "030615bf04c87f84ce023e4bdf28d4b097a1f91a3c094aa8eca851374fa8bb7d8b", - "021157e08a28e2357994f70f58fb4e119374dbd39a9d0dbc7bfbb3aa705e29f24c", - "030bca0908bc9dfa82b958e7e59bbd138ede2accd4a517e0e09c62953b2e0f2dee", - "022939dfbd48015883a82847f67fbbbe5f5616457fa68a622fe98aaba58540f639", - "0302a0edc2a771c1e84c78504e94b691d426d9eb5c1116974981945a1c59062161", - "030a453bb59a69ebaf7fb1bd15d8c3156c0ad07c415c4b85c8d564af164c486091", - "021a1f88feaf6319072a5c2f11374af4c55b2860733d7d6933080351f71402a4ff", - "02190090bb280be30af790dd2af8088e14f221c53d1ba38a4fe775c8f237c226fa", - "032897a41c0d15059948ea9fa455fd0fe2f512afe28b4a0794bb3373e3f0912f91", - "0212891eb5cc43edfd5bc50150bfe2137732330e5974a67c22b86058967b48e12a", - "0322cb3e039671289c5ec27ac409e267299438efa1c84f1ea9e0745741436fc65b", - "021e58f71349fdf6d33d76342b7803f6779acad4b4f10d4465d50089a81dbc65fc", - "021f9ea8664819c444b1704e4fa2277aa994378820315b329d8b140df741efe0f3", - "0214c08c290aa2d4d4c5abfa457d1bdff2eea8baaa295ab90c48ec0be0e1d963aa", - "021f5394a8f9c09e954cd0bc2c9151af8ba8e6cacf7bbe64002bb618a89c7979e9", - "022d97d29c7abc12643bad194fc09b7579fd57997420cbe824f41793b4e8621035", - "022ac2089812f3d72c53b55debfbf88e3de692c6f51499c08f03e0563763c5b8a6", - "031c805012c715161d551f2a8d0e3d2ec1f0aa8a52f65dbe4fc101c8e337b9cba3", - "0312175d7432d08ab7354c84e218b37b4bca53e800d82194e8f94cd2220722d15e", - "03235fc30ce58250632449529047cc42f2554b4acac7101ad77bfa7dc67d97d90d", - "031d56f5528b2664c3b67f67d2e2d5057152785bed231aaddf9327e9a84ed579af", - "020061a2bdc3894372a10e461a1b9e746d709a97376529258706356f8b1c1e46da", - "0325b6b8b1f33726e13724a6046940defbb8bcb9046e5aaf2f566e5aaedeeaac38", - "030f60fc144e2f060468f20a616493c76513e456ad385da04c3ed5075d62568b12", - "021f6eb4fdc24319ec11913eaae353e9b9c7c480338d14b53bb222735b7cccf3d1", - "031bb3156eac2e98b8493c1fa6226111221dd88269ff5f3fe34534add262e7c234", - "02035c25d95a15461aa07ed679018acded2f62cbe8d9e648e1436041768a2b0676", - "032303e9ddc6dd75e87430a0a6ffa97979d08ce76f84e7da370a9cd5e623f9114b", - "030fcc95543629696adae01b5a8cb1f36699aa9caeaa92b85f0f6fa072ed12aaa5", - "02211516d1119fcfeeb9304c41a9aebed583e3b06b8a41ba39c14194cf1ebdc9a6", - "031b36e07fac17121750491e0f32ad020f1b4c9bd6dfa920a2f68a778a51fc575f", - "0215dee35e3782c3f7b5820d95400d3ff1299d32dfe5e376349b482cc2c263df74", - "0220a5e39a037524ca6bc9a29dc43ce603e1c7c9d8c05bd45b55d0fe25659384f2", - "0220e91afdc7cf8f03bb8a76e39dfda44b5429e775fc16e7781921ba98b78d9f17", - "0225269e1f2e5a22bd4f242795179c381eca93ad0e48cf1f87269130f5e68ae494", - "0313d8225385d3b8b119c3c09d8db0a5e04a86f11251ad6db7dbf8e7766f774e8d", - "031e04b763e72d7a5828416d3b416a0f663f6c001eee92f02fd546ee4768b6337a", - "0317e812e191e46323001ec3d685538a37c8a3709f6adb75a466ddd87685b75988", - "031ea68ab4b3669f1842f23c0d81c29f8fa83dd6cdeb2e532368c57df7392c94ae", - "03014e636179a0f1b1cdbcab044feb7a78310d9e181e4c1abb4a748a139f5159e0", - "031297746c11808bf218a2a387aff6ef39e832033a278147242c68e4ba91217101", - "021b898f7a40f1e5eb866538cdc2ce16825be264f416cce0c7e13ec1f203de2c93", - "0330558e05557423008bb21336e36394253e7d582354b813275cbd08cbf563c486", - "02186f5c269067296bbffd0f4955e5acc5538b5b0cbed1e41d630614cf52178956", - "02040bbaeae02bae9407a500b042978a7076c78653a764702aafe2f8a27c007edb", - "020c6029efbba2e61aee5cecf06d8ccd1c35323a6f117ef7c5ee05b99195303c5b", - "02298aae0542ba3aa0d1a696e84ea6e74386273c1bbb974b262699a824b7cb858c", - "022dca8d83097447e02c667c11b01cf42d2351c6cf2444500dcf16c8f57a3aeb8b", - "02025af133705f590bb00f002719e808fc2a6540d4301680c77be04791584f6cf5", - "021fd7b22e24d45f7101a5397974f22292d45a09033c70deac6a4a202242ba86a0", - "0309743561ae8dcabe0388d194e4cc9a5e5170f86dd19878b23327ae303546c452", - "032a08b2f4e32a5378315d336069fe447d704a39bea226283e41466435b02412ad", - "0216cf71d0820022d6d2c91b923b2459c243b42c058330e9601a14ba03eec0fe03", - "021d0b07d75acb0d93807a8d1904399839360e54da90138d6c4949154c402da947", - "022bdbc0e4b43ea2544733c7f26c4ac8a2c1696fa1c3436065f00407bb808a39b9", - "0216f19ac15d37082cb62d4f199f8c81283de7ff73bcd67094511b57812093f323", - "02244a1f263b3528b2f2e27d9ca8878b2c241e82b6f3aec74dbd0f7fa305bbc5c5", - "02072e8584430c1dc8b7f8d4a041a28c1529557640932e7b3b65b98bdb515f08f1", - "032dc1f36c25b57499eeb4543aaf1ada6b6d88fffedd5d67b5b687ccabb6b1a6a2", - "0305ec95132fc82b86a2f36891655e19244e37f38b7b191a00ecc962873f9d89d8", - "032dc04e9e5146ac55031e31bedf85c5512335b491515a5df0d8e03c3f340ddc81", - "030e2d965007a19b17c1ca31b2a7d0994b5ee33d537bd3478a7edbe00d4c244c9c", - "021a7b23b06cf5377a90e504e42391abc2787a3fd18c31b1e46ae70d86231af637", - "03175f1c9d4f8dceec9ee249b800b8e30a594e36b556a28a033cf871adc5dfc95e", - "0309b733c6d6b0ac459020a9f7e1ac9dbe7361ca5990bb113bb8300cddc7561a02", - "0323e8ff8fbae9d0a95cd94f9eab7c55777c9e9f7509465e963302222a570b87d8", - "0311ad73e0feed5e034514d7d0dea4602e4a76509baffa300683e0fb32506d07ad", - "02208f9c18a75e4cf6a0f9cba3a37669297c90f14773e9f00f6fd09bd2eb2f7616", - "0213a1d86708c18260de9a8af7a69000914de201476167ea649036631043d9a0a0", - "03278b8ea9887f1483b007cffa92abd29de64e36e9b3db09c826019b071cef81a0", - "021f41ad3b1a836805a4f79ad7623021c257405adebce3a1204d302efdb252b49a", - "0304481409ccdacdccf6d581469033eee2ca92a8fc7e92718b67bbc98b78d76ef9", - "0203e249d15895d40e93a94ea633919e612827c05cd6c33a4b8e268c588bbf6f82", - "0328101cdab4fba54531901114e04b4fd1fddff510726747b0c4acd169fe087904", - "031321c841c8236b6a659704d9f768f873eb916f2e54cf9fde9d31249de8dc3e6d", - "032b6bfee3cde4103166b2c53040d32335d3c7172a819c2f58b905c3c346a3fca0", - "03067076ac98f8aca505658155d4b4e9e1c73d114d526b13e8b00af06232350ce7", - "031580199f53559876d93bb2880d1ffb85ac620143447444cf5dc9ef7f3644426a", - "021a55e60c68cef2d7384513bce84fe5393341a8249b785b2204f2aa612b211e9a", - "0300e13918ddff3decb2f5fd61cbffe2f79c34cf4396bb1f5ec8722182b1ef5574", - "0301fe1da243bbc98a2597be01e8156c8a9d151591c9265040d662d25c289cbf47", - "032db9bb2e0891632d3e4ba047e29257773793d8e721f995fd3ca65631b725801f", - "020b318604ef43da14473c0c4ca0bdf10e1061a78b5031c54699bdc8f7be2ed6f6", - "02183c6cc6b1498eff9149b2558b513a1d7fba19069e726e57fae18cf50515f0bd", - "030fe764d6a49e8e83a432d189ce454b529bb6c4b055b86955b6b656dfb708eccd", - "02081e6d1b83bea2c00228e4b721e148ac72826b69ed348b52dd0ee3eca5eb751a", - "021d1db70527503c5c41a61113d1e5c0fbadb643633cb3b7ca11d1a73070c23c74", - "0203c99a5c1d688eeb99f10f89a2e28e80318f0a030f0410dd4fc591dc30ea58c3", - "0224e7b9dd9ca51004c3245da8a55faea576446235b2c65198e582fb8306708367", - "0307f2390015993b82fe5d7ad78e12475e715446eaa7f88616cd5f2af1263d16df", - "020f65d531960eff3aa43d9d33b425cb9607cb338485df04445fe0e677dd7c96ea", - "020a86b44d13118da806a169d9f40189c693516361826bf1ab08dc64129c802701", - "020f092769a59ff7e263804bba9623e49273d59b89d80dc022c3df10ab59ad94b0", - "0321e35e224ad12747158f250cca9fbd2403e6b081f639dfa17a665293d599dbfe", - "032c6baf6f23674fd89a605db70d70394a5d3f41f218651d232462bbc953def7be", - "03302bb0162f8329668c4a4b8e1b9ac91fca207ef3d57aefd7f0763218dd35da3e", - "0217b1652bffe1d2ffd0a2ceb169c7d02fd861ae7e85d8dde1c7f04649d00c1957", - "0201e17c4f355f6dbf2373d6bdd8eccc98f5fa8479398efada559df2ca7f55dc9b", - "0222785977d8752d0ac49174a27010c0d46c2a3eb082e71f4fd13668d1572fc4be", - "032130e280c46a8b525a22aa8f57b893518010edc0fbb3d463469dc54e78694243", - "020946f8df0017e40f2c715a16498e004c0189fad4e9cff9ed28b22cee9a6da664", - "0322e436fb422600e11910ecb73127651c091a737b8f3139a68022de9d79148fe3", - "030eb1fc047f11b631d32486ef5df0d20de6067caeba3e645b412f87b63caeff12", - "022344a35bb7a2ab0cd428595a0a0dcde11e77cd4c22eab719299e0c6a8d71e6fd", - "031af3b96b943ed8b6c45fef205f1b7b4ded6090825d5cf78399d591fdae3eb1cc", - "0328579a666fb32e09bead2f6ada5b83a4adb573431a498f6d19ccf7dc6a4cc09f", - "030747fcdf592adb7add50bcb2882cb78deed8a6a70d008a6ff3727e73eb0145a7", - "0306d7c6a1b79b24358eddb03307dd3c95c11e4d485acc4146b050c014d6f50df3", - "02156bfa2bb710787224cf0261531b8523d56d8370a2b95ef592d5cb5e59c31c08", - "0322c2b18b8675b3e59d004f8eb1b250ded24ce42e74c842841c75a5179c227c19", - "03041ffb7b86b424bf6941e984a28fb206644001c475a3ae3a15db8619bb6271ca", - "022eeef74dd0ad23cad43d8b17bbaf8e917468340ea2e9494c546916517a84b7c9", - "02265ad2073f1869295ef1700bbb6475650ece75da101a5471e579e3fccb88ef80", - "0218cdae08d3aa4340796f6715414d4b1d5bcdccfaf525ae3eb31df3270ee346cb", - "03115818b654ddd25453951f547247d5d4170e706de06716590aba5686b0ea2140", - "032c626e61cda3c8cd6ea0f0be26ccae7748f1d28c9b8b3e5c98d4c360f8f04731", - "022200bdcfc2723edc571dd6d41d5d1b206f4eead1c11fb71cbc9be6d2d0592dd3", - "022d3a4c6e5c51e501f7ad2b320577edda6f0372ee007fc2fdfd48f1f545ac81a1", - "022bdef9b52c7c093fac511c6668b6ee9cc7fc54bdc28e2ec8af829d0d60f5e5ee", - "020b115b5f4c3c2f7ae25e8c1ad9bd763b3bd478da66e5ec5bae1821ba8867d4b1", - "031358ce8b794872e479bd2cb2cacf9cc17852cc608b20478fef465e5fd353aa86", - "0205182088204fd9b540fc68cac0e61a5a3331500ae87c6d9ef06ce3e06a1fbd91", - "021dfd387f13e24253a92c8d8c545e0941af4b30555b923bf9b4bbf5f211a3cc36", - "020c0e188710eb31a82a9aac517e6f6207cb9897550cdbd2ec305c064ed8c487d9", - "0214ddb309d55306e070c145a8e1cebf292f5b14ddd1a7592eca8246da13231178", - "022a4afdaeff4d60619ea3ef4ba5adbd5333d4f62b2aa52c3f06529b98a48e23d5", - "021c6e177772f79693281c778cebc50994017f62f08a2aa1a5ff42741f174b24f6", - "03084417d66ae5e8d375aa0a4221e25420bf2f533a4459bb1c5b784e9e93db741f", - "02118a3a8c93f385f4a93e0e8fa93f403b1bf083ac54119b290ab5251a8950f5e7", - "03209dc6ecda295d3e4ff7796627de5f330c246a72a78f73817e9ffd3b4209ee5a", - "0309ee8eaf06c654bc4960abd5cefd20695a3baa1252df4d2d2e0c56e1ae7333ae", - "020f231ceb633e9ad870181a366ea4f17393b702150838a918d5d39a3e78285690", - "021912a2e37fbada6e4a211fce53cbbaaae66ccde305c99887ec33271ca2622269", - "0225701b05de6de822a38d10c847d88fefa793198516ac0c98b88377fc27fd87da", - "0312ced9ea2ffbf71cbd7324bcce18aecfdd5869f75b3ebadbc48f97f9a5d4eb58", - "020e2ac3c023d08dc243dad55389b05e00a8b93637c2a1b11cff39bb70d989aabc", - "020cdbb393ca5f8ba6b43ad0b26b01d3e3ea0e6308438b1f93c6c2aee5a75a952b", - "021911b44921e669d10b2b72f60163e645aa707f7077ab3c04b3cd02ce8bd8e678", - "021b85048493ee369c6f068c04c53d08c7902ad1376dd4b24b2d6ee1a1f3800fc2", - "0200a0906ee492705486e9eac6b673812e0d7d14c41f6371cab49f7df7fc87a4cf", - "0302d9f667558027f284d15e28adf1ae1467972888ed0dcc5d4edc585623fd8ac2", - "030b795a08a6256af2b2656e0ed6e66c3cbe15718f424c17d8df796aedf4d6b069", - "03032a41e2ecd627ce7c569d2e05f77b95201fefe6935e99e971417e688fe0e43a", - "0320e8c4eec70bac14fe507ce85e8724869ef29d9d126a111def5c0bac6b214c43", - "03135f86dfd558b84162f2d5da76bd061159d45d48cf897b8846d093f23ed1bed0", - "020058a00c66704f24368f67acf3906e34146d9f4505a1c0932df69e3c6cdfa1b2", - "0206031deb5574c1ab90509cfa60802e22f9bee4179414435fe26d2089239cf451", - "02187b71e9406e66a43c0fe1ceafb1639282107cfd5067e04a7142d44b0a710c42", - "020de99f8a5d7268437909eb7a1af6c9be033929c9714d8629a933a3357d429359", - "021285b602f7f58fec8e24e089d7a249f95826e6c8e80ae78b6a787636592a5edb", - "0217cc1cea3a486b1bcacf458c38ca6013d9a573f0110033f0d6a2fbee607560c0", - "0318318aa84062a6d080646119d166d78d7fa6d8a5a55d976c634b68850fdb4db3", - "032e7b600739287fa9ec800a0f96d2730bdbb171603a212d126fefdf0c8fed6d0b", - "02227c90cd55aee10d808011489711909f3b7ecf25de2d633ae07cd85a05f90cd6", - "03045873776fcd232ca94ae52b9f60f95b3304eb3c5a5fbb550a2dae900c0b5e16", - "021d0fd8ea52a1987560e6f4b013449eba9f2f1cb8e28d08f8d3a6bc3b6ccf47ae", - "0324c7e29702b3a09c234d25a270ea9a73ebfe0c2bf83d622f9e76309e930a59b9", - "020df01d0da6a5bbd1773e07d037b105260c57b3be5a49a88997ad00cf0c1a7443", - "02037790bc188f5f6063f9daa30fc6e4612da9050af6d187cad1de61118e737600", - "03064dd3939d0ff834ad878e83599e0186c9c6761cde3300fae37ccb5462db47b4", - "031cf64f5533a6ad0007e8a4d8926301d0ad998634760f4b62b8e08dd5d692bfd9", - "020c31c47010a53aefa00f04098fbe32494809409d9ed07baa7f6bcd3877b9806b", - "032d056c45d83dce53e237b6b9bcbdcedf55e76406f155082854fac043e6321a36", - "032c8a45a0a3997bfee3fd66f52e0b5319a97dcd71e934c8b74ea00bf19d0804fe", - "030693749f35a3fb0dbd83dcede78fbba4f1e79a5316b70b9ea59b360cdde98092", - "0212e7664590890f96a47167e3ba2154b194e9bcc9cd956f5be21e785c7f283960", - "0216f43b22f1aa226e590d43e688014bfba33605b72f2b3494db71b2ff950553bf", - "021129d692b10e5a0ad4de50c0c1a90e4dc2313eef88c4b7ee3e90aa1bd0a6b08f", - "031e96ee848786609a0052c3ad834c3513753a062b4041ceccbe55c383cfc43b64", - "0310ccf1d5d71cd16407e6ff821035ac28e225e0ac1e9a6de16c69bd96eb6b0f85", - "02225c9ce37331b8d107d5b5c341dd1429a13e78a9526e79aea794142007a4948a", - "031fd6ef32202210aee926087db121f119daea4b54f07d6ee801b237ece57b00e1", - "021ac4e4ce031c6fe2c07caecab22a22cefe219ef66438fbf1c4f749c92b201f3f", - "0324af81944ab4fbd0af963b9cc7ccb5425065878244e5d7f3b7d31a74d86a6ec3", - "021a7c1a3430414d629aa9fee39e7efe86b8e3f838cb15e74c78d677d5309f4d54", - "0317195af98680ba2d430405ded6ad1254de997e0670693c53af63d12a979c21f1", - "032b501f170ad74289927a52ed9bb25f2576a95e0796637cca1ad43fcefe231011", - "020572bf751390fb0826aa25ec246d6c10d3ed12cbe54beae2111eae90acd4fe93", - "0315db6c0521b278143cf71e0802f0c90b1fe60bbc6b25a1910b65eeeb29e15f32", - "032406d664d23bc13d769e2c4ccbfdea3b332a3e20603c8469b162946964630a44", - "030ffb048c0bff01f54df3f60ef1ecacf8befac8ccfe577816fc92bd1bd05c078d", - "02226d02ab516ac5b2af61bfca89bb9edb9744def7338ac875d5483f3e5396ce32", - "03091edcfeb947adbba66671d547e71dc5c015f738ad049dc6c0795c2028b0d178", - "0310578c00d4709e079126d25d78077c33341e56b7bc77420fdfb4895f9eaf8a6c", - "03296059900b799d4ab04f31bf8fee628fe25ca375e3adb3ffc096b91e356d037b", - "030ffddfe6520a6a86ada73d99c1cc12dda6e742afeff4664c7baca3e3156e1d21", - "0320464ccf0a12eca9ef18d51163c5a9ce54a253d97e69eb6082cba1a18241c055", - "0323678eecae8c25e0dfc7646ac883c29723b7811a811a74d89b89783dc9ae4c28", - "0302788b5950d8134ba834fbe7c8022cdb721b2ea9c9f919212f8e7a132bdad864", - "031646c8f3a025e89acfdc1fb37117a407b8d26a86fd9dd26dc40c82d342203d06", - "0215d058bef3e473609f5501498f0dd6713051f8b5ecb038a072f94a3e276bfd68", - "0326014f789eadbfbf5fec52f89979c2ff90eb45935ee85394d1ce93f2cb45706a", - "0312057a34aa67e55ab39a3318f172dd45036aaadf3f2e75b99f1a9fbad0a17e7c", - "022f5e519f0835873690a4469daf3fdcd1d0ad0f58d5521881e8f2ad715786bf03", - "02017cda8fb46294b64b0c9f24fdef906b6c80b59a9e1d4190c198876e55d50b68", - "0319eaccae4b108aaebf0c2c8f01a090bb52eb79b5056549b58dda1f6567c42c07", - "031262730a30364ce2cd9858c141a8578e3c8467dacdf06ce0155d5843bcb2c4f4", - "031db7ff801414f2f1fb5b8c4cd3654d8186ebd150abbca9e7fbfbdd68085456e2", - "0305d51765fedccd7a4e50e763998579b1b132640890843d9f8c904c914d001313", - "032b064e8d4a228bdc4f6375e699d2aaee50ba1a5062956cb6acaf196c45cf113e", - "030f7f9ffaa103bc8eed9624c637e45690eba3a27d91ecdd681ffbcd9152c50e9c", - "0330383b20736426f98357746a93f947bcf2b1275a8fcfec674f40925bb6312626", - "021200a3e320a891da77d9bbfd930d64bbbadc933549036316d155032272083361", - "03194cfa49be8b3aa7fa6673a769c9e7576ee610b8b88ff20c44ecc65b6467cc63", - "021b6dd870560c7b537ffd22e4607fd6cdeef023057b3b387357634e6661e65d19", - "0225b1655042123d4ed731299f73a3985139f77cc535c824ec68f3d648d2784ae4", - "0200f26c6e05240b04e12dce20b6c3c9f653e9ec4881667ab426053512d16e3197", - "032be4b1d2292dfb0c44676a4a6d5f1c043f6b1832a5fb93896e40ca78ec093cb8", - "030a321fd8a1705dea1f92ae18a31637149e0cf8e30fbb08a8b8e485f9486e1174", - "0209b4f80e7b5ca686cad65d48f32a1b81d2c1eb1598a6aa557fb8291eb684221f", - "021848b488ba77baa1e4e0dcec4b9d5b96dffe4a1ad5c754d55d660126f6dcb01f", - "030f4efdf92f506c04e442088b858cdc1b93b7a4fa4856cb154d2530e5f819d6cf", - "021427bfffdd8118d1a3dad59165f8849158c59dadb25147ba4518f6801303cb9b", - "0315c7d189153079c749b9fec285a9b72704be8174e3b7672396c87f59d0578c66", - "032955e2dafa410911be4c1764a5ed7d47725e8de14ff128991a9fad63bde6e770", - "020dcfd3ea41f60433402b1f48317ff3cfec2ede960dccb4c78d301e32f79ad385", - "022365cda668513b50ad2885d2217968975599d241eb0fcf42884bbbb8aeaec184", - "033003009f68e6598066a58cc18ce2d1213bb9a2179247621ae5e2074e17bee222", - "032a38f350c1085c5a9dd85ad54a53c8052f125c60f7f38f1c6ffefd396746cc93", - "0313350aa744f67bbb07690c38f0fda6192695d2f8c50286abca9908643ffdf9b4", - "03273de93214116516ba2c28f6f72130248f5b41da417bb36cf4bc570474a27fbd", - "020b44741bff0f425ee5600025887ac6b60742b36f53b28a57a485d18da4983d3e", - "021f50877c7038a503f0aadcb397de8ee1ef10cc70d44435f9b237bf3d5fb9d50e", - "0229091208806a2e0da9cb4173e02a42831b678aa2f2afdf8d016f67ee49be9f81", - "021b8f0598385abc48c76ce29e10871f0867bfd67702519192c2bcfafc7987e70a", - "02154dec5e2456ca8baf2ea2c100fdf42324dc05b720851cbe3d8162103e42745e", - "022470fa5332bcabdd16ad588b0e9bdcb066733380d1add865df9abd0b653b741c", - "022528f6ad7a42285ef7f6c1cf9002b1c2ec17655424e45b1a273e97bcfbcd4912", - "022b27f80634af4167bf9bbf88fab9f0de9a4bc4d8f31c184d51d50e8c893930db", - "022451434e75d4b4abc9bf0ff6b68c122ee78fe84a1adb208bc658ecb616f2507b", - "032fbba7640c518328ed067e7181c095ea5a64d4d78fd48be2cc9ecd149b3c3ff4", - "031cb679ab035f8624ff59aa95f63932cf5ca8b4ad428d3be38270694df25a55cc", - "0226e38a8df0157dd48981472cc4a44c35c550468dd1c596431ee3b6a26bf4342a", - "020875be79751bd9e408b6a2ad95e10e6f6380c7501c9d7df6206f3a366a15fa7b", - "0307dff1c2df08a40fa4f777e83b0c29e61d1c2fb7663c23e1b0e454f82ac46e7c", - "0210fd848dbd3484f07b3bc2cd5ca9ef01a7cc8d94fe662d873c4581348d907e51", - "0318fc009b772670629818d6d4424cf96c4e809924f7def8917a7652cd6de46457", - "020cc7822fb0524a15cb91afcf284eef415501da46ae1c53d0f694ad4f53e5300d", - "022598363e3efff0ca7f84e6e91c63b308fe003d0d93fee6b01264dcc3f60ede1c", - "02285ebf157cd64613b65107c0ad3e67744fb5b233cfa8884169513e54ed254646", - "0203b505a0c1d9dc506e266e6568512c58a817455bb4ad2697202f87c15d3e1f99", - "0316755f5ff8fe99e8e0b7ce44363f2a02317dc7d2702779bcc2414473c63c3da3", - "030303759ac5291d53260d847a87bc76c086da01d35dac3d00a4caf5061181479a", - "0207cc6515a40a60c24a42d537874548afcbf29c27e26e6e2a4dd8e39b4de1b14a", - "032b8ebbeb0112ce6a52c2ab29e02d62a6b19f3dfc736b0b3bf594c7774ec1da3c", - "022ca45cd12519240b307070e0a663ffb06a042b4daa7d12833f5bd88ce5dd9655", - "02056b9a120b5425aa30dbc32d027a624e0f338f700b63d5459fb0a850b2d7e2d0", - "032815a8a2a0ca8e6b7b190c628e38297f9a5cff30677539c3a05c8d7e2445dc65", - "021c6f7a0f65781ed45bba7fe799f3a74369249b411ab537a1d3f042e62be963ac", - "022805c85502985242dc24e9dcebb9e8a7688cb5fdb529d156738be1b681cde523", - "020365b5831d387a4793ba83e4834cac490347b01b1bc4c84edae9fd4d5f418598", - "0309207371f429aad89524892625ba471a5231e5b08275f02d77a1d77fa31a95c4", - "021bd98852a44e92256f0a4622552ed77300da131bd2b7126da1df256e6fbd1db2", - "0210d871e9c672e8c294e076c77e9e2d907bba247f15acccac4fc8dad1bd6add24", - "022463f87b1d6fafbbd896b5dcb972ab9ffd55a03056536aa74e71a9122d380558", - "03234fefa221b3822971cbbdef73b850301d9dc3cd2108d7189e5c10e74fbfd1a9", - "02024ad3c078d7e7264d84c6d43a4d94a120e8483ac93b3ac2867aa8299205a8e3", - "020539437b9696e11974c7ed638a019a1e3db0d23d5f7e1247770f0bf5629e45bd", - "0328af950788c80bdb677f8cea05d3a04f9f30111df6be445ddcf5188ab6d0cd2a", - "0214ddb44725f5f6e105e1fd41eac5daf9fc5258ab93e69672aa560c3968400baf", - "021e033a101e7551cca3c3ed55628ce1f726bf59a6fb71bbd217dfb81d1cd45e5e", - "0306131dfe700c20f2e2cb1698e4b2192bd52ac35673c9a6c347705d1e7a2341a9", - "021fbf9f5a7823963fea3cc8b7e3edcf91048a8aed307aaade4fdd9192a87a010a", - "031408e68287c46a169a2a688c6f102c5c99ab0caf97815c08e6d35b2e5e468689", - "032a392d0d58ac1a97ed9b51ef9737851631251ce145363719a8d4f12395f40b98", - "0201b0ecca01cdf66757c2db20ad574501faa1238462e3cf7a25d85e44ce4675a5", - "0223a198cd5d08e983fdc80183e1d1b7aaf47e3c533aa91e080f09ddf07e186fc8", - "03195cc02349b7f658fdd7d689c262a7f414d2871daf14397377889ba2b52425ad", - "032ccf6e7fe705a9fe319f9deb2703c0a0e073badb9bc648e846900a0feac498d7", - "031601c36e8216b4751015ea577ca275f137479c659ff4214a1e8e7ca4f4851d31", - "022e334da7cf6665417f413424ff97b0fe4bcf3aa449778a5383d65e549165ce8e", - "0309530eeaf4d048273c103f1c3e5fca3611d69d3e3ad259e596efa5e1fff5c51b", - "02174c99e7466b23b6452449e8199e5adf4f2948c9bafe7152b7491f11a7a860be", - "030ee81055d0ef8dd582448b62c69d0c46d091616708538b2b9918dea57c3ce42b", - "03057a065ba94cfa1f96a2d87b2a1b9c0ed5ceb2cc72f523b6c3b076d27c7693cc", - "03172174891fc6e84b1137031135138065efba96d7f1eaf9225daa6f81532df273", - "032a2c558a0391d43ed56cd416a54cb3defb040704a3b83ebc300ce9b62a73a53e", - "030d27e61cb1152a3b76e47e30a7f23c4a93450cb831eed168ea5d4b1d0117d098", - "030f75bc0c934399d4f3d844fa1898b64149aade4a15933fa837263343afa0fea6", - "0309d39f85840faa9a47c899ff89bef228f6f45db7df4800e5e562492fe12ad6d0", - "0322e43bad8809ae4e7f8719fe07bd2e403474177af457ba270aed5bdc9758424e", - "0221bb97667a10485d4f6d4ad34edca17da2d1b6c8dcab3146190c4fdf4bd31347", - "03026b9dea89e89f05b94f7ef8c1cdb4e1ca92e71b39d07db74d85fa7ab45e8b41", - "031baacdd55a70f9a881693d86744ddf7991a41b178854426b8a03815990bacbb7", - "021739b1af8ee939ab885491d3f326416cc598729f9fdd9ee30e1cfaadea410945", - "020d0f6940e741ef7c92c4cd47109cf6e92a69cbce4e23cd1fb9efec42330473ec", - "021a54cece5102706d93edfe90aaaa1d582ce520b69fa9df367c0cdac2e19968a9", - "0300281ed02f31dd0d98875a2e2872789a1b4b86faf3a5a59fdad693b340bdf6df", - "021f15c2ded16c95b076b2680cb29bdd7d2ffbcb7d2bf2a9f032e7ff11b7134249", - "0215ad6f049f91d568331fdb7c8fba0c6c7ee9692413f4f18bec9614a49206c156", - "0215a9cefaffd26d9d1d8aa5d088d7f08e5fb889ff2ad10adbc1dbc25fc8f58e63", - "020f5242caab2e35af99d91f69e0fc3f378039706dbc22c958c8ee09bdd73708f4", - "031d5c21db7e45330a527fa35c214cdf7dcd427e437e6422dcd930e8b24ddf6864", - "032af526130430820d109db5a5316cf0d07b5748de8394925bad672ce750481c25", - "022428c630fcc2a200ab01b5775eebca20e08f62a166866f35c5d4c4304258f7b9", - "0220a553ddc15012c82a35804d0c56df02eb64d8bac42b0cc3027f02ff9addb298", - "020ec44a26bfe0569924d983691da3d160880b59c7aeb25a3af2fccd6dc288de11", - "021d9a82a021b347d60b9bc3672e827f3ac1222842dab7cc1d88ab077e722e015d", - "030c2cf871d9eceb5249daea7a3c230fbce9e0abb6214f7be7eadba7aafc0de58a", - "03234cf9d45547529cc753a0cff036321db7b61d061c4fa6ccf882d5af0381e79e", - "0214026025dd989af828ea5fa4a333f3dbb24cc31625d9fff097a01e58894a958e", - "030ab3be1b1f9c889e4ab003f5ca0b754e66ed4ebb1b8ad270f9bb96a4410f18e6", - "021a25c3f7bdd4523a1374db85fb291cf201b81f4ab260f5c08320d307a879f1b7", - "03109cf49fa0fc8c72d38eb15017c5b9d05fbc4e665b61424326b254c6f7b86c44", - "0329e56dd456ff87f0422ba72d53408df12109b4053c22fc3ffd99065f6a26618c", - "03111605e4548733754741e941067b4e5e97d5d3d19843eb03893ce9371e97f506", - "022ae8f07a5d6098890a49850609cbfa9bc2456c1e3a7405fc1d2a4c44d8b8d83c", - "0208e1d96af738a2ba2919bb93d045d3aaabf50a68dd91917aa882cde82fcce979", - "022931fa3ede666ea50f90aacbbbdb0e3028ef14758dcffc0bff4803af70f52d62", - "022a96bad6b66b4a9fdfdeb0d71f09de4fe0ed5f19129c0ea4aac5619a385d3bdd", - "0311838d99b0f53096ef4813f53179719839951117cee47395541e2bd6ac917f7a", - "0217bd5f4c39a197feaccaebf8374263d9d10a577eef48e8cd9d21c1fc7e1e4ed5", - "0310af6ef647308e97750568a766e42bec3b6742b482c0fac768e78decf76eccfa", - "030d3d9991e8dc6e61685a9fa10dd7480258fc823a4684e1a5e2f505e6d7e0445b", - "022c97ceba7fa3af831e2d43b284e4c0860c8b018ac87a8e9749b20c7aa222cfcd", - "0210ebea7e89b57bddadd48b44fa9190f0fec58335c088d25cf9b1352ce75323a9", - "0228efad4881af866c9c4c924dff9c4cf91ea3958f5b8d63c7a34f96be559cb955", - "031bcef483f64a96e779ed7e5dcd1eab0bd275c34bbe5de6d658d4436fdca5e40a", - "021a1cb583f011a6f6c026ed91fd62b72731ba975a509ac29cfab8ef9758801f67", - "0300529e62c0106e94f38efa36e9dd173a5480605dcf48badac8416a2d193f9eae", - "021ec3e41c142e7d72cc7ff648c2260d606f860c2123cc3bfc531660df7c5df515", - "0230462ad60d09711b3a7c734e8563ecde228501a39b453b234d3e34dbac803e72", - "020325bcf266b438fe6348ef36583debe10b0ba018f75fdf3b3dfe8bf7aa70d00f", - "031c8c92ffbf6e6b8b61c2a7a432a33f40946d15f5bf7f8ffb945a862e7ce678c5", - "0303921e760b161a204a2a56c311476b2ebd31b30987273b503210fa86d20dfb9c", - "031547f8d900a3c6b47ac27119e9f673c20e42a968487228626051ca17fa3532ae", - "0307bdd3279d46ffabece54f7b3bbcbdbcaf188d8eedae5863030f00eb803e256e", - "022816d4b987629c19f782ffd848db515c741d44b933fc9f914e4253eda484649a", - "03210204ea0d2512d1b5dfc0b6290d2cd148465ee3bd143c02d7b2a7c300dfad1f", - "02075ae1df97ba54b358c035990f8a10f17e6aba257d62a1a1281a87eab34b89a7", - "0216a8bc65d7950f3febb84ec6791b1f37dc6e68bb6902b8d050f8e63d1dfad16d", - "032d454312dd732c611d05e645652f338dd198ac3d7fe4826971d1b229cb9cbefd", - "0326a5cdd643d1875a34a61cf47f2f10af7689af6fc49007ab78781908216be8ab", - "031c56d8c526dccb904306932574270ae6bb9f8145bd890b19c877ee897a3e5e3e", - "020d250deabb6c4f068c09f478670d8df6542f2f7f1c5784d77e4dd60af1a743c5", - "03232462946162dea717da4a08f940cffd01a9193a5333929c29199a692e11d737", - "030dc6d1db8a1bd0c0bdc418a902e95779d9ea6fc54a24923d6bd9bcf5e9e55be5", - "022c94e3eea2a7dc1b4039a09d139b0e29bf5e764e2dcdb4c7e52d0909fec20407", - "02042909bca2e59e33dd1c3ec7ca12255781a529e4d1e767603ed1b55a38718a27", - "022414b96a4c9a15c774ff2296e1a488b6c611428411f77d23bd4848f89d7f0059", - "02216e2a23c48ee367d194f865a5340bbc3464890bf937f6a151df03f62ebd31d7", - "021a2d52c29b8a85c3054dd4ebb68d5e7ebc36a295a20889e7f9a3d1a77d5de77b", - "021bbd07def19d30fe8868fccbc94bd1a6fb26965d12330fcb6f68ed0a7df1287b", - "021c0d68ce88231e9f55516fe12109760abee35d80c31653d6c7ab67ccdf93f879", - "0304fc4965b85401db1d1a81223dcbb7e881b807a6724c463c38b23cbff03dbc47", - "030cd2e4b847f261e3ea3c10534e3d3990ef0e30682e9fa5339b6717ec80c96aee", - "022fec89eda5406d707e7d8d986f8778e3efc67ced585132e14c6557a465bdf397", - "0219f4f92c611aee3271be5fab629273f2e29242a1c737440e81195c73d19c73ff", - "0304e1e8c926b301f2964f7d67babded342e79930201dd880c3b4968d6f7606201", - "0220f4dbdfef38a7b159278f83961b8f8dae7822df58fb0bde2cc01312b96ed449", - "02268297f965b7ce1b9901f9c1b9550e81568aa50d4f197aeea823c3c0e0ba8b5f", - "0212dbe14bfe0de08409bcd02b588e84b74995fbf25fd2e08615b2a0392be887f9", - "032bf45f918c509da31551e0fd2d8a86a79610645c8e69bd1a6647486401b8e541", - "033049b790595756661368c579f354f88740c0ef67655623b95f3b6c840d8ab23f", - "0201f8b87187c5015fe02725d5106076fd18cc2f5d128de3838a9654d5593a9277", - "020bb61c2977544bcb60a054f3809a2c96a1fb54583d5b55e13ad4777d436e19de", - "0303d7855fde0e4a410e6c1a1539b1aed07a79c451061569031b7a3a4dda5d4a2e", - "0219d702d2117511f803893b33ea02ff8f47f23a9f639f63499602a406b0863c98", - "022506304e12e9d6de789c0b7bfc1dafd63bf225095105808393f5b98b5e627368", - "02262e869dc00d4eeaf68923ec51973ddb28086cc7b4bc9c97300f427110a2e333", - "03071ba2d655f4f48dab729b1e6f301cfde10899225bbc67ea47dd9a6ca4123c9f", - "02064f6b54fa41e98b661c25e5a6f8a95ca89647903e322d2f2d786953eecc2c8b", - "021935afabf988de5b852f1e8a08bf66033d99898767dfa3fe41d59d440c853f9c", - "022adc6bf1dfe8e2bc7848d899e4591a042276239ecc52012e66166bda49f5be3c", - "031380d0919ee194cd4e615907594dc585eec84b4f236b991ea9033660af637041", - "032cdb9c272549c10bc430bcd37ed9527ea63df1538e1a7e64568cea9cebcc7c4a", - "031eb2f42fc9b7917100c67e249928dd17797920d7b3835a85a28e1dfdb82ae787", - "0317dadee8219cdea39a31491424de60d13cc81da51834b9afade5b81779f2d5c0", - "020b8e9be05efe3b33a1dbb0157499388d31f2c4b833f8873f0013e5190071fa9c", - "031ca48aa3c043c46c0246a3da4cd8d455cb62012242c4b01bd0185a0337d107c9", - "0212af05440ff0ea8aa03d36db4b5af2679e3060153c555b7e11d09eb3d4419ef5", - "020103d254bca00cf7f3a4474ec580bdddb805e38a790f308cc0fb8a528655d013", - "032e722d944a3f1ab082a386504863b2ff0112ac7dd513dec4731bac945ab3c285", - "0321b4a1ea4ce7af10c822a4552ecc6196dc51ab097e63416fb045fe1f62ef9f0b", - "0302583621e5a5c7e9703479076cb6fc8d0dba2153840a80db6657a282afc29c57", - "030fd1bf2f4cc11fc7b9d483c6040ac0d73261a23e49096f7a0186140be5f0c3ec", - "032035060165cca02f512dfa975218b624b28d7c134ed278aa765899c4a637f98a", - "022ed0e4d12f1f54a38badd78b80046dd2d42f74e5da1558632fcecbf404ecb9bb", - "02122b9bbc92e559801e992b8e82d4820f3bf3228176add3f21aefb01fa0a1a208", - "02170c898e0841bdeab5735f465c73e5b5bbe2e0bb143fc2310c18047eda2135b6", - "0301a365471f97556306086da641ecc1ae4b251a45bcf200988ed87b251b725642", - "021aefbd94a18053a7564640fb628ff4292b95c35c0d564d075116e9fba3411a1f", - "031062cf05d778178e467c2bad0ae9bdc05a6fe2c0f0fe78a959c1b8f89373ba70", - "0217213dae446e44f7b3c79b589468d701873530afe2abb4a251593fc4679875d1", - "02072f60fee258a27b334544e3feaeb1ffae221e57737a9805045a890bd966d190", - "03188f3bfffa1e72adabfae707bfd3f5e0c0eb4d8854080e3f586f954f4d202257", - "021f5262dc6cc6092f84e2e8ba6940d0ffb24acef978fb4ea1eeb8db98b3d9b325", - "021be5297f3414954e49c7d653e37d4e1b8f21cf882ec2ce7d3e2c35d035b84dd1", - "02015049de0e6c7e477ddb69627c33f4cc5be55800a2917c474e0f87229d003351", - "02202f328bda05422a010e0f4fe59834c073a491b3d7d819cc3557bb30e435ba04", - "031a1c3f64743f5734882f407582b589aba76e8308d367f6e5650a96ac1140ca3f", - "0203098c91db4db3ca300ccfab4f123b4a5cc51f1fe003b22570f49d7ca02e4c07", - "032bbb62774516f0e633075a35216e1f970d2011772318403bc3f0b56c406642df", - "031a1573281746c2ed235a4657a897278a6c79c6fcbecd1c916d08ecf592c0c4ec", - "020a7ef0775bc94f69781748a5336f2441c80b048f990188fcc4a8c5479da4c396", - "020220f2335a24c60341ba6e6c1a5be2ed7676f5461cd3e8a6e40a8245e0c86839", - "021d4648797924faff854fd342545b9f1813be66e112cd40b16952c5ba75aac9e4", - "03243850c471d78e6dbfa51a82e5f1ed270b832e5c3a7d6b05229ac2533cd792c0", - "0210f4f9e560592c2cf78ed9dfd98577dbbac6bc21fbaa29c4996574402bb811a1", - "021c29aebdd0258f110cdf3b8d06fb0a3a3a26970079b37aa033e51fde03bdb05c", - "0323c0b1685cc21ee0ebd857a12f8ecee71a28bd1d3f02a0ff811f40f5da6518a7", - "030a686e5916eede33db7dcf075308937993e217973c210f2e8f5a1404366b082e", - "021b13530ff2d6c463f4de2c727cabab7b024cd00018d9b7aa27d2a99c6c72fc25", - "030e9a67cb06337f5459905d3210e4b238970d66e4dfd4008231acccefd2681f96", - "020891e0cce3205c3d78586a35df48eb88f014e4e4df50e55824988f079967bf0d", - "020c231ce7aa99d4613e3341e099c431f0e8623896cd1d3f92341cecb082ce556d", - "02193095cda2edc4fd085c1638057c3f29f30d7aff8fb6f90c9befd893b39fba2b", - "022f1d9cbef46aaeda77d814573cdddd38355d9c578f292042da5de1eb8d2c7a8d", - "03184672d38237f69edb7bd9ff79f2e82005abbbd6a1c70fed0a08ef71b992bbb8", - "02260d1710c8b38325e69f18444b9ae7725248c5d7e531f0738ecabbf0e7c85740", - "020adbb39b59096cde49ed8cd538a7eb37b477c00dcd045bc7710286f9a56a9acb", - "0311f623517fed4b8fea9276b0300881a999e7990e26c3c9b6a16f957ce187048a", - "0328782a3d1e55a5c7900e58d78429304d2c9d90522e4e1b97052e3bb0ed4df6a1", - "032c3e926f84062b52a6885165f863ea47828c86e9b882bb1586030d581d4e6e45", - "0213880e3c17daf5d7e906195e154be33ccfe897cd05a239c28d247703db6dc834", - "0200d902533fb3aa97bdd47aa7c9fb914857eb83dc9685c5688082808ca7b58dfa", - "020cc0469835a51d7baf8d4f95605bfe165fdf5d310801c429bc73425949e5e616", - "031755c3180e1492f098f33ac2976f4ccdcd63f0899cf35122272d7a8b7584b9c3", - "03267acd7b053cc1161fea01048dd52d0e38f22a9430e4fc0e7b7e33b4e4bbab27", - "020ac20c795b1211b413036fb651c8b3f4dd8904f5269734174c2bb825bf03f9f1", - "0201e661b7184e10a21b3096f7192545d768d7c256d35b7278cbe9b3b9cbfb25b5", - "030b3b31134bcf396ffd076b2fdbda13488ff39caba4203b537b11b28d7b6c3e78", - "03119b34653586fcbeb5d97cc903efb2e64946b420e8d6819c40b9277e36b7a12d", - "020afae330df7ae6a552e7204f2f6bf0cfe4c45dba8b8494f8f702fb877d61428a", - "021273da1005f9765c2b6af2062397e30efb95e86ac7a1742ec022443254e75068", - "020d1a5970a7aef7257238d28aa9f3839f3eb65fcbe7ea006c04924f01a2b466c7", - "0323468828c11d88d20dbd465525d6a264fa6666aa28b3ff3e9ca6ac0abaee2c75", - "031640687bc73d31966e1b810fdacaeb6250565514fe80d6063c213c093867801f", - "0300f7ed6f1592817320d914da2614e3659b56dd2ce48c0a7c3e6a54b38e221743", - "032c032ef165e15f4ae215737f5c4ac9fe376c57701bc01a1aacf206e6feb69d28", - "022fd66f879b0550912b29777057be12ba98051186815f1a387d7de2b4bd70e4e8", - "0303452e667993595706ee8db5f9c191bb528b0d4317e33f1948090e0ba92f49a4", - "0329b9f94b37910c9180e15006f9b524835b4caa0352c5ca436581dd4c2a236f24", - "020c560e731832b5ac726e3c25b2b306fe0305aa1d3f99994a26f09779e1d807eb", - "0311f09cc09e6b6b3f17d72c607159648702e8da233b774fac81e79b805b30e0ea", - "031b87d08563be43dc11596e4e4b973f4512912318c38685bb46e2164de15138b1", - "02081469d600bd05babe498a69a484c9eb4ae099292c983cb027ddec4e20a94602", - "0314421db9f22639a8ddfef9ecbd04610d25ac37156bfb17e0016f8ffbefb8af27", - "021e997bb54227138a57b1f9090288a54da2e4786ac97a71f4d4b930b68fdd8504", - "02182550e2edec910187ff2c4a3cb59ec25f04df2e9d9056d204ab8087f326e163", - "02082752cb33c5a971e377b61efa8fb65d7d67c7c5c92c6f4f94f8aa509a01cf43", - "021ca834404c95bcad4d7c5ad7d00f5abaf65ce92f8219848f8d958209b8937996", - "022a8dee494c39ec4c453d3583b6d2756172c8e1da58b13510d88955af6aecd07f", - "020a1deb7f2ca42c90dd60243b7ab45092805632590884fe073b2b65d21b8e097a", - "030b8467f39e9e3a5f4f46592169398bab84cad5a6e75ff4a2ba64faf315652d83", - "02160b0e1ba758043e38b4d02bc5a843f791bb8830f945ddf25ea8eb72f5aee100", - "030e55be32db85a50fbdfc8467c08e11e0f49d4e6255323efe315913306919e4d2", - "022969bf536da2552491178433e5ca38f365e49e35f22d2ac396f01a7ac4b5f395", - "03113a1cc1ad46d0c8b6e9c14e2d026be607eba1b4dc8274c2055d872f04acd734", - "0302c31573807bdf34053ae30fb71ee1cfcee77fc3143f9c10638b4de522befee1", - "0208248613082ca024cdd4d1ad2124efc7441540cc01d677f9f4a59d5c3ac76370", - "021297d47fa5610a23ed4fbcef08c6f43f6c33cd5e8026bf4095f81ae369eb7702", - "0227bb4bde3f914458c8593d5488ef8abaac9eb982b6109391d76a58197703f63e", - "020d3ddfe834550f028122b31d3366ed0e1b89475de25a3d3cba8aa38e03ae0b4c", - "022611166d0d13a46e900514c8e63734cb68d1e5b52f323b3e3ed26411534f799b", - "0219daf46adcd691fe6517b08098f392f013153ff9d52d7a3f642b6e35109d02b6", - "020ac2181ae5036a86cf525dfe20ecc8f95e38350b92e08020787b9560d95e0770", - "032ff5eb69270aaf9bbd518f8bee688b2cf07e9a9272104613b8406e2ece683e8c", - "02166101af562479a19af33161b9402473d745bde31d1a65f95893ff4224ad354a", - "030ffab929a100924f0af69baccdd1ad934976aa06daa0924cb11919b53256ff37", - "032cc8ea0868e25d7d6de110cacb6719ed34691528ffa32e324794d232720908fa", - "0221a98d60fcfa996334f2ae5be23fad53380c74740aa626c094a01b281f45ace5", - "0311851c85dd225fc9f263896b2dc6dc40be36bd09c1cb1d28279c75d15ffd6643", - "020da33c7b60bd1f5db67ea753ed5e5ec022418ee5467bf36f87c577fa368d611b", - "031fba263252732e8a95d6cfcdef3e0516574181bf7de7daaf69a6fbd7927cd768", - "0217f1f0ea2f1aafb483b4a78edfce5f1ce467530681754abcfb9306fec7ed5bd0", - "021ea08f1120969cf39203fecabaf15e4d277709cc6062344d8789b782c5f5ed5c", - "030a4ba8ae3d90903328c6446a8932773bb9634c8d78039e4a6c0fd1475eb878cb", - "021c329a583f25605953558914fef2210539eabfa04191a2bc793742ab17dd9cd6", - "02013d90a87286c34aec7fb6b0f9a405a97668c09997f96e314fd6967ebd969007", - "03080bec89888f274cf212166713a08aaa7773c7b37f6cac56ab15fa3f4862361e", - "030899f73263d395bf03fbfb7e6599a387858fc533ebb6cdb4481babbd85cda9fa", - "0322c031f7e1740b1e6a7e6c03572c65d8036f8f97816ac827a3ee4ef5c940723e", - "031799370fe60c0ee41026dc2e8220c7c915b08adf72021b4bb5cb507c39ddc07c", - "0302ab0f2f08b40b7fb49230806558c856882587a1d63b971d180f29b20c20367b", - "0306ce1da07c76bb25594cad21bb75ec4cd8f683b688ecf4b8b89b89e43368d9ff", - "03149a1e25bc4cefacb517c36e9406c21cccb418e49b93ae67906030b52423757d", - "021cbe5fe66fff7e382de1be1affd354c64eab2adc36dfcfa5cbc1663c0194fd77", - "0307d8b4380be1096bc20c8fc9adc287964b2ddf29f0ca70e92903efa0b213ca30", - "022a90941bff17b191222560f149518171e45f43658e2d7fe50056dc3e4b862b02", - "0307212047832eb5ad5f8473dbd6725f37521bede9c70bc35111fd30323eaa59e0", - "02252659166ad8910ee75b29ef3668cbe74237b481ee71a7ef5fbfccbb0eb9ffee", - "021bfb4c5cde785a0d367fab9e95eb6c9a0433c3328f680082418388e7153de2ae", - "020fd9bad91ef5032ce7a865b4af562a508e318797c424ee23f1d383bdb3f36d8c", - "022d380bcd40d7bb878af3f3edfcd47dbe9154fe2a465a4b22d4d6fff6d91a2f7c", - "021e4a23a8629e1138313ba2becd94679fa3d3f748fa7a0603dcd84290a9bcab3c", - "02106b0cff3911dd6adf24bdc2e3bbf96b2716b28871a29735e7d45f098962ce55", - "0200ccca1a0010a943e0cac152ec77f5c4ed3e6e9f80bf1bce48e3c4256743d34b", - "020f22d0062636b5fff92426ee6ea95e1cd70569f2b592507c2c6871670c46ba48", - "032cfb16418e4832f409cd222df414f27f640a05b7a65aad019010c7ebd2c53802", - "031046ada33589f542dac1a7ae8883dfc6119b18de81f617191d0932d5a55952df", - "022b2414e24a222e9826aa2267897896150f3aede017bb099c13276b575ccea326", - "0312f0d24aef90ce680eaf7883ff5a8cb68073bf0c0aa65ad7d4e0f44ea2829703", - "02097bc352739cc01deebcd3d3f815d3025b0f7f1c70fc3e227150d9eca80401e0", - "03075ad835ac606df49995dbbf8ee6d15171137e24e52f66d7379e466a76518468", - "020f035a8071407d12a53474c93120c693ce4f822ee11c0bb1edab9b510d620d27", - "030f6af794343b071e198a7109f664feaea46738164b777c9def2257b3f3bdb310", - "02082107d60e6c058801aa6dacf5d269466573dc484d333ea8d4bab18facf5a76a", - "032b960f7885ab85fc1f2740757077d4207cdc30a9030c38bd3c6b959b24fc4724", - "022d22fa9b31eaea080062804faf5a4fb8e081f981c700e463f3d8227640537d3f", - "03104799402d49eae87bd7b7fb495bd2b518ab624ed938d570e11449ad421c6567", - "0209353670fad155ccc42a6444624ce9900a00a2003e43f5cf3f49796f4394ac6c", - "021593e5476854904c3d53ec20a241bbdcea0768def23131d7c31eb13e7a582e26", - "031a0248d7603e2c6f4cf1d6af710fa20df863f42b59423296ffba4274784ffb82", - "0227d654da82f0d8dd223f2b4d22919a9987f98155760c3ac0c343588b196fefe3", - "020021128b30a3c52c3263645b679486e690b7c7506d67089cf62de8acfe584aff", - "032a4f4735f0e65ee5207cf543083a2cd7fd716302ded63697fe2bbbf3e99e1df6", - "02238d368eeea88a743ae9df8ae6c30db65113d9b4a5231b9811d5b6c6c347db6b", - "02058b32f77c33911ea0f36a269b0fdb3ea349ea0114e603a61a7742af1d729879", - "0205103f6b98344898734ac30f09a05a406ba42b9c05f9f92ba5bff386b62fe935", - "021ed4e2d3b563c8259abdf75663e44097b2620df5ea2f72656616afb6d32f888b", - "031139613fa1d0ea6e91a9b4c77997932a44efd26ee7a7c1f90870730820a62226", - "02302377886288e60f3d7386390b4412d466c1a971523324e563e38fd6ef16ec5f", - "021b0326262ef44dabff3c043fc67173c805c5ffd6aaa61b7c9b6dd623ac02b449", - "022fb4574ea2cd17a481cccfddc61e1ca466f89b4f064fc6d0265e7688ccc5bb27", - "021d1725e4cdace50a9e7535838b16bf7647fea9928e188985a831d3c642b22541", - "021e6bede76730cb56c8ffaff2789fbc2850730d60a7adf085167384e975b1a53c", - "0314d426c6272a61bd18541a2cf855ca31cbc89f5ec4d9ee41372a7ef1ddd2b9cf", - "0201e6fc32e200ac01865ad1ac03447d599aa62bbf517f1cada2005451a435b32f", - "020c1ed65a3f6b8e6013d221e09102471ebfd513a7a972e5b04866fa7d99dfaa65", - "02205ea0ef6d90fc60146eca7d534ef0e36e4513b2b0f7f95c489db4312fb966c6", - "0227758d7d9175fe4742286e27b0796afe302e670c54d88622e706dd952d71f74d", - "0314a0f791733b40f9cc17d860e33580f230f1652b056ad0309d2f3498b8c1dd72", - "022d377f54cf0b62c30d084f9df325d8fe31661d223b6f7f22a5b0cb409374ba29", - "021fd6f087003c022996eeabe0e960358cbd57b66caaecc024eb324b1f0f1b96a9", - "0214c01b68b44b602efe7fa1dca4f8996ad933b07689c633466481163092044ba2", - "030663aed894a29a7718f7aa88b23acc7948433c48e24c13a0457aa7d29ef92ae7", - "0312e10ab60db71572e8ec81025b634ad0cd50f4c57ccdc399e0f122658e507023", - "02261a6e481b26a453c3c5c260eb7e8f8aada070042306e371234d28f5835c65e1", - "022d655ca3ae24e1c85321573a858586013c2cde6b2e5440e360704d72345520c2", - "02093e8729d090f6c8192cadb2016d65a1b92f6f83c82a347c94cba37697c8b76e", - "0330548838701b5fb4b638a009568af0a222ffeab85bb27aacd75a0471d2b0629b", - "032831fbc50c7b75664872aa3a2d11c43fe991bb8b5105c3e118a0d4c535508a0d", - "03239e66db8fca867f45ce983b29b2c59bf055bb10fa21fff2394e1b76b401829a", - "0316eb2604a11763238c38853f357d2ba3d77a983add49956b8cfdeb36adf68925", - "031add4e8d2ddf3e818e62118bf8953dcbe9851227399cc9aada3516ee350cdfd6", - "0323ff73ea5e8a976361d683eb7760386a16dd82fb5bbdb3c569c3aadc85b8108a", - "03112daee4f01de614daafd2a6dee765ba20fed5d9e96712b54ec78622836fdded", - "032108c8cbd81bb9e349eb175e3043d2f8cc10bc878b879ec02a94a5782256aa0e", - "022cbc6c669fc73b44ea7abc9c557c34efc3a716679dfadfdd5dd929ff06dbe03b", - "032757fd3cf09d678276bf517f9b241ce797a1541a68f7aadb87ce06778680133f", - "031e684ef597a443ba21a3da11b48d8733947118acf98ca74865a6704e96de03fb", - "02232673fad023b84dc7a95d9bc9691eb690e4efc6db8da322da4a7e1e1705287f", - "030f8efa642986608d46f62d5bdfb06783ea767f0766d3e87611e2bf2d992ae2b0", - "0327525414b2c035ce6b2fe689bf9117a469a8fddf8faa947fed54d1a4c5f6d3b4", - "0212caca55263c9fd69956a5dd823b02710a057f09a6d2c49cff0dbd77f5130f14", - "0216400c30554f4c014d7725c0a29fe62a8ce3c157c4a6a9c3aeb1983c0b72a2e1", - "0329509498367cc6b8dd623297461d555c43ffe7272229d9580407578aeb319b94", - "032548ee9d90aaa57a3f3baa42b30e48e888d437cc89a9f4e9fd6ec1b2f055b104", - "03256f47b7d4f18bbe7787e385597d66ae265047bece9655e8b41e52ab859adeb3", - "032fc1dbbcaf77e5bb280b6b227336e64c7a68207256e6a2cd27f13441e7a40239", - "0300a33abfb1a1713e78f437380fac207dbc5bbc25dbd76e71b43f49300853e955", - "0315542aa34bdddc29ae5b36f0c4b8b5a23018a79d0760586425a68378d3047c86", - "02251e43aef6c8624e08181a980953da52ec41f371a71b603c2b1490c4b054a5e2", - "0214c59d7cbf5e3885b608daddf480e8339c6fe81ffdb02b24940d737a33f71bdf", - "022d8cd71438ef241ba9d10cba90482ec8db68b8e3c8994483096ed30cfa940d15", - "031f1f265caca745171e86a043a6207d8e35e5d9019ef5fcba1f7c2571f75a5bb3", - "031e1ab41cd25268e8c89363570bfb3e104de5ef3b1d9c7ef5083ed3aff96e6f0d", - "0314dc39906d1a8f19413a9e2c7ea08cff3dd8025ee94433ba211b649f05f19842", - "031e118813ad3907b558893c270113c7fe687191f2b0b99c369f624b55d1c552bc", - "02175cafbbc3d2403e73dc5a05a982ef06041ec1c5d56df432e5e31992cf9501ec", - "032a817a60344780998e5e4ec8f9c8049a72b7514ae971c064909757b0efb05fb1", - "0229c979e7a0339e502550754b0f266758deabbee304bbeb1d0f4e10e2e13806a0", - "032eb17605c66ce281fae90de8013c4757d1601c249c0af818af78e3deded129ea", - "02117d5052364887da02f833ff69eb73fddbcb1c183883a8b6a0ad0414bda9ef62", - "031f650861065d1c0527298a83b4a54732193db17e219bc794aa4e573282b5ca6c", - "03021ba1cb7e8a83e0c241731327af83c59a300870cdd36ccefd6a4797f4ef954b", - "030bd1640de868731b088cf617557e5e659b9435819400a0bd64b1db8ce2c74c37", - "031735cb2680d302d8ebd616811299bf4cb03e1daf4b5ffd519a211e24dad45229", - "020b5449aa80c384c78c58637e2893cc3bd5a768d958245c7f2bd3385d66ebc72d", - "031cbdfb594c078e76fee4348ba1f9f1f2e9bccf2ecee73504aa97ad55c24d2fcf", - "0311cc64da66eadd36e7d07c48303f0313e8c06b7323d648d7240ce8e686506b76", - "020b4b691a74b7e21d67f5b7264b6e95da5de24911e8c8a5c1cb1e5f63f73c9fab", - "032c960aed6c269afb5f817a2b80934db8088c28cbaebcf31f5bda551a1e1dfe96", - "03178ea622eeda9ec0c5a6665775f2bc57a3ac33650c1cdce9173dc9aa396761ee", - "0324b308d1161a99a0a11fdc2fe76ecaee46f63550930a08a1ca589e504cceedf5", - "0327af1acda651086484a8eb51d3a36b230951b9794fd1758c068f92628780f0af", - "032e5f79a07f10f732a7fcf797f85d2a57fa415f101b73eed72046f88a406a03d2", - "030d428beb7cd054994c263785dd0074618c7eba6bf64d5d953e2f9649efdb12c5", - "0212d46bc89d5491e02356b0b8f98b548e0cc8dd5529c5961725f4a3861deb1ca4", - "032fae9684372dccbd5d57ed3da90ccb3ec05e7d7a921ba9093e1644d6ca6f1b71", - "032e809745f696340d064734aebea8c2da878339ef0dd29232505ad7dfb13e0083", - "031db6f76c57da09ed60fffd6842025c24b75ea2f681d2da1933051236358af8f5", - "031843ed74f1570e97878077244a391c9b6f122c3162ba2afc07d4980be7d8b2d7", - "0320ce05e35c3a5460266731e2f1a91315d19002802dcca5a004f2c867399f0b23", - "0328c5d348e029f6225222de36f62cb64046589cce210a2c2cda54a0c8fa00575a", - "032188d1e13ea0a3610e363f36f701783706c87a3f620c0f2403f9bb4484ee24c6", - "030b2b88483812dba62293d2a9ef8d0abc7543abb6dfd770a84592fa4bc226709e", - "030a443128aa46176bee3585a64f7a8ad3371977ab60163c956b1e0d27567c0a44", - "031fcb826a4d8fc4d7afdf36b0980e96e1110e2da59f1b1790d55e8df8b3d4d860", - "0307a574a46445843e53172dd6d4ce98fd132cefba3b8832ad627cbce3691b8bda", - "02273a10e35d3c425cd289d6994a48290d7af53d921b225e24e540bb69825368e4", - "0325e3bbb4f46f64237a21a313345ac9b2f744c9dfe869483c82a8a86440766abb", - "022b010c029abc8340bd8546311637112e34dfbeacf0603d3a7f50e548151da9df", - "0205b962d8cd0397acc2f72b9da21519a412c55b2cc3e788f84c1f9b8a6b6e1da1", - "03168d2202ac480201a93b5eea93f92e9240be80e98f4d9e0ff716fc5165a638ae", - "032193fd7ee56b272317f061ad914607829a67625a0bb39f71ed393eab6609e2b8", - "02245277ae28623d07eba012e4b586f3e71a2851a78b069e760ae483a0bd6d7975", - "022fb3fc9b06efee42a14204a35417561971607d885da13684b0022331c858a296", - "022b85f440a21c3a1158e55081f52220b48f29f642e6aa11a5c8a51226d1ccb114", - "032d44812dae9cf27a17d5e703a92ddbad776d8a2084a1d308df78cfeb33bcb8a9", - "0224c0f83dce169d397750511fdd1b5e08e70ce1e8125a5213fc580c991f2991e3", - "02084adfc4011658da0138088cd0c5780cbed0683d12defedd126ae23e5f4dd967", - "020cc8dedb606bbd0423fbbe17a743beccbcddd550c9aee7f75b76f51e8225e420", - "0220ad2a858685e785f4521a8aa5c598da85de1cff1c99450c4fae433ba1e0bac0", - "03008ec2961f4c5c66777af6c628e58f08dde324efe0e0d0ff625965d250970229", - "022bab212175922e91bd31d042c43cc32d02738f53989764571c44b7d0b19b437b", - "022e0a133aa5df2454b650d691ce49bbbee0d142547e851441197ff8e2076d889a", - "0204dadcc6764e406b0c3c257255ff0160c111e87a12246d706e839b77d4642d8c", - "03045172ebe8599c8689e32aee2156e3b28422323c408fab95a3ddf0479d57174f", - "031a7f279e6ceccf0277b0250b2c489792d52af8effa28c7563eff874682fb763a", - "022fe074f427f486b1bde57bd9e64790d6fe0cfdf4e4ecd4560bd211a103f7a0cf", - "03045a4a0db79ab39c40341099d6b119c9d77bc62bd4e46eebc8ff78fae2dee2c9", - "0302dc54bd6b33cf7955ecdb2551c1b121ce918060018f4a196fcb13e1cd5794a2", - "0324f6526739f7dce480256d5f5d8909eafe4ee9de03f2758e6560cc592a404ed2", - "02256ca6f66fdf754b03ae6764ca5ef5eb8798abc1dd495508429d3c5e3fc169b4", - "02165e35771dd56cd985a51bf0975a6d99d4280a43580d314849941a600bf6cb11", - "031317a0039f326f5d56152139f73f952c2675db46eb17f8b8e4e40d05d6679a55", - "030494388b0c16e0bcf513f0410e3ed5b9ab107301a80588fbe9d0ac0f3ef14593", - "022df9554c630a775de32f811f47c6d26de7a1f97d337de7328364ce38ca8fe857", - "022e7df659f9ff2c79d3949470206b23781600d5e4125381e89b49ea3b48b159df", - "021ae8da42ebd853b5fb9ede328ac45fb04f9a05ef54cde66df66c8ebc8e30f615", - "020aaa5b29bb3139e630bb601c4fe02797f2ffc9f09d2d0270aa438aaa95fda4a9", - "03033c0118eb0d83d66be7065d9be590a03a5125af65252e78acd39ab2c6126524", - "031f2569113db9a3a37666fc48e6c6c61f5706e4657141ac0412a828f5afba7fa4", - "0308b8a3a6cdb2bec1d67437361aace71c76081027b5d94f8db02a7662737b7e67", - "030bdba2cd7d180f5baf2e12faad6f1da2b48ef2ce31b1e4ff3cad142428d0e69d", - "02297223966c99413bd51f4b869380d76c91715286e9852554457ff694c587a22f", - "0206f71c9a9e7e8d28e4f22dd723e1e80534ebc88dcf95dacefad7b57f4d7802be", - "03018ed13e0552f89b5d9f2fe046c060fa456033c43ac4c25605e138b6f34cb79e", - "020e1fdb975264b2ae31906f1cfbf7303905a49dd9a7901da4fa87f81b724ca416", - "03256380e66ce8073fe3f7698e4f0027da12376c743967654adf5c453e0243cc7a", - "022e3b382c5bb018dd4053f49df552fed9ba5ab5387460e361c3ea6aec3fda3d90", - "022c52105ce35e4925e9411ce3ee4e1504fe43ddbd75aa3a21f964f2b7a205bcff", - "0328d695896ce9afad6c1af4a2c874ff1c35fdc5f2a5c5cddd933fac63e0db46ea", - "03236de3a79b7d8613ce0839baa5d5c06e70af8f392a7b964c548083939f817792", - "0304500a745f5c9b22834dd069b4171a0475f0921292a8ef795357e94d8b346694", - "02042374bffaffea90d7aae89f0dcf2fcecd9010d35a7343b02b4a72b075c90f46", - "031c179d504e0c0c31c481a9861b87e97e9b6c64725126a8dbcd255cbb55da2e96", - "02198b70f5e9def83ba18be7ba68fbf7f43e7f1168062e17cd0f4a2718a1b92435", - "02028ec9d9b2faa753317f166495b42a55ade29e21eff89f8035409065bc3bfbf8", - "03297d8ad9de8eea953045cd7f681fa29758b54a912dd3316ef82f4833c89e17f6", - "020fb83425d0c9170cb21306266792952012905faa099480e2f170bc25af1d3a65", - "0304dd7c043405f5e872357c886f2ad40928ddafc6b79e44e642a7f70246818596", - "03083a1bcb4f4933ab1cc10034df036a911b4b0fa3b395a991c13d903dc92efea3", - "030839a214e60a83e726983a4f1f0665bb3feca2bcd5ca96d59999a6f33bdd5fb3", - "031693d37c80ce291b84017803ea7a6000a993b2e6f6854612be4bfaefc3c76313", - "0229cc7de3f6d3d343bdf237e20626fbc69d08ce77b2ec47d1fb9907a7d1b82c07", - "03122f1794e7d4e222323fed46b7a31b3d55d167effd41d16b39c1a66091cf19e1", - "0307a6506298f1d0f4c4a3d3330bc425fa33709957c89deb7c392ad6f6bccf0096", - "03217827fd5d15a1f29fa376d24fe8f9fc00cbfebe2171a2f647f81fab6ad55f6f", - "02126cb92c334d04eac90d1ed02258db3852364a49f8a96df4d690fe5810ebbb2f", - "0209332393ca1b91f9285b1a4b299d44e023018ff92441e18c4e046db6e52cfc1a", - "0212fdfe5e3fb6f14991ca5ddebdf93f0ad163b2ee595474f7e43b79e2d20b95fb", - "020f742bbaa9484890d088f80692d493ca40843b25d855285d5e45d0f9865f84ba", - "0208a6cb05884e5c40e9d5b59bebb6f5180aa58d527eb4a7c3d1ef41918490162b", - "022baa90049a4118efac13334a798c8e304a4081a130a5672e15c4e98776f71a3b", - "021a00eacb7fab5ed4ba3ca15251ff1b864ec90c17cbd9c12f21992db3587ab3ea", - "0310d1be14db0dbae6dac4afd16dcb55d428a2a8c1ffb909112f5d29b0ea1563c8", - "022ba7648ac9fc76a7471ac6c7c34be86c2396b1f7d13150711b66d07d9cd51a7a", - "032b6eaf700902918b553cab472afad9e89aeafb930b9df41f5df92d54882dc1eb", - "030d829498f34424b3cec1def8422258f884fb8875e744ce1b8e120827ebab2ae1", - "020906d50902d92860976289e669334eebac6d48f9abf06191e7814d939878b40c", - "02100969bf7dcdd152a5d060132bf3afae6fac7e6d5d4a727241831b882d2adf84", - "022c5811827c71ada9c9adebf745332c9112f5e35b7375ead01daecad90eb1a99a", - "03169b2b406e756a105ac4da0d7c8b65b48fdecb29a9eb6485ba6ba952480e1a32", - "03141f94f2ff2b4223c25b31eb183b29ba176678aa87e988cefc9b070494c45a04", - "0307407977626736cb2b73ec70db02cd46256821a7981bc65e7f8cf4315f11e79c", - "02220593c8b07133cc243f85c944cd6b5b4d396614b2dde7137bfbbf0b74e7bdcf", - "0323b95b52f6e1eeed1098a821920d73e9e8cd14f2253201d9a2efeb825805baa0", - "0324c37f18fcd8899bbc63c7c5c19deee1b6a6410068a75fc0f95418107a3edf25", - "0220b47c643dd333f0c38c96d66bba4f5c69b95c2320488fb4b198732d98e97cc0", - "02040e7ce8db4244bc9df8e76b902b2cab4b182044d7e49a63fc8844c0232f8ad7", - "022d5354f72d94503872d307c7d1b20ca8a2a2a15d9c7cf4b73895572654e16ac0", - "0213fb4c4ba8c2527f2f4bf9a13f512e38718f1a102c611896c5e637fa52c266d3", - "03013a54fa63999fc6879234e8f7d50db241e29ef5433fece0a2ba00d73d8246a8", - "021e4c69837df76a97c40fb79e044d9faf9ab602a538a2a1f461af181038d6caf0", - "0322ac2f92228ad47e348ff6bbce92365e40f4429ec1f62706a7e301f0dc4cb587", - "0314bf628707d9cc15d963b3fa6f6201b1c024e6692ab8841e8b1de9ac7c31e2c1", - "021d97ddecdac229546d70790d75a8cb8745671f05501783bf31e0e3f2f313dab0", - "0303a0d3c50d2e64bd62f82fa9473b9b529fe69299508a83f00110cba864ded5bb", - "0212ca01a7a0c390c5fff97e075460b5f31e7d941f18e85b10de452aebe2ba5811", - "022e8a77b2a75be6b0b7571c7bde1e384e38d78cdd364cdf791cc147504099ebe9", - "0314d5d693a7ee7801e2fdea8de0fd03a6eba04c05cef8b85767af4c6d9014decb", - "0208641181f873b0525efbde57b6fd31648e552a542d5b64db6eeaebfaca82d52b", - "030904ae57dbfb7514ad38b4d82b348f19811c99b4328cb9e52d7dc13013aa1b1c", - "031c31310f443ee90be4abb231d8b28d023ea82699b715940b2eeedfa1af32684c", - "031adcb20f1259fec6f37e2fb97e8c537c791b23521234d109b7c67d0d3769f6cf", - "031b530043091c0fe1cae940b7ea8d53d851f819e02c0800ac23f4399272f0ad15", - "0205525be47e4d8ba6c7bf854e9a596dc53c3d0d1007fed0345b43555225746ef3", - "022131dfdf62088d585a7e85c742fe5d27cf3d21cf2b79542ff11f95a3fefd8d93", - "0228d968fdeb3232add8e62e6abaf1a08065cb2e758a05381082d434a6c42aa772", - "021bca6b1ba77aee9d0847b13d75eafd80b14655051f121cf34177e9566c108ad3", - "030aedee3f5bf807935d020bac0384d5eef0ca3d88b1fa304d2efb2950c618f197", - "021272063bae4a0e378755f8ed1166ed10bebf24250bd59474eb0f5ee94352b1ab", - "0227ac95b617d7098642c6116bb8ef80387c221de81eb200258eafd6d2143fbb06", - "0329f8fbe351c0c0fede3bbf0b146fd40dd611b336677c33dda689e13a9e85632a", - "020e295ed953878e8a3a36b2451a43f02c9816632a2fd330698cb3c39c0003d805", - "0210c00e1c4b727fbf46ce5386bbb9dda1236451c82f1c5cff9324b45ff134f679", - "0224b8f2ede3a277d715fc7be7c86efd26d92484f21f0d0c0bd43686432104d077", - "0228b21efa0bffe047b6db23380e339be08fc488596ff4735efa574ed51419dd5a", - "022c0ed6d1dcc1f5d7313241662785c93649d545350532230d6c0c208e4891099d", - "030b1f910882aeb623cb0f8ce8050939cbe7e0fe03604b5fc2e1c74b0142737dc9", - "032881dd0ca58ae78faa6acff8ee1b88ca598e534d7f4c8264eebf80564dc61355", - "022d9e813ee4d2af34e6a429eefb920b8cf35884f0ec03c128466a9971107cfb6f", - "03142f43cf740e3ba88a6480a5ea726dcd496360657978cca5d010d4921f1d58e3", - "020c133aba26cf718a4a776843116916e02cdc2dbb8dead8bcb734ac981b53dfeb", - "03248a108ec00b648de93c26963d2d34a7b945fab520afbfcafba150cf3fd2417c", - "022f318784c0f251f0b4aef2f994487a5f821fc8e037747c9310db17037df4a394", - "0306f2046220938b49dcf66b8860c9e298d0f63642f96a7ee15bb0f6596feaa53c", - "020f25dc75780ba72851a7017aed91b4d920b6706a5267d587931c9e8e91a8dfe6", - "02177f8137adddd2a3bf2148aa57a6af994426651640c65a5694ae8f184210ab0b", - "0317741f1139f95898d853b102996537eb8c975ebb9b9a1dc2da3ebd93a05fc730", - "0215e95a936bf2c40908e0b9a9034cdaccf9967057f1824f720d41deb4461869b1", - "02042737f453ea8c1dd6bbe52dd8b36eae034113d47bc5ec51478df3bededbca81", - "031fd9a66399d6cf55e9ad609270cd355521ef76031f5d51b449de87021e6b90df", - "0303f4562fd80801d9b86579871009ac9b09a58c72dc8daf5af45504293c5c7a4b", - "030afbf9fa593a0a43b7c88cd5e3e4315c3fe508fe587e93e92a54394f1d514fff", - "0320212379620e8cfa4bb863b42c95c574a1e660691da476af1799ca2f6abe101e", - "030321a2e108d705203dfa69a5ebacafa8ea569f679315d1b231f94a3f70bc8580", - "03305b8c7ca1a84c799d8a9877997364e8801a1bc21a60c05a08b9abb07430e9fc", - "0230110bcad78ea5747baee69a3f7a289a878085f418c2616abb42b6d8b84f35b3", - "0309e2448c00702ab1928b94dfd1cfe0b965d91f4b38cf551beefe34f416705414", - "031dd379db6704fc3f5a6fbada9cf7f4aab63d6ea5516158b8a31707637b8a28d2", - "03232633b840005f12d9b16814a9d034e4183028d89b0db9707a853375c2718350", - "02239100a4ead93dc43a188f6a280ea47aa1eb3982fc11a40723d9c755ec078404", - "020c9a127511e4185049cad90db6eb3d03c9b17cdf0397ff7cca4542643d1f6434", - "0211fbfcafb9d6fbff25665682f00c6da97c76c5335b64ff27e508250a92e66191", - "031963e32e1aaa17e9fcc355cde269eca8374fb73d7e2f9bb06fb8a3f9faa58eec", - "02263f0103cfe75698fe908749bae931673b6a4de489c5c1acef349d53281deacb", - "0329026d4220a43d2c7711143e4a1ac6bd36d1e15cc983825e0be018124ba31d77", - "030c7fe1028535a7009eca3e6e92c24c0f91a024179a7239501a647b993dff20cd", - "03301436c23b39ca673eec4b8131c262a364e786628b641a7e077044397165411d", - "032afed61a3fce9edff5695fcbd9cfab42ed0f38ec222f6651c1ea812ed09b2444", - "03103674595ca5a7404ac07d7ca553fbd58ee71e871859c97cb4fa76933cb8c0a7", - "0204a3676db1a6836b88874d3b74afa57042f753eed3248541d523d10a22e63550", - "0203e9169ae3f991cce733dc60662987507485dcad7bc0c0ab9c07a16aa6d573f6", - "0324560da51abeb7ae5a49fc9fa1c7db7ca8cba483ad9e18d8e19f1171491e56e6", - "021905d4bd513e4301372d5ab7d85dfe8bdc8486623cb7cd10ff55b40fdadc03b6", - "030633c2ffc16d66fc5c8478acaf550671ee2448b9dc5a4d71cbb4675f10349f68", - "0219a6f94c6a49aa5e277ba1483c69406bf223c87a6707290dc997cace43a40a6b", - "021ae78f393b3836d59a15b5bcedbbaae0367959f5362c6d10bb64a5a810c371d3", - "02158e3217b48544c5f358cf1e03ee45a14033590eee20b14bf2feac512cd15aaf", - "032518fcdf6e98d284facf4e5709e360dfa2d0691ff7940ef3fe768128185bfdfd", - "03017760bd32385c4f1ecaf1582efabeab0fbc50b30a04b19b880ef228ae1ac374", - "020196fe415f5305024ed0d1fbed653822b291914090bfc80544eaaa6b0bfb8d05", - "0214c166280461c6b5e4ba9668a023c285b667d96c4d029f1335b667b166802c7f", - "03062a083c51fe0b2a77a392f62625b921462387d0c9480149349f6403d25301cb", - "030d3628c74a6a4cd73fd6701c24edf761b1c080a0df92d9c09a2a2d84631cdbb8", - "032e650559213b52ab2b89a9bc1dab3e4a15334db6a894722a082e97f1aa5cc026", - "03261039ff277f7c1592dc71b66eda5482a05660c0f0c9f84a547efa7ccf54c9ec", - "0214b99cacc8963c60afa46a8ef4f104bc76889c51dbda6bb1bbf627e4c46bac4d", - "022e93ec9eb714223b65b79d0e1ce7b985c27ee6e5e43f784c8e811c81620a17f9", - "0221bf32da839b098ee319a75f97e93be916748b764270a11be14ded182b9cde46", - "02008fbf4f19c71e789ad16d25c25c05501b25aff914dbce3b535adae5e3b10781", - "0204a3bd8b0d75f0c16bb334887825bfabe69e43e9732d1166f48d2022df2bc5ca", - "0224cdad293936d91500dfc5d1de7195406dbd9d75009ad3998cf1d35708de0316", - "02041d8102e115899f2d3034d0bed2f28faf92994f486db3e9bc2800887cfecc12", - "02291da17dbb411a1194f0336e394036e991da4aeae896d0f3486edb00540b98e7", - "020407d7508026fcf2cfe32c7d47b3a84a584838845016ebe97e51a0e26d1fa771", - "021db7d3bf9a1e7df12c27bda714f9d27821526774c43bf3f200f44fd2ccae206e", - "030a6eb775722c86e5b53eede2d8229463d79bce2621b5cb199f0bc2441647d036", - "021ff08a01753c912ac19715ab05706f2266ee3ba3fb82420e49e206d88f3af470", - "02061fbab39509e95715fbe08cfa4a214cf080a157dd7d6e899f21a4ec79e0eba7", - "030540646dfb7fe3541488eb881b3abfc45d999f0d18224f4c5acec00f1a1594e3", - "030c33725d5b39e358fbfbd1f0845fe07eabdbc122f0547de3980c90f6893fa788", - "020acad3b20c75be8f63315f3dd6ec9f9cbc9fe1c65abc2be5e0e4a1929ee7808d", - "02114686402f93706d5b94d180511f32aefa03fb0c94c14531034a0adac1736e8c", - "03264fbf2ea5ee201e6a2e1a50439e3140a3878f8058365fda1c010aa3ff382bb8", - "03169a34556a68351b408d95ad9452f6ccfd42b7bedf354035f21c0da3834f34f7", - "03171e2e4dc682158a107578523713664ccd6e6b447c1703d04858085c19ab3c9f", - "0226bc9e7f386b543e9061fcdd12488eaaf95c518655393bdc6c5d264cc5cb2e51", - "0204be2ccf3d1f9b217ba7b72d10567b746c188e5ee0a3be2c7b904de631cf1111", - "020ec91a8a1ce0c5061eec650efe5932831ac8778d0cee71715284aa29961cda85", - "02175ef8096773bffb60671c710e681f8fcea0e7b1ea96165d2ec7caa0d4c9368c", - "02116ef0cfe13cba752aa0707e6b163dae477eccc98e28d5fc377ca60982be2144", - "02281526e09f8f221977becf9fb19bb4b4b2908fbfda240b12c832d2384b6b6a38", - "022e6d9ae1f74f3f92176e034f7206cd160fc35ea4c4b88b5df7bf7b8c134fd8bd", - "030c7de194919f1ed8a8ee67f92d9c24dea5394bf2a922833f80aa1bba6a94fd24", - "0322ed8d732416a70a548140c5e13ecb5824c55142c4acc2a1ffc4e406ad431b3f", - "0223ea465caaa746dde414522ec26e1127d55410d23aa51feaf1e4c0c8c29b4a76", - "022305d76abe9b4d7a8847754c3db869653f21a27390d04c817fe58f00d2308cc4", - "03060ffbed99a1ed1c88484a38edb38862e0ee7f329e2e0924136629e88fa80c14", - "021e940a54e623672b73de2e1ddd7d6b28f38de5e615b653af4f62022b9b010e3e", - "0224868eb78fbd36aefade753d16cfd8ebd622f80081c6ed2462c71a812e6fe99d", - "02161cdae9db9ded0f3fae8c755dc4f11e38d547a85881438b01da882be07d9f6e", - "020d87008748f77758664b070e5965bb3b045fb1049e15fe2f8089cee7a58b7b3c", - "02002535d86d2bc97f69d4ef12737534cb0f1ffda9599cd14f39cd93944f11869b", - "031f589cbe22af3ade180634394f3034b3ed81c2565f5abceb9b65763069f33d60", - "032d633871f7cc24c7865eeeacbae0bd02a630dd19c1d7d20c1b67e86b5f5d0e18", - "0312bf884e59e29ffd63904aa70157672d711d95b2755df94dc0d9dc98ff948b8b", - "030b0decc72f17fe891129305f9f8d5e4a3bde107adf575dac1e927be7fb68c96f", - "032b1a78ce3829658ffa89f43a96f19dca171e3d0666a95094e41fbba60601e778", - "0322068ac2958c95e229fd856560fc698dfb88fd7e2d2ce8309be4302f5d4ad5be", - "030477c117ff72a1b2287a06fb4ba46ddf55d98436f2d8f1227f017281af2cf80b", - "0229094d5639abcbc2585a00e6210235db3f8dd7c7c49f2edd1c39e0f749c969b7", - "03206043f417752dd55a2282cd135c18e02a3e5c8fa7e739711b2a0a7c26e3d16a", - "022503e54fadf69a16436a9b95f84b23ef1cf375c10eef31e88e3c189f6620fcca", - "022046cbe8ae3a27a7dfeb1a3c02117a1b40cc1d63723c9d64b639ed71f267561d", - "031d2296781942d736a3f06d859befdec67428f97f2d798b8c440257565381f162", - "0200402d73205efe7631d802f16ce8a55448846253bba6cab6876af38cdb7c3d41", - "032e936215c8f1dc6d34af8d47a5f7206c543d657586f7554937605c10b38ed416", - "02296173f9bd9b76478637f98a0010e05655216ef22c03f1b7df0c81b2812b20bb", - "021c370cc33945fc3dcf483f10edc7be61dc15000f47499522e48b2a18150df12d", - "03289ad38e41066fadced5d7c9df2757cd2db0f25c49a4fa8828302ceca90dbdda", - "0223d70f601f8e88c8dbecfc351a624a4a53c1dc3269d3fb47ef2c6d4bbc46c11e", - "032f5d07a467e9f0c44edc6966dad66d4983755b6d96ddb89fc3b96fdb790e7c41", - "0300a29550d1716d5f941e808b05c70fb4269730602f8779f042466029c7fcf0a8", - "0218fe2e58997e811693635a96de4776b4098eac226b0bb3a2c180f642c23a38b1", - "0224b0c65acb45bbc9c0e97771551e946a6a629c1a08760ab33ea4eeaac17c62fd", - "02057168cd784a6d755d5e2b4d679e9e887a58cc641da1213737f8264a2db0da64", - "032e23fd8a146b6141c29376d226b449ef33fa6e1ccd0e87148033f6f93b351f3e", - "0314f6ff79bd12afe00af460072d0892c7edc7093dabe6121c9a2980fdb22c0d49", - "021f38e6c1a5da5d0c0dfa82fa9b0e4664e75712e87d878196a93b86b4d6ba7553", - "031e036fbdcf697b6004966d03ea012b43c59b4903e2bb537e9033ab9e59dd5f3a", - "0310982da93e99145dda8bf5c5532cbe878844f46b8bebe02b2a4b3000c6b26000", - "02058c48964ce96a95f5b3ffbc9c6d83a257b30cfd0d2dd81bb229ab316f13e46d", - "03195635d9b4c11ea9f9f6324773c8020069f36c72d5a43e2ea416c168521152bb", - "021d0858990830ca9819c8c6bb91a9b9c019d60154b78bdd9e991a272c5f6be7d9", - "0217f167c637fd1e647cfcd1d4ed523bf705113f6da05a7c2fdc3f81e618921ab5", - "021ea323f7311c10a66ff87f3217d22c4ea722969b292f0e26e147add6ec616fee", - "03160fef40e63a4d1c5f563352b0684e4da0cc3ace64b8d8e7184deca4e0d6068e", - "030de5844d8ec4bf8cd74b2d7b87d7f5b14b1a3003fa0df403eda7619064a5d256", - "030c28fa33106728f2b6d217e5f740635db98b9846a29470f4dda3dff6effb9071", - "020d431ff5ba2055abd37d2f41b96e7e4cdee08814e43d84c3517b3b3ba9138825", - "0311eb69c80295d859f095758d41aed9540acc9944d1eaa396b2a0d797604b7226", - "03232e409ff815b38266ac258b5e0709bd569186e2d0466aca02f0534c4d6506dd", - "0316d8c8bb32133e7bf9c6dc14c6fb2386b01efe276aa546e145ad57a510a43da9", - "021a75a7c3c7655e4727519e4ec444aca0c55fd2b76ed189f689e3706a7b20fd1f", - "030b7ecd6a44c14cd28c13901b850cf625c450160f3fb0ac35beba1049b82abda6", - "032c41b6d5d9b25464f8764fd645d50756c8085323938ae05bdfb23b7eb60d8bac", - "0218c5213fabeaf7c2f7fa68b1a54010f5b9caeced04fde273ffaee9b7b7b1d991", - "031706e2ea3e77e30637969db09d39e0b9eaf62052e44eeb6e21d5bf49d2b6331e", - "0226e2c79af12d465641d7299dd1b39ac57f6d38601e35ee7b43c8a93a863cce4b", - "030e3220dfefa50d62a705f97d4ecbc76a1ea957064425ff90b28d0aa6d8c9cf6b", - "0230289ab37f98172d3ba63e743fd3fd970a58208baa3f270d9d7bce20ae98d2bf", - "02079223ef90e0014aa68cee3ad697db506a876e3693e0fcc74089dd92ab1428fd", - "02156afcfe6ccb7cdf1b01fb61f4ce10b182142d475b0d1771a69fc2737b252eab", - "020e984d03d6aeb0b1556ef341288e543e03e096bfebd2d68a381e66dd38ccefcf", - "03247d4513683efc17d905059e6460204cd71ecdbf803a864d560d63815190813c", - "02139793613ba14199e4a0153c8cf56fecbdd87dbfaac594aed06fbd18ee24490c", - "03220effa301bd620bf5369339a9069fbedd1676c0778dd9d81e6c3d79bb911a1d", - "031939c927cddea9423aa4701b7c31a25c3550d06429714f11bd05db1da77f0cbe", - "02281f72e38f2be5777c300498a13fca968ef25c3fb1411b8bf5db2a7866ce0387", - "0205ae09b2a862287e31f541c918e3b10e37a8573eb891b3c1a0468f1bd3880d0d", - "02224b53f310aaf4dc2a22d0de9701acb1d24c3f6ef6b56bd1021ea86717d5b7b0", - "0325f18fe4c4b600b4888bd607a06756c25da492abbaf499103554b464f78c5b8d", - "02261dc7c28e8c966e5051f7081aa13a7b3cebaaf5ab1d0c48288708be1910ac43", - "021f00cc3efa7dfc285bf34795298dbebea74e8e54a00ee32b7ddb9e86adea4dac", - "0305d111a51c2a72cbfbd1885c32822412fc08eb38f05dcea1a243f9133f991462", - "020d66d57c12abb99365b7c4fba6e4ac2ad7b0801f7de87418b95618c0a4a1a1b8", - "020063e2254b902af5535fee18b48d92ceb2df6d727b86c25a9f09c8eb59a08a8a", - "031e54296f512df88e0c9ffe6514557c443bb578aea006bb9616d0346b62af7e56", - "020246f324dc9641b84cc5e428fe22c32dc523a1580efa2298ef2e4040648ce61c", - "031987fac0b8426c0c2c06c7a94a9c03894f318714c78d0f2066d6251c75bc2a81", - "020f7f7032d1ee6d492123e731dc5c14213d9d962af672baaa6fced4052cbbaa79", - "0218c5edafa3fbe1fcbc06068c47b07b1239d93fe3c7bb615f693a2e07a99a21c5", - "02164400115e3a9e4f19c629a430890f68ace697421888741713f38ebeae400492", - "022735541dfe23fe68dd4ecb53952e6a9db162192a01ba121f737230f72cd30b29", - "021c932f62ac9ed48fe063231fc362ea77cace591382fc4b3bcb1fdbffc91d4ed7", - "0312f3fa63becc9f561efc99367251fe48c19a63c4dd78ef578c07d4f088b8ae57", - "0214ee43c18c31d0542323d58ce23b916b269c8d0a4147da56da23b60250cd1da3", - "02058bf64bc21a9533b36edc1caf8d46180924178b4e2d3ac392770e618411c368", - "030a35ea9a55663d21d02d3112c4c5097432258434c7160fa270688e52a1459def", - "032edadc862d1baf8aef938e946c685cb2c5760da2feb90fb0db99f4c4dc37ddee", - "021b22983e5975dd9b9439935da0b24c53dfffbe18f6f380d804dde28efed53b3d", - "0310e6403c19eea1585c8a2d87dfe6236e754f185fb22a06db19621523179cfeca", - "020b61e14a2329c6e60ca9e6e8812a497544a1aab6643167bbd827bfe73442fa46", - "0224ec89b207b62ceea87d633027b80c395ea5772ac44f2d2c23137aff704db1e1", - "02302fcc7da527df42fa7055096bd0d865726a1d9e88dbd47b4de862437dfdd963", - "0321cbec0eb94a6117ac6b8136d2e51f21b805f8d84fe109bce14b33a4d0aa4750", - "0224dc0c1dd9a6d23ead93c44d5b55511358e9052d64726367461ce9997038669a", - "030465f372d818dfc32df69a965391e7ba6214f7ee588a459872b8edcd59332971", - "031fbaae747105e3a17d491e4a5acc7f0dec30ecd1a433fc1da10c89ecf4fa79f3", - "0228602979635a326e4a63c83d50554d96d0582a3dc67c2faf2821617b646a19df", - "0225ef69f5d67fa09cd4e3f3ee809e50d0f4da9dafebdd24f36dbee06d2829693c", - "0318ec55723152233b48abbc805067618cc326996961ee7eb8a6bdac1f1db2138f", - "031ceb5298f66bcfb6b5ca4e079a8e646e5c11e260ecfe88493349ccdca0aa9c26", - "02207cc9340a308a22b9cdd6f3ae19d59a4e9bb54c13e87105e7126784461aed7d", - "030eb9799e6b8670657ce49ceb0fad4eece147b550a8f6031badc1f3ea86951500", - "0223f3727a21eb15e67a477d2615334bd991d46feeb8294b9cdbbc5234ab3ac784", - "020495f4688372883987dcf7ba4f8bfb991d244250b39e96b08b6c8e3efaea2c62", - "032aaee0cc3fc0ccdd16f7e875f2886861399ecdcd1fd111163230fa7f443a186b", - "020f29bce300bab39555f1373a886a8a10db176a9b9161b28fa8542b36c7ba1952", - "0210fcadad993106f8df2e00dcfd084922052d2d164e6c8b305aee690f161738cb", - "021220ade36520de7f17d7cddbbb9188f5248e4000f6651637d024df2818feb774", - "023009d428708e6f7ddeca38c5928dddccb4ead5172d5d2151a44633e003d072c8", - "0210468c37affa352712732e1759d3bb38352f6c98e6ade0c23f78f48e305e7c94", - "020d713133a60a0cb0a49d2838f0b0d34cec11d5ff944145fde2fd37c4138e88c5", - "0200d37d368acc5668c352972a95c404af24b2626ebbdccaf73afb0ec84e5c9f7d", - "020c33e78aec2ea993424733c60c53bea7d40974c62f699a8487bec6acb47a12dc", - "030c260191431125b4fe9086887917fd0a337c14ef22485c6e12703c25a107d329", - "021bfcebabf68e77f440cb9d5db4f36f0911a9821a1dd17eccce7abd66965a5150", - "0326352435967ac0ab20c45f83287f832f4f2b64935aae6e38f113e6606f347e3c", - "020a7438074c820dca382b36391bd01cfb9c3da598c3bc1a7a960147404b10ee2c", - "0205e6f551d575be9d6a0594968e741aa3562fa4c05674f43df0eadff3691c6d5b", - "030a4b123b92493d37e7a85bef312aacf7014c5396e819360ad6034756fd3cac9e", - "032e0b0a5bcc13e85dc851e2dd0001e0de04c17b0ec1eaa0cd15d34f2f099cb660", - "0303a19dd3d2dc362e8c449fec5b55fcfb050e54258aae024f413ff59e35ca02ae", - "02032d58f9db45ebee69688dd94a5050bd6e9546c0bfc5030210fac078b4106df0", - "020f6691ef5bbef924ac44e65efe2cdcced805a1b101085027f60af1c4c07de55a", - "021e691a01245a989b4ceaaeede55b3e506004d512333cd3983473157b3bf25917", - "031ea7489652025dfc5e0e3737036976e9c46434a1563074e85fe49c445fa11d16", - "0320d4d5389bda41e8b7bfee724f7031a1bbba3e9cf5dc50ed6aaa323706ead370", - "020c782d30f58826f6dd09805b47e060378c59717611688a38be0887fe6a47027c", - "020c6ad5f1c662398ee6ca372805545c406e12fde1a99a9849361e28acb5354b7a", - "021317ed0df591717868924cb751f3f50f756cb4ec370a2d2bb2efdbe56478c4d3", - "032f4207390638880fe56e0baca11c91c1d6de9d158d913dac237eb0d0947c46eb", - "0321ccd2e16989ea5e31c7c999840fa8b7b9d950512f35b5ddb87e57079115be7c", - "02018d268b24f0d67fe68ef6d64af5b682ea9e27abe093b9c917f8b9347123814c", - "021f5270eef162f65b6c368dd83299bf1bbcf9b33baaf19f19fad4732d4dc91991", - "021cf8f5280050988466af01226b4c6154934988bd9e070f09d6267671e036d29b", - "02251b80d428d6ea5b8c27dd2572f4f04b64b256088360cd62515bd659ef6d488c", - "02268c1d1cf627f1f71ef9a6f264d60c668ad629f987d3527fea245570e9201e8b", - "030da25fcbf37e670db336639c1021b99978146a07622bcebd800e2c6ad11d0a65", - "02048b3d3c6601e2160314be7ff9ec5429a492e5c88d47e5b44ac2f4571204dfba", - "032c8ad032ba43302e3cd702534019b53db83cf19222c754aa2f16e1db027081f7", - "032cf1894cdd650823079f47ce3051b084843580e4bb7586d064ad070524a3f45e", - "0321dd6e63c7149c2c8e91cdaf9fb5b26747c2b8662c922dcd4ea9f09e94324c27", - "021beda45a135a2c98f67c54bfb0d8d2de54d3fb01d6a0a0dd92faa7dc13377a36", - "0203ed84c8771deba9d46f691d0dd204acca220df7d5b21f061c0137a69abb76a4", - "032f6bf41c50e4eddd90c404c957531403f444fdf4a5b658001547336521c3cf6e", - "022b26978e86c6761cee1afdcbe98afd674f61ff631b14ec4841f34e40fb4b2b94", - "022fada13454f750b958d92f2068809ae801af575868b5e5d39e63fdcc8bcb00ad", - "020a7c7eebcdec5e440ff90a66864c7c1f348b37088548071cc4bbfcedc74753bc", - "0221e7ffb5f91098599b9480d3ac635d8fc56c692a611f575a397caff3c764fa8e", - "033056a6e1a56b99f3e25f35b3d2a563ea6380e8bc13fa7d86a95e0743bb67d7b7", - "0217259e4331444248945e1922fd26662376af35a5ae9a9872af2906ed78c8382f", - "0307794ced184fce6987e0a37bcaafcaab190fd40d36a173597fb5dd9cc8c16ba1", - "0313a024e366a027e2c77fbdcd310e0ba6b5d5d93f902acb2830070ed9d1d123ce", - "032d7a1b76df0cff0b2a88f17aede6aaff8b6a35a238670d3f68428b8ed4a69ddf", - "0325a2c7aebfd73254396266a468d26c220e2c4abec9b8bf8caa515a745694245a", - "02176ba6d537b6ef27eb975b43027ac8b30f9ecfcab4cbc8b22f1bfe9877653b96", - "0312dc12eb78f2669b46c61df80710639544ce1d7a629be76e8c367c0d060f5197", - "030342dff72cbfe4c719e40afa07ce3889295f0b936a9a297ac2e35110e0191501", - "020e6fb262d5043ff3acbd319cb10b14349fb7626072fa2dc0fc5c223d163cac99", - "031edcf7deb8f13e7d4a5bf78662c3c9fa3235216ed4013b7494d03add7e4ea139", - "032dda77de8c9b2211a907ed3ce03f37c856eb9a4ebf6b6501eadce35a4b4f65b3", - "0225443f6ca4064289e512493dc57bd7feca8657d66fc24151cbd6e0d603f300d1", - "030f40f34ac4238155ee5846358954b46cc748b7dedcd75ee0e42025197f9bccd6", - "03192770f37db21763a81f77c4cfe2a51036d54828ffae3ee904e1ac63ee8d9ee6", - "0226b57f3c60a4d2b45167e7a398bf241cb43aea8144ca1550027321416de7c0f4", - "031b9732229d03c436780d2033840e976702d0488d1cd1d744cb847ace10c5e6b0", - "022e696c6f2ba96c6494d2dd48e95ab229b134640d4a1eb222f04999b0f81ece74", - "022a542589d2e88b0b1d2ed596d38931a524a64753e3d2932cfa4cbcb8d789117c", - "03269a1d159c58e569f52ee3360c4c26158c7748f92d7654ea552e695a33110c1a", - "031c0195afde69eef540ded8959098ff424f0ef2ae3f7d29705ebdbc8433114810", - "0310066e6bd1e9a2191f49ccd61a308e61440bdf41b75469fb2661006959781790", - "0304160cbdafa061df55d0c450b6b5e4b198a92f67c30a3d1105493f0c1b5cbc21", - "0301e7b4146c3cf3e030cc2825657b85a3141226f3a89e3f279ca305a6bf76a2a1", - "022856d2239513e6ecab436ceb89947fdf04ee036016e0643d74d0b76b5deb9ae5", - "0214dacc4a171a5b72097a20053fa02bb634895de67a9f122629dfe8f23b250adb", - "0217c47bba5f802e860647a5bcc31b336ccce5a13886624d14a053175b5ec4657e", - "0303d827c44e58489d37ed2e25a9e12e8d68e2b7607aaa3fd74d7a6ce1b4b5a0b1", - "0211b3b27419d9f6a4e452c6ffe6fe9698799d78cdb872af18c6e775115de35c5c", - "021047a35356f4d661a6c8431db249f5a1918d082827e7b23270ae1c3d936ad4f2", - "032cab34f4240d7e8383057bdad8d6d737268308dc5b7b55679768c6b6e98a4d5f", - "022d6f167c5818c1e122d25bb532733c7b12899ab7ac9397e9bc0361aeeecbdec0", - "020c9891bd0226faf65c8bce6a6cc82cc7199a77fb61613a0f0a8fcbe8aa99f458", - "021d3b62a83d40db6872b9294a788ddb0b2db764b37796007588a737af20092131", - "0314ffa2a84498877875bfa1e99a71630d1608eb629f535d4284c2be671dd91a8e", - "030f67fab05ad34ee25fa763c5d577bb341e1607a4d9d8a06b4ae4ade5f3aa8a28", - "031c43260712c8dff0f174f340debe6b01a4752f6719e063ba8870c5f6fc8bace1", - "030f08c19a9118434ef6be4bcd9b3ce89cea26f623ddc43eefce93c36495f10ba4", - "022083249158f6496cec53e076da3ad0fed7e4a8354db4e6d0a6089beb2b5125d1", - "021271ff30bffff90179c97ffcc1825233e10dc6b39e92e97c29ce736a3c2776fa", - "022ffe3b073635e0e6fec8950746621b90a7d00c920499e5a12ea9c8e9782772e5", - "021b3e06e390532a79a44248ac9ac70cbff4e7a3bf0ebc87eb78f9e2dfa5341101", - "020e31119062f5bba287aaeb3947b1947e2353c60c09a4198346a32dea4b300cdd", - "021005a6355219a801064a500d8ac7f71b35108d09b69b71cbc242f205f2b56674", - "032f6ca0c822f7bb7eb169de3d6aecd07a3328dee4f2fab171f12b83d39a0f109a", - "02031377b76b90ca987b081aa53a277401060368501aeafdecaaea9ca33ff036c6", - "020e0aff658b7279642c6c561b0d510fd31233f7e542d1b0eaff31afade0d575a6", - "02057fc9ce726b091d445ce6c006d3daf140f5313c860897de9b4eec02350602d2", - "030d785f0803a7507dbf4117a4fc780a822f857432d30e7cdd68323ae514d2abcc", - "020c3c0f3fbb2b95a319b7aba6508dae1700fe5c78e0304f150676565f3324844a", - "02082c55f5b4e2667ae562cea792d4d9489253976b1bdcb2c952ac7035123173ae", - "032e82c6e99593186fe94aa69f914f3466050a77b2ddc8ce989c5c6d4b41b3947a", - "032950c1c03ca98c3839a960f2602147ee96dabe730f1417420a8a31f45aed2f63", - "021f252840090621585dab778832c6e16ee826f4604ba69fd356085271eb7dc72c", - "0316a034bb9f48cca2c3a91ce6bcd0243076f8acac03026066718060fc10fde84c", - "022861e844e3af201136566c8a23e0d7f86a220bfc7edcca32974de88491a0d3f8", - "022a36b7106a5b6013e131dc05cce52811a72c5fe5ec99786f73f68ce21c1e004e", - "020c0b56c00b00d5e2348cc5f61c1992bf430514b671767227a47d778b30f9ddff", - "0310c0a0971bb286d1dc7d9f9fb2bbfed7cf144f6b25c907a35e7ee7b73b2b2bb4", - "021107ba5961e174c20fdc28d34fab54cd2ed4a1c5500545bfabc67abd06eb6024", - "032bb3544f37620ceb3a73d11e9c135f791cc6733d229b5c9be242ae715528fca5", - "03070939b6346419d05f461895f9d24d64356866e213db1c07855397bfd4188034", - "0212d5851e45d761350fae377a942474a806d14987fc57aaf08f8e4d5e627e8f6e", - "02277c46281d8d2d7656aa9f16369b057c95bba1a7ac0b1971977796122eec058d", - "0220bef333e442bc035bb5f1cfb059f2388e99c63e30809257e0cba31b66e34022", - "032f53f707f6d2e19fcf91f2a201ddc276568aeefe64ee16bd679573c677c9e5c7", - "02077aee0fa4124f5ed5ad17e93a117ee1885463b6e01a62a826d9d92f2f0f0fa5", - "032bd5cf4be241d8c02bb0282d3b0f7cf45ccf57f527d7258ba77f1bec6e1216cc", - "0327448ddd3ba88dbb2cd0a23c2f2be2a244c4eacc16581c5db5196e428a82b5ce", - "022d94b33cc190b383aca0aabb6612d518e7149cd7e6c6fd925c440b6085910e55", - "032d69b58ce89bf90e556cdfc114fd61ac5053129730c5100f35159b791d033fdf", - "0222fb23543dfbbb11db1177f8e1ad866609cd9fea5d2754b0b047951711c770b0", - "030f08bcf40fee2d93fed648380814d47074c5d93bd53a1fa45289571b539127c8", - "0300a41496e27ff0491a89ce323ad54d94c1a97bda616e484b7e5100d0cd14ad6e", - "020a152175fb86be8b4f9b34f22e8e54a7b5d57a98c5bda77b36b0a5494ea358d3", - "032f1b5331f70ebc7d60774495b61b1cc92f6531af38b17fd17c4f5dfe1fb55059", - "0310058fc9ef592a50c996fbda27211d31698a826a2047bd172b0466c547910f22", - "031541e3d515c3bdc615f8d0c8e406f2420e1548d20e8a7e126ef8f919eca50381", - "020c278676a659dde726dd853e908889a335a5ec44f56b2dd01635a3ce8e223a4a", - "0213955b1f6ab0dbe54ae4a4965e67b93ef47c3de50d08e7542ea4f796bae4f8b3", - "031d3160fc03fed14c4a6df23b3b072a8ceb54548502db9e3ea561bd93837ac0a4", - "02247661118c6868aa11effdce9ab359141b39b3abd47986a45c3826671b8e5ffe", - "032e897b249f166be783064341e7590b30af2c62668d27122bbad3fca479ff65b6", - "020667fb937a906144b97373a61ff85f8400a952dc9676a111b073c9114ca343fd", - "0201bdf2b9bb451ee5054757712edb8f819ff87a5458f0e4b5aae862b4fb32acc2", - "022339efc5fb353678f98bfe080cd05fdec97205238a66903841014617f110272f", - "0220226524f118353b698b8fc93b2f5b63437ff00bb06e386e2dc9b3a57ef4ddf1", - "0204530787e0913ee7ade4c53c66d76017e25323645d72e712f5c7ba854c407868", - "031e70c3544e38fd4a441426d8ecab515735ca18a045cecbc32f57b92a34df4fc3", - "03218fe2aac0c78217eadd4064e890d6540d9e257424fdaab69d4896e925416d31", - "0206a758f7eeeeedfba2c84accb3cd545c82447ab3d96dd209e144956ce060d440", - "0319899b81c41f82163884b106c8c4bbd6bc384d2448eb2d47bced5caf40b9ca9f", - "03161ff6c96248be9d140bd898d72cc3fb17252a3c487a416a9a00900e6b034d11", - "021720112f1a564ba97534c4b3560b4b32b8f6a0af4d736ece2907d5451bc55f15", - "021c66d60ee986eb15002728d481ed6f6132ef3f38e2126ff732876c968d6b39c9", - "0210bbb5d2374d8f1c5a58af41874430c8b131445bc7f15183bcf95247712ff16a", - "0201bd5faea4a39ef34be749533890bcfd5f986a5333791342e8938a37d6dfd941", - "021afbf8a3b25d0eaaf3010cd16d794a1cbac8395b81e831fd9a671a62dedf5e06", - "0308b074b8db7f9b62b6c9c15c5e1055d7eade499c0721ddc946abf0c5f26bdc5c", - "0301eb8ebda69aad3607e1c37c7205e50ab1bdb8f4ccb7b29141303158165201eb", - "03244f04a83710667ca921ca35af1fd53689482114cb0dde5aa23a43ed901b7f5f", - "022176204833bc7b3b6864457018928d466cad60292e6e3c245882e429144b6611", - "0214fdda1374319a56904c98851b6814a03f6cf570284de3448adab2fd4ed806a8", - "0220d68be4812f754ef2282f7842eaed215f84e0131d35ee2c02ad937e220f4a1f", - "030faf8f0163b30e6e143572af8e5d2437f9d9deb29d583bea853e6a8ae9338cda", - "02266003ffc8fd614a113454f07091b50bb0c8466346d9f337993c16e45bfd18f4", - "020261ac5a17632fcd3fc1c49cdf88ce07d74418bbb1fc125ae148bacdc24d38b9", - "0218c0b3e1065ee3149593eb71321322cbf19b17981f0505364101fa35b6a3ae9a", - "031f04e3217b0487cbf96a17769cdac5c370d726521f882f8bfecbbd82019db714", - "030f3db918c24da59b845bebef03c7ced27636af4108703b1f2287d1a13f147bb5", - "03049c94fc96ac580ed2bec73795b51de465822a565f4576de585b3cfe43cf0991", - "02196726136a6ba8615a66581a7eb63089c6b3434bc3a8fb2fa70204279fdb229c", - "030df3bab4ee5dc89c4e924920522163cd67d5ad745eeb4eb0a1e231e1263d5319", - "0201f82af729862d65f584ab13217d12d6304b168629b50ffd1f357fd86d32fa2d", - "02281afc2f77b91c44efb0dc601bf4b59ac9cc5940297466ac3a9d32c271fb7af2", - "0211f0f03ea344781d7de19d5f304e9a7edf921263b06dbbdb2e90aff2411dbbec", - "031ae27bfd01282d29be8c4e1942c936147bf63b23162db7d46dc89df524b0cd06", - "021aea7ce2d01054f1b32d79c921701e6f49a242945edc69fe7cf5aaf825cbc914", - "021531e32cfb15be78c52e7659a8ea9e7e923cf64e6d1e6348f118e693c752fa52", - "031512f13236a7bfd0d6e06de5d45587eba855d8e84898a01f0558af768b8f1186", - "021cebc6a9ac2f2432dcd56e54be72244371081bbc985a073e1c5e13fe807a10ac", - "020674d137337ef9126331ea8dfd2b0092583175aa878ab068ccfdc5f1580c7f23", - "022ae456949c223b34253a5cc0cf474aee2a1d380f86e4ff831a815f83285049c6", - "0212b18567271daafc906c71c562144ba0f235388c0cf56a172a260e9a16490654", - "030e1902860cd551851d6fd015d655a26035bff25ae8895962aa813eadec229a92", - "022d093aa9c49221b76073ab9b0697858b154ac02e9f06d2039f5d2bad8ae85d1f", - "0223e03ff159e608e4fe25e7303a41dc2bfa5672079d6acba3e694c20e567540ca", - "032fd71171f6a462408f5269ff67c752c71dfa8c441583f50c6f5296d29c834838", - "030f7c53748802294f1fef1840b95c514e48800a27b6df49cc0a7c1d13c36cc2d3", - "031d09196be522086e36ab79642b4a3f79f20357dec366df3398c78ee2ffb28766", - "020ea7bfcc274c40ee71a61a80e70e3f8b1f80496f691db0fae6f28d863d81c9e8", - "03091cee200bbb172b5350c7a14f1e808b542f222045781aef1a5580ca3d8d1ff7", - "0206d94d7c7b284479762221a1c76e28347d98597b37000f3cec8a6349924fcc4d", - "030b5d8730995fed81d3cc0aafcaac2bb35f07d35f32dada725c4d311cfc8a543c", - "02019c4cfcbd56287f115b51096bcc2e9ebcdd58021df6e21b4a1a8945ac675fea", - "020ec4c36ac7bab7eba7880d0cefc3c019c9184cfcf67e3d567c441bcb757f67cf", - "0314fa23a9141a3431adbc96f81ccdaa4f5059e7953ece44db22177a1354b3b8cd", - "031d29e64f0e7efed9af2c21acf53c715194fac3fb738b90e1c3a50809caf63f13", - "031987b7c2a6a86812b174fd612bb3be1e38f91fcfdbb9b953fb27703ccd01f29a", - "021a336785f67b8a97fd052907b8628d3c12dd29854706e778a9fa2dfad6dee24d", - "03089fb13c82ea08ccf167614022b25079bb040806e61471e4f7a1a0caa75dddb5", - "0324276128eaa37a62c34c0a0a10e805c4140cbaeac4d7d2929d622350eca335c3", - "020e6b66017d7b15b91d2d437fe459defde95dd94c3a667c0df544469cd6e06c24", - "0314d1e42baaf8f65bc75bee8a21c8b3e6412244bbdf3276469295a24f94f48b7d", - "0302ad5c333a726018da0f8744628a4ade04dc7674816432039a12288c619c92d4", - "022315644f643cef5c4bfa6e8a3052bc76c8a11025cc54ec6a6ae86a8991278af9", - "0326acdb1308412f29f655becd6a8fae9e4c8fe6174ff758c08d92c1201a22b79e", - "021e3e75817de9ef75d438df841bae56027143c13d2228ad3aff93f25c51939d2b", - "021b70b7a227f0d7b8c8ce435ef9b427cf2a494c951daddde4255b0c44c1ddf5e0", - "030beca06658fe58ecfa0ca7ac9d0d5cb4262b0641f5519d1bcd16562d6c7cf03c", - "02055b1fb83d29bfd3991dfca22f779f899eee2ee6fe6ee44a4bd29bdd5a6eceab", - "022ff0c3b893535d0f764ef0ebc901b5bbd6231de2f59b40914f571e879a05027c", - "021006176afb6893988e73a77ba30a6997131e71e45d4648ddd1c85b62e01c7d2a", - "022feb754addee89002bcc2e959267835c56c551a7d24d603840ced63d7d656516", - "032e98ecb0d4f6043008b7c866b123c0f3eead5a3b7457229301301ec27c96da7f", - "021940061285e6e1146d74ded75c35e662e59d0dd7470c28219da9f1fa9f109a0c", - "0214bebe306c9392b33a25fcbf627a6fd2262479b397fad39da23e170941a58d1b", - "0303d21bc10f9a193c431ae35b965510ccf83178f109e19c3077bc1fa02877fa91", - "0300b89440599c52463b3c75cd54439d6da68adc6dd984594c006f55ac8c2cdef3", - "021909a5cfe33d229c7b4716693d02fc0f65651e653ef087d11f806a182bc1418c", - "030830cfd738ba3450deb18618d46bbb6b3c88585a4d61fc2048ca56a9e284713b", - "022670a7102b253d94b78708a0e2abc19b077ccb85403a5316f0fd1da2052c9a6e", - "021affba5b00f536c663c053129e1aee8252945e4b44e63a5784aeeeb0e1050b26", - "0217b602ab227ac6f1c2c3ed76995fb4635a0a0882e457a5ecc399d74cd3d78000", - "03240df80c4f997999b064c8886d78967c9ac199c409cd5bb31624d3960a652730", - "03248aa85a285e862a2ce51bfb501e1666b91995d1352371a10549c1bb2e0c1d49", - "0307704be65f02407c003871c7807823217eda1e874c22c58541f88e6ce4c1d33d", - "0302878ed1d017a9d370dba6b81513239e8d6c7b00a3b0bbf419299abea582d3c8", - "0204955cce8c7e6732b7e86e1f04482909d8bb16b47c62a13bddd1e8ceea84b18e", - "030ce5e68e8eb81fb52bd468cc60eaf6067d35bb55484f76da2dfc4092cc0ce625", - "021275e1f9cb6efc5f91c4b05bfc60006bd5796266c53e1b92f67a79edbcbb4f13", - "030e0c7a494d4a5c22bce68c789184e42e81f0b6fc551f7037ef80e8c33db61cf2", - "0206449107142509acae1bef988569badfb3b684987f31e7525ce1a6558bb36606", - "02239f65b12f60ca7a7caca46b18346cadf8edccf630547cac3cd761f7d0901ade", - "031938aa0c7dfdf5a27575b0e9452a681be32e858064a1ecadda4d9339042da56d", - "030077f0628afaaefc084c393f9854a87e5ec2b326898be52db169606b6cd5de25", - "0307dabf1d92c889208c80172e6a8184f8963166e2ca05800db83bce9f67102b24", - "02201bbba22a115523e88c41bfa63dac7182b5a889c6dad4c3551c055db54df3be", - "02091a876cc0aa381a8086f177556dc03d3e63b355989883c1a080c179b96db902", - "030b614ec17f825bd16463213ae53487fd33db14186149b0a95ce1eaab78bcd659", - "022ebc845a9134d757c2de15d60a7eb5d2a4ff6787494eaf38984b89f753738b20", - "022f16a801194c9a9d41588ef734527ba58a321734711f0bb3bde92737e9d2f5e2", - "032b4ac94e2084492df041548a2d4e1282c786b2268d9fbf91097cc3b352abca2b", - "0312e8b00dff1463a5f48fa27c5ca130c8ad2bda386d3d633c001b27076e8ad4e4", - "03165d407a075234e98fc75f0b499e175b36a1f1fe4a7dca1f22fd8a78d8dcb030", - "02291e425dc22e3c0b41d03f29947a2c06325ae530d5d2b2a6d8526a9fad9169cc", - "030257c187579ca1223ad710ccf86214d918f24da58c6bf77c461a48396476ac4a", - "022f29b644dd17d3672c4d765da96e1186f18156ba51515e85e3748bd872f14c61", - "032674a6d4336e826bc3ccd2bc16de0ea86e83ca9ab25353e6c30eb547658f4d69", - "032407625662340a6b19435d66600296fd5f2ed56e1899d562275c769e622b183c", - "0211d7fd5181cf88726c8da0bf303b8e81ae6bd658db0850ec1815354f92157c33", - "032fee5d778c4ebc0ab50a8415858e1743a216151fafa2df147e18b83f719fa2d9", - "03006a07e4a13b318282cb13a3171ebebc7d6007451f27737d98a7fd80a1f29afa", - "0210e7be6ff22538a58ad19fc3256c6a060461cfcd8991a3aecf7fb650e6dfc030", - "0324480ecbbbca43f0fc8ba334af1e309677999eb0159e68ba7112206c6aad926f", - "0320880315a62eee31f9fdd83bc0c7c8c3a16451bdbd1d7edeef61998409fa0fb1", - "031e3e799f530bf423678f6f7a15c1ec300e9e71b74f1b2fb1cc2a1b48fb3a06de", - "020cba6d37a8109b3d52d3dc7fcfc9629acf0c8dbebbec0a0c34570c523deb1d5b", - "020a0411834dba1998dc0a0305984442ba270bf7ada06fa1daf6dddeaa1b547874", - "0314b69cc8d0905f1807c18bdedc6da26d6d37610c1704a03c53435c9fa53551d7", - "0222546636518ac097348e0046e597855a97d74e7ee8b92b0af91b5a84aa81e13f", - "0315c328181cd46f8252bb830f476e5508227f812663b28f945b2087e85e899809", - "032b8bf227ba1a446e8d06b60e9038703bf6490d66f1a3ebd1d10b35a3a9ca497f", - "0200d8d85787929d70315444b58565352fb4b1bba80ae01ae74712809167172f0b", - "031b3e18dfb0590445be56450d965c56c9031bbe2e31dc2c16f14c62bef22dbcf5", - "022aee191eb352b614d28a82c596fdfebd2bc60d71fd10d060164089235874ab01", - "0304cec6866a04c3850316383148083955d700304f6e89c33feb22ca0d312b4ab0", - "0304de238574e38e1905187db905fca98aed202992c4ba261b08c2741255d2e996", - "02289d7ea1469d9b6f6439c5195cc7c9213d6badb71243fa53680a19b8718dc83e", - "030f23954aba978eabe6da7df3cc504ac06c0e12a33dbb9d13e444aedf501fe5d8", - "0202a4bf57e1818ebca9df0917ff44cbad163bf346e85c15242c851c39d3e0bd45", - "030a0ab05ab655825c601611eeedb86938a1b299e11a4af8d66773b8d677a79d97", - "032b46682a4b397834439b6c8eca6484d33fc3edc499aa82463419b5a9b449fc58", - "0329a3b883afa046802f3d6b1e5f5cdf3348c957a55190a629eab7408e33b35877", - "03016bea227069cfd3ae7419d66ac2ef7f8078958f57918a6c3b41833de572df06", - "021163dac97e148945828cf9e63dff5c4bbc368829c82299b51bdc034a0e434099", - "021d7030c4be58e6f5eb73c749a32ffd83387951f0b8ed74efdc25239eee7bcf6f", - "031565289b3080107eabe64b5fa7b68c2971b332e0dc7cf4accc6996005f050a60", - "032ba5594fbfb69a0e4b6da17bdf725b63a34f39e3ef853bb3de5bd333fe4574f1", - "0328e1b014e2eca43ed873822da227c20e3c5c1132d77f2329ae7cc357a580ea9d", - "0214bea09a9a4e324a80b2ec53012fc43ea8dfdec7794b9e8b1c2d6cfe52468268", - "02261f1267e9cf548fbc64bd5726e58fef9a9e1460b87d39ef551d40a73ada1f83", - "032b595a1c614f78d6552cb277c46f2fb475d093a4e62684a69f44fa39075839c1", - "0227843e16b0d682f6165ef61e02c0f237edb40d3f189e6b6cdb0ddda54b5ac8fd", - "0216e3509bb6049eaecbe0e6cd3d04cabc620da0abfc958d2758d46137c8f1d579", - "022c0293454c85a4876520ff58bf823267d9dce72df031da5dd91b4a63f5e6c408", - "0329917e8795e4b1b6aee5b5d801fcc0354dff4a5f02691276a8445ce93ffe11f3", - "03202466ca55bbf247929fe7d7b179142713247ccf9938d240dbaa4481c9844fe6", - "021304d06cce189759791fabade322ca24a0ce8fa7ba7a20e8866fa036d27cfc61", - "022ae545b1a8509219c65d6848823183c0a96d843db5bdd94b8e34739c298ac6e6", - "032bdcd390563c975fb7ac885356f94b5ac8daf0d3f6849a66026755e2b6b76730", - "021c2ad432b4edba5f4e542a0632dc58d58816c3bee35c4ae046f85621d3758278", - "032f21042abd025678a6064e229adcd8490e86187b0199c4bad0f249760de0f105", - "032d291fb00d517691f2efca31b2313148bda10a189079bb62f4ed8f9a962da5aa", - "022a52ecba1542578da54c363e49411bc4ab5d640fce855863b369cbfdff6308c3", - "03128fbcac0bd86998da1afb909fd4dad04ad8067d029dbb8a35d0e60f87aab872", - "030239e67cff3677d988e69dd507e038bb158b5b52563a4779acaf3f840d8d1719", - "032ec0fcae4a39962b6c9cfe1deb2513f4df9590c42cd40aea8f5d89300a1952d6", - "020e30fa0b3a3cc6f353e1f5dc667d753fa5c31e292781696bc077d9fe9b1f2814", - "030b6214e348ef6600ee94a53b39f5511f51bab9677890fc94e2ffdf34c5086310", - "032cc1761ea57f0eacc94818aa59f7dcac78180e3e185cd1a920a27474bf65ef8a", - "0210b1c772ebfe3b30d252cb75096cf08ee83ae0260ef8b903df481f78e41974ff", - "030e52f64ac3bf866d5706de8843299586ed8a44e3bcb4c5488665e5c374869057", - "03276f3f626781e075f8047644a2b6981ebc58068436a3a82e016ce314f7ff7529", - "02093b4026170451699860e39bed882d091539fae132d11d606d6ed4783b98cee7", - "021e761240dc26c94214bfa1a5ea06c8bddc5067768a9ff7f54d04a252c82d10d3", - "032e5278543b5a54c4ed444b663a94c053f0b42467b2cdbb8c05edf33e4b168e82", - "0200fda9a93be38d4150112cd1b839b12906878a54b9ee7bf766ae9a7db2d4bd78", - "032d6df9140226a64721f0e9a186d23b3e0d89759777f48f0ec4353a5a37255322", - "0327168c329ebda74e3c528226813ce05cc0c7c267e6be8ee2f4c742694d0f16bc", - "0205421c3798cc67163e5191d68cdf2f111d75d5657aa2dd8d84f522fe6e102dca", - "031c331dc5fde72cc2db5176dcfb05bb26ec3c07489efd33553c3c0c591a47967e", - "0209f34a5fb076a036792ae5fd2b4e34d409f5d1f1dcb4b5e84374b338d5661ee6", - "03094f943f2b0941887a90de5c41553d888c79cdbbe31f8881813459dda2630a50", - "0215b934ac37e03a51671c1d182c746874cab611095f51ecf5732b424ddde93e14", - "0324d6f21ce94f7c2a7493ea6667f55d0a7c7640197cc7c7e2ac85ef6ca0c6ecfd", - "021873f12cb24f2d01c3b8870168e815d4b5606a8f3b55a3c57aa327c07456c40d", - "021a1f0d9c4232509d969dbce6a4283a332b043b6f6762a2435ea14eca095e4e67", - "022059498589d9debfb113cbb5c15165bbf405001a491df6f45e00f0e3782497c5", - "031e9e7fd2e9766e52397aba186f9ee60d7aa736b00b052d23c4d8f64060d7c7ec", - "022efc2e5e244dc0fa243458448689a02eeabacb6bf8ad01f7fd8608d7236fcfc6", - "022ec9957c6a096afbafbefb72920017842d207d04cf882bcedc019a7b703dfb98", - "032c5e9e0744697e960cf62b0cd3c48b963eac56f19021b55e16df455b7ad5fe88", - "03051bd631bc57103ed54d1226b0cafd86f9370d4a021914a1ec2904af5fddaf89", - "0325d8d3d032b1d2874a2417662e2acbe2f67f32112a1796260eecd0f862f984b0", - "021bcba0b223279a651644a690c0fbdeaeff41450ad6113c97e5032830302bc0f4", - "0229c3bcf6122c1ae2d768e0caca7201543c861f15ca670de29973d4c2e92f97cd", - "0317fe1bc072cc42c84142767bf1af052bc8e9d13b18c4002374cc4fd656072748", - "032294910283665005ac0ce44b7ef67ec3b547ad98cce36e97dd95573a989af6ec", - "030b52a06d5dc0551bec418d5bf56e548dedb7f732aee5c3e80f89785b4c550f22", - "022fc862dc0f1c9a6e4415c01a5df49b0176157ab6708e250b7d1746f7292d66a4", - "031438c6cd9abb1554aa0199fd537a2816b0986c298e487117a85a161546539f86", - "0320e497a9ac189d908bdd1280808da9be646bd1496e91c42cba582709001e8980", - "0211da42ae66a78525b83b18d2794c16d6cf3a79f91587623651fd971e47ccd435", - "032da22963f852c79eeb00b56357f128154db8acdb95881b6af17d047c05958209", - "031968f5ec849e51d2177fadbeed59fae0e271fb5748d18951104d144428c5e782", - "020c68fe3896bd05a08c395d079124ac7b25354183220163f6a07aaa3b850a29da", - "021f9c37e3d66579c63e247f3dc53c52a05e81be75ca1b3f0aff1336472a6f55bc", - "020c91e6c618999bf31479bcdde71f94582129cf196aa85b469dac02593dad4db1", - "031239a6f365f1cded0c3b2853998eba7d52d215bf030b5a86f5bf326596fcad8f", - "022cb916592c935989cdbf8ba5a3e9374f129e9182748fb697e94d4916af507db3", - "03216965bf279197bbc9e334a08d3bf0b963989117e77d8de2c4f4fc71b3beef49", - "032921295cde096776035d056d61fa0c59092f7ec629151eacc4b036d1709ba970", - "03198d6a40e78951c0974d1a61e85f1c35e6f852bcc27c8466c323ec55d09e3276", - "032ebc4a9e3e65f2bc8fa0f21a185b87fa0a0ffbf5a633e160aad4fa937f3963c3", - "030abe3d6f50e6e371d1b3f17169bc7d8f9d3d0dfd29999d73dc88d79b14274e45", - "02172c96056e54f5ee5abf4cb5586c5a5bf8a0f58894b9e223fbdee1f612e7cf32", - "0203af647dca397b69c1fffb1623cf0bfd47941c8c3a28847c4442ea1b24ac7339", - "032f27e22b497acfd0343af567a56da27c6dc038c24bacab94d026d07fb177fb33", - "021deae5be3ea5ef690a41ccc8bfd2da762739ce0f38fdab6e7f33ba0574213509", - "031c5f9f49b0fc5551384ec2b0f570e2ea4c6f874c21719e485d2415136d5d7880", - "02267ac9acf14d5bbacb429f1d83151c883e053ef50172e4c8cfadf2331c385944", - "02122f9f71bda7315a1f7216f0149cafa74f7952e9227067c74f91aea4bff1042d", - "0328fa6cfa3d98a62a479e3dc70eed2dd402ebc14ac0cf9c1e3654c0833ae8fb64", - "021cedc27429786d78a35aa1711866d85790495902358cf0210d133e6911c7ff5b", - "030cfcb2b45217fcab5d436a30db8f7f6184f98e050e1c2f8b9516997a1eb8aa42", - "03056bdff4719e6bc1e194ba0671005eb8b0c94d9806ed7c09a27c94a9b03cf711", - "022dbd0e7e7fe013541452a5e4b1bdb4431931dfff998f10dfba538a0274cf0fec", - "0315ba303a7e4a442632c59257f252972f698bda1052f54a7f72ea013ee664d6f5", - "020b8aaa1992ac1d36becec394b91917033dfd6575bd7dc99567ca76f04aedc739", - "022197280220eb6c08633ecd416b3006f78188fb97b7e0f8ef143b0cf45af3d606", - "02077259755fbbabbc03834ae56334045ef61db75b9aeb2f41d7f294bbac64be33", - "031d0c4d0d478c0db1ca402d7dfb6d58def63a2c599b8ec1f44c3ecf7746f9fd29", - "0300090df21753d878e25e4a5182dd4c04afadad78ab6239b0a089517d38302b71", - "0200c3a5eb97a66d9d09aa3a57045eb482ad7b8b7605181dc5dc6d8b6ae8e80cbb", - "020884e551d5789b05a7dea244c61fddc53da7291f9d8cf93c4afcd24e6832a8f2", - "020c2ca67aabc9ed92d00c85401f3ecda46626e3813fdbd25d24ab25e26db5eec4", - "0304a530c013f4446102530d3e849f4eddd3e44029971d193dcd4f848305276fb1", - "0324090c16335b6660f8eb365b1c3829c5825a31758509f580e58de885bb7f3a3f", - "021bcadf7c2d842ce7ed32cdc0bbfec0e3a6115a8198c5e3794a81e29bace37f5d", - "0307535181507d7577caa2ce2fd7d5a9fd896211b95e6298bfccf0af417084f8df", - "022cc6e4c10c6e82402af439698b12eb95abe72e6bea33006818e35f80c4bfb521", - "030aaba4598cd1c4230ce65e1f26ac756a30148d627ee0367795fd6604fa705fad", - "022e93c221080cec737318377a6cd597d8e729f149376d4c7ff53d50492da893f7", - "032046c9ae96fd209e55922c62780809154755dea1bc4f73e4cdcc4216f6a735e7", - "031ddbd63e8d901d52015aa66bde5b4608ba7bbfe3c9f1b34d082ec2884485e082", - "0201d02aaad41f7f0a85acf666f8df603d74481b938601181786547200a9a6ddec", - "0209a12cbb805ef57e40478b56131e8ced81f16bf7c5966ae3190406022de27eed", - "02040b92c415e2dc15ef043a105db52b78f008772fb95c908f6572d7eee43193c4", - "020dbcbc28291023577a27e198a8d8e993f588e43fcc7409e9dd201d3927adf923", - "0321988d29fcebbd8e0aeed4dd6e1402f92097b72b0e5bd2a6d05c23ff0ba6ef32", - "0325817f77e1fc504e232a82da31aea82b5adf86b3b8260333bfe1a2a9b59650bf", - "030813da2084cc5a28ddee17259e98d4e71f8ce5a94fc3a4836386a1cefa2fe047", - "031632155579fcb919da375394e8fb3ef07f15a8e555fd1c60f69d38a1d24830a8", - "0221a3eb556a9626bbbba9d016fc1119c760e306dab4db20756bac05821a6db1d1", - "021bc5449b6f3f89c3514b536c9fa8699048beb7dd9aee65d6869db8dace82ceb6", - "0326f84afb2e5aff9399bc6acb3e41ecddcd49b455ad19f109397566499e1e2d73", - "0317a4dd06056dc234d0223a8cfd56a85c4014c965704f46c16dfed30e5236b09b", - "031773140103225a848af042ce38439b35335b4977d2dd02d9acba0cc4e8ac26c6", - "031ddba4bb747f7bc794c2a6d14a1b3e75bbadfd5de4d363f49820490d2bb9de71", - "032059babcdd760d531d366559b0d56c7d12bed9a501de02017f8211c2935e96ba", - "0214383fa8bf41266aac3415780517fa3c506ccd157fd9d6b3954a44fc08e6e0dc", - "0228ca63e9de47b8605a70b1c579724eedf58e8f3eb7bdd8348923cf98bf302178", - "021bc514e529411b4bf14191dabe4c2af42801efcabcb567c91758171fb8459134", - "0329aa04bd52d50e5e18c126bde62301c1b0c2c8e069b40fd10918a4366b8b1572", - "022e1880005e6bd2ef3854d23195f7150f5cb958bc584beea3d62a3661d9f62be3", - "0323b17d0f925383e9d0e404dc98c489fe51331a3bbefc731e18d8891251d653ff", - "02252efe507a13aebb11ae9c5199f2504789d4b2b1bc97ce45eedc02c54d65edb1", - "030487823df4b4a8cdeef07f8ac2583751f7fbabf3456c45c4d28c856057ec0363", - "030019678dc7110d7386260c68719e8d85eafc9a8012ba91f064ee5c6631872bb1", - "022ef0b42342b9962619bcb2786e040aa4ba4733594c38960464cdf4fdee728dd2", - "03106001060df1e19dc630d660104b63ac701961c94111160bddf83387804c1f20", - "032b404f210d6da8b8abc67ea8e5a50601fc3ba3356002dafa5fe33b77a1cfde38", - "03198ea8024a01f011749c967187fac49c68c9e29801574d6c225c4d130ddcf1ee", - "02077a070abdd6f689e01fa6073d55427b38880bdedfec1b7db6e40dcb27ee258f", - "032ca4e849a7f15540c70f9a8902f2f8f35032e0bf4c1dae640712fdb692a1733e", - "0222278cf71243877b9eca1fc3bb1406eac35ac75c3f98f6d5964729abd8e842d6", - "0307245daebae04e1d4a490015d196d39d96f1632c7b048060f2dedaca38a87af6", - "0306dc6e22bc61a7a07ed13fbf217edadb224b4e9dccd1e4739e7bcecc2cc83bb4", - "0221528819b92c8dc48397059b18411c02f9adaf7eec79841c96818bc2eb398de0", - "0326a3dcd3284518556f0209549e145463fb652f3fbd348d80fa6bd112c721a49f", - "03031abb43ded370f1e509ab6daa33a4e30a4a30e4aeaf5b8e60138e19544739ee", - "0317876798fa3be883cfbeb1655afb7e6bd30e8292ee8c6e434d5a2f2e734d7fe7", - "031aa5c4547169c4fb8d6cf42f30ed4079e785967213215f0f1a6ac4676c826307", - "021875fab6ab72db9718c03ba504632001b899db7bb5de45c567a25b1429237ca7", - "02021d4aa2972ce7b12818e98d44c318beeeda6bbb110b5a636fadced290a580f4", - "032de032c97c4877ee2356fc9a5817335c777c96e17644b47faad6d159f1643629", - "031e7ec24c60b8a2751e82622a77bf3c5dd245a368787f41af48115d55ae68e376", - "03057f2ae8878401f589c459ec86972afe3f386dc27798f05c13575d60f90c23c7", - "031ee9ab03f6d9f0efbde3f5e86581f702ba9ed7c0b30f17bfb70b0cd637ed8019", - "0328a50086e57f1ec3df1d4f601f9c1350b0260ca0529f4231c7b46de9f256cf51", - "032779a74b8111eccf9e41c87c8c88591e80577c89c4a2409001bce2ec1bbee580", - "03063b8e7d472bd9ac6d4e6383fd439d7d8ea437aa39584c2e0781306b1736fe39", - "0203730baa5b5ea425f2d3fa8e59da0f184958fb576616a0071c2f37d27b11a421", - "022752d8afdfc2217530372e37376e58a88e6d574766545c0a23233ba69c39d8ba", - "021d8fabc3219acd9dfcc74f43a2f7060c24318c0f9d776348ae17cbf4d7864e8a", - "031f06cfb985440bd0b633b8cc7e6fe326e183df2fa54381c2c9dba8c6680b82a9", - "0304516636a65c1fb092c857c08a538de7f2e74e99e2407b794941ac8e26203037", - "032d84fdbcc52a5a8ae98931d943b2e6b8d6863fdbe7fe33a4bba37cbe1a3fa4df", - "0207bc5fab750397d7ec2aa876b45f10e7f38aba7f31a82fcaeadf588c78cdd339", - "0217561652de069c6a980483570486320bae73e2655f5c5f62f3e7e4de527fcd03", - "0223eee05329dd2fb56853edea3f38826dbce9957139f8239e738eb70f2cf33b6f", - "0323bf8252502e9b27353a6320032c43114ca7a5a0ae3c23537d9c51646f88cbdc", - "02291c95593e9f4f8045074185ba71cd17a627848a320fcc1772f1ad2ac005aae1", - "031ea4fe75f2cea79a2d23b8c2114eb84fde5eb906ffe7168ec413d203b6850d00", - "020a2abc524d61e3edbd5fd4044206a82551788cce69adfa46a8d5cb00f0353bd4", - "022cc6f46dcf131b4415ea56fde0307ea47a981bee9e97be239cd5b3f467780459", - "021eff847185142b2e55d9f84e61fab1fb2e4bae5b47be978689681f465481f266", - "0227e19f4b27b23463599a6a654f5ccaaa696e1ec427c99c2ce6ef511da7ec4f22", - "02100b99c026476955837822a97d49c695546b40c96b96ec5c1eadd77695771965", - "021e35f6eb0d11b8636bf77686cb40e33efd814de2268bc1423b2e04cb83695015", - "02263dae08849366c9300610bea1c36b2196d5c02e206495dd19795d951208442e", - "0220cf246843d98814914fc6aa0e9c4d8d6177a7f75860fdb5285f99fc6c2dc1ee", - "0312615913b93da849abf33db1cf496fa7684a419eaeb4bda62dba1777b166e778", - "020c9c05b6d0c4aff763ec4fc7157d3e7b7e0988d73308530e0ed2d2b95465759a", - "0229a3a88430496e6cf1c30b106efcd7ce7f5a0d6eb6f3c290875791b03d123dcf", - "0206253592b7783c4b90fc411b2b0e1871998e3ed8ad8ccd43ba78e03628588782", - "030c2667b38e3c48ee5d7fb91add47d0c56cd41899c131041547d3d931f2d3feab", - "02042ed0bc6c4d9ea7a70c5f122d0013b5df0c3c1699033bede648c4a8dfca1faf", - "022be9b3382d7e8022824eaa12cfe3ae05826fe46ba595bee493f1f73708d7a655", - "030943a5e15d3003322c1d469e519d391eae788dcf6d806cea244f5d0d839ab3be", - "0301126a4c3d75931f4b1e278086cd114bc354161b7b57813c4bb126c819a3cd50", - "03046b812fc2fed9dbd5e19033101a618349bd27bf874433f93910a58752267a19", - "030e2864088b6fddb03aaab2015190ef4f7e519f4dffe94bf962bcb47a78778575", - "021a521a6c6683f3b6688b62f517b60365d7cb653dd27a648ba4f82e3502ebaca9", - "021f48572e52ad093fa2169b205fa9e52ece1a28fa9805f65e124aade0fcea2e25", - "0316e14367ddf2e30cab1f346426d3dd5d3e93ae03a12a32cc0b8e5e13f349d8ef", - "020dd6360c6cfe55155c23c7306ea4ee95ac7a776cfa368c99ffe986877f8d0e52", - "032c1c426e00cfc1783ebb8bab19531060be4fef361e7bfbf191bd3191ae3fa38b", - "0304e094253daea58ec2615164db7e8b5f7e73b42d4a697e6f3f17b7174cb13513", - "020202a94348348dcd9fa7f68113e1fe740fc86dc92b203ea72f31139c1cbd1007", - "020c29c0b5efd73826894530f57f11f869d2c6b3fae7c867eea56b1f0de887a0ba", - "032bdbd79c1a2d176085c614156dc0b55a931f9f5c9051b64af27c2fefebdf36e4", - "021eea4b18cba555ea694f18a9c5274888c5355aca52f9bd2836be0c9be6b9f058", - "022efb7f5e10139e294142fe2257741342fafbdd85c37cedd4490470fed8e8159c", - "0216f941761c1a489138927c91ded5549e80ad110f3ddb519464f56ca3ce0f61e3", - "02227bead36e447ade4c2ab83d07d455418d46d0dbd9ed8c367255ef36b7e16867", - "021bc626a2e28cecb05d5540b2cd15f1ae74102e9ab3f6f563542d969f00cb3d1b", - "031038cf172657d827f12cd870620b3f6e4202266ec9f9af690f8d7275d88a6b87", - "022abe6f302bd2d42905b4348e9235283f6ffcf758f0f2e2d29c8438779af197f2", - "02091072f65087b3e1d4e7a35c0996a9713bdf902b053fd6ad240b298042d23ee0", - "02244d4876075c74313a96859a2cac85dada0d479a1cb5a6ef55546045c7c5af53", - "03196130177a7db5a671e269c215001f06bf50c8f371f63ea3e95a78e2b068b887", - "0201ba72f59a18e7afcdfa2d6762fb2632a0be2024eb8754840aee6c0f9b7e110a", - "031742c32bd75b0b0aac927367dfabdae9438529a8cfed602537e4f95f2cccedf1", - "0328339abec867bd81ac745a3dfa1760b18ac883be35e0fe55866cf7323cdc03f5", - "031a41f62e30ff35559c13c1f366047347dada4dd3865d096f12c9c4b41a212ce7", - "021e37fd020308ebe2ec710f81032d9d93e468bf25297e73f26ef7423990fb164b", - "03065470adad0f7880029e107ef440926c309be8217a5823afb89303ff8b3243b5", - "0320453cb3ef391f3d5b055e6c697b64139f5523b8d179040738c07ee63a1e39e2", - "031db56ae8b8623e507e0bff1892fe0d0bdee9dac8046f1d8c6e3a34dac5edf3ee", - "0218084f88d08f42f1191dc131e9498e951ba444817a9b97500e6c02a3ca9dabf9", - "03074abcf9af2732663cdabc08b00ee6c2612724bf479b0d87b29bf065404df4fc", - "031801780333e50195addf9fb86da4c71f3ce7beb49ec428f9b131b72769a4bd15", - "0319b4513e1275ce0e535c514b56dba4b102f6bb0cfc108d3d8aaa7975c0e0ce0c", - "022fd4a039e63df9b29f787257b3de936ce873c951feb105b95b0ca81abdea0ec1", - "031d35e5e9687c25a78bae23956acc599199f75372bf3d01e2aa3dc8a0d87128da", - "02085906c665fa14b75a7c60ca56f59e7e150453fdac9743db171adff0a462a7ed", - "0222622129e75103b3e0ca516a85a15e5e8df5de91846046156be0b3fe730f35d9", - "0304263a7d45595141e875a904b4c0d045f7e0ccf8aa462396ac757ddc8c1a8dae", - "0329ec6f5a7b066f4171dda163550ec34d395b9d37aa0c8edc7ad3904b23607ee8", - "0228cc2f77ce68d58f9b82bdd9363c33cbfeba09e426c6aac0c4c596e7e20fd20e", - "030abd5570475c5f553e95835a2b9f4499b22c88f81441504fd56234b4dad80819", - "031dc9b0622e2da0c9d52b1ed12dce2ce0bdaec21557cb00bb69338061dfc54f94", - "020d7131d95547f919b42c2623d8cd1acb084f55323e181566a7249a3def27b7b9", - "0302fa4e2bfb47f7eef58c83ba60af6a915b20ade982f771fac7f69d3907342269", - "0219c2d17bd93208a6d336d28869f74bca4d4e11cdf9d2653c8bc883a298f98e70", - "031c298f831fb8924d2a22c0ffb7909068b8b5f2a2247f03a8b7142eb19d84a40e", - "02198702e86fd6925b6036e1fd639d585267e4d3a83546767151178b849a0f7cea", - "030f50ea82647e0dbc34317c3663de234daaa7f6e759c724b668fca9321cb89321", - "030daa3fa5f5b841cfad4ace9630868bbcdc39caee37a48d4a3f1cfbaff5347066", - "030c2c88c544cfb5fe280c0a8934ac2e7eefbde56c7eebfe88ad1258c0fb65bd10", - "0329c7f5d4f8aa269b9f3cbd93e08ef951271cb142479befec5f82bd48b9b0f8fb", - "021716bc3eab77ea3be289d2c0b744932f58a2fb5ff347c991df72ed6049aefe8c", - "03033db043c3b4634c7972c4b9879940cf82dba4535d4337bbc7ff53be9abdd5cf", - "031ff16213cd2df89d701b9aa5ebeeb1038b27acca9e8f9cc05982cbf0fe6a9ef9", - "020db62d40f3cabcaef871b19b09eedc65c17d88a092fe079a9d6151c0de6c10f8", - "032f05b9d6f1acfd40ce37a3ad71992f7b8ca211b3b3911e839fae665798c07c96", - "02135f51ebd188eba39b22778a6c457330e3c44959aee5f7ec02a3e217b5b938f0", - "021ea14d771c9ff04e1b0a7ba3c5659b3bc3689caac303d1e6ca2a68ba0672aeaf", - "03198d6e6777d27620dc651bec0677720a2cd9439fdba2b3ad5cfcc601c48877ba", - "020c74b348956ec7c0b82b172e37ccc3191d1531733c976bebc0a966b88094cf44", - "03107439278123027630ccb40d95384fddbe41b28a80efa70856e9cfe5b95326be", - "0318b9c93f6e4e54e339511ba69d152b1999f01143176b18d0fff573625931042d", - "030bc647df4d7fbc56c2602ba219fb5d57a01b5f7f350928552ff1ae385b95f56d", - "03200877f732030ce3e5c44f244d2c1e5af8a8f2e19775d395889f4be24eed4678", - "03116fe93c5e2f2c2b9a4c941825c8278c5094f79f46bf557c58205b11e993db17", - "022e5542ab50f6724a5cfcc971977a8bd350e135df339db70372c98df88f7f59bb", - "0222776733baa6bd22bd5a3c6e03a06d1cf6d6efe1b0ed2dc76cb49d91068f4057", - "032a35745a6d437036a0a8282ad645a795c9d6817da33ff05f1aba99176f5286ab", - "0313370678a52d12f7087cc5476c50a486e5781397a2a826b186b5a5d0d7b9fc74", - "031f5546c344c8c3eab1dc37d5c8f0a2962cf89df22697317e04d5fa43f9faba25", - "021c6aa7ab1c5242942f00de9e29bb4b6ebaa99835e689375bbf84cec45ee54bbf", - "021d8c5add1005a6794100ac44c6f8ae23e7bb6543f08a3725d7273207dbd3f8af", - "0306d1166e043d4109340da8f3afe93658a629c3c1e706eeb9fe8bd2431e3e6e37", - "0305fecdb2c674368ec5ed3d429101ea43b0b6b03eb3521e5558e47b496ba23fb4", - "0312bd9b611f56689f2ab650461e85ce5602ce86e4f57351d007c302b97814067d", - "020a1719ad8ef8f858eb189b744f62cb4bcae282d2ef10528c64d66eec3ed60062", - "022ac7d93645fb062553197b8f18c75edb3cfe7b655b82a1ae1ef23d35066979c8", - "0206161be454ab3f18472f7b88e096cf04e8be317c3102a6fbdce23ac748e9e14a", - "021596ff1f1c00322d3285f621b6d53c9fb408ff7733aeed1c0e6dfedc5233e59d", - "0226d57837472854396e069bfe261dea58f614440b625614920a12195fcfb864cd", - "031ed86399a7b6540d8b15a77dea213eb43d9c5453f24644b6d59816d1c5188fa2", - "02190259068d9bb78ec76e7bfa87d43ccecb51b5b330e2dce9f6f2eb81e05930da", - "021cfed308977555749ee374718637b88a019dbbb13ddf75de7527947560f10df7", - "0225170becc5be628175adbfffd6a437b27fbe497b656e8a402723a236e8ad1350", - "0305b1cbf480c6f223985052248dc2a80ef6691323151383c82d912db9a2a01306", - "032ca23ab731c64fa17b291a73ab11ce2013f69f934147744815a799f2b793aa1d", - "03166c12e8f87e956825f149fce70b32929268dd101a41891e3873d14e548f6906", - "021c0e5f238cceef4994adfaccc37fd6f090c5b9ffbb0b2395fb9474e6edff7d5f", - "022e1693e15a078fd7428803784eaa8faee4b401cda48e4eec3f5f6a9925531369", - "030cff365223bbcadc79a867ab53b42cd07dfe293c8b5b4ff09a5f46a1222c1f20", - "020f972222cf8e895212038cdd3ee23d2d230de4ff05281a44e729238bc562a997", - "02167bb8b00030933dd6d11d3faf7184b07984eb9cc455ca5dbfcd0beac5cd15b2", - "0223e5443d8a9cbefe1ba275ab779943217be136e1dfc9dfb4c16a353a7ce575f5", - "020ac60d5612a5cea3b69f4b0ae1532978487fbd2655ea822109cb03a15dbacdee", - "030d5bbe1adb94d246bf4a0a03b955bdac14c32bcb2e0c8205691699a25a272234", - "021b937ee35873c0c578f32453b52b93912cd6c8bd40c4468ab2bb79791f725258", - "020e538e00381dee6480e4696125e5f8926a82cbbd16e2bd1f6a52fc015f2d916e", - "020f62ee6a300447e9810f400f6d80cbdfcb7717b36adfdf875b05a001d7a26239", - "03102233457956fac91c6fce4d856ab7289ece12eda69cb28244b65760e7c6006a", - "03204e2d7c8d9f8a734582e7125833582cc668288ba3e0b61601b8fecc7d9f45ae", - "031a24f3d815274e37d88912317a3e12b44b76b00133a39ad15380ce6a43d608b5", - "03086011e78d8a858d7cd1823c9482f081219d61bbf36186fb7dc8581043523122", - "0214fc391496a0ecbc1422ecc0c652a5000a7f31248b62c9f96ac5549c933069d4", - "03014cfc677ca9d2d79789d83844ce8e34500004939f90d0b03e0c85c8fd44a60e", - "022fe60f5c242f36954d44562a748faf8b505ea2a198512b3e0d3e9e0ddc675edc", - "03254b936190796e5a2f2573e930e0d5ab24ac7954feaa10cc8c3254b2111c551f", - "032f3f3314cd571b8b32f34afe1a7b6c5bbf83bfa74ea6df3ea9716d3b8114d838", - "032bbb394e50d7de000434dc63727d85f1282c68708fe40b1d87f1028bb1274f86", - "022edb0d8834e3d9075665a8de475145c5006e2b6464062a57f520166850ad09cf", - "032f856f84200327a83eb050aba5472bbed9603b3ca9e91517ac4d6aa7c46e9d25", - "0311944e237232913309e212637a7f2f84c75d2f66565a8a6a9902359374709ee5", - "022e3d01e2b753cd85c5c03b4ccc28067fd18be85e5aff0da89ac84ac17a77c2ad", - "032f9e8732efec38857c46b5fd79097efb48866bf1c0607dd2d7dcf249a67165ef", - "030a0d91d95795e2dd60afe030453193cd2cc3d3e930321d953fa9d1ff79dc07d8", - "022bda269eed1ae06603de99f59c6958ab4c7801b9f8fd5c1db8daf65e1bff15ee", - "032dab68e13be3354044be673d376046e7a04624618594e075b9cbea972de189c9", - "032b8069dfa6971f7c409ee89e9bbd4e0adeccf011696098e8bbdd409886cdf817", - "0318d15c2c6c9f6469a953ec9f140de66cdd5008a4ccec66e0dadc1e79382035f6", - "02258c8f16f03e7d593329a8f9a64874d3e1a3034559855404cd875a7a7c163c6c", - "03023f4087e4bc81865bd8423346bcaea45fa7e1a007edda255111bc924b4412f9", - "020b2407b228776f4c82406eeab90625e8e0138524f7c24a4429ccc75f24189126", - "021826327ff9629821077ec9eddbda55a5d5b6f6fa51fc5beccf1f582c10e37ff1", - "0210b33ecc1670b589ccb6cf821e6cd4615a1e66d8268cea61169df7b0ab3dd982", - "0209342c285b6dd64822016ba4dcf5117f2067c03e22a5b8a40a36813c9fbc90ea", - "022882e179b27a35bb4ca42538c58aeea72520ca4768b6d70cc19f848a3f5feb13", - "0326ea3e890dfbf4a8cd62ba1748cb76bd29bce2f0e4bf9efad32fe952714b4fd4", - "031680bc35cfaf42b9ba40d297715f1d964bfe739c50a4fbe3a662b711027f629e", - "030f40472d07a563fe2808289f68bee53a680862efd06d8a249d47f59a68286f89", - "03045659dee132810bc9240d4fdd9efc5667753f5f69fe8602ca8b26bd494ecf04", - "0311cec44c33c50cb44437e8805e6c55c270892b587a321ddff23e1025c2215493", - "020952ff71f0cb52bfd1bada2bf0c82b4650491c42b11edc6341b43726af0cf38c", - "0214edb136c03d2a85ac833c0f2f91b8f35e401ee57f0ff66d7472a49f2541723c", - "03185656d51704031d12edfeaf77dfd53ffa210a023143062c53e73c8469371208", - "0301b52840d93cf7fcfa64b8319de11ca9327fb91079029b5fc1e795a5112ce7eb", - "022c354af704acf03559d74fac5236a89da20930b9cb2219a7deed184b9559d7ff", - "030c040f4692ffe84db905e20e2dd2ac891fa832da027ce842128da420d7dfba16", - "021d1871b179b7f38f9b81803b574eb8bcab366835a89b6b16880dbb5ffdae60ab", - "031193a96eec899406bb2bf16360389681c4296e4253c390e2f0ce658fce7fe782", - "0223948efec835cda2c64f63ad138c1cfe48971ee58553c927c6742d7ff1e0adba", - "030a1ab786d3db5ed89b151ff2f09c3e4a3c6492541c602eab55556baa41685748", - "030a0c9d3aa087ac9670217c5252e8cd80741b7a59959186ce7a069b947487c5c3", - "020e4e105d445fdcc62692bfa61e1fa8ee0127dec80e087b45d29706d735e1d6d2", - "022a5e258cb8dd8b7239ee2fd20ff44618c358fd926541ed8d5b50ce58396ecc2b", - "0207773ce719d6c3dd87c7cba02da30eb95f622795c2d69f32155f0dc6fb8bcafe", - "02210e50055dbcc3cbf6586f28a7a2c17a057794a1b91710aac7aec947b08e1e76", - "032371d9de2701db8b39b2a7a537e4c33d38f325d037415489158db4b49ac97de5", - "03070badbc84c0d847ff1456ccd2113907127832514ed3d5c68324e4225d5e60c8", - "031d3173ebf76e2fa9dbd537b1f9fbbab29b3c91b72222ef982e3f79b386e3eeb3", - "032768e834a9c726705711622bcd0fcca0ddd0624792e571fbb63443cc7fc5648d", - "030e7fcc74762cf19b149d1b82fbd30a1a241848cacefba76623463472a6e22a93", - "02019f04a5e4881346bc216654bec862fe0a406e52b8045c496f00ca3ffe41d9e8", - "021b3868448a954402526d27724271946de8a905561f489535b05bd227d1619f4d", - "021d4ff28c86100c9273aa5fe4c35208a19c57ea001a6207caae15aa4c8c517481", - "022b76234750f78298d629dbedfe3aa2ecf9d49d5832534cb9fb719d7a7646b7a4", - "0319a799a0460f4616a50c84fe666c9ca916742196ef033554041248e2c29df584", - "03121a942c9b00dd85b246e2a6254e08ec9f9b914c34a9bddbf2b8e9151d550d27", - "031d9de5586b94e7c80b155feac288faed8c199762584e2d9d05907ccff716d40f", - "032ccb936da8ac8ba8a181b9847bc8468e29be1af67d7a0adacacc563ad8ed9555", - "020393f7216e1128bd5e261ff0c313fca09b0f711e0b19e97918754ff0ffde070d", - "0212f527c534c0eefbda40acdfa9d7a8475ff3ee9673ab8b5f0c65b4a8462daba9", - "0222332853f647636c9de30404b16c7cefa238fd9b675e9c4bc3b12a0784d5d68f", - "020452b760b1b058c3c30fea7d3300df9fc411e58539a637d7dc17c84f70316a5d", - "0320a001c4b8b90e6c9bd852ef981b5fbda5fc40cc1c0b149e95f9f267ccd7d354", - "020c16fa809f03bba176afab49fcb296ad479f71a03eed053e1e7e530415fccc91", - "020104063e4d0d4411371d4b321387c9b3f6f04a69ea4a79822893793c3b8e48e9", - "030eb7d90e3bb32eccd341a4a723270085a0ab519b0dabafdb4eaef7747e3fdd6a", - "02190ce3a7c2fd0e44d3617acb02b22d8c87f1b003fdd78bfd4c2535e52a5d12f2", - "0215a8bd5bcc1d3604308e74f5c20ae7d6a16c07ff490d29b207ef5f42bf04c5f7", - "03061d87923e08ba3cb4cc4b2223f14f9e3b91887af21c095ba80d2749c8e9edd4", - "031f2696c6a61a0ec632339f422ea1474190fe620d6f4d1a847df7bb78052228fb", - "03144d1ede70fe0abc7758fe981799e10b2ced59a929195bf0671e6e47b3c79fa6", - "02020a82228aa58681c796043c1002cedffb15a91099c5700bcae4a082db803ffd", - "0313b0a4e169c46dad90dd57ae1327a4e3b3f617c6558e778b5720f1545beedb21", - "0328129c0ec394e5812fea8213c7d15529868f50f5263a321e49672743f607ee85", - "0329a821394fa0cb7b15bb4edfe4faf99d119ec1480de0e5844472eee9b8306119", - "022a8a09badaa74d6ad82fbd1b1653400d34559bc08d452329440ffee32f313561", - "02061d21cf10b98de5014df19acd4f156d3f43b649be38c132280c45c93a34b291", - "022738c5f2c27b2cf156115a8095060d0d6a6ac4b040892c5630944a55dcbd14b8", - "03151c05f788a3d5b026e1bd40445dc83c4c2ec1a522e0a90cadf6ac67887f04b6", - "03251165a637d69744372a8eb0dc4dbac5a03166deb63d877a2eac74ddb50b74d6", - "0315fb9ff207934ad2241fde8723588465a0734b28edd837183031c80dc9d44d08", - "020f841788ecf7d77bc6b1ab80bcd40952bb5bcf428b3bec91fd64e17386b4f049", - "031f215bf619f511944e41a397e636add00c276a87428eea63e2d19d82fde9290a", - "031f27b44f5fcb3a602aacb1c0d52ba084f6f479edfae7248072640fa7c2fbc182", - "030e29ca239e4b51e49906251b338d94d6ee464b2b9849b66d4116addfecd64c50", - "0326fff7d0f0337e8f793ca9a8a98848be2f45e48566966f4c2a618e018ad392bf", - "032bf0266f62851e9e737114b5409b5ec4e3c8afabae83e36ef86ae45ba2f9b03e", - "0316698b2e2b04b98f218782a0cd2478b6c922df25b4392a36dff464777f0ed33a", - "022b36df58f2941d0464d3767284aa4b3a403ac92645425a2ec49fd655445ea16a", - "03043c48b4fd19df1aad5a8e78874b9f9c9bcdc7f6a340ae52936a0f04ded847fa", - "0226f31bd67b3615c74716d463f67c30326730523e6317763f4ca5a4a1aff49ddd", - "021d5eec8aedb08bbd41e4bc20fbe14bc20e6fa025d57deb1dcd6f31219bc0e37f", - "031a59cf2b56462d3b5990b39a40452556ea045c159d806e2c13c245a0d9930a27", - "0218242f1bf7c22d48d04853f90aba18e293cc9668de3fa56ea821fafb86d102ab", - "022ea4b94f319d7f8397fef79c0b0240261e96c84ade8543c2a694cc3f0d0c1dd4", - "022afd938fa80ddd72919015f4120584dc3629ce193faea49c6e77b8fb3f747ed4", - "021555bd0ea55799d6a2dc26c9ac48dbe505b6f6fc63221cc1eadf5b8e3671aad5", - "0314308a1f495ae980ec0319589ffb7b811a32c1f576d97392e23cd1214de4dd0c", - "0218916ec9b93f65b69326ed8f538e56bf49aef22d56606170a531d5a334c7eb21", - "020e477dff9761f0d2cf44b83758d58c9ffa7dc45ebbe2280c1feecd7e5777ab96", - "022aa85b3cc30a2128ed9dae7e39043338c1b81d0400f21b9c013a95c340994c11", - "0214ce887c731cfcc6961179195d656b4d2dbd3c3e0938612f3f6d24f0d4c44fdc", - "02153cf0e2186fd148884d00903744d0c3d7c3e7e504103dc722ad9090a062cdff", - "022d57f6cfc8b61b888a3fc2012f2e166e2c9b8da0f50a5cd8e72f2b5ee92ad9c5", - "03011b0c317374ecadb8ada0177530ab4face0274e4703304004d4eb0dadd3a6ee", - "0300d5757b6ff208ebc3a0ff444acefbfd8b41ef4b489e0747f605e9c83db0f761", - "021b0aea684e29f271d52689ef73eb71690d18cf75c5fb4c1e8a6737089ba73daa", - "021ff51a097d355a0101a66febad0fc62a463b7cf89e29eb1ab2f4cd47f9d3888c", - "020143a89cdc528fc1a63476053f83e7bdcdc3ae1940e0c6b4c421ec4a91c61da3", - "020365ecbb120293ee0d877215fee4c7c183b090f7f02a769337779feda327f108", - "022697983b50e2a1badfb11e10abe445d31ba373e175af1dae7b3299d327390208", - "03078d47278078b09a51a170bad264e82841b45dd35844bb84dc5e607f0e22fa1b", - "022691417083b9dfaa0d76de91b1f6421bf0aea3f993da3616422d6c2f42d3d022", - "0326cf4fece585f6411b57a754019066bdb24b1703c85ad257eb8a7bc0d3cb6ca9", - "0223ee76dabb3d8e717b3345daa41a97b5521c84fb1367b6d6f3a0d0b5cded97ee", - "031a2cd423db3131d81375a824d3bfd2d8685eb6461dcd60d21e42898836a0b036", - "022de8f154dc7cfd469ceaeaab4ef5725556295b896968752a8c0891b2022f1abe", - "0207f325cec45d46417e4635d555eb88f8203a428b48e60a653d0c3643f8720579", - "021b62661b2223e56a551f2bec9810de8777b45ae7731a88acb3e790561268cb0a", - "030064a13bca89e92f1a83ee083c17480917d0199a62e72bb31d5bf139ce03d2ea", - "0200a3385c47b83777e2819ab5d9926c6b861c61af5d35ef6715b47cd1b64876af", - "0210394bc1232dfc1fb4c2317b563c6f60f522846ab822b0d70fb1284f28bea370", - "0204327011b1dc045067cf1f7a319914991fe5bbb37651b16e1104e74ec493852c", - "022079c958ed024446285b06e9f0676c5c7e97d02a94f973a4b606e7a0ec2fab43", - "03291cac2259809ea024e6f4141765f1940d624465b9ed73b99e24bdb05da4f984", - "0305cc12f663d916908a6cdeed7bd4ca0fb57c79c70d2685ba92a1ffc91a04226f", - "032564f26b0896495fcab136a2bc5db7fc709e35e9bbcb7df770c9728b6714f49e", - "0224236cb1c41baddebacd7d4c197a9b366f8a7635e3883fc8b372bce7ce854e6a", - "03146b9438f21971f45ccfe47ac0947cb1daf47f3ce2c7c38f83fd519223ba8823", - "0324e92d7ba8d7c252e343fdf7f3b1e15358da4e10b1d2ab30c5a45370b132fe30", - "0226189ced9905904b149c8370c7e78c2b74c24dbefd6423f96117432def0550ec", - "0217e80b90a07b79cfb82a3fd082edbec5ddc1bf7b426e896650c417de8d27e5b9", - "021388a821a5dd0648331c88a7f7bb1aa9c71702a1395a2be6dbe6fd669619586b", - "0325072b00741d6f4756d941f0e1d61c02c921245b3e3d6d509b5fc87532985dd2", - "02201bf99d6fab4fb8879b6d9e73473369e6faed19545b6ce00ab01dc4991df045", - "0212936dc6a9b2d5db143e732001d47c6b70b6901fca615a652ea2234abaf1fdc1", - "022f5f2d6f6a7036c3e1a6a6d42969d3998ca2f1e888751276d5402b95a3807e53", - "030dbee11f433761c7d0621846d237d49b1d40ed9d6bdcc6ad3d90d1657570e076", - "03115aab837748aeefb45599c2ba1b17fa083ef1e816212bd9dfe3bae2b93a02c6", - "021b489a7abede639efb526a03cce2209281609a234cf6e081bfedaafc51d2ea60", - "022fde62ebaa208595a55dc213df5e1a0b2ca6daf357413c25345fc340af027bef", - "0227f4e4811e0e434da084ebf67ff569bea33081b12f6f5fe88a3e10adcd90a28a", - "020d387a9af3831767ac1a508a847b16b4bc23cb053693850e15ff46be150e9676", - "03222877d63d3b09d87d06a6fe3b23bed5b8020597be998fc473771882206715e2", - "030fb7d495291b8f8ecd1c25828a42eaaf589b1bcc9c07288db6f9cc5c0180ad54", - "0302e8082eaba98930551e2376856b7a3b400244d0fea75751988b3a8ab33da29e", - "03149aa51655831d26368c5df4a0a58602e4130eae7d63f9ef176f18f1630b549e", - "032009c89e857c9cfad25d6da5bf8822034a3633415f2142183d4282f4965c3dcf", - "020c7daecb8be20869e8f0a2c064ae30ee72fd2ffaa313c74bde72817f7d800e37", - "0305680191eba83132d9b765e7fad55b779ce8766e3434ca3d0e1f38d08a9cb5bb", - "022ff4cc1402ec129b078904864c67f5cf345add5e30962eeada98c231bb9f996e", - "0216932c8df3f6cb20aed124c61eef67b3f03530266457aa9b4d5def532c36de8c", - "03080a21e1660934a156ebf9e083c3d64c18af36b1db76d51e7982913b319dd973", - "021ee8f7815b725b0ea3427c5057e146dd03764bde37a9001ee946433185cb9228", - "03109aa1da066655961137c406538273288222963290d68d4d05433f3027c8ff65", - "0217e3dc0853e76905a64bdad1cb718572117d77a72e6140880bc656e8fb95162e", - "02115ed73f28460154679c9e7ddb76a848ca010f1c621a3dc48c4d5fa0161cfdc4", - "021d703b0b8a217b7956335b1b25669017753c46b9305fa77766ba8e67151d9e9c", - "020eb1054eb32746b0768ec3e98358bd70c2302b1533148787d6759d511b828eda", - "030b2b3488d1429163e54c07d7da4b296db0d8e85d531e8f888b04aae8b5edd6d8", - "02096304e7ca4cd44c07d0029acdd886e2449a1d79c968ecfe48c4679b7f79c013", - "032f1b21979989b1c6852882a9f30a218f7eb35facdf56688e45e5fde6860589a9", - "0309095fbff545c53ee8a6833033ff6079e8d1acc2d20999a973a80dafb1ee2c64", - "021a1fe21aeb3c51aada9160e9a240e86bb48a4a44e153ad2c5597c01f55e9d736", - "030c94523f50de732f6c56b76d5f8c002b4e6b869eff63cc33b0319a577b2a3dd2", - "030425a4680fc683354855f4ca79cd3d2a5eec231b9daac070332a05fa6874c43e", - "022fa5605b328f6c9e1ed76856fc4fa6f36ea507fdbb266a028c826808e56dcc46", - "0221dd19c70e9166c4f22a9bb8ea191edcdb28ca156e97619849544be160389c41", - "02079a33d9cd2384b7d78a7e409be9e32bfbab41632e27470ec2ce92667b84c882", - "031f9de00fcb3e7c7c12b478d40f14d359e12d94dcb99c94095ee81ce4a595d041", - "02133bf10c82f9b10dc4da8fc245ca97d1f71157854c485de3b8c3bbbc1efd352b", - "0319fc9adb3d8e74fd13d6c706ae642576b6376eeb8941dee240848497d8185e45", - "032d7e39f5f061fa55646ec032ee1712a57ec9338251b64cb6ed5ba7007961253c", - "022cc179e0481b654fa7803b3da41474a0e7bc201add8fb032e7d0c00136e31e5d", - "021b32021fee9dd9735a318d921056e6e713c8335358ab76b35ac74bb7078f76f9", - "0215e1763b02ce787436d0b6bf7b0b7339f9564f789abe02219c07026b1abd1542", - "02162518a608b02ed22d2387243d2c5c523f281925f42c8284f45e2c97fd150fff", - "0317d1dcbd0f36e40ccfa90e84d8de0d59de9d299ec582357a31a6579d409a3ee5", - "0206be6b9af485cf6acbe85b5ffddddd5d09bdb632a506258f06461df09e53065c", - "02213b9ed3cfd8a16e9de08cf2f824aea7810ff03c3199f092c0855545c2f345ea", - "022b7963bd06911377d9c5b25472897b02580a20cd692496e2882fa4dcea6c0417", - "021140fd608a5cb34c39e9e87cb6d4e896a8ab530ec4cffb4876a6b337d7443a0a", - "032ce2752090e4318fdf94b6329fd19638dae555df44f803f4f1a8b68c54b05b9b", - "021acfb70999907949eea4d7703692fc6f25e2de360c83361884b14fb7df2deaec", - "020fdb6614f120164ebb371a0067f9983aca660ef649b2efe79f2e7f63444648f0", - "022a7f3945e658d164b03245cce74a9157608d02e000018641e9c84cd79892361a", - "0326d4475301d8712b8a18ea436935bdbfc5cef52ae91d52047a217c6709866b55", - "030fc092ad3c8cdf62c521f286ec2fa650c442675721f1716286504b4d2d4481bc", - "02035bdfe77bbe671405fc7774440f3ab1d56417b7af340d38f89cf1ec07a9fa5c", - "020ffa236a9270af8948323f33e231339766e319a70e86eafcbaf8d5f2d37eba3b", - "0319c47a03e305590745512f0ba32ea262c3e81ce0c9ad1648cdc284ad1b84f3ee", - "0315d515f746d07f0912a6c92a78da978d4a9fe57b70d9c46d17c7d838ad35c524", - "030519b49f5a95c1e1c062bf7f538bb823493cda2c6933bf91cc0d940987c2957e", - "0228b89cdf90ae9e227f87624aa864140036aed562af37cbb20166a2d7fe298abd", - "020397ed81d62025fe6b3daefeba7f9b1d566cda6e89884cf94667b9b1a340c25a", - "022b193b7a39c2dd80f34250613b1bb4fbb1ac85426fc9af49375d6dfaa2fb3ef0", - "02220c4e29ec7a5aeed2ceccbc91c0677dfa59bce4d3a07db81ab56589f925d0be", - "031c096f426e1a42ee93912d4eaa13820c75e581c7e0a36c63f45f28a168e3510b", - "032194e4c42a902320fcb7d1da42e5ed5701fbdc6e18eb08f0b154237d27527db5", - "02299f6c2d0fd13758ecd7106f50ca056bd806058c017f012ba9ff986d29809f9c", - "02025ba4607594a292d2b8e4ed8ed5d26ad3cf04634460f4d7889baecbe69cbfb7", - "021a14bf6779e0d78fe75aa8b80ac0c11190ba6144a08426b2b852854871ea36be", - "02224fea54937f31e3b413dd7733b09f1d0796c40df1ae7cea4f19b09fca6480ca", - "020ea026edd6b847a08365ca9ab610c563dedbe45a23532c564f061c1b1a725c54", - "0306588825ffaebbe007d4ae98bb69e5cd4f3e4953b2d369200d2526e1bf7bdf25", - "022105f4ca90b113b820b1ca5524b7fdab113187787e98f7683770c4154a81b0af", - "0207d97a682355f638d8622b160225339b49935043b8f17873768059b5bb886caf", - "032446256bc3d1e5184493ab7fd5a7a2aa838fd9dc35c19ced0bc713ec43a17462", - "02285277fdba8a8c472f14911efdc34867ab2845cc0fa60c43dad212346462cece", - "0222d417da9c9e469517adfe008fafe6b6f58a097c4bc990813d54cf9a6737bffe", - "03142e0db823eddfd486ab0141d6b76a11a622640f4543cf23edaf1fcaaf8b61a4", - "022505c76f068cc043f8d98e5fc5bf60a7da4f0c5751d1e28b03ed5d12b81fed7d", - "0207187a70d29aab14cb33f0db96cb498da8becff1109cfcd4e2354b3a445d69d9", - "030cd9a5e878a1d704c3397b5782ea7f659d369d6b0a4831bb3cf01d58aca141f0", - "02107cdd4ebf4a011e7ad99876da85655d290bbacba51d1bbda2435da767d69035", - "022a2a9aabc0a9670236e233437f22351a8428308e3108e87b3fabe23045ad08bb", - "030c92a7dc2fd5d7b76bd92cef770453b508fa990ba1beb433b8ff380aba8884e8", - "0310e9779432fcd9355c6601f7de9b27afc0e1be584a5dacaa46aa5be36f6ea255", - "031879d994712dc89b4936b65f27314a2cae8b9a52b703087d34b78379ed18df77", - "0309cbef1e0423918309426d76c458edc0e69b6b1f125d1281c86284455ec6ff0c", - "032f69541aa3ea21ace38621f50318285e7de746d72b1dcdb929d6b627b10e3113", - "032c80d50f8aeb2b5b2c34738fb54eaac0cf2f7e5a711c291f41a3693a40942d97", - "032716befe9b262e32d9b4ebc840a837e7808a4acc82083a19f286b51d38d82690", - "032120f355c8957b1ec3be3d4a47e6770d9f7da0e7473fc03372d660d7bb0bb7aa", - "02037fbc9d0a4d8cd7229f1dc0b364f25e9b33450605ed616dcd2e94748e4da5e9", - "022bd9ad790f153d83399b93d1db47a2d9a8b912bb4be0f06d677a4d037e92ddcf", - "0304c4b3450f868b8ed882f84ef00cc31e61649137a60bd619d9151621fb86a495", - "03227fdb7c1534acf6486c85c87f17a8e0cde5d1826911827cc3b931a47a10c6c3", - "0203b6f8fcda216a940a5a7a637244208b756094535155c19e24de2edd1ad9a721", - "0225fb3794e149c634b85c61c304eb11c08335a8e7f8190985c5498e4c0cf35eba", - "03132b67230637d1b0850322da72f61cd94e796267e8c143706d75fe59efd85ab2", - "0300eff813eff9780747ad95496f2d94ca2bf698ffddd62a73efb6db8da950f4f2", - "030f65706e7a20eb6c35cad42a90835f9326b85361807e08bed7a887ecefa91da4", - "0325e8daef56d7a0b5f5817ea44add668e06ea3a374d22b2b1cda18c24f39d63a8", - "021baf375b08ec45b5e395e52db076cd742993ca12ab6cc3ce8339d4d89615d31d", - "03304f0fa3514b900893d4049db3cfb898bbf1c645b4e7e2051a493193094a1651", - "0311e3109cdbb8c445651ce01888eb0086560609e5daa6c4fc6c71a7de7ac4d537", - "03036701addb3fc9d01e56a8688150479587d2be6def61af8398825ba1ca3b5256", - "031b6c8b61a4a2302698d811da44289a70b22810b377be71b39d33c1c76c5d98f9", - "021cc014de5b26318b350064129bc025b2aba1a0fff3a937df7c1be78f2ba77ae9", - "032428f3cbcce933d11f28c7418a788a6c0b547534bc5385421a4d22f54c7a74e7", - "022ff9a7eec479ee31c6236abe778f0021d8b8254c98e596b8a49b530ed205409f", - "032a031025c1b8a04e2c911630b63720537a188fc1ee9bb5dec1a7df5a2f158caa", - "022026a12b651fb960c88e14f307c15ee0d2e253ba33f603256539ae6a6f2e033c", - "031b5b2a07f985ef52dba054ee5706d01c72efbc9087a86ccf68427f43e283d977", - "0324b2265ca8a2c05d0472e413b8ab159b8929fdc30cf88a3a909d20d06748eb3b", - "0208ee6d93a30b7fa9c2bfc5e42613d3bfcd16f198a5191b04a8581373998bbc82", - "03160678472b08e820286fe73f7a91fa5af5378c678afe6755561f01ca7bd8515a", - "0314cd077ba848ac2c5a152bb96bf453916b38930c3ecd633a7b73c633de8c6686", - "0219c1017d83f0507721432c8f8e59d65d95a96b0db681fadaf824f0491ddde1f9", - "020fccac2321590086c0b5b68bb05d754182dbeb4f5dd41341747bb6efa2beb94e", - "022f656373f31e13685684f3ceeb08e1eef181a0f316f79eb598570130439e297f", - "021df1a216441eeab1be78716020ef20c2bf60b2759505547d0797b232da7a1874", - "032541de228a01b2a62cc795e292f9fb75bea59cf07f8ae43ed979812d611d1fab", - "0221a60e46fb0415cf8992856983fdae2665e4244c8ef48df6c1eabfad43879729", - "030e692b3717afd6d4bc4032eb9801340c79496ab083526979195753a4da555ccc", - "0225e635daa1f84c26f92076a7f52ac7b7ceccadce5b4f30e21e3c00763b4ada86", - "03279bf28d7606deac8af5b8d58107cca5711ba1a20b2ab350fb3e7eeade867577", - "02198c9bceb574775897344ad4655a2506e5d4072b29232a36c997493f30d1e324", - "032b8f6d731aa982ed0dbb794897586ddd08bb02638f80ed3b6904e919692b4b8a", - "0308f6dc51016254e87a3574886f149e98becc2cd4deefdaa83e10262caa74e224", - "030274a676ba8c7c0421f8a28cf98dd5497e00bb309d3c9938c440c3358c8c297e", - "020972bb8e11017a803a565ce3427b1c17b9b4cd1ddd101cb424a6836ceec006a9", - "0212787c3a153348149744a515e76c630556aa1ea9d1607d87dce917faf180e544", - "0230401cefe109c3600d4f22f541590e347d82557b7509eb16d5bd4ba65a52f099", - "0304c7a651782cb9294e0ad965f0c2387899ac32418792b238b8b3a2e28172fbdc", - "0302dd4340beb48a25399d554b03345fb04858d8df3232a6d6cde527ec995def25", - "022253fef36ee218024b0459e65cae9c5ddd7d22937696d60f9036510ff389a6d4", - "02129c18560f5b1a9dc72253753c9b5fe77c83debe6850c3f2444a42483b3b5673", - "020903edc201a37d19f226e5722a3cee56514f46085cd0bbaf0074dc2cc544e7be", - "031fad1013ff22ef028c6ba8f28996c702f58029e63079ec0bc7c5cc806d847a2d", - "030835614e9f66f2b43d38f97b6e22c7a80a7f56af0bc643ec5ef59d3f66e5215a", - "021b30d5e8bd8ee41e7a60ed178ca3d17ddbf4105255f4c2250571490dba96b3d0", - "022f3904b352678743825b564fac1790a6678c37dd94bf8f4a6f0bb42339fce101", - "031be6f26b648396e164a2b9bd7dc9dcac1aaf39111d75101c3cd948f8886ebfdc", - "032eb6f78830e7933e40c75e82f3af6949549f70dfa8bb7bb9298dcb9949180882", - "020dfe6ddfd3bbf32689758405a2418502b9d21b0e6e7799f101f31c0ce528ba41", - "0211ad45411fa3ba44471aa0b66c39c39394c47285cc9bc98dac21d58377666438", - "03065a15f8c27b1c7f5d7fd560607d90898036b3d32369d024c6e8c8d7ac0e370a", - "021166948117c070bb31fc5e2d87899e7a11a29d679963a29f4a86ce30e98c6323", - "0318f855d584be1a6d6523065c9d1ee0d24c685cfd935c537d7feb8c058a44ae1c", - "021c3aaec9949c7e8e5f8b8eec36529044b4ea888c57792266209dec4ac344012d", - "030b31181d0780fcbff91db259e338b7ba47b18c0efb95fdd033422ba334930170", - "02236409556a8b4cad1ff34f0c7e17a1699a700979c5e2ba25a832601d6f45d905", - "021a2c0d2eefbd60ebe444d1f351510639a4489bfb6350f5d9d23d3f37120fb0fa", - "021460599a2f94cf8d848dd44bebf467795207ac954d1d41fd4e8c0b01035a5891", - "022469025767d4f3db426bc601255b9190f7c455f7297be366d0e19fefcd34abcf", - "030a923c35f5170ef6236f2e4841c80f409c39b1deea0628fe8900310e2de4356f", - "0222100f6f1f12b160fbc447c8d077b7c8f18572f8a166e13828f634954d3f3c21", - "022070cf6ed5a997ab02e25b50ebf72645219f0e3f40eacb645e0da121eeecd2f9", - "0327e498024534683d70a9eec0c5ea8c68cb681368b40d68fc769f26fab286a4c3", - "021d149906e07ad844de9f6c3122dd6d6b6bc1fc9f8decc15c84684501a2d1554b", - "0312177d92a099f9391cd1d0a38d29a0319393ebaad11c781fac3ac63c64097825", - "0307b21c9bc1f784cc3e8a2f5aa703a4d2edc418cfbf3cee6aca9a6beac4d785a6", - "0319fad48ee2b38f88d93435d42715b0b3ab5bf4581e6d18c5e23e4b0a5dc6d120", - "032c1b186c3b17831fd977089dd974abf8b6a6472f4f6c5c6b1665a654d6130606", - "020002eca96b0ae409e3e04afb1e244d2107fad0c363a3f531d856117a9b0b8bd9", - "022fee8c376b3adb76b7042cd2cc8e78d2d931dde053dcf85a4bb0004b4fc700e9", - "02267539af3fd1025875ab4b9ae2f30ac3dd2a50bdb61dd95796b85199ba75d7ff", - "0313a2e3277569683e43099dda101fd3f27b511616145ce35219677ec31aea8e77", - "021c7d4535d7efd6b6625fd9475f03cd1cb0473fa4fbf2b3c733482f51eeb171cc", - "0300e42ff6be9407e5261ddf5876b04b0558fa600ad8d8b074f235590c93d41cbf", - "0215da55673d42aadc54335f7fead94dcf193317aca45fb7fe5a0c59b0477b0ed6", - "031dfec326319aabe2627ddcc9ef0e6644d1b9684a541a37dadaca9cd4d5b85974", - "021885677f9acded9c7c75c9ef721474c63f523291b6e040c45c409ddefcf8f4df", - "030eb038fe2e01a9a991c052cc32a266e6f58035e18e1f15c228582f61026c12f7", - "032d91512adaa6e1971426993632b92d8dd5c634477e8b8b2d2c11bb9be3db3182", - "030d11a758ce1b293b452db675c652e2afdb8e61530ebcaf0043c504b1d20e492d", - "021c72c50210f1a39310ef01643a1881ef13dc740fc516bcfca4d1d5ef0b626e1f", - "030a352e31b59aee2eba2d826f98335355154c0249c2eb67f43cc6137294e82b52", - "0217068de891644cbf79b0143c7846bbb4318988d4fc67dcdef3b359acb764ab05", - "020d46a09514de6b5d13e8b2528928efe7e6d1361ea5d4edc4badea2fb5aa0ac70", - "0209a4c275bda00a0c6f206dd5dd789cbdb6d9f3493323823c48ee52cddf6e39a5", - "02038a247769999c5932eefd1508131c2d024378cad9aaaa10271c3dfd030269fb", - "031a7202f140d35f14dc1e0285bfb8fd111eb76f977bc7a89db913bcfe18569ca6", - "031837bc5ebee791f69115d14bbd2e6b07f3efa97b8d5725921b1b95f08a2c4589", - "022a503cf7535fd5e7d60f7b859f9cd6b4a52ed87281515120ec33879738fd12d0", - "0308f110d76c777c0533d2efe18ec5fdb08cc2f792d3fb06d6d7e47870a206437e", - "022220693b5a4b193b14c3543cc401d9ebdd994435d56ea6e4d99cb3c41cea40c9", - "0217f0d80a348b791016199a279cf13bbe965cd2febff9c159b634541037ae06e5", - "021467b2694095fe5c64c77ba646dcccbf59ba35f3c4b9f15464b80cf353f582d3", - "0212811cf1634265e4cdb02149fdc17b8deb396a86217394f7acfce9391783763c", - "022d7dcb144681ddaa60b42b4aeffc5fdb5edec9fb81a0d72c384b86d492832c6e", - "031a34d82c8bebda69c7ed2a45bdbc093feeb332d5f095c96a4f779ecfd104ec3d", - "032e9225f1455ead316cc762785939809a1450241f77d4f4835bf2c1b0fbef2556", - "02213a8f97d2d88f2dc49a5ec0348ab36c494537e8b47c27ec0d2615b16b8ebb7a", - "02101d76771dc058f90ab6edcd9eb270d90a9524c4cc184fb55c6d9aba18718f36", - "0224fbaba78ca9a228101a6f071bdc3f53de931e0cc7188ab0faf8c631c99a5ef6", - "03292da7599dcc1ca7da917f76254b1744b3789ee5565ddf7960fc9ae9f7413e43", - "02148261de716394f4a2f50875d8cf0d10fde80027566143b5e28c19fdf5d89fee", - "0323adda224c906486429ad7b5e41969e5b711a11f48c84a47100499522116d48f", - "021d5b177488dc3811a9190e8a4ac5386f81a9ffcb6a94c7724b6b025c3dc5c3e5", - "021baa22ee8ff1ce16c29d8e1c93baaa13f9bc64bb6c84dc4643bd05f61d0e6add", - "03166709e861e59665a171055d3b9a22b1492d148774ee5c8c0a109d2d69b0fee6", - "0311bd72cbb9c90c438aac9360f582d2c7c7ddaabd7bd470990af9e4c6e2fdadae", - "0210e5aee4df94beaa0cffa54fb96c7e32748a6769e2cf9db3b351e5f5a0a9e9aa", - "022cb5b6ac89ec5a45f9a12509df5d882a74173bae0685fdd2a95c890adc784114", - "030cf4da7b5f216549843cf2f3b180ede6beac35f10d705443c2ce8f05482dec22", - "0300eddb4d76495253a5f3f2f1fbbe60f3bc613f8309a416d8d5b8d64542dab7ea", - "0215691ae94b075b14af32e80391e485ed1327520d66ebd9900154b09d25f10c28", - "022970cc2cdad1b2bc2e87087b6c570ac7608dae082753df8f1df537d21922850c", - "031556e3768e0769b01394db248d043d2e0fb486e5f0e76eb8d9cd048e11fa1a0e", - "022b5a0a0c845b8b883eb99b4f87085c6f94c7fe68e9db4cfbc582be0c25229c01", - "020b02d0c41c4c2041100b9c70c166671b1f45c950a9f3427161e45b922a1fdcc8", - "032b2588dbc775edd286fd679832338a6f236f5566566b27738504fbed8ecd6fe2", - "03239b1865e2ebd1e5dff425c9c7b5682cdf07abfb976c4e4241de2b6d621d4685", - "022e512bd9c57b724807ea4d87537478036974d0f82c5b64e3c82958c012a9d86e", - "03143511c94c71e1652c9d2542652e8a029ad17d0df1b5588fd958cb172560192d", - "0314387da637c65527c84448fedeef45abd8bc10a1327396b752289ec3cdfd77f0", - "020f44c8650f50f2dc0ef271df4f22f91737f57f49131ca82ade69d8771195900f", - "0304d91770d8dac3fd932afc1e444e41701e3930af25f77a0afb2279f078cf0780", - "030107b9b2532c01fbd269324ff53cba9fc6e6e7b7adb7d8cf4f55f4fb374b6c4f", - "030da881d7669955d569c9d4eee715cfd4ee862b02c1d4dd3bdca24bcdb5e140b6", - "020ee8d82a105461b9448fe2f3cd4bdf35dafcc502162a8636d928ffaa247fa81e", - "020c36815788e6eb04693acd9c7b2d6cb283dcd94624d301deb65b684e4e7fbf5c", - "03299dff18a6807a85c010e6621cf52aab1d678363e6b76f9384ab6880d85a4a9f", - "03013fed2b3450f4c54cc728c4bc9edd38e343597cb817106db5ec57ac43fa625e", - "0312ed4e31f1f7eedac67c50f30440b03db7c3d67b1bdf80206363ab67fe952d57", - "021cf1c7288041e866bcdb802ec1e2fe14819088f9c9225e79973a15b688ae41ae", - "0218bda458bcc4b9bb8fdbbe05ad4b6f7333e9a2e53e1bf3c7b5c708f6d341823f", - "032ca34211e177aa0d918bc7ebf133a7aa2a8de25c7bdcb0b8fde27d3fb556624f", - "02066792225721ffc899e88fa3b932ab35dd5b965053912cde3ff902797572990a", - "020a0991233ac51bf94382a3ec4384fe1ba4374e930a97142b294182ef15039b6c", - "02194f084ebfb239c3645fcc4d1b350770a48abcf1c1756657dd56ab910cca5cc7", - "020e90dff806641190ef3d76885e6ffce6559f8c903ef28e5d4e9f9bd62139ab29", - "0226cd6791466048ccdf0ab9e510c0eb9010803f58f2d239ea1239876cea978eb6", - "0329a215424ef1336f40434f56a1bd8453af05f3d7bbf9b014227e669df6b351cc", - "0224d98c5fd08ea7d31a0f955e491935a6dbd6e43445bf2fb2a263cf42b8dae060", - "030a32daf2429f8505928da7d19900343e64557e08d2765fd5bb56b44be33982f4", - "0325c45430e19c1db5134a964566513a6fdcb9de82683154b6db5ea7d1a5229a12", - "020e6c369615bd10f2c6532362145e4160e6afb216bee2b5d21a316464c391c15d", - "032e6f1d9243a8e98d63c0ca783d0f2899eb8832283a939ee4625dcba86f80afcf", - "0305c4acc7d8bfa9d280c703988a94ecd73b6520e550949b6ca512bce11e5ce434", - "0221bbe725f22d7258f302f9c3f65687ed4892d78a7d76ae06acc8f85e943f8aca", - "0329edae15d279ecbd4f8683cda2ec5a9f826da183021d383b3c08afa114546baf", - "0314050c0062f68dc644f21f2c1510a02be105bd2b945c8543418056661c6ccbcd", - "030bf34752ede01e8f480dce3cec76c343600ce115d7850c2b26a109e8773d318c", - "021d62a126646b7d51e048fb505e0f767d8b00e09e54c2b6dfb86da6c21cb24fd1", - "022bf1feff34e667914e28e9d21789713525c505542970f972b10c860d035bbd22", - "0312b832e5f955d0b746b428cec84cb77787dc02113dd19f9e312117b4f59540da", - "03016def85adff886c45b98940cc4f2d889525b1198fcf83efaf7dec16de642f10", - "031f1c5b9066a1c66b57ad13f96d10ef74015f9a18690b1238910203f2ecae93df", - "031f06bcc383efe9130e0efcdeb45445a43b330c02bef6b2b35dc83c7c3869f4ff", - "0227804e229cf03ef07e3512b3e7738d1a6222ff0bca9ad73041ea270fd3c09dbf", - "030b5dbb9383769d2ac9323dd86288c3669c2986814216ac3de5c1f77e4a1a3035", - "032aa0f2bab9c41aa86dce6191ced7c689b4e0381645489b382e5be15bfa1bc90a", - "0217959e01730f975fe514bd09430305485588e0ab18667055e4495b04a2697f9d", - "0323817878cac0005f2e1377dc6b14b36724a10cc619cea602193483fdf116b867", - "020e3f07ed3b6c176600d29bdfc37e40fbc0243c7895ad2bf2dffd2b209292b06e", - "032a8226a22125ba8871b402e16899ea40164f4d4db59c703075035245d1abdf7a", - "0323d21d0a0a4e346f705765199de90d5db819c789d304fbde5355a383e5723a9a", - "0302ec7bceff87694cccb66fcecd17f2f03818cdee8ecf0c4a8ce04d51c4b681cd", - "021f35fdffd64f75b9c6eb676d95582e547e5997ed98121b944506230c4a704695", - "032007efcbea6b27629070b6fc58feeedf7f33cf7417bf6df9020faa7901445b65", - "0316d137c0a2d4c7eaca84b194cf23bd3d81d8e1333ed5cb884cac16261b25f805", - "020450ff50235ef7bc4dc29ac43066b1ba077f0b0fa1677ca5af0ac05ce58e995b", - "022c58b88b3759f4776a320cee104d9bd07356b8bedb99584f101078ad05bb1926", - "030bf30fc575270e41123191d84d245745618f04a11219bfb82969c64bebb42033", - "0208adce8adabd68a463f0ebb9af5022a6c1fa0d9e646f7c1f2b26a0122c6efe5c", - "0213d59650aba3d3aba9bf722fa7cb8d37511d824f92feb2e8d21585549461fe15", - "030fc24f20491ec1b5b2e016ab497cf4fe1b2fefef2f2c2c832a57b9e08c2c0e83", - "0323a858f47d670bd261d2cf0765a2f1e34803efb1e85b777561583d789176b3a6", - "032125ef927da142d02483b73d845283eb9d14bb3a14c74f1f2aaf51bc2fca912f", - "03162386919d595fa3968957eaf24ac10ab317dbb09551239366298b4c43c1b648", - "021fa97793dbb9312bf173b57025c3404fb856dd5e3dd081a2c6f4852b811ceeda", - "0306bf1f9bef7b94245b865ae8ec4482c0e3f26b4282461e9f6590ee37b0173ff5", - "022f8e647d68117c59f05c29298be3e9fe8c87e6d2adea43dc866cc732a2cb807c", - "0216c183920bb90e8a3960f84731059d7bd28d169a112acd145d16ec7df2802d61", - "0309d3cf8982eb17a3a3b14708f917f6fe335059553642dc3b441ec9e9b130e8f1", - "030cbec727a90071ba99bbf8ee5f7870ef1f926aff9317f32b55c5f23e59293d74", - "021c5ca87516278cdf36875984caed561b8bdf402806ae9a96a4119d60cfda3660", - "032905bb6491c15e644d717672b21348dfb0044c33b4df6b9a0a54c566729cec2b", - "030f8531d1ec7432a1039bb476ff7a7bc7fca1fb4918d4da639feee143f2046ae2", - "0212e6590c47d53eab42f114d03a2111386912c8b289dea8abadb1bf15f803ba23", - "022ffe5f3684b2d83f29c5d0c9430008574b2c6ab97c460228cf82749c0af5c5f0", - "022ffffaa8d59ea480208f8ab352b21f94899b44029547d271b54c1e67a77833de", - "02050b80930e916d8515dc9eb785597aa5ea47e915cac5bbe5f2bd0ff929f2dca2", - "031f43dbdb527591f86718c5f7b7c2c58d3b256e8e8bec03660471a98d2f1e1030", - "02104f22efd998356fe1b76244ca8e001cfdbccf9356a914e6cf6f1ec37de6a1b2", - "0302b8949894668ef107ab4f61f40ce18cc0e186b7ca037a844fc08245b5472e23", - "0229acf7a2c806c14ac217ceb574bd617c887381e6a9eb39ff7ee5934e33557ae9", - "020b0cccd9c7417712c6b9e3a2f818b0d3f267e2ade857d1cf09131153150fc2d1", - "0201f82e4aa313b345b611c3fc7b0c50502fb91e3f912cee948aa549ba20b35cda", - "0325e9eee83bb0a6860dab812d9e5f7e1d7491830d355b244fb2ff4c7fac353741", - "0328963ed9f5a428848629985a023f26778076729a41546c6abcff49ea49229ed3", - "03051a895369787ce9dd2a4d25e8159e111bba8b9c3200498c2c34b89f406175a1", - "0208f55256ed1001a6d7876098fe70696b308ee5e5447abf12773ae839bf15b138", - "020ccf2e2066968dd09127a370b3a6907ff223f4d8ca04396a3559c1cfcdb6201b", - "031159c8303df89382736bd53fe9d9957a2abc918f36b4fc79a6f3fad866216cab", - "020c6490eaea50e35c4054f3f2afbe1d8697453d3419e8d17b070b3d00e1164fcf", - "020878fd98071652cd7e92143b31f74bca3de02063b79814f922311e5f2b8eeb8a", - "0330190f0cca96f1c01172c5b8f8fa2edde90079c0d7ab03f3e89c80b9d9cbbe9e", - "03174a433be71ebdb822d471f34c5d51253ef3cedcb22a96c56494a3ddb8cc1d1a", - "030180d9c34c3607ccc575728922c73043a5911f43d6620d9796f39e050b04d890", - "03115476a80530cb12f842679953bc7fc58fcc8e87694247e1b48472562259c966", - "032c34afa948694d0e088b9e97f391843879b04373023a0d1e9d452ae856755862", - "0212939841e90c863e492f658d12d1082b19dd189bbedfe5891ccfd299bc4cfffd", - "022578f9c10ad34b677a3c81ce58fe7dd311fc5a6eb254d3736533cb4033cb1adb", - "020b75f79479931d371425185eab75f85639ffc7745a343ffd364d0e7b74b567db", - "02132d71d93904cde888c960465b2d8f569a85ae0540dbf7e6f54a030d1fe42f1a", - "032b1856ddd8f7a0e32c2cfd45a202cc61411675531f8deb61b2b83543da810bbb", - "0213befb8f1199349d789552a2571bc4c45fd217e1b48b128978ff4fddcc7cd8af", - "03150f2961ddb349411bc69dcf639d1b5f4f65abf8d2a41c320080ef8006bfcff3", - "030695f87671c04946aee0d9616e32415cfde779ea82ca60eca15816a02a9bb8c1", - "02236522653b7c23e5e35774c3fa1d98f0c70b68b828af667c9db6219808203ac7", - "0314b95ce43e1d13c67ffea653a8c7edef72fb63a5be33693ea41ed888f605ffa2", - "0227c1265b9ea761af0a8b5fb022247fb6c078097a6b7bf69a2e48b12559c2a630", - "021982f6c77f5a4c6427dc64a924262e7bbf95ca432da677a7285be01a987f055c", - "03210dc8dcedc32a70130f427e680b39a4b799cfcf2ca1ea28ef5ca0f85135d454", - "020c83e08dbd043130919d8d3462f8b24c445330e6b5ced6b22b6bb5b4ce44ce8a", - "031e7ee62aa3a4ccf3b534c6bf6c364bcf3dfbe6fa3e46b91225535cc00514214e", - "02262c2cef22f85ed85a839ab36e8679cb1a7a576547fbd18b8e6c4c6c84e3846d", - "032560a0e6b351be5574d1a52b9ec19698a3db65e4ab06d6d3a98c0f082d0b9071", - "0317cc8bbd4d1d0c9069d9242baf42c388dab0485ef606e35a1664339412386a3c", - "020c9093b60844894fa313c2205c94ee831881475313208659775062d6a64a572c", - "03074b7bd4a0ceba1fbdd2320070d9ff293ef9a160589c857f3de9f542007cf67b", - "03201fce87241289ed760f645e4c57512bd37029f22ad01cbadcbfdc17a27b1ed7", - "031ad23bc83cc1960927a0b1ca999cc9d718bc751ca57e8a306a76c0684ae456e3", - "031758c8e3053f5f3f8fff25721fe217a7ea1517e315ceea2ceadc3532bdd2a6a2", - "032abe07b146674f970662da549b2d486678e5a85a842df4b8c4b78d8bcfbd5135", - "030113125e6fe519cd6afa7d32a6931ccb0fa4f14b3d9b0f522eb491c118d94f75", - "02154f0018499476ae9ca21ace673f6b85bb4364957bf24952edde1ba2a1ae2da6", - "0224ea38b5d9d8da8ac7a38d935e872d95384c97600698575fb355270c4e83fee4", - "032cc9b5838f1a384a834fc06abc3f8a534134b993357b2a20ca786e4e779a9fb7", - "031b633e865850bc52a889637948ff3c922fa4eac642f562bba7c0717570c8ff9a", - "0204c6f563bfaa42ddfcec3cb3f31bd9ed62e18ae488a2ca929e922bddc60cde36", - "020ccfe6ad5033b31f102dd853826b412ee6088552ebddb10dd5e75dc5448f6718", - "02270957fc6768cfefe236be16e9c1b14d3e55fa4853fb7b17dfd2d295c19d109b", - "03037ac7714d3de816e1e88ce4011cb62b1c19fa28919675dd5f4500a2e414543d", - "021dd9394f79f1eb22241db5e2072cba447fe48ce383b53fc1d3bcf27f9f3a3980", - "0308fb7777eab884118813a500fc465e50a20c9eccfc9b3bceb74cafbe55aa692c", - "0205f47b8e0441743d1a6b2bebe0fb6fdc18a6af9c5d18437ac7faaa7d2d8e2b13", - "032b317c7e5c63c5edb95aa548e4305bfa532371b9c415a0e0bad3af440328e80a", - "0203591518765d07fd08ee0889d70cfcd8cd276c7f988d64f741f7843bf12116df", - "0321d8b29760d072c3428b2609808ce2456ea0142a15b3594b705d2848f82862af", - "020da0f603f45d2b3a43c41b419e1c1689891b2e91a6228e7db2f2867265642217", - "0312b4fdb2100993e482b65d29fec8ad5f8e46b5510a4ad4b6e0d480504bc534ab", - "021eb5c5c49557c41a3cb48da651b8f01828d966820448b4b9b9beffd939e40fda", - "0229c402c01aa47257955e0e2314e1bed92eeb2e447a35dd27c4ac3c8a389cd159", - "0310172494142c658acafdbdd3831f59b7ae5f59303facb89023c39cebe41a5139", - "03193959de2fa0c06e120521149777156806370d4f2aac5fda2322c02ff1ab658c", - "022efa6e974384405b74e78c1d5a5afbcc788043c51d1ca185563cfda5d2e92a81", - "031c5e37ca6bc6d942e14aafd6995cd87f52be8282ed313bf60173c939400a6bfc", - "02013b53a655d50dff07fcb19e70c20da101b082185aa0cef71c096f77a04760c5", - "022fe6d86e4c0a16f207b6ddf81be4bab5c9eaf21f2bfa7a381e15de2e42d03b6a", - "032f2d7b8d702d59a9a33360df9b0a24a029ad874449658360b451cb948d8dc1de", - "021a779d2472b3612aed094d3ebb1c369a663e6ffaa595056da5b3da630e1e2489", - "0321fe015b56546106b0e46ace083840eafa8a9eaa1bb5e604d6d40537a2fd1dbe", - "03103bfb1617e5f6c05df56455c91fafbae8e29cc7b9fad33b43734b5a393d3ed1", - "02146419b4033d590d965d9bf1d7add586f4c10fbd35919205f9686f4a9fbc5304", - "0213f732f4a35e0c990105c22e6c293f0d1cd467b34a4b6509e0d8a5a972c6bc1d", - "0309adef028565b8ab8fff1ea9b2ea9ea91ad370cdc846aed0db317a1d36049a83", - "02076eb28ab96cd4ae4d01f971fe09f075e661f900c1e8321d5994b9c72fc9dcff", - "031c3c1d25509330c42c1927a6f424e85520afc1823145f1dae1e5b4fc8aba55e0", - "021326f6ab4021d8371d6ecb17ce75c557c82f8fa2fba39ec263c404e64b6f609b", - "032550a988e7db5e6a1eff3b33d97b8b6bab8b4496e811b8eda6779f398e269ff4", - "03106984a0c93fd249fd49d352c909e1f548338ed9cb9aacc893d5e0bdfe971644", - "020a48ccfaec4b95d609e7e48906d514e7cf337b6606c571f81ac26401c71975b9", - "0209a2fe99003714d95fb5ec0e6385ba3480cd623e56486705fe1bfef779baa8b0", - "031bdc47dae6f74e9556f43eadd5e50ab582be7b0454dc56894d6f111af55e4355", - "0204987dc1eec9d54a0e32e04658ec6d8177dd7633bb7d801636387550a519dd11", - "02147bac73cd1bb85ce1a982eb5081e46bac226f866fab4a0a8bbc8c7a36117879", - "03189a89d43e85960b0393fe444a25771005fe689e48f033efc8e6c22904a06c86", - "031ead7a2b2ab79a7e1381b5941fc0465cd9b9e3e69fb3989a93082e35232fe067", - "0203e0c6cccb9dd27e37e63a59468d8285ded3244f686bc662214c37431b492516", - "02217a1a7571fd63bb5482ed7fd95c72f7d2364f172f7cb66bde86467761395077", - "032be71530a5a4eecd3eb03d1da4e5b2295ae10d17ec54334ba1baef16c8377f55", - "03070d82cde20a099ce195b878cc58e5d71fdc395fdbdc2a7f37c21bb519fb2d83", - "0203d16338d08a59e1004e9d05d892955b4e84f6a0aee57a23139c1f90baa87433", - "03039d6a823ab24121182db529117d25c3bd40169d8b4012964086459b43f8f1f2", - "02236c29d560f3fcf46365877289d8aa7e8859f94e92ed69650f2f9282241ff258", - "02134a44754fa9ae7fe1df7751a2c2e26727e1f8cd5f0466559c258d89c4a27a4e", - "020a618e17982ceb3c528bb32c2771dd17e28efa6f5edc737c64e3f54bbd2ae063", - "03122086ed3110c2f1a37c33134ee5a6e87e48cc6a6e9a1be65331429a78e073ff", - "03055bfd386845c93345173754c8ca767b79582da319600bc18af3971b59ab69de", - "02239896f04aa94b494c5f5a057aee23008316703101fa8532458767ca5339d2f8", - "020fc31d355945e6c65827cefdec6dc98ba6accc2db0cf14d369362da0e82558df", - "032d32cbdd17c142bfc1d2375355ea023bc0a60d851836a6c4dea6c833ed421697", - "030cb38533a3bb6411f2184d6d731721cc54581ffd7fac3b3fa16f035b8ef8dd7f", - "0226c3ac68b67e72b22821544c24de5fa8dfa3e4d9b6fdd4aac4b3ae7e26f97ea6", - "0304c0069a465b4d461ff4f555f5c192c1aadc35db39367db898385b4ae1457551", - "03241b52552a76044d99010d715619875c21d4a32889dc816e55c5db856f413033", - "0328e15721ef81043577040888696dbff9838364278487a945d556a6669e9ff09d", - "02203a58bf22b7e89cde87764ea1ec1d8ccd958ca9477fd3854065440439dd45cb", - "021064050d60953176b9ff85da259f9738b2be80176f4e80c90cc2775a7cd4d19f", - "020a40550d5f3eb35ba68decb17e94ae605ac4d35e8ec86adbd6d211a37aa70a5e", - "021d466708e5fa493a0b4d51d80f156b9a95c796854c0610c6d5def0742f6b09cd", - "0303a0d3a34e84406076ebfe1c9726d4715dd2b9eb8846eb1b1aab02ef150b72ed", - "022a82a9f98c78f209cd7248fe0eedc9bbfc076d6d930dceafed5d31cfd0ed7100", - "0203fdc11454a57bc1b736b42ca4b34dd6d7a11a3c2ce31ed90dff799607415d99", - "032d82cd94ca3a03f71d61d7d9c713399213cb27fdbc062deec2cd07fbd900e24d", - "021d0f383b34c954a6dc9c5270158c9a16a48146f4a0c2fc44721eef72016004c5", - "030eb5bbac3a173ca2f33f2386dc4504b008e4a5e3ebcec95aeac56160e0ea5068", - "030d788d0381e229b9ecbbfdb3a4fe29ed537ce6dfee82d55463578f0edbb8fcd1", - "0308761bff3db0d5e3ad85fa3f7cb94352021059dd55245da11c100be54871eafc", - "021d64f8196b89497b68ba9c12e3c7f7deaa0d2979803726cd6862deba75bb8756", - "020632423c38e3f2ca9af8a769d2bfae529fe89704e5154d798e7da040308e4277", - "032487379b11ebff71a1b305534b53ab797249907aca0d0327f93c1d5062a1b443", - "0221c25565bcbcbebc82858737d8c8229813636c5fefda90f9608d6582a8079ec6", - "021c3dc096bd5ab86156546768353775679acf9421b2c6bad5e80b7b6f7484f7a8", - "020defbf4118be514d17ad70b165fbf1da974c8bcdc08c12107f3b5e809f314580", - "0208dfd00daa3958fd76a29124b9ac9bd79f9837d2334b20a3828af825a4e7eaae", - "0216273ee1bdfc345724b268526f3d71363473862ecd7743452c9f5e0849fcb6d9", - "02005f6bf6f513e21a2ae1ffb8abbcd2ea3dcfc3673cc77cb1ed184ba774c638b2", - "02206805f7dfd04b2f5660962c58fbd028caed812e91f7f6261812eaa04985c74a", - "031f07c1b60b6bd8f43103a6c429a113e27dd1598194391b08daa7fcac9fa93e30", - "021ed908392d5879a69c9b375bf6957b9a1c84bd6a74a81feca684bc178eb20e8a", - "020e1fc19ec6bd36943fd0f6b9daab5e914280602b89e7d4472ad69264414fa708", - "021fc7c9768c9b2311f07c12ebc4cc3f8d1e00f46616f57a79c38c3b03aec7d50b", - "021f791de077555a26133b9b37a2ff23e7311c72a640d0d3b75d6bb78d0c67b86b", - "021479a9d71f516c72cadb9c8495d77a165111f4fe77ba4ef398f9912da0593444", - "031de6ae42643e772359785e8c3e162562ed05b3d172098905492aee6f6dc549f0", - "031fcaf2f37205b6a6733ed9307bf51b99deaef1d507060be844d7da9a52c34efd", - "032fdebf273c8aaa81e0721eff9360656f0dcad95f3faa1406afbdff40602168e0", - "030a37ae00f6af8d0ef71b37c643beb7dc762dca7636fd80b3d2822008f46e7f90", - "0322400af9775c45d99a6886ac8814e29a24f477553d752d690485566afc1e260d", - "020017280f5341b19aa9ac6f48f349d045b6a21941e75447e698ba968f2dc7b4b0", - "020fb3eaad75939f38771f0feae2f4954e892243cbc63e10e3c4bf6ddb84fb44f2", - "0304c2206aaa421dd76ba362a81bda864cced2db05de04d403a1e86276b56201a7", - "020ca771551d2ac5f9d822b4a67ffb963a9c0bc15fbe405adccb22e90316fec1d2", - "03123ae4d674e35118ccfe883d8bb74455c45630b1bcd6cd49405c74e11d22a114", - "021dac12ab106bcaf4beef5d8c1066c5fa985701480c1f002ac3a4832ecd4c139e", - "031e973b1f2e9a312123fa6e9d0a863c8e9d93766109284939fed2df3c2da855d7", - "0327734059c59c3721696e894923c1c0ecf2b19f0ba1dbc5aecb1df47cd10b91bc", - "02015c8970b6b24feefe24978b35f27c4538f1532f104d8a5f480ab2eb0f8db812", - "03146a087c80df06b6262e0dfc7f488ffbd8a2ca3e2d1561be6136ccbca734122d", - "0222e3e03161884dbc7446d98d3b86c338cae87980171a8059a308aaedc043d0b3", - "022fb096ea99989c1a7d59f4c625eb0f314af9432e2cfa0d4158cb525be9b0c1dc", - "021b3fd03f0bbd42f0bf5e2d006ac79e23e6cb1b546b30d3133ef6a7db69b7e786", - "03248ab82a8d045cc34e2ac8f23f52839b0aa565b64e8238f20acd576978c50cb1", - "0319cbbff1e94217e18d88971165d3f5692cb080b041bf75042919665b3b4123ea", - "0301c5558f18af63e2205dec6d9f20349682ba96adefcb82c2361b20ae64b32167", - "0316515b16f9e9f9aec64ac2de4ab009b94b474cbe4976df6c230e35e2c2b02a1b", - "031e32c0e741d3b91397090ab698156c89c8851c3e175b3c63f711ba827b6e82c9", - "0304354fcd7d6207c2455da12bad65c4ddc967ab6a9774ac3496f802c2c4473c9a", - "030ed3254e34f64df49d4fc6cf75ee1a70914160655306cada877523b0c50f67e1", - "0321a6369da827e96e7a6cc57647d4c8d1167e3f9c105b633bc85c130a522a7b6f", - "0207342aaf35127cc3b643ce1d51a9a9bdb61b90d9433a2d3c09f9697d51dbef58", - "022dbf26cc48c3ffb8f82a5ccaa6c6979ab610cd862a34889a4e4f003d25da667f", - "0217e2157752f1ffcbe984e1ff5d81d8a3a4978a1ea134e2db5a3e0dbdc8b45257", - "021d863021936a415cbcb7abd1828a7ef902984cbfb15f75be819b930af6207cf9", - "031f2da663c817b50ad4f600d1159912d2e9579d8feb3f126c05ad0d600f61622d", - "0312be64efa9b48c0acfc0a4c6aeba0f1cfb5bbd480546b737cc2639eada93eefb", - "021aac48a0ea226966c899100e774d5039ffb23646743fd1330f6813e754256c87", - "021cb855244da4046496bf71140b31c3da9b9474889f4115556b979d2e78e6dd02", - "0218ff241513d998019e5891d0130de785e678b2e3cfc1a98653c381a38b42cb51", - "022ac5bdb575bf88a5c88ce7e7b39ade0808b19a39dc8c033c9dca30f897c1002d", - "0227ab051547fe162ca2852f90966a768cdc27a1b564c1e910586c5074a11529be", - "02053292b6318e256d84a27aaeafe1fdea64549153609bd41ca63e9cedd25983aa", - "021d3f95883e68df8b3d1d25fc72fefa2f4d425fd918bfa24089aa66a03e694b48", - "0324be3515de4a65ddcb52aee62f2ce4e05cf700fcb20730a20ff46481745de093", - "031a3c40c0855ca1412682af01871ed14b94c206bb607398c658ff578c363b89c9", - "0304d6bea679821d0acb1feff2d15c90f149ddfb3fd8ca762d6fd85998f5603503", - "022b76adb520d221a25e3fadd029cedf56f7a45d76ba6cd8e9b541a55b72dfbc24", - "030bbfca2918294324eb2b4885969bec47389fa95d29d4d54e290413956514d00e", - "031fcc5cdf4107ddf751cc0849de07c541662c26b20581dbaa919da9640dd3cb4f", - "03259e44f01cb9efee3e366b39f48da3c15700dc09a1d49ffb1d05254fe0ebb805", - "02074c1c4ac4733e9f0491fd517ad1e1fbfe9a5653a5bccbd5277ef0109dbb52ab", - "02274f76127439524e12392abf117998d2a4a7aa7cde79a99c53d62b341fe283e8", - "031e9f56abe9e149bcf56c643acc9819dbc9d99f08476f149cf7dad3c152d9dbe8", - "020d38fe626b3c0fc5e627b216e77397190c781e07af741fc65054453daf85fd2b", - "0318201bee5151c56cd98eb804a2b1f9047e73b59e9e370f3b5bddcebfe6d885ed", - "02296d98a94e9fa0bedbddaa6ccb808b95d026d6ebea0139e0385e5e55566d5b01", - "032909f45b996cf804d93e4057d2e917477a9171504f7b5637a475244c9d05eb2f", - "031b8d09435a637de8c665d692b1282babbd5d44df6f6bbdf5dec05f6462bd7636", - "021bd083b038b95d0d3ea04d71d66904425a0ffd3989c8ca7fef34badf272dcebf", - "032f6e3f93510b16c9416003a896af91d5b764bb9b31898ef216c1a1051378aa50", - "0306da89d65fe07c9a8ca12a607710fc185c72b394a380a4bd64d8d654e138acc0", - "02140fa614bcf8d32a2f56ffc1d522aa9a1c8169da449bb5ed0ced5a01e2aa2cd4", - "0321a45ca1d931d89616c369be527dc9abec27d3524f35bd2efa63e6b3c375e73d", - "02094dfb3dac789fb3abe1b24c8673478a927f2e69ded9e9284cd5d3e8a0affa68", - "0204d4b788efa407358447937c8075aec39c8726df76f0a6712f09bd8146014851", - "0217eaeb739e883e337b0c99c52fdd71969faaf1f3147cff66a88d9345e71a8109", - "0304399a3aae500e97231468dd7605186fb1a0d61e77c619a8397364009e984aac", - "030e69b8815a80339b42aeeed2be79db0cc31304a3b535c2a2d71192f85cb0dbed", - "03075172e1dbc01b000188a958fa9f84c5b86025b37ef4309bf68c16756fd9ce86", - "03140a3f89a0f58827620a85fda4d50b1ccce469d6f3555c75a54d9a9d91d3555f", - "022f8d30433ba9757fb95901ca9563dfac97f34812316f04eadab1dfb89feee4cf", - "022f13d41dbf0ece75515ecea0b8664344e7610d815be9a9076ad94d217f56c4b4", - "031e7248bd3bd0cb126c03aa4d2d1f60f396a314debd0fcddf8608e0c26a8aac0c", - "020320acbc38508815c48aa8e36cd09d6ab34c7952f084fd778e93472e1047f088", - "03139d99c073839a67796ddc561a63e77116242323c9505b84fd107eca0dc73ebf", - "031042f34f0f184c21d7f01b534e00032aad9c442be5cd1cff0381c0c3e7f81b2a", - "021b5b1ae9ec188ddde2373be38c40b4548e021e9385d72f6f3bd0a2eed8544cb2", - "031e2ccec7c66ce950c547fcda00a38200273316a55e29693e1cbe11fbe9823067", - "031f63c44505329e13dabe22b60047830acf2a312b0ab123b1a5c5fc425242678e", - "0321d4af46bb5bb968f7ea3c2fcf1a25d74f147986f02fd23f03e3eb1e9a01a133", - "0306d978dc693be4d8b11dbe4d117255c525f49b5c1a14c34c91412196c246160b", - "031322b4128d2a3b66f3dedc3aaf83e5786889949758e3db764677e75380aa68b7", - "0208c600ba6e258e3ec8e78f6f9351ba1ee35f8463f0075135cde427e4c8734113", - "02024d2085b408e4c049f9be2df70e8c0fb5d6ff948bd8be88727bbf396ec0cb5c", - "031959d54d4a78a7c5147b617fb4bfb79d06af81a4820acef46125e340d8473264", - "0327a161d7c3dab9e3de9a9f5908c432f32f82495142829c5ec34bb6f1cd5723d6", - "0228ab574e9424915370e1c94f584981b9b01842d0049931855984ccd66dc579fd", - "032c493191868ff885fca56fb0c89546b928659ac1186b8d09444df9e35d53f583", - "0305994bd8ac685957402722be5a351aa93a9bf8b8d59d23c5ab9a87d5b539af0a", - "0307bca6a0fabc0c7d9dd91f8fed996df3bea00c8c9b009564dad33bc0253b4ecc", - "03300dbffeda9391adeb3dc933532b60e790f1a429a10e80c2a0666464fc9de44f", - "031ed8986f8cd9f91ce1dede35f27dd29685218f5578aa6e9f953a8d8327e22681", - "030a02dacdf20a242cd7e3a74301b5af29f2dd67a340318859cb0dfd1e489a2809", - "033023b4262ef40726304193651d5f0e15850a4dc9f0d7cb3ce7238aedf99b987a", - "03151006599a3e40d1c87d809f5d670f73dec9196e0445fa8550ee66a2aa24f1b2", - "0321dfd88077be597572d401e106302e77f3548d20f73272d32d226f9b9f419c32", - "032dd47d3451f4c9ee3f9f1ab0e8fe2eaafc703d12aafa4d645b0a061f2b12ec5a", - "032f44f84049d366c5f8f543510707666fdff362d6f7df47c345c2f29de120d5a2", - "02179c05feb627f833cf65578b99396ff9fff92a7026b79c8f6550628958ffbb7a", - "022ead7e97bd9a623d70f6efa142b5bbb329cb33f30280a9b66e353f825a72f5fb", - "030f8bbef72a18a815d920253b8034aa883e9c3b502efc1f43b82ec8ba89e6123a", - "0315d498f0cee19f8973689abd77fffb0f258e4d03779ae440119717465cc803a7", - "020e43890642e69628440deff6fa6c0fd3e5c6bd4c30d10c20910412e400b028f1", - "021c06227ea4c89d8109df71a1dbf503114230324331127952899505341b5bb1ac", - "022fb1ce018822ff362680b9ba3b71a14047595dda84844051a2f28c1120aa88e5", - "021d038c66d0ac824c0a362c0678b8c970c31b77d42f1a4ecb7faabaef16ba644b", - "030f9f6b23bbdd7c1785fc929d8ac2ef212cd5fabadc2289fb8107c2dc8a52ac2d", - "0222719f16b107b5cd4e9cbc605827b7432190d911da2254728ff780e90e9c8db5", - "0325b26095cf640f4a7181d1a2d53da12d70fc563dcd42e1ca07b72af94a853bb6", - "032eb6376bf557b9e627be381e3e918066adb39fdc7d8e06be415d5833700d6c37", - "02305d1e2deb037de6a3b58d4fb09f46aef60c3b74fbc16b7dce87ee2e7803dd89", - "030487d89a302f2fc503e98589b712e1fada6c132362c41ac113361cb504f6eb19", - "0315a24ab4c4b4a490f77982ad6ee0971dfc72dee435ef7f5099897b7e2155d125", - "032c78742fb8a4e0a71993005d9b34b2a8850308db137e1383641bbb9549a8376c", - "021034f04a05c8177b515b282ab807c8ec16d22f653517cc0bf0db7267c6202f16", - "021269cbe4988d6ed4a86f260216bac8e19eb9cde2616ed3c419512ac2ff1704a7", - "03080eaea607659121dec9b5ee3b5bb4122e7fe53a6dc1a1927fb9dd530a78e97c", - "03263a8cb4a6e0cad8d6f068d47c27307b350bce2fa54a538927e81130c8c2f022", - "020c139b688af7620d664ac4e39a846561013bac3215360c802997a6657e5e1010", - "02064dabcc36a6d2e3d53c892ade30b8a71ea3e0bd68198c99698c827f239daf96", - "0218a3fdd861c22d63c3f69807e502fe1f3f1d9642be6955c5e3577e66d3d318c3", - "02272fc1938e46908bd2a9d87132e53d647474aede901a4047fe7aaee66e8c6cc7", - "02172c7a860529690d71691377784fa4a39d7dbc3bb7a894863959e4a5c50984fc", - "022327241c413e01484b1c316528da4a67c5794bfa0e973174da45de088c4d86e3", - "021b26d06369c845fa9242cfeea7e43cbaed34c7729def45fb3f44c74288fe32cb", - "020638b641b47b31681904f31dc569566c326daa8d2893ad50eed57ba6bb1da4b8", - "031dce3648376a6c4d53dc1afbaa33a167fd7fc88cb54eb54ab039a59e7ae27647", - "0317529eb1a0331e49b771b5b7677567ac305be20d74a77ff093305211a10010f5", - "022be13aa951a3ce5b2894e10875574adb5a32a64cd6372035bbd0f6b2e374e876", - "032e148b1fa45470009a5d09be5cf8351da2ca12c4f90284f6e98dc5a251b3a583", - "03183fc8336722de432d46b5c2fb856e6271e2fa8f02dc8981c6cf2a3aedfcaf99", - "0204b3e4b99e5508808ba3177989b872ac8048da07afdf4a3269f3d108cd9f52dd", - "032293bc2b4a960d715b4b0e0ea28fd1b020b89753015369155bbb317a6292e8e1", - "020bfd5b7d1e8a0ff9e542a3892b59a60d27ec8376bdce952108a6ef6ec8b2ba3f", - "032de04e3a1295ca66deaab74313b401ed24ee38d26f73af0c68378a5c2a91246e", - "0315f591b69267c14de530966e9b6f49271d8763aaa238840587e4cf9d29bb9e0f", - "03152191f28818b41be320569fdbecfc5637a29834393695dbefd684567ec21b5f", - "032bb910b1e62984f6ad6213d404714a6f0193370eccbdfff8d885911989225426", - "0225851c69695123aaeb0c0a419aafa81b31149e14a946ed9254900a1c39211682", - "031822907bee3815233f0e67956e1d11cbe4dec84d25f11a221a83b2b356d4dc26", - "0223119e6b44c981a000411808a9fd34cf0a9188e9cd1e3df8663641a220f6ea3e", - "022cd499e8fa64cbd10cd090567008e9099adfc1e780a9542c53268b1f14421867", - "0218b8aca2ff8f7e3b90837defce4713c0c709aad75e2c85329b6081ed124552ea", - "0225aedbdd7d63a6e4e0204cde0cd2f4cc2e0b566905eaa40539176e952bf4ca81", - "0228d300c3fdd2ee93152789e10f595daf215a03d9879c9303ede68d0c861a38cd", - "020706aa509d037df2bd79bc0495d32585d3917c6fc1bf7d3be8c0a1480ae4f321", - "032f7f45aaf95f49aa811ec64882d951e09eed2b8b54248b60108ce4dea2cc2e9b", - "0200c30b7c30f58bffdc3f56cbf5898f4f63ded70b39ba14de1416cdf166c07e2a", - "0216e9a90d0b385f51caa3012810b40ab06689e9cf63e891c9840775960e38b182", - "0217e32df2d3e3ffaf35fbc3d68ec0ca590d35ee58cf20e615dbaa757b0a65f8ce", - "0219fd5e10d9cc255622a3cc2f4ad88824c11b0828d2ec6613f8bb9c8d5a535536", - "03280074e7000beceadd99c81be32d862e83caabcfa6c60cf6ade3dddeef681a13", - "03031fbf35ce7b39f05849570a9e5e61a4bf708c01d8e4ab3c1df3c96ad9566554", - "03195f3c317401bcf5baae65566afb50727edcf217f08ba33f47b9265817c11fda", - "0227874d368b4b0a4edb778af37611a4b89377730280dad85da9f5ea7b3cfa283c", - "021a5753706b2b666bc5118d5e56dcb9c94d9c0195e5d4dfae91ff3e3c63e036cf", - "031925df79a79579dfc1118fb52358fd63ae6323213730e5fa2899272e749cd3db", - "0302c1b0f9a2228b73bf31a7650f13a00fa026d4d4b0c033016d146113de2e08fd", - "0329ac28920afb6344af2c4cd012fd03c5799ea62e3d4d635b6172e1b578717d37", - "0210550269dc7abcd566f0ab31e930d6ef6336f2563a7143f5e3742c51fadb6a78", - "03150bd0d1c557228b676cc2190cc851d7201e1bc9ae200c9052b3a22deb7a7d1e", - "022ff81a20588a34bd915e006602b59d425e2a36bdb758ee0e1de5a4039ca95651", - "031c9292da54269e684114c22afd77ab7e09f187138fe6fb1296ff65c587afb062", - "0227df4c0d25238b295044496599ae50ce568fba3343c884bae73819e4987d7587", - "02119610353efef7f01705d2fbd1a35abca4e82fae5a1e8f717c2bc57db3a188d3", - "021f41bd67ae4e7ced6481ed3e0c13a2788bca095f1054acef2b35fb4872cbda1e", - "020d3798313bc1454eafb01e910e777140b4f7c000a5272f48565eba4e52aff8fc", - "0222933ad06cb6fae5787f57d2fefe4677d1959afbb2a50d869dd21d96e4821526", - "020996c02acd8af29be97a24bb4c5795857ac0b07549dea385f8d4b9642525da6f", - "02018be4faf684dab9dc7468a8df9b58065ad66921b08e8dc0b64bdfd8307cf266", - "022d2923919e84adb634b01a0caca5c30e27fd99c2a1d5f19d91d029b25de96c6e", - "0324e6403d5972e054940cbce2d5aea5dc298b9e107a2e03f80e80f1f73dc151a2", - "02195cd5deb621f62b1f3c5168835eef77621635d7ed9037c8268a59eec76e90d6", - "0220342325c09077bc44b6c9fa3e2202221fc89234d5d56eb4650f8b14b5293be0", - "022784ecf3bda296db3a5bb56fd36048d284463173de42672216819e5164a4b756", - "020bee1213680793c93266cacc6e2e9a83502b02ae3bb7e7ae93779785532eb10e", - "0207ce49ccb351e7ab6625dfe3a7cf4accd06ece7897f725ddae48c53ee06a0434", - "022318bc6c064d8105d1d33a383e4e057d161a11533a279ffbec315063c2307950", - "02043c5931b481657200aa626f050d366ace279eac2b9c52c6b9909b539206e2ff", - "021e785ff43043dac48e91df3eb60d02e1b3a1f67575966daf4fb53512b0b1aa0d", - "02122a1a21ef98d8a142defc3332b8ef35f3059fb0f2491056c4ba470fed109043", - "022905ab318fe50803a91c9cd53542d293d52827e18cd62700de3806777da1aa7c", - "021ec734c3b9e43c9039df57755aaa56a79e9616151759cab900da00370ece88ed", - "02056c7e1ba25c724169cce2a793b467238f552185c94351b8aee95510c3bcff77", - "022e70a1b20f52a28bf0badea650105607685e8c485faed3ccdc6c7c63c22aba3a", - "032298585127d5c10a8ed5328aa1ee7c72893a2ebd55f7173eae24ee6eb49f2f96", - "03296c8fdea3b78bca50d4cd526e70cda6ed939bd14000871f2ff6ad6a84adff10", - "0222e72f680edfc7b8c29b88465aee3e38cd5011f2a5058de1f400f3e0366d8a66", - "0321502dd7f962313d89ec1376f34a833aec4dc64d4213974b610449903844863c", - "032bce4ce3ff0753a71993fa465c3cc4f32c589b8be60c5a40d39faa3b4284eb32", - "020fb602586150e1976ae3611e4c4251f9e54ad9f901ad3c1b21fa013786a84699", - "020ded0140be558b168f9242e3693771b7de921ae3dc620742ec096fc81bbac58e", - "03143c37f6fa97c6ca9b93b8e342fbf2f7594950a818d1ce0920cb3addfa238745", - "02134a6405049b619449061212b688011364fc933ac71bdfd88dd93ac334206265", - "0314a275c70a06d065c073aa5e546731da700554219cce42e2b447eea95843d8c8", - "032e3cd041b7a781507939d707407d8553868068bf3f51b6680a9fe85c0363a004", - "020fe9c61e1c6fc5edd27f79fb7573810d48eee0c78364d6f58aa2b8baa7490a36", - "021e7fde10b4ab413fe14842160e7e6d9959b7c976842ded722d749b707693d4a5", - "0223a9d5a534411f11eb8a2d5ffc7c532bc17b0f522a0b3af02a78be6e1a36cf0f", - "032799077ddc694bddd3a41cfd981355aa6c789d5bb59beff759faf2fd6715a98f", - "030cdb850e3e78888462556f6a5092725b6cb9cb800b6fe8827aeada4b604dda01", - "03008f8d130bdf0a7c7ea7d0d2765f26b44ef4c5889cdd440f64e1db863d68f335", - "0202ffc468cc99130226e39383dd619e96c9f4b338e6e8418e431b8a432b1356c5", - "0304b89d83198251ebf4d60bdb45cb6c67663e056b3ed7e9e30ad38098cabaee64", - "022276d0e18180def4f0bc2f96189c3a601ae47ff7e8fe9f8da00d2e79e13d4eb1", - "0229eb786d7ec09d065268b090ae10bcb41982987716ca04cb6652461682381fa8", - "022d196213ec3f0f1961f81803ce10f72d3df298d8cfa8b34e57572a4a88c4df54", - "0327c8b4c7a83cef2373accc86eeb2fcd2a43cb6ef0df7b53f040e85440475d83c", - "0229f6429a545a4768c9f8a62352e9fc7e27f9a0b71ad8f95f3abef5b4c883796e", - "0217564478050ca10a58a3ee36146552fec8e283bc7ccf88fe2143dbe64cde065c", - "0205fb984489f245d35ad8f1ec2e59e982ea3e5ef61abac90917579ba48f04c566", - "020c3cfaef14ab76ad99b2041d0f78458e6b2171e02fa9a7130100411cd74ac0ac", - "022a1d086c131b5bec293fd7faf4ef69dbc9e33015608950a56c092a989f877483", - "022d77b31804297bd72d76f84b6ec62c7b740569ad0ec2cf29c7392a5ce6a7b1c8", - "0218bc70ab3aba445d1b59fc766ba076df856503d42d397398c4057e88cf0716c3", - "0324b4539d23590347d9654a68353d1712d8e4a03116380d01b578845b6886a604", - "031aa1f55e5459eb4d0e9f6d3ea7482e035a8eb538eca5d3f1d8a29adaf97d2480", - "033009d4fe866ad1dbc3c6f123746ebfe1e8bc1708aaa584783015130517ebe784", - "02267a84a0e7142d18c1e641354ecca9393c85c9230711293fff802193239327e1", - "02182c7a50893889ea596f0637d882fcf48701e30911cc1b7767a8aa2aac6aeefd", - "0313afabe1b2f89f45834c1153b33651aa26c06d03a512f4aa0c6da0aaef17ef90", - "0303d182c3b35422cc99c2294b08078ea19158d69e6c75a63c3843b13bcdbd580a", - "032c1ecf0afa43577ad07ccdbed480a80f4e5cb40e3c9dcb577fd55c42e7dd9b49", - "0319abc00d3f6b7c4d8b5201cfb59aafbcc1b2a31b0733f5a0a48f8ef35993b4a4", - "0317f77237d53575015389b00e141a5b106cc2e94cafbfb356e5766b62c3ae4de6", - "02022019da010e47d68d0ece89b97be5de3f21c835fbd77ea031d34021bd33342c", - "032860b3820102021e1f59b63f5e3840fbdf00e9967aba106564e412e32a8bd6a3", - "0302d0343c1d47ea9f9e3622559d4dc40705c2ce3572852a3f409036e8dc52e509", - "031436c7b3a29ea4f20b6d84b548d867ddf9b87433b5e200fbb401ac6173a69ae5", - "032602646e5a628ec4d2629b6814c7e93b0d0f97e2eb219383a347f4c66ac5f91b", - "020c58feb94b39ff469cb7ab5a4f36f4a4894e79e64a3c083b90a8107e6178d9ea", - "033053f2059e201f4764804dba1d0f811bc7b7af336e729aaed13324139eee01f2", - "0215695df82c095a090822bbefafba2c0d1c2c67e69dfa73326e2cb7489a400709", - "0209d678a6a2f7641cb44493007204be59dd08a71f49e7e86fdaa46e03c1b2a991", - "022e075ef0aa3c8865b19e5347950300cc192af494512d6cf0e2f7c03c319f3f03", - "0311ec6951bc410f796bc496f2c65a4c9c091d97d5109a29d5954e2671621250b3", - "0217bb0ea8251120c8b631fc523ef31ada83531eccc98c48c8662678e3b0378754", - "03206bfb0356ee69dbf5ce0374f696d53edf6b3bd2c7867b13b11be9ad27938ade", - "021e7ec887ef263338001078c4ee5442321efb270d646e23c5ccf2c20a7c8e8996", - "0315ac5d39f0014664dca42e78407da573d4f2abb7fe7110edfeae2161273cb1eb", - "022950356b6382430f7922fe7bccd68bcb37acbf6261c587b760e3cb8f3bf75c9a", - "02289e2481a3cf6d77e0be4a603663b854b8b68b2394257f3484d2ac1752630936", - "0318e9235624dc02f650681ee077a817b39bb21d50a388717815afcede6b851403", - "02023bd6d4dff77c9b59de480f34e35e5bcf5188f83c1c108e02c75894716bf9d4", - "0203a66f02d9c7a3aca84a2f9efdd5fe252e5c86573f931d1cfcc1776beda5b86f", - "032943c3691ce0dd2294dc100c9806542ec5772fd88ca073af462b143f88a43aae", - "032df3ef84436e30fdd07bc407dd3963ddd69a4f2a9150426663ee7972869fd082", - "0207564292860a91891368eb723af735241b0e74dfc90661ef5fd18fcdc12e0958", - "022a94fc9dd5123b58afb0f81e9021d0351b30ced9bf1f47b9eca739ff4c20cb18", - "022f4844db047e09303c64b7d38075c9b2e36b467b91c9f4b0ebbe7051a27d76ad", - "0226219d1768cb262bf8b49988561344da73b3d1d85d45e0d2d04c545e86568c36", - "030e8d76b9f529ba7432a4cf957920f1f54c9468a4ec45c729089b00cb020c3034", - "0229a182c5bbbe5e6e53c73a963f17bed4337637bda261136962e8c586a82f4a3e", - "030895cb312e3293ab8ada1882d4627baab763f5fa4073a5e617384ad8c7b1b0ab", - "0215a0381f2cb43a8766e78a0d4d16f7efdfd3f5933c4ab18bb64c2b4ce981e9db", - "0304ec4f661b46f9d579fd58d82c1b9ce6ac11131fc1535b8f4089d5b8157460cb", - "0225a7ce46995874bb20bbc0016384ef7be256c126eb6cf21cb37306f1a5a87045", - "032af25608b96c81c256a8875a16aff747372d0a4b7d41a9509e930110719dda7b", - "030b1e6953da700a57657b38ea35045fcfffd49b7ca5b80cc1eecb1311b1418d22", - "0203577b9e7efb8804825b7f1e9d1df791caea53755df314623edab53fb4d2e929", - "031e1b54822e52883232dae6ac11b97aef5b52b638f4807a47951b15a8b7dae514", - "031177b0a230a839ea5e20e25481cb059476a3c035bce9bcd3b160061eda90b8a8", - "022392ceb06f6f7d029232fb3140361b2698d2ac7a77008702ee0987cbb78b4867", - "021c5aad8e340cd76f7fd0492d27dedb5c125cfd36e434f039bc8da7b4da999d04", - "0324777352285696e27d73b02b1698ab0af5f7a2f739d540f26f9da9539054d35e", - "020d156b83be400773bcb2419d5d5138c3b20856b0afe31b2cdedc5cca3b970d1e", - "0222f567caa7bdb5b35d9cdbac648fd858f7d3bf324415e9eb4fc1a4b6c2002205", - "032204523568b810641950226a7ad531b6f9354047fb5542005150831eebdcb92d", - "0320ba86959dfa40a5efef783fe8e79f6fb775f0689a4d3da0302a11bff71b403b", - "021a3c054b1aba070a33e530450ec0f90d991eb09f58b8d54005f4c17c5859468f", - "032403471d35d25c1de35980fa9448505a405eb70eb2c4785b5fc8c0cffab99cba", - "0325c0c1c2a7488ead6828f0bd24033be93083d7a782a69c3b0a70af7a129a7805", - "0219d88459beb6aaf22a15656aa229c35cea603463c9ab5ffa90c665ecfee22f14", - "0208469f08c069493f85e870e414baec694030cd625ac69adfea4261f0977483c2", - "031c0e6634a85875def975350921da166011e3abf55b581dc7dbb9c8fda9841cc7", - "022f46c964b610941491ebdc343582488b8de2bcd363661fee2e812f59b222ea4a", - "03106d0e54265f99ab61d724121960abf8b1f512d122699814b75e9ab4ed7eb194", - "021ccd5c0e2099fdfb74880f718489f757a960e5e426cc9e963c08ea708fad7668", - "030de19a9a105f9202e01b43678d1a810be55ecaa289ea6d2b5d84fdc21062dc69", - "0327d3d9af3d711ca27d4a8ee4eba1b7dec3e6cc11c3f62230021bb7ceadbf8092", - "0317e5157452d2a8aca7d43f95f5b3e73244c49823e588330601cde88564dcd0a2", - "032fdbe5bb5e45f7adbb7d580a6a9f7377caa0efed30dd293e6533324fed940c37", - "03161853fdc317bfb13812f34191b2d8c77d9bc7bc1d8afd68c79d31a1d367f980", - "02280be1334de3c956b76d5731d82f68420558706dbcccfbbeff55402772b0c155", - "020d5eddb8106868caa2f2b9552cbaf96aba3eec44092ca3add495f1ff15c7be12", - "021626c57ef117ed44b91183ad2cf338021e5f1fee4c749e52532d0fbd2c3b4918", - "030968acaa07cc0d6c60f48ad429fda0b540dfcd54bb82415250357172e6f460ea", - "030cc1df69c200ddd5a2e72c30a405b44e2c5f9644e52b1b29c73ca66313d53806", - "032f35f35f925609c9bab1bb1874bd1a5e02db16d61d72cbeabc41bedeb95eb775", - "02292acdbdf4d753729f7f934f8580de0ad89396665af1e39bd5087f20b2e0420b", - "032afc04c3d1ff1e25442b55937e5d3bb995509633627d524e666ae033e5a55cad", - "031f90db1d46b0a87377c07a573fd8be8e0768a122cd1f4940279ab420f945a366", - "0218315e32da8f2d2f437ab27d848494f3d5963783c2462eba4d45322d01a1c9d4", - "030b90afe200a5025cd9dd4962748c329afb12b42035045e7e48c021ae227f4edf", - "030f7374c5742aab78d1b0a0fe0768065f9a7a2ba6384ce48acd1d88005a9a28ac", - "02255930853702d445ed5547a130e24507b4c6dd6833fc82064b7e014d90054de9", - "030f2a7a3e1eff6189077ac4430fc1d830395a87c4cdc6fc4219e1e611928f66e7", - "03138f1adb18be240039ca7302a6bba923f75158f93509aa90e51bd930f6ec4ebc", - "0215b7b2039ac2220b61c6f6e8c978d6334bbc87181d2550393067a7229cd937c3", - "030efa7117c9c386e71461e96a9f8bea25369ea3ef7313959b45aa53e90b326004", - "02110e57bff64d80684a85d610a1f862373a0c646398ee90010c6a9a6682b17a72", - "0315a710aeccbb7cda97fe2961fc975a4c4e1d932339721e3904c7b79183ee4a5e", - "0200505bda3b38b55952d6a4991d1fd07f4645265200b31feb53b6634fb4a55c8d", - "022140e217d22ef2949c595f7a6b242da6426f8d9e82c9d024511e9f558c1b637d", - "020915620ff8ce246119d5b074de935e7a071d142daf8cc4339192fd8ef10f01b9", - "02004ea03d6665909c8812840c0d37049adc92852cd7ffd2e0238b0e6269cb920c", - "0316c2acb287083e490590b947b2002b66ac5ba9e775fcfe41feb61c35b04548e9", - "0312d377f588fe372bbf898898e16225b46f9fe2b686488534637210bfe86e37d1", - "022733983b5db2e7e15c4fc815336f0259264072655fa94a81fb2fce77cfb68a50", - "032a08cf29fa3b0ca0753782576055a437e42882b0bd216128627c6cef27bb035b", - "031da96cfe356ecceca0d57129e414eac1a9cab522f46ad4408d42fb800259a125", - "0323767682186fa3f7a20ee7d445857b748c975c3b577849834ace9d04ac5cd02c", - "0300123e77744d505a11886b385ecb1e1a5ae1b144d87ecec2aecafc226c315aa2", - "031a0d572b460c09e73ec6bd8e3faadd4b515d2de4871b83bb43a4a799a21161a4", - "0207e87a3a3dae7de583d5c08fa27e0cea16338ebb976844ba281fc34da810cf14", - "021eb6fef44a4005a1caae29971240771c2e0eaac715866d026b410fbcbcf39e4a", - "03099f9fe22a9617206f4ac00022ff988103b115c619bf3b913744271b0051e65e", - "0320a1dbc5846fc2e6d8baf1e57a3c0cb7dcc568a388895feb147ef6e033ab134f", - "022fb2c649fcf8cdf90b271f0c14f92030711f2918ac8bce3745603593a77f708a", - "0223cb8bb0c413d54ef3a4a09840968e944286399df9fd57f0799b28df6881c4b4", - "03037832ce17bac43ca9964d84961e093e11e70526374e7e5785e43c37c8cbed3d", - "020ca1dcae391177e467f17623208086b36363d36c440b711515cafa070347d222", - "0317a726d871937e85fdd830f54f21973ecf93fa12d7abb232be33cc1bce20a4e5", - "0209b269038b47beda3a3aff5bf579846147ffdb838c0e1651ea16a83b46392911", - "0220ff73eda80e4fa99b70ec77ab6c7bd03fbb9c2d47361202cda8b7037fe8c935", - "0227ee35c3d15f02a3c82b8b7253493a84c2369f7ba665dc059b3e2a1e720e93d9", - "03167e5662f0cb892884be7913969f8416b1d260d1a38ca6515575faa6b008c047", - "022af592e4d69c604c88deb7886a4317845d32e5012405660dff2404918385f21d", - "030c678822fef0b18ab5179187bf8fadf3c25d731eeb168ebe0330a81556346d81", - "02163e5b81e85c7a47a6c68081163b084e1995b6f408d656a7a05aeb78bf00dfbb", - "022831a25e769917ea35da3043203cb83b6f223081d99862cc37adb03da5e4d9e2", - "0219c56679d8baa9d12a547b8c15feae7641d6c637ff59deb415887c67060a416d", - "020b6a645ab414b96bcc6661a42215756e7619ffb115ae2d005f6e1e8bb891b63a", - "022b9c8f7792ef53b20ba2b0e9464ce0c860231f7b7e1b6e0bfb3cf25813082984", - "021dbd20e7e61bedbab029fee14191559e28b989e2763768fe6b6265ceb6eb7a8c", - "02190a9c774b18dd05f71e93accad1b7f58c548f3dde2e17a6287bbc34cdafed2f", - "021c44f89257ee7a175f63fd9adbe7436ca992f24245d895de34ce138df70ce113", - "0314eb98196f9f67167e30387907d934116ddc9091bc398a99f924fe3fc3a6b3b6", - "02126a18f0b652d1ce03e4b9557d92cb698a8e83ca0ff02c70e37429e29e0d10c3", - "02296f34fa3ebcacbbe4c214a343b6627b16ea70cc30f57375966ce99401978318", - "020277096766712b47a29d381b8e8ef55437a6b7c7ef2a9f0fc94e08dbf1091f79", - "032e7bb8388e4d989e733fdec26ffb96465caeaaf104b81ea7f48f7c26947476ab", - "032bcb234834401433716b956341ed827e0fffbff0be42ca8e562c624a0a463169", - "031803601cc51a17b0ecb863b51443509664f9c4762c7ee5d253c18ccc1cb67cae", - "022bccfa9619e338dbfa0136442bda7e1c9bae1d6345194ea76424b9baeadd4525", - "0213a5f42607695227b8aaaf9e5bd61bc7b76977c6419fd5072009ee61c3283c2d", - "021f056eadc70ef4f3f72ff0d325db2d9f0268c4ae980296b9a7ad970e8932b2ed", - "0206a6c87bdd118de9ff5baaf32aeb8411d3104311c73ee1a5bb5cddceca75794f", - "030e007c9ccc4ee9a45d828a20034cf650c0c742fa732c2796837da5f72074be1b", - "0301c81a3a0828270bdaa188fce0e7098a9d384a2277916328133da1eaa9f5f45e", - "020dee140f471d415498d09b01dea6a35b5010f5b5f6f2ebc8829316db2652b513", - "021e35ca4a63ae61452557563cbe22cb8c00135c946ecb82e774dd7e1fcf548fb9", - "0202cd7016c01fcd3cfa79e68a47607ac28ef254405d396d1e200af223cd4ebbea", - "0206f9e56884ededb090033812257d3be92cb5272f9a4582bbac3a21f29463c607", - "03181de39ec28ad7a7c8d800afe167bdb09df68bfca5c0a9d8efc59fba5d9d7074", - "032ece8ea501b552ce78f7babdb9760bc52a934a3ff835097aae1957291d4ababa", - "022b9cfe2729c2b96518003e082a7d749fd7ba0a4ef89597050c6b8eeee4932026", - "031000a261e2f34a3bffd596b13994c2bc11451fbb836a9bc4d4191f8f8caeb252", - "03241cad2526de199946acc1990b9da2bc7c17fb10ddd1876d830c1540345c697e", - "022f3a86d576c468a035c5bac28b6ecf1cd8ddd77932d4faaa5204335a4cfaa8b3", - "0201306e158fd179292dd1c6fbd2f703437fe2bf6ba4993f80678202e2301069d8", - "03070df028bccb292b0e8b3ff7650a924c8b045a9d06953de907eb1e1f6083c9f1", - "021832903aa7a8bd5a4fb1769b785e2f22ef45f5e34e998f5b56e1ed7b9e171d07", - "031d3c46065e4777d37945db37f645f64f5944946ff11c10657911f07a3fe0713b", - "02210035377d07b74a2181d642e52174056ffcef1c799495c45a4a0f81aa8552fe", - "0214d320dc41aa66fb95e7fd63291c65c1338cedd691963f46163402366def4bff", - "02263459c19ea97bb5502afe9b0120bc36936f55e792dc6c38af1dafa157205301", - "02014f1bf72e7665cf1bbf0a7e44b6665cdc58afba75195eb04fc549417bf8d5fd", - "032c1e98e6db410a596949e41c7aaa045597a3db1e0b7cd3a2ea2f13ae03a72ebd", - "020b96636ec4161a6eb3e112279ebb4736098b27e7b43820bbf5b4b759e9d9d72c", - "02074d4c9d36e32bc72f8071746b3db27c69cd954a451ffeae1bee23f86ad4aa48", - "0221e0e05429dd283ce127e728e964a9be73caa765f0938a0268f84480c2b73ca1", - "020e61667d41045e2ebe702cc939e7ac43ddbc7dfac91b1c9dbc68d66deb570fcd", - "0204dee04d5c5a8baa375f04d6d9982b4be905d61a998deb9e8fafa5ac9bb634a4", - "021e3910acf7dff945ae12b6db973c3570e067a79df98bc16814c8609d32c5f9d9", - "03101e5384659b73b107dcc7893a6f80184a5bee704cc5fabd3269f931cfbc54b6", - "03083a7541da0cc6d19c550d2be7ee198cdf4d668a398ea57f7fc33644616d6c7a", - "0216ef11c0199d93910a75b8bcbc45f043a60b557eed9f89d139a50d5467c13d00", - "022c970b2db8af3da464c519c1567d9855c43a501ca88e58b37292efbe14f5cf47", - "0227e27f45679c105f3db89c610e882f7a7dfc3640dda3b3b70a8a9ae9b5e03ded", - "031e1e547e108863a340db27ea2107a0fa7464e4b57e535b41adf3e2a76e3b5592", - "03187f43c2621040f06891adbcdfe0cd806b81874d26c681108b4a165aa942efcc", - "0229f7d045ece7949ef8d32cecff4abe222f86b369dd5f0d3119bcc74112ee8d70", - "022d67f0d30bde0bc25cf9aaf078da4cc240581f05260da7578d7257ab0b0dcfeb", - "0207d635397bbc5b19df72a7267563f00f9ee79b28569032968ebd2fe3f950154b", - "0301fba9436cbbc3ff4ced4e24f1deeb93073dff7fe9acf39c2c39ebbe72aed157", - "022ca10975dc834ea51e086e716338e9102ad5bbc6cc99205b959188e5009ad4ab", - "03200cd7eb1970ee541bc4224ae61aecae989bfedc4067e1ac923b4f9578264960", - "022f05ed53f68f7b2773ac82f748666e82279c04484ab0e2dda6b1ef390dd26bba", - "0218702663b80bcb894297171386d707af54ce067bc58018022ed3d52c700b60db", - "0306242502e3319afd65b8f665d2f51df984a99f1e47b9ac1d2c50aa1926183142", - "021f0879e0b212e82a74db6d574b710d7bef5124b14163611c7f48d059edb5ed52", - "0329419fd169be1f404cd00d0372fc5a93c9946aca2c677b90747c06eb343b4361", - "0201f991569c9aa948c80babd193e93fb2c212014194c59472a17d97d1fac673bc", - "022b693979d18a3b11c53a5ae6bf54e55845fd7cd1caeeb8fea4f8d34ac2d089b1", - "0305ef18c36467146f92a6a9adc4d4937f1a04375f83ab3aa7ea150426b3146c69", - "022b9ba9e1d5433beed72150ef357f5850b145a16c96177fbec4e27330c96e526f", - "020428ec6ebca48f337d8266598c19c2a194efd2cb90dbce39c753cc5efebca179", - "020dea0b0cb2992fb52beb44bb424bf5fcfca9c89a601e8fe47bb03d03f923a1b0", - "0205760957dd0733a4005d566de5685c5d4601a71d553e1d195e9663bd755b4797", - "030dc3838ddc731da5e25ee397217857ea7a34edfc95b89c4fcb9d01439b5f6a7a", - "032ea105ac52bb6d7914f33967da2d3bac0c1128a2e66a4443face2e25925d035e", - "031803e9451feeac10248965f8890e20992ac8131fb2060fcb239cc4987c9f0105", - "03263268c2a92d09bacdcee5f74091f18a8681fab6ae18ee427de1f9123c17132b", - "0223ae4b9693f970d18109de0a117f006d30c11df76bfa21b6120c317e16d13012", - "03017956e696c13df8ce5010657cd2b99bfdaf5560ea18dd3ae4936d9e18587087", - "030d10e5ecd5cdc870967b5c5adb432957405d066738dbde720cb9885e2a98c13c", - "0214e7cf4280ee0d48555e138b335d3cb7facf9fe3ec413905ca7a2761c2bea704", - "030ebd9cebc770e9eeb28176063f99969dfe3b3164807f91c4c24fd95873e09922", - "02065f99784daad60c0ffd449195365e4620fa6622356eec2b340dcac85e9f778e", - "0201970af0dbb01bebf518da6321911d81ea73ec1ed864ce3db7a46460d9894316", - "020aa9b2218265a70cc7d60f7dd2ad7d54ee678c8c0e892268abd7d78cf3694cf5", - "02073e2ecf5013580b01ca79bcb51a4a99546629f31e94415538a9094e8e2a172f", - "031408cef02d121d751a3cd983d6578962084c2668b6191d0bc9313fa2ad3f483d", - "02161642cbb7d7f0b003a1b756447f94c3894139233a993c42f198770fcf86c1a4", - "030bdf36086d511668220612a9d9a5ac02c2411641b912c1aba7e159b0fcaad83e", - "0229766e39b545724e1f247861c411f992677910bd7c6dbb2f86955fab4f04f108", - "0227955f77d1106b4c7b9f5f61ce502fa999a3ee528fdde0fd40e0c7b3845901b2", - "031ac0d49a1cb73b3e998cd024dedffec26aaac9c93c75ed0b691dfa71d5a6f3a9", - "032e0dc48dee735f57910820b2df4e7b271c52a3f385a64f5be6fbee3f55af0c81", - "030930439f7aa51e8240cf0257a731ef429a5edb7fcdae5007ffb697bf77d95a8a", - "030b4509b167c643f58f05b04af193d937f86b4f603b464cefac5a44447324a8a0", - "0204704d591871716dd3e7efdc3e663d7a62c1db195a5acfee5429a69f198f1dbc", - "020f95603947065b24c0f5886d545dd20679e995d3d719f43f625cdb0370c85208", - "02192810a752181cb6f861d266a4b22eb548ea278d7355542c5a7781d95bd4601b", - "0316713bbb99588964ad7cc79a7af2cf39241a5d30526afbb1ce1d4d023cbca151", - "021ac0ec6a5611bcb2f401d24238d9407980ac671e50e6667912b8c2623c0d7836", - "0229680d551984354deea0b7810ea52870188d1e93664ec8975b3a6c0753ee60c4", - "030b9f26a0f670b5f4fe8600a339f8492e8f85592473e5ff8975f406443d998306", - "0221c1f3673568533a2f6203065480bef93a26fe60d62a54ff9e99946352cf7624", - "03000d3c36f0cb00ed93aa898044223f2c3ee326306e191d9dd8d50a361bda1377", - "030b9fab2781094f5544bf66af3cfb78344db272f1167dd8ef3eb7397fae63f518", - "031d8257ed7bb929cfb2f840fc576017891c27ae8277b53b3ba201f3b0f692a2e4", - "022777c21ec9842d42f38d61c8ffe2a3f99ed196e1757e26aa4cdcbc9d3e83fee3", - "032720d9ffeed5319deb5e96e6b6cd73b0077d069ea6923373709c5d6b4da8188f", - "032203f634fe9761794427624924d0d76b64c850b43668654ea3e1d942ee1f7c8b", - "02100ce44c6d5b00bfaea6d01176982c97cdc6237441c3a59686428981eaed20bd", - "02039e5ff133ca3581770835c67ab558812c99d2ea11e7be9a0aac8e231c49fbbb", - "03026c66ccddc2f6ad673e25b7f462e0d62a1f75772e179f324eb61e1aca9c320a", - "0226e9689ce21020b7b586775f0fdf26c730087a3817715badd8c5b19416a7a1e7", - "021c9a3b9f4c84ae05d4a91a836f7a4e4d5e443b3a5956209d545df82c7f91f778", - "021b921ca874d57e2aa5c34ffe1d1faf5ac2f0ecec79ceb35877541b1d083123eb", - "030194a52c52b885e7866bc51fc5f688055eab8d93fd02d365df83a918a98e1184", - "02288fb49d8a140e90d373af7f9d54ca8bf7c63da3e753337a176f5fcfa80e6054", - "0205889db82c5112ea9626d5391a8fe10b54f27a77d5071ec5d022f4d24ab433b7", - "03280e0265449c172149256a6be523a6c48ce639997e56616e6672f8aabc3b9557", - "0205eea4c0a5e9d651524f7cfa619150d8bbfd1452054a46f1789f12784e111d7e", - "0304318c868083b8575f511b23f4e43bd03de2113dbcb5ee541a8230dda7f5b8e0", - "021cbb4a2358d1bfca29784a7468320b0bfe65362723de709cb5abcdd90df59491", - "0311014c4b61f6618080ac1c08f771897603464ff40fa8bcb0ac87341d27ef7e5c", - "0300e9d602471311c3c72a6c398086203fb8d2db1010ffaa066fc43ddf5701541f", - "022ed284870d57a30d27dd0666e8a45215f83cc5b8b0d4795147a4627cc15db7f8", - "021ce34d63cf6a8722b138cce029e4cf4653f3d3513bfcedec35baeb9fb0c903e1", - "0316355ddefb068fd82590f0f0bac34e84d8392cdd6a65abed533f312285909842", - "0210c7c43bf4fc4d0f3b01acc2c824fd15d6805a93f5a0cd52e403c2962bd4d9ff", - "0210a158dba7c4bbc1dc49f38d4d52a99314b770c195b9a24bcd650381bbb6f3f6", - "0218d91af2f379a98372a7b69ac6f3de191b1114653851bba2b72bc296ba0c66ef", - "020e7e1d2154dca41259f3710a754d006eb04cf1530acb864fded9fff030fa1bf7", - "03166c46efb7bcca2719e11ffa22dd3617359d4dc1df3e19b93b8c8aadb839f405", - "032abca14656376ee4dad6fd259fac5a774fd5b5f54bb180d794364d4479aa2035", - "031b0a1b5287e7ea6dee3f4cb0f7c4ec2dacd584c9d5ddbcb6a695b22118d90992", - "022499ca86ed4300a80bb2fc2f7e1817c6efb868089743f6b5af463659676ece2f", - "03050dad60645dd43e84e44abf225679126de2636da2db1af8a70678e742b39bd0", - "0309a0e514736c58fa5f4a1b60c1e15854a560ae659d3588ae7aea6d02b80a6944", - "0202d000cbdb6bcb645eba0cb2c46eaa0af83751b735bc23be753ddd1f51429b10", - "03220d40e3fc3720f6368fa618b7e48b19f3e71751accaf2a2313245ff3ac8143e", - "022ca19b0f27d4f0593a068f05c7689f93a16a565624bc43efffe748d6ede520a4", - "0315d1c7aacc6c953361d886fe1bff9d1af306c0b72f0ae90447ded1ebf428ecd4", - "030f03d69f888c59e138016f7ec794324f035ba7f6692666e8b922f43b5dd743c9", - "020071f34807f86a351b6d94cedf7070e8bde7a2a39a35dfabbcad579407324e20", - "032af73a0ddb31e0203fd8431a5515fa2756a523492f6e21f22c2b455aa3f2701a", - "031d6977161d4f18b410f2f79138f04071900102b29f8ee58d3a5c02c32f75d449", - "022bd24a8a69f2a0f2240e91f9f2608102f96a0a7f06228455f86ef495c2709701", - "022684a843303e17f2e27fce097f190124ac3fd73db424492cfa0cc53c2a77ace7", - "02276296a4bc276bce3ca131fc89a2dca562e94852b5ee6cb441f8a6edd5cc8b9f", - "030af1104339e3862b6ad8b100ef034226a6829a93edcf867e143501ffc9764597", - "03018ccaf6748db14369d71c519bbda413c4537a0813025a48be31dbeed8007b4f", - "0204365a32f157be9cedd358abb4c80e6af0b183ab42f266e389e7594ec28b18ab", - "02181ac6f2c47d9e0fd3a5e64d2c576c085bf7e1619103ee51c0fbb32472eb530d", - "0304fb8502ac2da9ccb8c40a8630a1ebd519d89cf0013ec210d992f37ff86ba2e1", - "031ddbc50b9f70be3734d6df3c1cc9c2a7711fdd835f3060c459c07b0195380615", - "022235105182ab75aca18f23ee3295015c9267b97cc39390315281c7c5508ff81d", - "03134429f9615b80543c37b85669804fbb04d3f2c472fec25ace05ba2bea1a081c", - "0321f70c2eaf1c01b5349f30a9135f0cfc4fdd35260c112c58750cf723022a17a1", - "02144474e51b1d85c82283fb64a10d3f52de4aa73d4e09b2cc9e221917d6068fcf", - "032a2cd0751f9ba6b337f369ddedfbeb5f47bc3631364edb3f4a4b456cabb986f3", - "032545b8f1f524c7c9afbe2b55713fa6705cdfe77c3044119f3790f9ef2704afd6", - "0215802d9c5dbddbdc7eef4304079843c74bfc1eb5de2171d53fa5b167c1f4f1e6", - "030738bf5b91963c4463ff34f144041c9238fc8ed5a28e6f0dfffbb5e5f2b1aabb", - "02127bbc1bd9b45ddd6c6ce019fdaa272731715e9c0174229a6a7e844a7499b02a", - "0214965fce81cc23d110df6265a2e7c940ffae18400dbe9abeaf2f6949da42a05b", - "0220983712e2009251bbe83f9029eddc84a5f2f677538fd9fe1d92b6c0071189e8", - "03130eb5b1257cbdb6964a054258a0c61584236c9e9f5a34f66266896993291ea3", - "0219a0c0502666fb26a00520576887090102d20c1d4b1d12090785d6bba82d2387", - "0204d556e2c966986a5c8f36d250c5ac77b364de693eb18b0b44640a131a24376b", - "032eb3287578255c50d687e041ca23992b7c1d21c478eca91c97772742787ca832", - "0307ddc346395c7d63f47f71008b8224b55617aa75712fddfecafc6a40e9c8da92", - "020e55ddeb40c3ed8904d7f5d855b297856438137a6d5061a7134c8f6aac771795", - "022529d21576fcf581da350c5e96e5069706bff13db6d6627a1da9483733abdfd1", - "031c2dd16336ebe0f5a1d6a98d8473aade2abd5bda737b012e6cd2b5be5b77d39f", - "032440d2dcec77fbb42ec90cad299ea91e5759ea52d97428231048254938712c52", - "02044d3d999cc5fd7d11f4c2bedf697a28da56666758bf9fa5b8986ff6e33c93e2", - "030919c7f0126fbebfe345faf0736fe63c3c24b24fc2181f45a65fa022490abf6c", - "020196e09afd4da33102b24111a313515f1c4ee4911c4b2a7ec518e9276329ae42", - "020b05b56ee316c52ffea1e3bf8707804258246ce74bb1c97d9e635f2d8681b6fe", - "020b5325b5be2bad65a7f070fb0ccc068442fc66450de33da57a027e4595079d09", - "0317c8d79b25ac8a6afa38a7354e044ef1153b6bdad85443e7fe904a365a53140b", - "022b987bc4844432765eef48f653bbb372b38a755e28da65751326449868f5ab9d", - "030923fadea9dd702fc646ba857a24ff6c4e57b42392c697ffc725014cc01470c0", - "021ccb57e2e7164e04b1770d08a22db48d6615d08782e78c0e2be0997bfa305879", - "0309b8a60df1a01a88b252517f6312ab8155b74b85420bdb8379413db758c0c186", - "0220a49ea43ab6c21448423a925a9da525de1c2f6d643a5aea266e0a696fab2cb8", - "0301b89590d7e2a35a5cfa82a6d8af949818b6877ba9c15a898f4d1bfe9588e7d9", - "02110aebc11d554c36cc563749fe267782487864b30053a92e90febc0a5a5b8817", - "031df13bf5d667562bff1ae6401d2f5315eb6c1ec9eb05536beddddcdb558797e9", - "021c0a69b98d5cd9a11835967b0a89c567db44b7394b5c948a4c6a86affcd5e6c0", - "031eb186f5d6b5f442b4a84e38fe9a39d67b69dfd42832784020a0c537f373b2cd", - "0317288643f85f2a46eb5140e0267226085a2d460cf943a13fda157d73d7728c06", - "0301467c07320377595a1cdd1f90bb329c58ee539312e1a33b7b1a2f0c9fb3997a", - "0308e06ac65b0c4fb7c7d9a15f5234b2cff4f0b7d1681cb777afeff9638bdd7a12", - "031427852eb213cba81919bc58d1c5dbbb9f7394ecfba60832ae0145b07790e152", - "0306fd858e50f695cc5389f9344531fd24fa98cf61f9b601ed38459e20893ad365", - "032cbe21eb5e372952e2b3c10603eee78c177d832ed1bae389e802f6f88af86251", - "0316c4ce6aa247de272566b68117b528e55764e8cb38373656c7839c90ded70ee3", - "022762ad55199d36caa291d3feef01f47cac02f4884a872074182faf547c8c8a0a", - "0314c7ea3ee8b7031560d2f77f325ca7447c77ca54155d47b6787a66a6653a8a75", - "030855c3d4575e373bcf0fa473c1b769e8ec8f579a22e08b467d28a6b86fc478cd", - "030f9952f46ec47723d4edf134906e098a993b213730867bc9436077cff05ef6f6", - "021b14569f0b20148911a2b701448b6826a341d2f51f0a32a9bf80c86c327c3970", - "021382e302a4d7a77bf9e5c674d82488ec8a607621257f56391a300629073120dc", - "02300bfcb6f2864eed1c97f23bfb5a4f78b4bfb5d56aeb397923b536bdf1d7f1b8", - "020cffeb1d4787e7c37090a833e4fc418c8eee7182adf68d6ed4eb6babb14ad3c1", - "0319713195902916cc682b54996cb79e2f0c00ac5998dd2e3f4b6dd5d868669681", - "030093e745fb2ba0292c4b5427c7b1842f8df342d2125273db1e09e70992149420", - "031fda472e5f8fa7985c35caaf6320c1a3ad95aa1536933539a9ff22954d7edc6c", - "03161c862bb3e3b44c4ea593293f52b67a2ddc1fc941e9774e011526ebae2a0785", - "02210ee529dfb8ff9f416965aa351e8899e1369ffb394f471dd946fe7ccd2fc213", - "03192dca62b09eb2ca1f9d59bd344eb532f0d87cba28d69d3352422a59bb10ad6d", - "0300ca6d2f44fd47ed6fe7a52e0d8430fea64884e36f0575719ba9eddc87bf6372", - "030e0bdc6537e9171027b0197de0135ba41849285351ee0884a27cfbccecd8c4f4", - "03182f4d16b8f9f9e516f985ac7cfb07f0293a62ddcc585d476f33ffc2d8c853b7", - "0219ca3b31faf79138e8b361cd2067c9ba821d8afd5d79e465e4aa937c5a84d731", - "032e6bfeb83b7a61aa56078e79bdf69f7eb7400e65c2807a014617e7b6025cd7fe", - "0221daea1c472761e3c539c716f160e89016bfd76c808ab2c6272e78ff06042c5d", - "0323c2da4a1329dac48f0036c751ba81c6961948da4e56f8d37bc1e65b7f39ebe1", - "020dcf911eecdecef639f98a478dec5e8bb2e3bb49353e5954864ba50b87534bee", - "0223a1d229335f323825e4a6a0bfbde7d87be860c1367bc30b138d321cc3b981a9", - "021a37a9453d6b0c58b01f80bfc95704827baba6d7326346b2211444f6a2375ca6", - "0328d881e58615399314c66521044b2fe0ad0ad143dc89034ca5b9967a317cd54f", - "021c2c6fc8e3399dcb78a5f1d2b5ce270b2e696f0199f091dedb6affa654caa383", - "0214209b2f856ea69433fdca0942d885adb143630851cb147cbd5ad9fa2a804380", - "032f53107bd412f80bf38cd19e4053369ead677bc2d9def2e7d957506dc8de78fb", - "02106ac9919805a17f9e635a454880831b41cdc9ccc33dbfa2fc4baa12fd41c65c", - "022b4ecc477665257a7435663a5b08c9c5138d17e9f912a06f0ccb050aaccb03cd", - "020e0a2b8496a1b9e8cebb2b937d6fd607f73b435f9211b8828d7be0cfa0270ad3", - "02020258527a1dce05015fe87d1d8e0bc29a0cd24162bb8f9c6c160a13a45e55d9", - "020bb8e51b2aa204f9630476f32a5865099bd0cf3d0519da7c99c5ba1caca5b085", - "0315952ce3969931318aa077c4e9e992e5b59f73b94b5a407aead00d92dc713533", - "02083b377688cf86124727430427d8ff4024bf0c8a9108e25c928f758e6d7a3f18", - "0306fc620587f33112163dc4fdfc56d2502c15f2239b7b2976449c0d62cb6e012c", - "022ed07560550a55a4ac2ca005821b0298c27c081be7d750e90ee0930348624f3a", - "0318ebc2c311c09d0cbcd155bc8e59b7b904e66c66ef8f68a8211700add7963af7", - "0208c05948edab8e0f45b4097557888bc12ed552abbbc75ca8698e45452f759753", - "0226501a7ee13d44f116f80c6fd4de33ec911c1cc5ec52541d20af654119c24f01", - "031ccf03c1ea17e06c7d4578527a2250d39e85e45ec61b00c9a56d949153baef54", - "03150228059cc7dd68e3e5dcc5f6c4f448247503941730ea16b9aee434ddbf81d4", - "03099fdab47d4a6c0b446016392e13cd86b624e933881f32ce63a88ac3734c1422", - "0301781d31cda94d4cc1b9546673e577b0dbaa8a944fee880fa88ff2b0071164c6", - "032a88f5ee6f2bdd9bd1f09611c7f1a2af1fa842b7996981534d08d7225759c741", - "020c5e791531d64260f4f5f7604c950b5dce740157400e9bc5cc00af8c409473a8", - "020d6affbcf6c178a19c5cc1c227154c074b5b09f02f71c26d412e1f0cb9142252", - "021d5d0e311b68f79adff8ba2968e6b8bc54f6cf85f017f8b770259da090db51a2", - "022ccbc952f0ceeb36deab342b9de5cb5c1fa3c0d12ff641a31839b96a78126b5c", - "02300b3681010aa0917ee744b83859e2ff99ea8809fd52302f2a1db3cc98e5d570", - "02128507d172922d66ae570680831f5b1dcc3d1863c52c658c90784de8253e409b", - "03169f0553310f67d179c1b9ae38f1f3b38379d101b5834d78741c87b72a6f26c7", - "0202d8a73b0427232cec25c9a803e8829b8c62614740d79fd56f2ce556db460c7a", - "030ff0fc8c18d3eb238c504024340953921993b55b8c1486e19e308f6991d4e767", - "031b34a3f4a76033b763e59cc7db3409172cc351bffb465360605ef15f8e8d2ccc", - "022db3fc8eb4145760643a7b65bdf61c216d54df963df101ca9c9b29b29f48e680", - "03046fa100a1c0a1a82f4a3f0fbf826fa90d0d36afc6476bf0cc6edba16003f3cd", - "03280e07c6d89eb7ca81fd32a6dfa2c2a6fa9334f9076a49f68c7677eef003bb6f", - "032a6e6578bc05f88044a652fc8292643eb5d112ea14f3688efb4f60d31a51ff66", - "0324449b1e86da4a4f85cb8811a918533faa1592b398455f3d6a403b92a84a7939", - "0326be0521ed450d5f03786228bcaf1e83200778e47ba6f0c6554b906d07c138c6", - "020efbdc2ec34d4d0583528484546aee00a1d0c4204643ffddfd2d9903cbde00d2", - "0300c142c98c5d93f6529a7da7a50487f2fcd2e89fec0cca215b97341a5ae1c6a0", - "0213299827f6844b9a66e6232cbbeef200f151a96d10709be7a8ec771e6db97de2", - "03270363e69a9e595eb3e8ce2bac61ae8a7b790a8e24f2a0a686ba0d8f6d42cebe", - "0300ce899cd9666a8b69848a677f0d0840f2d6d32ec6167d8f128dd2b53e64186d", - "02261e3e723507dbe0e9c693f9356bb504d7e8a08dca04a4ae445c47139eea6fa6", - "0318757d712ab1111b38c0ba2e2ba89a1c36e80b10b785a63e7214b8c968266a82", - "03303fa4c89a0998c57faedeb381011c758f5e45ae7e2504e2e7a77c7adeb71345", - "03289fadd6e461ceab3ba3a99c4adae0e81d2108a1a62ee75da2dffe0818de6190", - "0305fde62ddab46d335869ec6b2f0d70fc25379af7715c153043f7eb378f34adec", - "021b04ad4463227364136e70b4fd4b98db555e81507973a561cdc1eb5a1e499572", - "031db43bcade39250a7900ec91d270acea0ad5780c7db7e2b563ee73998f0ded99", - "02024ea5e373d0fe4929ed710ee5b3097d9d7f25c060c33898aa7d6f99520b454c", - "022ece39da11a51488ee816edd7cd19a7e99926c1ffd825e1fc25635a5b0c7bbd1", - "03024830c697a200a574259165318671a4e41af662755feab7af2bc305c8f2323a", - "030767a1527e1df50d8716450bf2ce2abcbf0c870bdcce7033d1a96cd7b2af4c06", - "0201a82f23f1ae4c7f53601fcec89052f6add5fb0b6ddeae9fdacb8b297e4f8acf", - "020597d83a8fb64ec0a5bc7f8dcf85ddffca0cc2687059580767a14321c00ce3f2", - "022651e4f149cefdd76eac943a0c31727069983195e76b16bb4bfd4ea10815ef86", - "020d0cde8873c8e7df0d8616c11017325f8100c5eba8a68d82f0cbb754f7ccf0d0", - "031946868987d0e3b82daf4e254dab31506d670d3ff42fdb38a7451198ebc86738", - "0212a4d04e8b4a6e20f1ce1dee5d2322eb054d2561b3749a9c0d3ab6c5dc47b9cf", - "02282bc6aecee6e39613e100fd5252043bd66bc98dd26befddeaa36548880f7667", - "031bd4ddaa5f4232931ad93939aada1ee268094fcdf60290cbf8baeb7e07186b23", - "030c576104c83e7a33a97526e2b2ab7e448d6b28515d526887c6815fbea23bdfb8", - "032b69a6297f53692abe4cba375955e439bfb9fa502b1e2bd55dc9b5c5a3ce37f8", - "03172c4104921667313856c4ca8320ad9e8c07864e9e75d2f4034b2d9bb117756b", - "0209db59cd2d17cd75ac626045d6b755450d83da68f08f30158b5108aca6979176", - "030060dc8b9a8da692b60752b0abcccfd572833db1fa0f91dd6885b2fdb409891c", - "02019d4b99cbc82b45c4b5c72d88558b4db498e5bf2518c96256c681e013d32ea8", - "0209c110fecc02f13c3614e932b59fc8e89a7bd868e014b0b62dd885e51733788a", - "0304d74ccc61301697bb4b141f4ca20f93ada1ad4a4622e9142c4a6cf16b25aa91", - "030a1f0a7b2e5a96f66b888a89fc93dd601ac8b31d55cce6b3fffda6cab261fe60", - "0202ec96cdab2d828c8d77ec9070baa67122c1a6ed986034f93f10fde9cec293e7", - "021706575286b1662ce29485f466578b407bbe153da32abb720c25f75e345dc5eb", - "0304f77899f66c4f082458cfdc6aee53fae512410a3ed944a46dd8780adb46febc", - "020ce65a34ac7debd5a975725a6d559495821ee4c92b3630bca4c3251c6819d071", - "020c3a2e59c8b67ea48396a726adbe9cfa80fe3995dfbd1f08a41d86779e153794", - "030ba9674451782b026891ea9f271ff6d3e168a05272de64c04900743d149828ac", - "030b69e4697e3b204d4ccbbf0c218384482320219cff2ff8333d1020b50688c5fb", - "03227ccb6cbc5d129340827c500730599c3c708a688d9dff6330ad1dc1db77a31c", - "02261ea2c6d662aa11d72be5e7bc209a95cae8e6b65fbdc3db7df8f2ca65d9b65d", - "02262778ce51d65361fc1c77e1113286e6a5fdab051fdda345d5a8aa5b2018ef71", - "022097db3564e64434b48dc6901e07209197778b696bb175df0bfa69295f066d68", - "0216df0e06088ec6e188693a4510121b4ad32816536e47727cb4fdbd85d69f3322", - "021d45b520ad2ba0d70f39e5c82b368d5f826e038d47dd0fe2954141e4773522ef", - "022aba26beee9a283c2528982f92a234364872ceeac7fedb767950ec7edf6f8575", - "03304edd12c46ae037c9a5df29f2ae10fa87c9d1f82e78fae200a9a5ec5e04c3db", - "03232c06b4267b1aa644ca65cbe49e9c63966a4928f582bdf177c1cb37665bbca0", - "020c1a3a518ef2f09fb1ef317582a6d2b9267084f86be4c5fd79fdaf471f0d19a6", - "020d7fc2b96787125a7a72d9f759b04708a51d697cb857a279113a9e01c97e0aea", - "02007aa225cce9cc2f72d55ef33c798c39d60810593f3fb8784e62ac9dd1d2efdd", - "022c35fe51ec28511a5ff3726d22afb455e6c8e99ea727d92464ae4ae6710f5297", - "0328ee23ed69ef4ee47942e1fc7eed80122f2caa86c57969d96a4623d23fbde465", - "030de61a70c72a64a68e0f36c7169bf4a52a1318a5d9bdd1c75db618e04f5f0976", - "0207c3fcc8957b47128872d8d26a5993629410c7e561b8c49a3e17cce3259600c4", - "0228cb5605156821ff96c15881e16d7c1757b4672ad4dd9f588fadb10b83747f68", - "022307b338132758a782385e2e9efd1cb77b96cbc0894ea1cac53bb268dbaf72e2", - "022b906a7a4e2dc1080d8530a08972c46b9b93073e45d934d1846c27942e9c1fae", - "03291ab1ace70694a6af99281493509b947ebffe65469c1197f8dd9a6fee6f48f5", - "0301a18b287794a81f0a23f29c3db104e578cbc05429299a65e824289b9d71fb60", - "022480036fa204619d4e99f59ddc61480f36e29976a94bb6bdb3b2b1a11353ecdc", - "032585a89c93a4c3e3a6ae34a082ee260dd8bffe880cb4af2e0bfb10fc59bd34d6", - "030102bdaa4b07e7c082169198a25f33aa17412552bb02d174c28040c106609adc", - "020d4163f073e082635a9c34aa742a49e7a6e4f350fb5a0e3abae44c04c77670a9", - "031566b27769119a9d039f7ad73a7cce56c7a0ec03a7adc75653b7d6eb77125734", - "032b3d5dc6e4441b27d38e282603ad1fca64fcce2d2046f725ab4af9711e794094", - "031ffc5df23f5baee6976cfc3500ac13a71bb5c54b25e211ff86e0afd8478a3557", - "0321d4a342c0b3e02c70e7b2f38423df8db23e4d090eddc992bedd53b7e353eec5", - "022d1927e46c94d5d7aa960c19339798abeeeb09bbd457302f2ccf2e0ca715637f", - "022ac9fc0c4582685b4171e22cfea2b3f992989045c695a8847985bc6fc78ce48a", - "030b44890fd3e8849ae34e079683b06d8678cb9cfc4ad5bb5650f7229421772689", - "032bf012018b42c8665530ec78389940027a91c556847dc31152584ca844a29060", - "0223d43851b6a2369ea5868b4cadf8b77a80b62324fcdf18cef3e97726212bb43a", - "031638b26e633864524e94e1bed6d76bdcb0d5668e50a587b326395e5a1ba740f3", - "03192f4dcd770d53621118c5ecc69e378b0c8c9da5ee6397b746df61af610f1a20", - "020672cd05bde429e216c37e4194fc1a9cb84c1b093eab4a36dda42170303e5ae8", - "031eb2553248d3f464ce74a63752a246a4b62485d7738e9fcf7fef6389e361c09b", - "030f9b2f4bd0cc00820b114cdaa6c90d25a0e3550e8d4f46bd71c9aea41e46967c", - "022b1f0860c37d4c02fcd32e063044b62407a3cf4c624d5cfeadbb5965d425061d", - "02287c69980fba92174c1f5778fb746de4e400306f6fcc4af5034559d1a43f6719", - "03114ca1ac0cbb848f1a665f56dd4230d26c20856308c692c0003bea5b37ce1827", - "032fe49bc36168191285c01c71617d4cbe9d42ddd77ffd32d4bf5f4c16dce75985", - "032aadc599fc250827525ca756cd9f7fc21146399b82a3df29d3bb9f02f863ac02", - "030f9fe4c39d5a85e26e43814c0e97ce93211d1a011d1bdcd0f5cd07f9aaec5998", - "03039eb7a1f82e986d094f08c2a92fa9a9a53928c149e50f33bfb2f8478203f152", - "03098b9cb2533a0bd1268d71fb75c6db362317bf5107017fa193e56da176ff5312", - "031a71e5996976269e713374d78ca4645f6c8bb7fc9e7e4645123ca4b58018473e", - "021aff42f1ab684b37a1632c78841c0c79adc71119f5a066aa7ffbdbf0a5207232", - "0213252f864bf9848f6ca2b4792b1781b1dfa91622fe8d4d934a53e2c796bab21b", - "03142c6ecc9013895233173aadfe3c9001cb0892324c360f2311d3a75a4a912157", - "03084158448ff6ce367e0deff5066c8f307feaad6ec81d97c7a825404a06add819", - "031fd9562244e4d18945f7f4c6af6e8b2eeae8cdc1862a10f232025c875e2a8442", - "032a962c79f7039011687fe6bc54536f545863c7af8f727ecacc66e340100cacad", - "03296b097274908463dd0ce4437bc6f28e32eb7f9b1cf360adf3e8d3296d92e839", - "030cbd8001b4d06d82402ef19c9087d38d5b2545fcad1b819ff7e165501877f2d4", - "032bc65737aa87e58a3cf35d3715b3bfe8fc945a918d9126c128d5037f4500e3ef", - "0222ab60315bb5bc4f19f243bfe32e308cedf3a2823e29a8b22f4491f71bc5514e", - "031f15cf5d15de15e9caf8a56c71b39e40a352ea1cbceff6cb4a468528710f58e4", - "0201f59d9877bbaaa21116de0b93bda34dea7fb19232acb8239c251ce9bf6d07b4", - "022505cff6ed91e169d8ef87a6a49d2fe07175bec923e3b17bfd3aa2f8c9203f3d", - "0228c6f0ac08dbdedefe220433f8ff8ce874da374754299fd209efd316cc74de19", - "032c9286422d3f18ac0d627b0895eb092833cd1033a6ae60b98c2159ab1424a4d4", - "0305f4dc1fece3630f8cc8c0ad423ad7c91dd5064ef28423037ee278b52366d508", - "021c7968528cbc945540f9cb88ee29cea00b0487cee34142f2ce7fcef376d622ea", - "020187de48884e8a3a57993d8e9f34dd9e1e549fe97337089dfc8c1c01fda5ad95", - "030848abbbb40c7565e38c7ea7a3699a001e7c03c476e48d9326818c723bb272c6", - "0207b2c9c794e77b1c6f8b008abbff354368348e3f2cfd7af5a4f98769670c654b", - "03069a8fd3d7d253a0565460737f4a439b83d5249708b2d956013e26e474273650", - "020b0dfbe8333762bd36ceaf0430e87e215000c2e8a210061b1bc6937df953ed32", - "0206038913b2aac5f42dfafb1a957b8e69c05c7e9a5677bcb6b9fcc72fe91dc9bf", - "032387ca37e34ccb98497749beee58ff512e507e1c2835a6dd5943653b5e6224b9", - "0210915f681a3062a5dd3fcdaf227c916899032503a41c94f73cb965d657174994", - "030048391cff3a4534fdd20006900ae4b85421b03a6427532a539aea2c4a60afc7", - "030bef2f023909afd397db1ee8d85c634d3c380978fee1c3fd485943355efffbae", - "031b87f1cfdb7ab540bdb79dc5e92c8e6e2177f9c89da8dbd8d284bfd6fd6cd332", - "022d63e43c2cf02b197525da62d435054f0067514faf11206cbec567edbe6b0d06", - "022e5bdd066e211dbd56c5fdbe11d4300cd5ae0c4103020dc2f21244a1b9db20a1", - "0213fe43ea671f981f1d7329934c8cefdb7a32f42e6545c5b43fc93bdcebc6bd13", - "031ab8f20841adb9975d6fc11a2931366fabb279dda89eaf86830a704fb2c17eb0", - "03057843c22c9dce0e2cf5150b563b0bceb2a3c985ef280b97549fbc003e7362e0", - "022a76f457d19140a051b7374eb34cc2e3999c79581a9ab69ca666624ce26c740c", - "0315fdbdbdf4a9e9f0fdd9491897eaa48b0359e8ede234bbd834f202737caec5b3", - "03300105969d1febab1a2442557fa065f3440992d54e13c2b15393f9168dafaa26", - "032ae5bbd7604858303a28025821a200cb8978c3da026896297c05d8564986658c", - "032ababd2c0ba6ec42efc1e650d96c7297b6a1373eac311a40bd2f3193565bf732", - "0314d679f8775d65d54a78507ee3fdae8b23086ec96bb9ced9ea4306ddbcf78c15", - "02218410f62ffc9e8da4a650215c6816d618da300f27850e32689a376fa3a7f149", - "021d1c32356661f0dc28013fcf3e83844d28f8824a3177b1f79b99159297a05872", - "0300ccb8ac78706a89719ab3b93901a8f480e699b7965ae11c1cbe56de3454f2e9", - "0204855dd18855f729c358452915bab6a417e98ce81924e83957b0668a1530ecf5", - "020baefcf64bc41f585545f6e9a60be112699d7021222a1bd77334940ca751ffd5", - "020b1d233363581d2a2b2c3970125272688e0bfc3be3d010714d0f24a66cb77cdd", - "0229f27f37e91661a470d67ac07c1aff117246ce276022529c0908db3b28ea0b4e", - "0319daca7b40f9f3c26fa70921ac0b1977f6a86ab37c1bcf5797f203ba4d30e191", - "021facab9471eee263f1a4ae343331910330f6a54c4b0042c533d91ee5066c5976", - "020ec1aa0ac600ababf1f911f9ddc0a1b6ecf1ed2d1a70ad6e8917aabb56c2e3e3", - "0326dace613e9153c5bb07392b230a7944da9fe38ef51add8843737f6f1cc08a16", - "022188bb6f69cd51e470567c149839e867df557904a9ed1147c2b095466ed3d0ef", - "032307cae22f7d5f030637f1457e85fb9f8bfd713acb49ea2f80d79bf471d59db2", - "0216d0c762d23f5a9c5f21c3785f9511d2464989e0852df4328973c3ad40572667", - "030263967ca39cb3c068b8c20b08e79fe88663e1123ce467ee6f9911f8c7701c90", - "022dcafd1546cbbddc98cfcd3da6a421cf8882404d1e110c0111ed5adba5fce563", - "03281bb731ed98583a0c14e0492b41ff32c366588e680dd870574df1fa9bfc0c7f", - "030faac769af0023f8022187c7c70be8d65b189dd5fdc0118a071c4448c77b206f", - "02074e30214f9e710899cc14cc1bd5c70fd439577894ad324b1e92e39b87b2d5ed", - "0200fac17d64f984b39911cb65e59411772219d49126abea052cfd400e492a1a06", - "020e50bb0ced4a7264ddfb1d3a545cc79640080b722899d241a6fbf6b6d23539d3", - "020bbf4ef09b549d6d9be466d2773310f4351f8df2e641f99d55c2645cc34fa9e4", - "020129e218c2664020561c6b71ba61827e0913fd3648d49b5e0ee1e30a00cfc876", - "032a2879c40fdae842b4bb1998d5d5877b17d9c4a9fc4ee10c1e8ca0adedc25115", - "0313b9affb3bc6da68abd0f0b0a3edff4ca8630baac722d0d95c1acc1760c719ab", - "022bbfcfd8e821f8d8addec75ad22e202f656f548c23a86e83aa02bfad3d67a0cf", - "02287d099584fa066096fc78f23b07c4dee4c10c8717b8cd4275f68fc49b297c03", - "0206b754bc936c748469db728f14bb78cf8f85d4f2387aafd8ef0aaa3ac02e8790", - "03184d412b3409e438e609fd6b92913f1dc9d0832792e6567648f2a970196abb82", - "022d9fc7a6f256ff3bf125ca287454302f209a85cc669d7283ca74f9247f4b614d", - "03111f14cb3be0dd3b2a31ce2764191087832391d9bb6806f7b849779e79eb2e23", - "0329c64a87c11b115d951554d9fd86e6d96af1798cc67559a4ac880e6051d64c34", - "0321983e141054451dbf0b66b231f6fdbf4d23bde7c067fa1896688f92430f6635", - "031d914470e41352e2005b5ee916260f24fbe9b38d4775a95ad257ce294060ee7c", - "030203d64fb823c1821d830b251fde5151b3638a7938deca31cb6c1477afa3cce6", - "0329b32a411a97938aec20fa1af01ec119411d863db9642e91c5ca35b0ebd5ef02", - "020849d7292d625e763aec434a4da0ff6f4dd54589429351d85fb425636c0d25f7", - "0210fce3df5b36f9051d9e7923f950c6f4c4993c47ccb318e93f7944a911072259", - "032adc14e7e2af73f880d72fc310c1f2e2c9283b1e2b3d965148d1b38afde5c70b", - "0201c8ce4dba119b4b62261e15a4fbe62508428157f13df92bd44615aa9b91fec8", - "03111fc81ee3a78f3c7ac1f415310e0a580f71b4f3b1ed3edf18e1b45d06d3fa8d", - "03253bd331d6afbf8b88143ee46b0405655ad5f191148382c94dc325eeea3f04a5", - "0319f817f67496a179447b3058006c2f55bd8e03c52456a08dd9efe21371408e77", - "020374441c1727ed0a5c087087d78fd8beab475b71996a1687aa4c139ba3e20006", - "030437d32171e648b03abba0ac3f54d39411ee58bde74c808f1b63691de7b9601f", - "020d4f80ab22c0851ad4ab191c849e4fd41167aff3f4da5400afe518186bdf078f", - "031caa23b63d6b18eff962080e78d33bdc78129cd50fbb8a2847c00049794e7b88", - "0306ee9d79b37aaae1121c49397ee905d22803f2ef858c085c2d86117dd31a6357", - "02265405acbf7e3e0ad182d0b51480ebdf03d67988eed4e85c9b4866216fec1af0", - "032b29eb01b7925db352ed8a888b56f28efad17b228fda9900014ade730b3537f2", - "03206e132748594fe7fe44b13abe2b0d8d818b41c957f93295dce37f7aeb405eb6", - "022c4b68c449bd7914d3327a42928a60f43325ca17053649e809455469be9a79ba", - "0315b4201b5bb43c330be9942ac746a1893ca762a359160a3f6f3af45b6fa725b8", - "030db81f3a80f0454d95a3b1063380498539065bf965fcd9e124b788e2c455b88c", - "030e2649a8dbb64d8eaa1e53970da4d92e44294d3b08c9db04f196cd928f706821", - "0327a50edf42c4947efcf2dd1aed4e81d39b3e34e545bdb7e182335851141a92ec", - "02110bfbb7885294f5649dbb720f0509cdcbf02f92d623d74a807c3668383ee204", - "03283575e9f00be68fb8f9d37aa7e8c973736a70595d1795f7cbe1593050f41971", - "0204ce1f8889a4f6f8aebdf0a067db4915e273fd78158aef64aabdacd4b9d84f08", - "020507a497173bdf3befaa9b489a63fcee63684dea0eb55d15b6e572bcca6682dc", - "0226c344a6e22c731008a1999c37443b30946833e614f95c94a0f79469e05f3789", - "022a54b64922eea460dadaf06ccfadfd1fa2c8fd71fcac6e7a858c1c4257238ef1", - "031c2277535691488174b78a7e1676c1acbe2af90f9dfb37d410edc375d8601037", - "020a5c1e1706facaed00baa9918fdb24d5bdf6fe904e5216909c72dbeb142e6188", - "0306ee8bd751b6342a81059e816ea251d33b0628662c3ef35053ed62c82e13c855", - "0321789268187533cbac8df71932a6be15300c0384f149d96fdbd64c67d05931f4", - "032dc7ab70322ec2a332bdb4de6e024d303c317f7637db5da5cac3d0b983517bfc", - "0315bf1f662d91c4f884e3fc00883c8e1c9acd23f561643f8c093b0150f8c5dd66", - "03046f2446b5185383a4ead9bb9e3156088643c2df31417e84fb8269b0dc6c7266", - "02113c51f5924b88670ad23fcfcf899eb6cb3cc0dd2ed256d992c032d21678a27c", - "0309ac8294c512ea2bccec48c51b8193c530c379d102b32bff8162b6d97aecd4cf", - "0307c7fa75a0f596cdefc4e9afe0072ef172be74005afa6eb4e0b188d869e4a0f0", - "022b7d543f9cf7f031948209a0427f5223cab2954dfe27661291bfe967637546b4", - "030a133ab2b5bdb95289413c912715968241b45b8f668571f1a97e50a6ffb9cc8a", - "0211e7fa83d2ddae97c9ebaa92d5020a2139ace8415778afe545883be7eda97fc3", - "020c483e57effe17b7768affed9b28d5e67d1eae72f4d6126a3cba89f44e6120ab", - "0327409006ad77e449690d4fbf36ef55e4551877882e0ca5b709c3747d5b3650b3", - "022e5560fecabe3c94e2986602935c6d152ed2d2c2c36765c2bcf3bf0d29dff4fe", - "021625f27d5e593195270c71875623515388505d54db8ebec327287834c57715f7", - "020a48e01cac5aa56f65465d7f590bd4e17cac5ffff06e65bb7152fa5f2a931ef7", - "022415c0176143b2360627773fb0fe7dc6143e139acae5ae4e7c97d5e43b6eb6d7", - "031d2ace983505d6bdc10779ac52ec32a93a2ca97fc48bf24da62062fc90bd171e", - "031001078bf730d35f31b1afd1841303b3118f42c4f364be4838636de70af088f1", - "0226ae92bd8756e9951042e04e1300d298c38b466651b7494866af0c065a0980b3", - "03093bf41baec785cfe5553ed306359cdee4580960f2a357fd9e950962aeb17262", - "0221a264b03d9b723af0a56ac317e602d4b5935b8fb86b88c04e8a47be08f0d184", - "021a3cdaa9cf1d61295ab6d41d370c870c31f05db7825e3b00aa9ebdc5aba76f08", - "020078fc29c6d570bb08e5706aeeba0a137b24be6fc88f2d73799d409329e4f692", - "02007b6e287ee9d1a2de55fe92ab5a2df8e66366a59d0ee08d08de706f4e0d430a", - "0207f32c11d6b1d2fe49d00cb7258e75e46f0bd408a6c40f79e6e057dd1101904d", - "022447c7d06a5e8d13e6e291fe42a5765129e7694e50d9984fd08319a439905437", - "02253e07bb7b70dd29f609ae8ed9f09a52a1e884dd3ff968807471c4e2d41b9969", - "02136eb83f87ced59a9b225c1b10a73ad3dfea61ba1d2c1beb9cb2a71ed630b67e", - "0211703752133aca6431f97c614a4d7bf5f55ab195042928c9687bb8449c9ca943", - "032585e529b95172ebc7b8c94d334620b9dbc1180066b5bd86bfd1bc2c59766c36", - "0228750ca98b9415bc0cb78dfe86435d101ffce411a9f3dbc84b5970fd71b0b2f5", - "0209c4828b217acfec9476afdb33f606b3dd047eb817d6624106bb88581d0495e6", - "032b71a37f900593e875a097c292729b81e477484196c0d52955e2194c4be378ba", - "0329aefda4478396e6b525be13d33d6cadd098bb25451be4e899a7a2ce3df93672", - "021a366084d1660eb62d27e5b2cb234fcf69e2c4932ebbdbcb23596c71ef521857", - "021e14ce54ceb329daa14285fb33083db6144f9f46039824266146350cf98b9f03", - "032637863f666be73ea089b1cc7b6345b912060a7948e0425fc31c14eae8beb467", - "02129a330b1247a917261be6d4253da30b60f25bd16cedf78e1fe0575e2660294b", - "03085870a673599c6d54e8080d9a4b98eba21d5648442a56d47773792e53017056", - "031512acc6e57e3c2099f26853cc391187a55c744177eee22d5b103f2e56f6e64f", - "0322649f74d9336bc9d71d876abbfe5a5d45a73743713647cff9a394a278f39a44", - "0311eddc350b278b901d6f7e1104df0949ce8a2ba66bab6e12d1db08e979f686a1", - "03142847e5f353356aa46bd476f4102484f0fd182345b4ce512516c87e00cdedf5", - "030884813fe06210c5accbb09432c554ff0ef0be3714bb64aba99c72452910e61f", - "0317e441f1a16dc80ec08547cea19efb84dd6fb5885bcb70ccd4eb1d568acc8373", - "0301db3b64da17da8f454aa5f826c002ef7d13b407a223a59b8b2042dd8ae40922", - "0226fd24d2fd9506e470bc248c4eb8487fb4ce70bc9ea0ff5f9f7f889121d0cd1b", - "0321d7c0a937051d9a13af69218e54a06b941cb21d052921b7f9309050850ade53", - "0317ce8016f862cc2373c90871e77e4250ac6084427d8a63de73199deadad74039", - "0227b1d65e335844339cfc98deb8869de59cd06d757e9452eecb8ab24f45d3d9f1", - "02116fe7b41452a141bef49b83638870ab3a13381d60c3f08086101554a562fc79", - "032766e3c5dcff4e22564116ea590311b314ccd07788ed36dd80fc57725c7f3081", - "032deb5fd4f84438a6fb98a55d865d93d48cdf7d6f7f2f3d309e525eeeff9beab3", - "0208d1271d8d2f44705814db5f8ceea217ac57a4dc347f4a4a49bbc14ecf5daa52", - "030a85956d88213b4c80eb8bde41f4f7090cc74925dc12f65757bea99ba5036343", - "0318ca9565799e1e1d84b71dccdee2cb4871ff029b449c1cd1d834ce6c9637055b", - "0304c31ee8a207624148901cc523c57b3831d9b2c90452ce16a9ce48e83a8ed99c", - "0207d8e80850ff134327e6ec2b93464fb734e2d753528b50c0c0e19d94a128fd6b", - "03026319905f5b80ef06a53c380910bf577acd166a6590c8baa411172f1c2d624e", - "022519ed483b87fba8209d86275453f542855abad8efeee0a9828e5b311695f349", - "0211e287840e3690eefa2f0d37800a35714105e7ba5b9970a891bf602146a7c3b0", - "021ceef686f6d966a0e9733e8abd1ead41d116e3f7196f8595a9328a7caf1976df", - "0318964759dae9971055a801f3b0191c5594fbaf175d2cc9c4f904053b35b1d99a", - "0226bbda92f21151bd08e29037ac96c24d0a0dbd46b6e1e366a0b3eccde2dbf768", - "020d208dbb31708af36a222b0b80314159d5e72e9551782cbf54ccc98ed7f712c3", - "02087acf046ba06d93aa2dddddbaf6fb8ea6e6543999429ef389b2a2c3ad0e4a1f", - "020eb7e814368e5f5047143e40bde478febaf5446b2cb51f69fefe5f27c3020f38", - "031f5d488de0783a6c2ba3205b7e3e21b700766ed9a3f4ac238a87ca6fb609f0f7", - "0304ace8bd434eb6c555dba8ad7160ecd5d24674bca9c99bae6ff0e3e50325fd44", - "031ad595ab76a21096dbdd5201e616d8c371327ccf2aa7770fb1003bab2c52f814", - "0211b3de08a98f3869ca1fa53fb9a0549ae3901dce1167a3b0786a1687c425c50e", - "030949fa1c17a2dc7c76efcff7f089126813322dbf5fca976e687872629568265b", - "032a5b297544aac307bd44e6e4d122774e6452702444aaf8f2396b324d44dd9235", - "021e0f9b943fcb128d6ee0e2db39fb9fab220d69383450d629925d68962f96f6a2", - "0304aef0aa7ad6c0838cde2dfb289eff46b255bd602407de0563ab813bfa1fc412", - "021dfda2cd9ee6e34f13687b5e25bd70ed4d0e882067eab7d93a95c7e5764a3bbd", - "032cb70d9f2d2b037e425cb8d94ac682783e28fbafdaf224b43b01838a58ac0f70", - "030f8e6542e7a85a5e437b372d24231bae1f4a8f127dbd7e0469afd90bd0e30d09", - "021cf89d661ac06bc5565d218b7aa0f8508c0e3ac4bb05202d25d7ab2ef9d92f30", - "0316b6ecfef863dd1743b7949988c9d547ab3c16d53884bb87f23aa613a6803eb5", - "03289b75c151f8b72becdbf3946270241d08c0167ea54568b0029f235a8a0f653a", - "0320ca87b1bb8daf6ac8f9638b7e9a05528e0a4ad6b66057e053d139715a806bef", - "0227413a83b2248229d658eb71da1fbc088b1d2381b564bc9babb87a56373e4858", - "031a5d199e795f45b839ce57060ffedf6af48c15ab50a9382c42719bd88d62a569", - "031afb956e867f27b0b259cd1218028d3f008d4d9846c4da7759a064cee0f37c69", - "020a05015fc71e3995b634e615b9cd673835202eabbfca12666484eed25cc39052", - "0300ffa71a1031798cb9637e3dab477ba6c1c8ffe0198584701a717483360b9457", - "0319cf015196d656100059708ce7db25a181ca81182922ceeb56eaf0b9ecee4992", - "021d6fe90d00011bc2ffc7e8358db7ecfa9cb5162219f3c62df9d1e39e3904035c", - "022f28b5af6773edfabbdfb83d2d4dea4f30cd29a6e733821c06f4972dfa125ce8", - "0202e42738b11e4ec2073dae2c0c14048ed04691493ec4212700a4b30be4b73522", - "0315d8958f303c1308e87ffafb32258ccbb48059ca98af4a27438de48a218dbe74", - "0319ed7afd0d3763606c1b89b44be01d3878c4d051bff7e41717da8ffc7141276f", - "0218fe064adaf52c4c3e902feb555364985ff08e164c44c310cef6a955ada1afd6", - "032d2c6083af7dedb047266208c4194ca78a018b4d9e72001c6abc1acf2c6098ea", - "021f13cbd27712aa5d9c83c98d8c20333f67d4e6f451455a585cc41e2ba2c27fc9", - "02122b237c0dacf32813ba507326f0bd2d3dc29429a5b61a9c68937745e42b76ec", - "022278c446e01d99b1877ec9971cb1f80fb0d83beee9564dc099c5aaef50911240", - "0317822f044f20565316afd2708b6bc59f15dfb3e3322f2a46fdaf212f037616a9", - "030616b5049e5155625a50bece8f516adace33cafc46c164a14289d8f9f9b983ac", - "032290b6f16a8f7085fb0dc6ed0f25a85b00945be1aa7ae4ea81e13ad691b7e8af", - "0202cf9595251735fcb811565c5bdfae1276f4be25681edeb06a08c41cd851c0ac", - "020ec1bf2e75fdff60af5cd72705748f5348aedca5866c7420d3e9e0677ad59122", - "032921ea2dc9c513968c72945dbeca1ed2ff655c20446a24214bb2ad6be662a32e", - "020faebefafb5d54fae8cf0f28add52254545e4a6f17c96456b8fecd1362b3b100", - "0200633d43f46cc9c2697061fd274792aa2841f0f0092d3e994e5de36c173b0ea5", - "021bf25ae4caa1364a849c9d9552fbc0b67d40b2f9f37fc28f396ca0d145f3bef9", - "022423324feb3b93f5e997411b3ad0470a595d76eaa29244092623bf390cb64964", - "021a0ac99eaa01a0b3d25bf864300281d445697edd185587c5f78f25e095997d1a", - "021d1e8e27c9b0af2031b7f1768a2a74e13fd7dde9a6baa9b5f82159075a9ae8c8", - "0218b99bd93856ba72b6bcbd0304d0d87ce67fac36d62842a82128e81b1792f654", - "02259b9acc72de2346a932acb05972b54deda6096171cb9b88b675cb8e80571c9a", - "0215037e329fefedbf043a8767b9ea629a96a401e10976ddb19804892dd1dd1279", - "032bba9f4bf058f711bcb5236c925f4eea5e1848d6c9d862963cce65bfe1cab912", - "0304becf9e0d3fe44edcd40e7d7ed4419e8e9314f2903067b21c98f307aaa9b2fa", - "031efd2b93163f2763b32f89f740434e44b09db487a3c336cb585519adeb2b8407", - "020b11c427a5a42289f6250291811a30c17f5f4ff2bdc7bf87379d451e0b211fcd", - "0313eef4d037d8b926753d754fe717f7d69492f52dd4766ef68b27345eda979b7d", - "0205b844a8f3cb66a254a2504fd18ac817f44d7b027675039f3dd54b9728d2129d", - "03161cb0ba1e151497c62c983e272fa782513fbbcfb26e142fb078015339c5bd62", - "021bce0a37f0e6bc41fdba8bca3e20cf810a9b6f47f64d738dd07c8271f1a64913", - "03199dec57b358bbfaa5536eed945509809d77088f97e29deb2696f2384826f984", - "032cb9ea0ebf6f658f066c17d6c8e5e17b54a78f6638f22ff68a4640cdceea7de4", - "030efb46312e446b72ba0fff3da603628dbb1f4b072f449a7730034989c9c778b1", - "030ccd25bb32157fd6b41276611e5499cb686eb7461bb8de7372f87e43eb9fa6bb", - "032c812f2753d718db2c5c0895e992da673e9a2bf69bb0ed10533d6d32fc450e9e", - "021911d7329fab70831e5210613b0d8956802da96ec98ff33872f8dcc64b781012", - "0219eb7ebc7aa4a4d2aabeb1b7310cff41b9308d51becd0207b9804d7001e896a5", - "021a49e8d8eee7c84341bd55d34f71384b393f51864677c7576cd87bafa6bcaf80", - "021776c6c97e55459c4e5337800c5be789d0ccc387ed225ea6ea505e879539a660", - "0202ac07699a2e73d8623b5add19a3f5c79bcf6aecdf1dfa4e5d524cc334bb7f18", - "021cdc61b8fb99ca26ab166a9945f8acd1d8046b23849c5946c45f87cf5a73de66", - "02281f056f1d6d6e83245d026a51998a2f9b885cad7c6fdee544d89206b71f4b44", - "021c5d918214aafffa36256a471bea491a48ddeccb02de122d7288ca312b46faca", - "022885d144ebb81804f2c288f2cead7679ec11d37fa08a0667cf7b5f11e7b912cc", - "0223f8e46d956fffb953ea6dc619a28072c9771132f140a95db134db7441daf16b", - "030303335e1b39c15304a40e3acd34ce12e24f9e02267fb76edb5d1ffe745da56a", - "03017f7d4fe673db800a58da41cc31f84d24161ac527805f2150006866a90e69c3", - "02300835ef46edada0c66e29e2ad4b6cdeede4aa6095f8815b077689bfc3c9a445", - "030fb66d1770875f245819c3a91add530368fa47aae8606019824de5adff651c1e", - "022597059b3b20a8c3c5dbc967b95d7f4570e2ed0daa0c701201b0363a3616fdaa", - "021e21c7a18d067e5ae44606f03e7b890f0aa7d82ea2aedb71ac1d96d76e54623b", - "0222219ec7ec6890f48647352d87a149869c81d5f73628f390479b36e0bb76d434", - "02226b13c8fdcd20743c42ded33b4f04289fa27a03e137f0e93b225b984600796e", - "031b09cf30c19d2ed627146b67ae23164c722b536add7511141b54106cff004d72", - "031f2623b26bcbdff3ac54a88f2b438b3cb54c18bca9231b2316742ad3e9c9c5da", - "032e68077e9ebd8dcc9606692c1fda141e72b7503ec2e78378fd234d8154a6a9fb", - "022df44bc545a440f2136b7648c271bd20d3e09a5f02c694fafee4fc5e437ba2a7", - "0205ad91c5248867c20d20b676fcdf65505164a2acf77021bf78d796fdbd7e7202", - "0327f632cb4687861d0410407b431f16fb124796044fc7b99a10bddaec0011971a", - "0304de18aad17d9ef55153e2340bf7fd09b705e2f853110eec574bdfae24d20683", - "02008a20933ebcee147bba711c91567f414d0cbff5024283124e49a11d9018c798", - "02074d7995e3dc343cb5101ebcd31e609d334a24db3b90ccb6626330a8d434578e", - "03161be34fc9fa12bcf7e8c884bf151baa1b339ed279304fb14f32b051bed8c8c1", - "0313003e85e17df1b662f94dda2b4960838245c127992043487af3dc6701e8c8ea", - "0215d4693ad0692045c54293ccd1f98275e7a7f42132cb14a5907e98d4418f2571", - "030b37be54ea2f042e4b16cbf9415daaee8f71fce3098aba4237cf0be5f890b34c", - "02148a2e6425ff2d173cb2e77c89f562829e99d7e6c4ac8960817eaa62bed08d9c", - "02101dbf5da6916dfc093871f5591d6c99f40e8dc11831022b13e557c966d74aaa", - "03028842d69e0fb1f6ab2f929d3308873dffc92d2a7f1f58c70aa1b34e14a9196e", - "030fea64005974799642b1b04cd0bbd4b2d56d65707e2a42807ae251360243b59c", - "0326dd6d6f129b4d3d93b9079162564b6a4e945523d624989209707366739c5167", - "0323d479a94bbfa8a56a2c50748163996a88f3d6d28ae14fe76a364c24f42e1f6f", - "02062fca29f78a9b9abed04ebbe4bf8d8abd271d4cb1d16e9b7ca4248e12005f9d", - "030d7f93e53af9d9feb5233b546713a612aa5c423ae86e13684a2b0f1e46490983", - "02276dfc21011ce92766d49e53850cf63a9f214d7434bc73034f5cf96efbd651da", - "031cbd0d1cacf991d2445417730faa7fc62bd04614beb93dc8e04e5db3f07a04ce", - "03051e24caa2f6b0f59d4c5b89d1570d7f65a6613b9b310e61473a45645d0b9baa", - "020ac9261e9a15082f065123a1de8993f3e7c07c344b065f5c09f8b851a9cf70b0", - "02217d0b31e3a84d971f8486f6f45b76cd0d596444fe732ace7ee3d4cf8305d033", - "0225cc3f79e236714b68bfea13a5da2b4b7f42a6341ad8ad17dcb000f839957eeb", - "022d70fc63f470e65a525bc2a0d7b086c2431dd1345b2b68f03be71443a1870fbf", - "0306b23dd1c70b816afce7ddf9a3b7f5cbc908c699438acdbf8188277694874108", - "03293f80c3977618e6b2d5ba8d5ffe9a14c8aca0536c07ed2128e2892088e0b6ec", - "031820b31a26554c446fbc1c62a7b3f911e87f6f5ddc30c09d09ee56fa4d2db3bb", - "030ffe8bcc1a207d03be9f4ca7569a0238386a3b24542b094428f6064b5df0eac3", - "032bb3f6c7524d183ec15ba69cf9903f054f78f07da4f8574143f093e3aab1bd97", - "021811251cef6cb6dc98214cd9d19ba548d2af2de63e63e637a621e477c52074e7", - "022f8138ecce218ec71514f0ff03368b7e9a54db2b34f27f015b9c7cde2c7ff8e1", - "032fc1d871400fdba2dad3044ca4e335b72841bb064b1c7f6da068366b5c0666c6", - "021a5b81791cd37b1dc5f6919ad715223e4bec57af4ede5f72b53d65fa4ab2d9d4", - "0308cfa4dffbd40fa257f0f64f4434ca6e1b0dae659d9d212774f4cc0f53eff59c", - "0315a131f969e59f26bf7c11f9540de1a011a590f7982ad8c2a9d933d632e30f45", - "0221823628470e6646fae6c61f8cdef79b50bb16e668f88b79b57c30cf2f588835", - "030833cb32e189e1c825f2f8bd8311c423bb59d79a48314182c26c26ceb6adc1cb", - "021894bc005b8eeee1655ecc2aa9278f51447d3b4be1ea38f8bf6372b2f8642992", - "0322d1d8dc4d6740492718a388bb17767ff0026180d9966bb28d4d1a94c9addf5b", - "020c2e5a642b1d7bad6605e910706ac02c7e165657d37613f09ba6da6f2642f67f", - "030404bc75b3277ee14a94a232e03d7f2f8b0d06632b18d2132620f232cf2858d5", - "0320bdd49acaf17ac110e63edf3c02d0d048e94e184c57ecd034ad554e63e712df", - "0228e5e5466207fc0970b30c949d17c524f4e74aa7ae2d3f3794ba7aad1487eba1", - "0320f4b5f59ba7d2e616954167e2c2a703dd3ac09f1d4543fa1527324192e04bc4", - "022143464fcec1267ba2ff7b812ba7db3ded1ab02b4d0bda0f8de023796d0edde4", - "021787cb9212f10c23d9bf0161b42e6f112f8c8e2464875f28d9fb2132f81bc926", - "0213c74ab925a5f071f345fc0de9f383c4f56c3408ba77f00a7529fe957eeb1f0b", - "0213363a4a56f63fe3f1daa63206f55a9d8e4c853952dba89f56e20f49ed89a463", - "022a1e85498658333adeb4f41e047e4f5d41cfbfbf57098479199ef4e99b5f8138", - "0229633169488dee9f3290556bbb0304870f54fefc509540a0ed61edd0774bdb70", - "030511dd2360a3246887d08a914b650369cd22cd17921af6d2dcf580c8b9864a59", - "0320b97d5064f1aa0592e234c0db8f0877cb63fb8b3151f3e0ac107f7c49b70443", - "0313a2bb4bc2c1ae3f0543260a368f51c276a3944350c8ce3d6f17fda5b99f0e79", - "032dc32ef1add1c32b764e29a30e78d2b23eee62a002329174405a1da747eb3212", - "02085502e2bae3ab01bb87e073faae8ac12b6757bb57f7b660df15566a926f8584", - "030de2d21814fa0e1cd7d5e0fc4d6d3ce31a487598db89a9fe5070cff5e395cce6", - "03175cded40a597cdb5b3d5c4944c9ac25253c7235c0de43a2b3306b7a23cbe88a", - "032b0e4d30d68d01828d0dd3a490d367fbb23f967d5e8c983bc9d3fa16f3491b4e", - "020b8c01d65b6ced128d3319b5ebd6da3613a4adf67f422591b0be4c1323769bae", - "030915a37a4088456890011d41fb8a0d3a39170eeb7ee8cafc3ded973d9b947646", - "0325f83a6c93d777daa96d97a567d1be7a0240ecb3fa722448512ac651f31fdce1", - "031826f7b7d441e8297075fdc4038ebe11913d7aa28e60e31b189f96689f6f03df", - "031d15da1c4e851dc8a35b3225e4fc7a4d2eda10ac98e2a9398e082b35f355e3f2", - "0225c13a06ecd761ae41eb99b63f994e89e897522c9ae5cf4147dda7127f5b9bd0", - "020b19a0c41b2057d416f303adc30902f23ad121f4c0fd9cec5a1108ce83b27c5a", - "03303206db5a1776d055460582752266c09fffb4f711bb508bdeb5c633bf80d4e7", - "02185a8cb45610219f3e7d13b8fef37647842568f0c054d25b7b152693f1e398a0", - "031ca425d297e2ec9d30c7295fd1cb4c02bd6a8193a90b97575f39a55ae92e7947", - "030a957ef565f9b62cd51c64407f5b775b82124ea14af7e1a775d3d2f680070c1c", - "0221458f572d3eae214d07531f965a55dcb2576149377c40ee5494a9157ace89d0", - "03133922ae6db0a48f1319dcb7eeb262fcbb56e32e8ebbaa6f5fa69580fa6ff6c3", - "022227f4ff339e103f6581bdd827c77b27423a478207bf3bfeba1f76ae9051d753", - "031534614111aeb9d526d437631b89821bc2afe9263c947c42ad42dda3ff1a76fb", - "02074fe9dc95e6a3f046a2c299c876bfc4f55b8e2fa7589e90214ed1d4d7b118b1", - "0202bee44c23c656653b4ac1c20cd7fd563790d7bea2723ed99921709ae66428e2", - "021eafa3f5d0f5a1d0e77fcf8c7989646054650c3729110a57edd267809b31e45f", - "0329db0b2b0d9d6422f25a578e78440865a4d30c65ade5ad559e8320bcf214d885", - "031b7468db4b1f63698d79bfeea7c177815a4aa332656f23d4800a602300262e49", - "021d59715fdb4754aa5b517b45f6ea6e7fce05e145048c98350a75efe2589db9fe", - "030d7df5a30dcf924b98270f8d748498e0f1ebd0d34576fc700935271dc9c12810", - "021712b180c3c644f09fe9163e1a718f4b8a49c84bf4a2366423f9962f0af9c607", - "0328e3481b452ed3edd5058b9162f48af95b2357843d24fe63d4de78ece7479079", - "0229421b834fcaf76779f0331e72a246e471c42beecf336ac5625f545cd63eb6d7", - "0227d2938bfc9b769af83c2681a8de2fb24d7ffbb4582b2396c070599239395d1f", - "0216f43114a2d8ae7e44f3e33bcd65c38ad7d5acea6f198105a9b910e3e20d2efb", - "031c29ede487e822e1d184043cfaf2def9a70cb8c8050cee6de8d936c7528e1f6d", - "030c848e3cd359d3a4f3a2f3a36937d9f970d2e1a1e51896b081e52d4ad7dcef7f", - "020e65d5af64deb45925d0e0f72715d640f29d4e6d3965e5ac00a7d71cc2c5fbbe", - "02165e0aaf8a25ab59c378d1ccef2f3d617e26ed57b1a865ecec5f7069adfa42b4", - "032a6546cb0ed05c2cfaa19b36f944581669ee52fe6d0db76da3ce13d1136d40f5", - "0305a19b5ff5442e632d75c1b66daa345e599b11e12e7b5c979dd9e818e4846ea3", - "031285f8daf40c3f2099282b8a4ab639dddada3468a75636bb2886b9aab45b1e33", - "030ffd3092a7e0ac9d1b1835fc1597a91985ee5872593dd296e030346ffccce088", - "03215961cbfb6aa499208a892c7f71c001f5efb18f4da3934389d9328651d5ec43", - "031785e5c93101f5e328b1adca6c460802e7b97ee95728c3e6bdfdf54939dddec1", - "022d085f7539c38cbe517adb195a5627a94dc62eb388e40cd9d0c3d995e0bd721e", - "0218259d1e8ba67d1413b843b0a45fb3dee09bd7b4096ae77c122f7e449852b3a8", - "032f5e1e0e0c8b61b0564d12a5da3da18205d36c5ec195d6d2d65d14be6a9198d7", - "03056714201ec1b7bf397385afc1f454ba0d06406d8fa7469bd1c008f6c66e7099", - "0309a89bc3cd3b907ed1f473b3a4a0b60cfc97103a3de9c723a8b429c9c5f8d4ea", - "022c03eaf427fdaf077ec7b3c4531c9589c07c974e5a58875bf1eb441d90654824", - "0316a2b4629776946e9515e8ea100b4e858935fc29ac0d3bc1e9be922e3e5fcc46", - "030ad0c83a0c5ae0cb74de325e16c4a906d5314e429c49d6d7f070dcf0d05627a6", - "02163c877254f9997838ef97bf647f2d124ae7c69b1f9ee9c5a89aa031952a6e72", - "0327bb6fc0fb1271824b2c78a729703318b1d994926287590a10a722c24c3272bb", - "031866e6f776e3f0422984a88731d6445a022beb65236cbadaf83c002396775fe5", - "020d63c3e61e7921ee2d50596038899f5a49c46424efa703b1cb1b668efb45fed7", - "02200212a81f0f1665a4a57dc3241c00b9afb2e316422a7c3f870f6bfadd45738e", - "020049e7d158f9b79868dc63ce4e76da5a5a9f136e8f2032164526113725c67d35", - "022a59477597165d3a8547ebc977b25e3a1c6d4802a17b8c849b51776b2198c661", - "022e9248110e719298d460e66533af458c10e8e0ba7b2590794f6e89315d846afa", - "02252e9cfa69d308bdef4305c2e310407d8bb5def1ee5452d27d85428792db3d72", - "020345b5719d7c8e3800aa8f17ad5e2c9d367cc492f4a8c6831ff53c7afbf15c14", - "0305dccd513933c6aa2dca086fa808b3d2baebb1744d07d01748ed9a758b154625", - "020d6762a9a83da768fa2456f7cfaf9962611797dfa916a0959046e5bb9c85fbea", - "02200c5f32457d4136255dfe1ac0147984ab64c7bd322b8d9693e1a3d290966aca", - "020cbe3f69eb0b6b3f0d2349ec19e130d3899750f04a260afb3cbc0be75634ae1a", - "0320924c26a0ac14527a42a21d8777f4a7a6553992cbb5f840f8d45f9f3cd50661", - "030d70ae87b0ba8dc5bfee645120f3605b7d0ae5aee6a298ad6ebcd2d80b67324e", - "021f7e4a7d49067b05976f33468865c30d34a1c72a59d0b424a4d8101c3a9685fb", - "0317c51494b2f2105b2a2f483c4416b3b303d19024de62d11e9bc6a578e3fb28dc", - "022501e259990e3f0461aa2961c265cda67b481c4bcfc35ff0430015fe8a183f66", - "022e764b83d858fbb610940d3498a9aa0e9875de07438c6f2731efef0e47dbd51f", - "032fca24f0337e1949de8aec7c1545b1ce5a3e6225f4a7b0a2e1409be37a4e8fd6", - "03242277b4ef27dd1611e86bf80dc5b9f107d9ee1a351895ebf73ec91ff868d202", - "0303ff4d516cb52b852c92a4c47c6b4d17648a455be4b658de325a52d4b41a4e6c", - "031638fdea92df52e3e4ee6843e968b301f59cd8193e903cd78347c5aa55119d89", - "0312db25bf81f09fd99deec2f2ccf4ce0088b5043af7ecc81eaa2182229d7f5eb5", - "032123cbe6ca475ba3031dbdb2f8c4b9bef77cb7b94d5738e3b31b93382dc70f6f", - "0222337103953d0db9417e2cff76ab458a92571f3758b4df7d6294ce581bb45099", - "032ed134717033669dda982c592fd2b2763ab58eef750a0cf272df07caf88111db", - "0219366d7b933b670fb1152af6c2bb74a05300c5f997d21e6600ce003da63c697a", - "030953135c6270a14ce9b8878f020e1cec4eec5ab867ae01f027d830ba339ada7d", - "02071f6c24be129e46bfcb355dce584e976ea6aed5f8d4d76d028bbb26087d5a1f", - "020720cf8b3d7de0ec42fb836411d94c8477dd0e02f06ff647878653dceb576740", - "022982584372cee8f8cbf6a5d45eb17bd25e9b44f649d789e337f3de10079e5a06", - "0205ab4cea84a1a9892fb073c2c4c2b33f5e41864097139d4d1bcbc6b23033fa77", - "03261a1527821a2e8f4c0976ef2fe218f7af99a3b4e39e8d3e2357af0e44489f12", - "032053027e0437349ee23d24773111a3765b36b19885b5e66f947164aba9906458", - "0330351fffaeacac1167eb0c453d329ff7875fea5b4a48fe6590f68a09b4076918", - "0223071c53cfd0b4ecc28bc1f664bd44e8b7cb757ccd90148f2e70761a3cac2f13", - "0317c258f5bf65e2e55e57196e6ef1bce66e3c35cbeda41df91c43d0c4456c0230", - "02302e7adf754a19d92d1728292477da0e767caf0d34db4a81580c81359a2d8c5d", - "03239ee2c82a4a212946cd5eb9f393f0bbab641c393f55e55557610e8b32eb28b6", - "03290069257a751f940595068e408afb8ed49578112c26ac062a98cb2de9bcb225", - "030ca273821d4b79f2e3434425620cdb0a99b03f3b1f3bfca24ec1a4e5108ded39", - "0220b39bbecb0eeff9d8e3371eb9e461112651d5cd6a251f89d200f7e6515b4396", - "0312ab305acb8aac1891c4d2d45e62a23e01cbf9e6e7d7e494435ba5e0d4ef4d9d", - "0201481ee202f0259a4d82beb0d510b37e078e2318ebd4be0a4a93db717096ff3f", - "020c2ddc4f07b68b15cc85df307fb4729d17b7aecaba7037f5e56e8edf3a33b42b", - "03151677f21a1ee9de22e75ba70c1aca90c5b594c0ee3f4e6193758424565e6684", - "031a25c83191f9fc323324c5eb3f6d82ecec89f8fe5eda60fe8b9a9999f5487826", - "02148e11229b2b178a4569b9a29bdbe750e1d8bcca31ea9a441d8c33288bd3babd", - "0207ca5342f7f06591f30398bb860cc62ad469c10c54032a20e0a99f291044d1dc", - "020267b8f74a175d73b6c242a3bbacf563937f5a7b85f2f68aca255a86bbaf3997", - "022c3a1a2cefc3ecb6e876801ef8fcef2d01080a66f5098c10eab5919bf196a9e2", - "0221737358e7b870ff55bd7fb40ae8cd6c52cc030d71e7e24f5a950d9c7836f73f", - "030ccec4a150a3d1c3fd2c7ad4d9fddaba0a0fa9f5800e4d2d2aea0e1d6dfc1f96", - "031cba37bbd1221eb4ed6a4f55542b362af3528b19335cbbce9df7d53a7054774c", - "0216bb9c092bc2f291038c3adcddcce9e1803317a0d1e0956bd20ed34c4f5b5fc8", - "030ab855e42ec1a4bdd02f5f8bf30e64e16c0022754b8fab4d50d9199164fc04de", - "0322c2e5af86ec8f4926dbe791b60803436db520df1da748a93732d914e0087fa5", - "03026bf3999aff012bffbef511eca168f6ff6f2fd515089f9554539f85d2e185dd", - "0215ca52233c0d2323bbd8ae2a794e5ce8315ca3517b3261f6cda1b556686e11a7", - "021f4e7969df75cc99b10b99d43c430359362c233db4e4242cab682d2107816913", - "03221440716fcb377dd67b0d322d40dad1853ca259bcdd14df666ecd88e22f73d2", - "020dc24272d7ebd08b2797ed666d4fb69c9007e4c505f0147730693c7e78783a11", - "032e2c262c6ab31fb577bbc5adad70a091491ed607728b32d24c0616775aa9683d", - "02118dbf5e7989f144b98a11ee8b650f22a2af4a82034f2e2d6e99337842e9b753", - "032d86b178efbea6d854f8bbeeb492eb491234d4ea2a176ce037906a438d5c60a1", - "020d7be69dc37038b24b8b6d7e3fbbd9697b2fee291165e82ffdfdd301bf54cb9b", - "030271a23e06f52a2683624e1d577896d342768553e7797831c3d23af386ea0ec1", - "021c734b5fd2c1c640efa910359272b7b44de3b7a0d43bb33b74fd7b6b2a366806", - "0226607f5422b2bc652c03992145c12f6e768fb2ae87f9817b21e7af6c31aaa28d", - "02093eee7bacb90f614e059304d194f17613441f1f342e775f33bbdce58876e4ae", - "021f9a822d2cf52795c51c1b56d268d0f3b20562a056033b26257844762bd885ee", - "031081e62b06ba645122362f850b3473c9e780107783b3479678d6d7400341f165", - "031053cdbcadb083dfc8adab214f78f586f212382e7e313ac13e271504a2f1a79c", - "0325d8c59325342c6ea018bf9b28d7d6984f0a44d12cbcf1b1b330c52fd25fad97", - "022bb1e7fdfdff17b17686d7f0fb97a2caa20c733bfb2cc6db299aaf10d562fd7f", - "020e4646e3fbd2a2df6ed950e35263026ba051ffe5643b695b263edf3f9c6e3bba", - "03174e08fe617f570ec93d22ea2dffb1dc55522668c340ecde737bd8007a420b2a", - "0219d8636ee23c6de0a242bbe4d3cd50190c7870d3b7aac9af7a57535081828306", - "02034882bfc00ec84daeb3f8d284040d05cfe60bb62555b1e1b259dc11650f987f", - "0203c53b7530d07508b7147a631002d59d3c6b2f9be3cbecfdc3af000ec935d465", - "03214b7fb6836625f9df7349dd033c0d85d3b9ad164df8996b3ee0e8d08ac3938c", - "0214e4acaa2a5bb09dc1d53efa640e9e95b1f02834b748d783374bffc4b23127c1", - "021d0ff9482a32c77dffc9725a2707331ea2eab1955bae658ded5f02f76c35c5c1", - "020e9909e7213bf8700ff40c8914f5bb472e12d599072bf8b9f98159c55725e652", - "030d75a0a8f11849cd060f41bf7fa2890d655010262c634dd2fcc77f05b178249f", - "032f86d710acadbca62e5c731f88c942e6967106f9e57ca5870bd01ac7162039aa", - "0224dd4952784e445f7a08f57b2b9ea391cf65bb800cff02eed98695f17a06f1bb", - "021be733e68b594a303634a6c3a10a4dc600c7183e724ef42f2a7b37dcdb6657c1", - "030f5fb8c411c72e01d9f92b0ae9674018c8cabde51b0c51c8e98ab9f42a99b5c8", - "030cf0df1655923c9285d01c58903df980dbb3a574bf67e82c1969a6d01f272599", - "031ace74a9354a910906a4a0883fae114a46d3836b7b3bfa136e454204bb11a75e", - "031ea8de97cb0c68f3dadf83f13a66dcae9a455c5a8c3e4da2869bc2cb9272301c", - "031d3889c1c3d93685c483f2a24de7a97c6b9ea14691f6ff877f977443a55e80dd", - "0222e11d3ddb8dc89c0d12d51218da62f6fb478e775d213477382b984dba5112f7", - "0302c3ee79061c3763c916648cf1d00c496db7f5e5b9cfd52cb27bdca22ae668f3", - "032afa7e06cda4f90f2869ebe4904422c5cb0905538e5863c11e64790f5a4f56b4", - "032792258a4dba090271791b24ace46aff18e68a361d44aa128003f5b273ef6e6b", - "021a3994aa3d461fcae055cf8287a453add85d57ba8880769967bd3cfb91dad3e9", - "032680ad811c2c9184bed3e6f5909585e2ff3b2f1f695840bcc98b0bb90cb21923", - "020bf6580d47a8136f730c127499c23f5d77f306c58cfcfe81ec9d8742498e5040", - "030e05bae70d5581bc87cda5fb00e4e58a6401bc34fd052de476aa91024d6b4981", - "0201c6881c6dd05db59c1521f44eeea81200693efc58979df272dc29fbca0d32fc", - "020f11c1560bdbc1bc8f44d1d5fb25b7528d83913e16ea6c8607e8ef60575e0596", - "02069501dc2f01eadb215a96abcdcc12ce714ec3ad13d2f5e00f2460406363a69c", - "0326fc3bff331983fe52f382b0360b508dd6d56e7659479606546296b5acc86e9d", - "0218c8828c9c74fd83b703e7edc96f37394d74eab06bbc419cf4dccae310f9c7d1", - "0216b7fd3539c45204481a4c6bb08a5ae08f205b7bdac7ea87384719767e2b4830", - "032480e5ff15dbd99b94ddb25520c1c8bf52a71cf59fdad1b28304539b4f10d74c", - "02251367344f7a272ab4edbe9a36cb3b30fd0f3fdd8ee89a3bdaaecc828cb5cb6a", - "0220949d74ec9f4a4970871383bd05c11ac994b124ddef03cda520986228dc9868", - "0319d7e1516fde37d83e4656848656a580aab06eb9b5d7dd43c03f8efcf893eb6e", - "030f981420262fe1c86882b3a0e019a9d9e016f2410fc06dc95536ba51131457fb", - "021fa12d703fd543fe0e91a9994c5fcddaecc625bf0a2f71183edf257dd38e798f", - "030f94b7a632177303b8ef9fa6f9c14ac05ebdd6a4c5b6fda13c6dd4cfcb697424", - "031edba46c6c86d4b774b7f60d6d2cd441467612fce706a0f3039428b23bc3f32b", - "0313731617194464f0e78040358d74348bc283e024bb299e78ebc932438a56e9d8", - "0226c14a11fd4f03b32c3ecc41dae8ad0f0e4946cc09ec339ff8cc623f459b88b7", - "0317edbbf196656170848a2916daf6417aa45eebc884f07bad51af34a522579090", - "0314b9cb96b4390481e0d94abc9b875a5cce91f86380dc2b115885c2f734a88cdb", - "0301d97ce3d007dce2d0f8f13e996282fb07ddf5e798f7e95a7209d23de547b33a", - "0228560eb712183f5c1d6ef9bd69e4d81b5e555f39183eb1b3f2cd255f8ea4f605", - "0316be0fb84af2d1b9781a362fbb4f674e45867d9dca0651bde85155cb44372591", - "0326f1d18c274472d0e1fcb07155a8ce50e8c6d95a26268846420a303856ad8f80", - "0313d3f6ae8b12611f98611d4671d86cbafad70f78df11cadddafb1fe5490e8fcf", - "03056b8237b6b40afbdc742c18ed556ba46af95c68f94448393495a511907e60df", - "0223e130f6df07e39d6f0b6aba06deecc7ebd1792d38812f57d6ebba1119c1d728", - "0325d96ebc9cf074fbbd91fe3813cd60c2cbc30e36c0f8bd070d256169d194298a", - "031dddde43c0c956f0e9d6fbfd14a529a78ccb9e292fb885651b7fee561b3cb473", - "0317fcbb25e2f847a5bc0b37c72a6675b91e4e787625c66d97044ab79856c37fc8", - "03196b1bfc41ecbcced8fd7f814e3723d3924050f446ad2c0f453cb97997693b20", - "021e03f7a3f0677448bdf8f25c2de61081578af0cbf2c68b4347e23d1797520ec1", - "03155ff0d273299cef0ba4bf940042863b918f209e499e61dca0cc967f3bfe7048", - "022f6a79025c3ffb72047715e3d7dbcd4ac413985b417872718af9caae5da5b453", - "030584a254d508d50bf7b089d1caa00eebbdea51f584c1758623aa603ba793d7dd", - "021359668ef872ddf4d7ecf1b75695b57e5a13317c23e84ac0e2521c4fd5a1a2bf", - "020b92776e10f0d8f613e2ed930a13a001f48ee793110061848a15419533a2ec3b", - "03132a348355ca44fd65124e313943fa72119245a50d748c907f8b6ccf11d068b9", - "0301d59145b546c0c2f60db76981ad4c3dc6d14ca4fe6cfb9fdc278ffa1b7a87bd", - "03036da522b2433d766b9b2e7404545fe66a5d7ec59220091160b028c8dffb6799", - "032215a62e0facf5275ce004eeb98c83244596f7a0d00fcc2db7498182a639fb8b", - "030e798d6553d5bdb2535bd24563bb6749ea01e7bf07d92715ad3bafae7f12470c", - "02053daf2c6fa744ba90c46fd767df1f513faf7efb0543bb24b2b9c8bf20aca8cc", - "031851955de95796b24a1c405ef85ac1e0d90e97c2867503dfb444cc6570a57842", - "03291b16a6a9f72193c0a255f50ae6da6fb7f009f76c72b7d81212b6419f48f2ac", - "021930788d47e8f13a1f00b3ba6da796deb4cceb68a7c54df561e308bc0cf66f1d", - "021087ba63bb237a5477c155c32e7d3b3466b3e8047cff02c3707da880c71892bb", - "0229a5f3c6e6bbc79db606375beefd2c43f3954847b1eb7e8e6089a2fa538a0139", - "0210e4c7577b6b5fe2ac00f52b2e996137509628ce417eef39b93dd2c676638b6f", - "0310974f5dede5e3f8059f660a056920235874a8eb72ed27b8d0c08a0526922da8", - "032cc93c35e551a2f32fc11e7f27afe23e618f0bb2f671217c3dc34ae968c6e7e0", - "02031d7f8b34954be78fd450521c31b87dd010de00659706de11a78eaf88c983c5", - "022636f975d0b1a7e7f4bc88bf9343fde9639bdec38b8f146d002ca5c9d238205c", - "02285e3aeb2813c080fb225365487e4b21f05426e22e3350d6af4e9dd4d9108a68", - "022015d0bad07d9187080758ab1795de0eb7e057295bf1f77bc279ef48772ab0a5", - "030215e4542234d4b4bb545925d443e98abd58193cb697a1dc6f40bc23fcb4d8e9", - "032eaad4744b7ccf9048af198a43236185b602daa4a684d1fc7b2e50910a461cd8", - "0306699f729e164abee001968592b99348db970e9a743856586ea5ad808b49d6da", - "02295c4522e2a46cb5f327f05fd79bd193be1fa67625f42bc3bc8e18604b0b3165", - "030eb37972a323bb73c16712d8841f20fd02f2891b136d92269d99392b6a220ef1", - "020dcc854ba1cd1261a83aa8ba4eba4ea381293ae00a1dd01b4d3a2d8c38fa9114", - "0221a363e8066610a6307f4d8c7ed4e920347143422435c02a2e99c1f34f6751e1", - "031e490e41eb49391d7ddd619adbb3f606d5b0ddebbba312345aa0ec62fea690ab", - "0330246110dd267465f7ab1792b50ce7228cb01455de2a44bf7bd66d52820981f8", - "0300f89b04588f4e583c08071b4a5135033de1410265fcac6a690121f2b4cf75b4", - "0309cad1b1ebac085ccdb4bf1085adcc1af8ab4931de3b9c6186b976a31ebdfb26", - "0217fbf32d47c2c00ee75195c6ae31b247b14dde105d8cab2915a08393172a1176", - "022aaeaefd4bda544f0cca7c162f29a2fd8bae1665c37f1795783ddb7c40fd7beb", - "0320d7ae4036ce88e9f6470c91e373c8e8bd039c843504ad6c0d732d01073b7230", - "020cb51eb375d831032d806b2caf55289150ecb7c61ef9e692a3b78b0156c18dab", - "031d7adf3e46b042b240896242e4d449af1aadf91ae312fd6fbc4e920a1b7b3a3c", - "0209fa5be28531ecce6e2c8ae5fa89c40c4b34065d4e5ddb85c4768305a56e329b", - "03149a701853d7fc6db55d682890ba09aeaf261f254fb172ab0624a7dc7dde3e7f", - "03034704cd59163009b17f9bc24eb40b4bfd31dd8ea3e28c8e15fee44168511d33", - "0308e3f2d1d7f47b67a21a7de75dd1254309603d2fb1ca8e2bbbe2e9582ef3c2d8", - "03282e047de39f0f7b5afcb8e35c60eced2a0f85bc31edf6930bd5aac8ab29ba56", - "02234ef99724fb561fd8783327b5798275850185db055b8bc7dcd6d8fdf74f3901", - "030a4177b9a155601d51b446e295b2e99a9d2e3f57901f3efc5ebc1fe0a32078b0", - "03188d465928fe72c202dda05915ba8d0f985a69279dffa7f8e4cd35240d171555", - "0303a8c348a660fed759c960a834b519031772d9bc11390ee71c7bb1a761be6c3a", - "021aa9dc40fbe82fc1be521022cce284f318cbc401f8f14062054f9b039c2cd04e", - "0317afc4c65364541fb481101a7bfc8ff5cdce3e0bee93df5f3425d68f3eb2fffa", - "031e1d0a453d08d54fc060aab05cfaf9d16334c28a83562148ec1e7cfe00762d57", - "0311e60eda80221c22c4cf099c1ffa59e86220b90f4f8d0d17f8ae77137061415f", - "03113d980bb0c99806b2cbe7839344230d4bd03752b363c9af5fd5d9fdf73fda37", - "03085daab103d8c4323fe3576a4e5f6bb99db027525a5a734b9e5d8bc948430af1", - "030af6d72094b28c7762ad553867f490cf125831720636a1738ba87a8fda0b8ca2", - "031a0ef4b9ba3d33668238ffcd3a9d9659d792312d66368dfc54efc40ea28b9217", - "03043b639e2509254bd04410cd288d713341c9256358bad77f6b262019e424159e", - "02267f83769d25075361ef49a61d383b3245d9527468032be4f167690bd03e8114", - "0209feba07b426ff9dae4166ccc20b73843da7b68013f4f8c1a82167a4fb25c2fe", - "030aeda316fc85d95c0a91ff97b8f3d97c481b109a3b65bcde2b8f8976f6b6fedb", - "0203d70919b9a950a18dc28e0f2cb5f85c48d28958163997ea3f80a2b975241ed3", - "03188c80bd8dfec6d829a440281fceb14361c61e7c9a5dd70f815f893fcf3659cf", - "0205a218debac10ea0a1b8d8cab6d9e27b4a75fc8e293c6df4d72249c634be6b2b", - "0308ec18c50a8c44c425449a99e84ad53837b935fb2b95fc0f62bca7d729979a9e", - "0322189faa23b109fa98c248fafb0be991bccc5f9c8bbab280cbc2a7fdaca95b62", - "0328680756c0153625ce2d819afc6c44bbacc89126d753f8655b68d98dd608ec22", - "03066a8677e66a9f49dd4470fe6199f3f108b7e77ee261019aec93fefc817e2ad9", - "032acb1c0cf96603e99d7663405586702e3f2090b0c0223138a861bd91cfc9df3c", - "0225620f482254d7472bed79abc74567ad1667e0a64df53d0f3fbaf0a6c22e9a51", - "03101188e6a48f9a55e7353c4d42bec5b9ab56b0f344d66ebcd81c91c332b2eeb1", - "0226fff0d2893f53439f137e039ef9e238f2741b72cce05fc931fffe7f5908eec1", - "033006e121ccb6618b610bb595ed6541ee0f10b9eee1fd72145e42b57eba56430a", - "030c078c95ab490acac0f8452bc9c53d98385b10198eedae811544095bb1644667", - "03054fce4141e6cfd732b144546d0f123de26d6bfd39ce4e7b1a74515a4096c67a", - "032c71e81ed38641ce8a02781f09a9b3310c2ab764df376c7b8f5db5c09c12529e", - "020547ff4498d59e6f42544e853ab4b0447daeb691cff438a41234bfe887f5bfd8", - "0310c35b3b985f3584a49278382d67efa0120143cc82da4834a771d13e8d7b6dfb", - "0208bfe10dc8dc02d763ecfa8ee11c7479eebab0ee63574e14b7b4c10d307fa312", - "021d59468291fb1b166eeb04479e85c6207d1753911248dfc90f5cda47ee51d96e", - "022c551ef9689807f427750d2c0afd1dd806170f123376ae0e464b0b97187f6ced", - "032eb7518aba7f7ac6c59e5f1845fcbffdfa4be2835ebb523863a6f60db95d6760", - "020fd300f2b37a3e8d34bf5c7cd7150d7ece2dc14bdaf0b138e53e370e736e0200", - "032ef6a6664d7aa568afd4bca0d02cbc5073bbc79600c8453bbccd271511b0d330", - "031395c999489a055918665a5e53f30a5a8325eea85a60e35e88d0b0d2119d94d1", - "020886778606acf4edac14e7745fb0902a6a8febd04967cd7e9fd2df77ae1c1ddd", - "0310d959e1d359abe1d6fa640c6aaf5c80f648d8fff8b909385b33d395240496e5", - "03250d115e628da17d08c08fc37a2aa7b2e03d52afa29ca8f911c6887e34b34e5a", - "0317224f8bdc839c484f68a671913eabf5509d51930045f97e47941b76a3bccb13", - "031edae34008f6eaa4a90083c9d8a862d50d102946243fca5109b152404fbcef3c", - "021ed82f654635a9276eb74a52a6fa6279790f0c040e875677c2b11b90b5588f84", - "0319ccf5d52f3e76a95b5fbfe0d76f04e1d70be19553d2e97bae03477d2f8e4a91", - "0219cb49c2d549b9b7df5ac3a1fd2d33780ee6fb32279da270c26549dfc7ffa082", - "02133a064f6aa684cf2910331ae5104fb0e4100f46abf2c5bb92e4f221db6062f8", - "02260177950447400cce8597297fb8fb5ab160d40b798f40b2961a2f07454901ab", - "030f6ceea1b3779e7b20e7c4537c453d441393849f9f2be1444e01268cfc3cd87e", - "032e3f5d2cf2de0f471d3d1e91bc4365ce52c8edf27535cf5809b9fd1cc5f94754", - "0215d154346360a080596dedce3d856e023cd21da294c4a97d1146020039115dd7", - "0322c83ecc63143ae843ae6664a5ad2122edda794fcffcb8477f811f88605c4040", - "0206cf44ed30ef22c1b382a6ad61cce8b7019e62e82b7e52a4b81e4d4b22bb7fb9", - "03249d8b4e0f22457d266482269a2cf114fe015bc38101da75f72fbc5dff9bda72", - "02172ff3dfa170f120ea7a21016f1b047de28348c49f62307c297801f0567b6c7f", - "030816d2d6cccad48c05e01dc2deb841f58eb034905137f257dc21266421296bb7", - "032ae94247d5a3c94bda9bd35df4dd106c22156a4ad10e887893ba7530127e0a39", - "021a46d398b40af54964e9acfd3fccc6cb5eb719238d02aa7d2c65c7fd4bcacf77", - "022944ff0476bc8cd54fb255a1c6786335152e3a7553e1aa628acc4249a559da77", - "021325f80239bad67c58bd31feb84f7223cf18c7a80d1c5e42a7817bccb802cc4f", - "032746034ff5ca6d5037755fb140d656e0098ffd24693e979602e7cfc45788dd82", - "030eedf045f0af0f9b27b404ef9fcc282321e72e527d6133f78771f995bc22e5a4", - "031480bb576422a2fc49463b9a9a147b22d7409e08a2bdf110d5cb9c11fcb60f3b", - "0313606bc4d416d8f47323a6ee87da6ab8effa05b2de6edc9d251a487a018e1875", - "021abf399c4ef598528b9d3decfb8de75f6bf20acccea9406e53694eac75dd8fc1", - "022801c412a330719b458751ec9d940612b43eeecf4d2e8765cb18b470f32c7f85", - "032630b012877a44fcfdaec72cae54bb3683b7211744ccc9ddc1dbe060c9b7f03f", - "0323633f7e383481dce7fae8a66e67b07b2eb816c68fe55f77421a3ebbc1bb3bdb", - "02199a0543b507a44b08072824bda2890f8c5ac495895336e86333203c90e3efe8", - "02192918a813f3a48ab6c616a52c3fbabce0b8e32575c3a30c6f82648d4df61c37", - "03143539c3a9f14e73bfde003f8b25e38665ef5bc6bf56b9110b4e4e586c610cc2", - "03200b1ceb294977a672900ca5daee32ba5bf5e02f45f73f08ac18ed0e38987ade", - "0226037e84c38b91262c8863a2637bcc3eb1d7508ccde7dc7d598b335477e0592d", - "021e63e98b69823f9056a0161e92b9a33834397ec7644595713d40e7cb29cb344c", - "021fea3383af33d6bdd87824c7a81267f6c431ff6f647c66be3b6a0e984c31b322", - "02142f7a1db60c8b13a7e4fbef307caaac6e8ff7425a309d3f219cf07ce94842e1", - "0219969d688b9075f81811d7c4f06a8cb017deff13c8a77f16c6d6db01fb2beb1b", - "0205ba9dd10ad21e5b072ee7c874d82874e732531d75385b0291a6b39168ef8c21", - "02045f7ecd9196d420e5de0d2415ce16f746c1ea256fe5f35ef73eef339040f9ff", - "02165933b1d1add4ca9e4b3abe0e46bbb58178f80aaa500b23ed20341f83cdc65a", - "030904dcacf1a702e2c8727dd69898fa0f1ac3ac428c0ed1bc3a075be09c6a46e3", - "0219634e0dcba59378d3853e2a3bf8efe4122b45e09f00db7461341abddd494819", - "0208759d5d99ce7e551b3b4f516a8e8f66a087b245aa227bb8f98c975d4605fa04", - "03064f48c5f694b78cdd37640b1da1a58bd6f485e3c197cc1e6d9932c0fd3292a7", - "021088ac3818cb6ed5ee07a11db548407732e820394f5a4d8cd23e6af80f700275", - "02113975a32dfca7b34784de5281fed5b7f7cd5ec1d2ee351b9b3da7670fdf9246", - "030b20f40cebde696de4c9ffac8e996e075830d1f6b255a1d212f1136da1c58dbb", - "0313fc47886a76379a15fb8e1de56462ea34fef3c0b5ecb2e731d01d0ab2592204", - "0205fb2f94895446a0b15b0defc1b441e272ff3c8313768d612186039cdec102d8", - "022127c432090b681482568ec49ca195e41eff0e0ca464752f788d27cdb86940d9", - "0318d5ca709a349fabed26528e66f4e951772fb41d4f7ef00953edc1ebc52d7899", - "0201dd2cfc84f98f062122bdedd9afc1be3c57a5f799919374137ea88cd898561f", - "031fa9a8ad7ccb553098231b2e0fc9f704b1318832c31b7ff1f55842f4b1c8df30", - "0317279396a25dd5d4ff009219e62b1791f5169d2177b2321f85ede0e748bbacdb", - "022d1cb2d89d9ee64fb88ed01e257089d798cade1826c77180781f429565d082fc", - "03038de9a876df773475476783f6978d6ec6f571de63adc374ef89024c56ba8774", - "0318cfaa8655e497b1d1ff937ba5ff5a02b6c2c812f086d928c045dc04afed1eff", - "0307133cdf08de6266a46f8f421d326252139d1326fe82ae7881f4d8c78511f66f", - "020a6af9541bca90d3d713a92157fae1d5a77b768939edc80da8319705b4821349", - "0227602b42493355596429a8c41182924b6e1fd71ff957a43e37d266b34331a4c1", - "02124cf1239d25ed12b0b3b7ca38374e0a8bc1035425b2f2cca8cd8458b5de005c", - "021a93309656b6698be30b90e46f9a1ed6f1ae935315b95f1bc5ac980c6dc72cb2", - "021b123817e71ef7954914fbd036df6b96ed8d58b53917905a4756d807a296e4e7", - "022297a4dd498f722b723bfb3653087656a5ad73060a97238782608086627ed1a6", - "02036da071a09f35522eb270fc2669777de69171c607390009cc9d4745243ed928", - "032c5490597eeaab137d27cc48df2913ead10a5a98b53af5ab4a620d8ca6b159ba", - "020479cd58011d0eb629891b569b334bbfe9f27b7fbb123e8a9afc4ef831561e34", - "0202d749a11a3ae4e61e6d9fed17a73beecd1822aa88b93759dc32561d683c1e6c", - "02240f5378946fed7a827e3fd6bc901af58b64707b8e35025e83ddb3a0c77e2f4d", - "020bc2606c47c7b9c29b026833ed9dcd5caaa2d7a506bdf372e2e574b0f044fc2b", - "0216d7258337e7c8c84659aa10fcf41a98783dc4ac13f5b6199e8881b3e29b67a7", - "031e974e8bd27f8e65e1d9f35b4b1cb00733c605609b8c4f9c5f479fb81dfa6877", - "0204ac6d4dcc23ef4f8c2b4e3623aedff945388cee00548af034153973a6f9564b", - "022a1d563ee2b9ad79c7ab67bdbfad66ed3d5d919ccb9e2b769ce07896a2d559cb", - "031aa56bc2fcc1561c2e9a7294f1b645f2e64afa72372fe190c4e59cfe474c48d1", - "031828cf32ba3c0a97c922e2dcc3bf8f7422b7e46f02156ef6ee038a32b5501a6f", - "0216a7956e28a7c3162877ec466da89567c53e602d950636bcd7013ada55f6c6b4", - "022727194aa706f2b955133c301523b564949599e40e60ff91a47949bc82b29ad1", - "021a7acb6f66ee5706935bf3e8f72e76015e950753ded2977068dabf7c4a6d09b6", - "030005b22e0706e9c2257f50fd6bd9928dd495967bc56896f3a3bbcf25bb7b9e30", - "031498aa4e91a2ef9db57259b356fa08716b59e8c864c11b094f08b259d1bb5ff4", - "032000875e401ad63b9be9c0d9eea1c324c53c295b94c6a4cee4150a40d8ce2f7c", - "020b492aad672402153cf4d54fa59acf57b81f474fe106fa3482c85ccfc029b672", - "021b20038f15fc7b43d5b0619f92e07bb0deaddf35f82d5fce0e1b6e33a27cbb03", - "021577735c7081025508d853859a654b51c1910fd612dee23edbdab87b61bbdb66", - "0302b165421259aba2486c16e8a3a7679b2fb46ea4a89f74d860419235d3b63116", - "031c5d8851093b3715f761ee91687e22d547818080329ddb84a844ef8d909021fd", - "0219a0f11d9b44f002566103f9d650c6c682ddde541bcf05b7c9df2d757051e35b", - "03177c93494b1afe14148d41452027add44be3003fcf7f03f3267fdaa6783e62a4", - "032d05df25c7e37bff7d7c1945608c0c9606c7d84a1c885d58aa869db72acf5616", - "03196b5baf5e4c0d5d1f5974a87a5cf85b5cf238056cb760195b51857993d607a4", - "0200888d5e1f197bf99fef3365e1b9552c7caa1e622d06b7bde002d49100aecf62", - "030c956871a8cf90e272c38c5ad9748754ba94a647a2541db33648ae0b4084cf73", - "020c03c940cd70fe1d4e8b96a66f78b7dd0b8b146029508965e5bc099d244a6b77", - "03187e27aba9a8e85f650ef735736feee6fc02bdb386ecbb03e28414349f9d3e8e", - "030c312580b7578649c9969e3d255ffdfb11adc78a676abc6765719b27d2137977", - "0222bc07d00c1dfb9bb75e21a1b647d2a7bae738ae6a40d28698d4a566b8af9911", - "032daa22e695db8ad7f4a046092c87c102c9cd409b1476e9fa843a788b55537ca1", - "0300f8e427e01000a688f6ec199c415d22316f462f333835feeaf88d5a2e6933ab", - "0221968b5f65c0623ab913dd3450b6b659fbd85a9b7bfc3b5fbf0cce0fa8ca3e45", - "021b4fd31f3ca2979e3fd059edb058edc80e20e1156d0ff0f47332fa8503c31545", - "032018dba16763aabba870852949616e75a36348bc9e3bfaf4be84cec3adf6b843", - "0316dcce44f4bab48d1adc986e31bced54667ed56a2deff55b94bde54e16c5bb4c", - "020a0443be562b81e1f4f8c365d9e25283965b197372a293fbeae5eb68119a609d", - "021e91b99e0252b275395b52a5ce64b1ec604a5a7d368dafb5997a64680d1f5f92", - "032694e8627de14d2327293daac9a52d1344bec7d3c9e6752ef7f53526d798a60a", - "0201e2ce578d26351e6f6fc55ec4d44c843cb665e87245dc548c511889b281b68e", - "021a8d12a6021be7c920e02738e06b41a1b39fa7dd77a0c2a9c6305f37a7fdb121", - "0312187e8b2e5c97bfacbd4e4c5fcce63dc2515307df5f16792f70bc70f30e7e2b", - "0209f9f58a56e9686be0bde2a353a8597119d1adc2e6976d556c12ca13363d8bc9", - "021ad0fc004300a9d9c37e2a4ff60042d634df18ac66c317bf481f6244bcdaeccf", - "020c489d4e4b963e632e28742ebb1714d0d01474d43a64f2f3092fc03fcdf69e38", - "021b733cafb85cd6142a94cdb41aca5b0ff668dfc2646f8951db2f1e3402b54639", - "0217400f47c75d23ae90be3b4fcda19e5949dc06e8ed37b911cb7a72e1cb9da5ae", - "03100b01317980b7f3bb0246537dd1c2cc112532a9e32db36bad9e6a2e71fbe322", - "032a9c76ca41bae60d3d5c003d18e2024f4f5604c08b16bbec881ecc3ade88846a", - "020bf3515f5ee72ebe6f97b684d673c66f44d41935de8d28c1813378df868e9def", - "0228260e94212bf4613ca528927857899a0970ffb1e31b4fb937f9c150f99821fa", - "03003847bec2fbfe911bfa236d034494ef78ea3766176d9f8b1b1175687f9fe152", - "0229b53f502c687316ee894a8fba5ad940196fc7674e633a5cb4c3d73ba8952d29", - "020edea0973c8f328fc804312b030804379a0439837e45b62260dca491b1a2f1d4", - "0308f83694f65a4df6d14353c10d0703ec600605a3ce1f4ca1ccdd4efedb32ee92", - "0219375e2de6da49a4cc7d268a29b5beb3b008f3b7ef722f101bc81f655f133fa3", - "0213264288a2dd962388783a394e102df9d4ece3db10cabad9d51a18f16d86f3d7", - "0224dfabe35d1503d7c39a94e7d23491bae8725e60b7c01b2a4a3a681bec017f69", - "030968cb52587ab0a098321820f791f0bba0942b537235d36712644937a4186b2d", - "0206f32b990d8796d49240c6b42e3e76d3a0ab0b944bca196a2a83aa557e710e60", - "03259b5c3778d05c4ab796d01f24381f6c2d916f375ff49676eb1173707d6b5ffd", - "031e5ae16abc997f9857c7ea537d95473963d03f81861d3b4b45cec6ca42629e28", - "021ebdf3ad680b030e74b8ca58ad323ca4ede9a8c0fe46ee5d237555215497091f", - "031399514f089ce0770398e309793e2c74bac3138d90fe7cb139096bd800fbf028", - "020a56aa455dd1ff2eb273228f530300f4816119526d8ceba49c1d9bdba1bd1351", - "0320775379bb909779fad8c0f25911b6e65dd8fcfa4f88cb057d15825ae9e20eb4", - "021d36b205b99c49ce79aa8588b853a88022dcf38b3a788b654aa29a30ab07cb4f", - "02038cbdffc4882364d7a385bcb9cea866c574248ae245f1dab1d39a8319cfae41", - "021e47ea05dcc31f1cbe4e612b6407e4b199c728b1ca6c8ce579eca7bbfaad5b00", - "021ded516ea24876d1a75d7c14cfa1c32c0d53c53a228e19b50ce0988791e59e06", - "0315d81f67614df8449992f34d591ee2c8049410170f9ce30571b4199307016d47", - "021487b360cbb9a8961bbe1719b14f9c00487455c283d4e26c05a6f3dd68d6096f", - "021db244eb34e01ff569aac65fd12792bd9d08bdf6099333e21d0a81257b56f4b2", - "03287894b1c990551935f950a25b40952efd901c15bfed636e986efabcfcdaab0d", - "0302dba02d227bcbb0a13bf34707081794ac3221b194d7b1801b88c39680637a6f", - "030e9e48bb57814a695a875fef930417c6ff9ef93805f4bb13d88f1665c9798627", - "021ea3fb49edbf3aa866f608b0b56ddbcc45aff62db9718d8108545f521f605a3d", - "0308f8c8b57738e8b3e50f84123ae97250b16e109966de12ecc27d1598496d1aad", - "0319de84ac7c50345bdbc591f7fc420b140f40d924208ca319294b9a350623c718", - "022d2678a96cf96cc7fbb77329b44fba15d08c974c5dd0c46ccd394519f4ee49b6", - "0304b08d66cb36ea06008d6dc159fa9c5e6c749f295f4fcf2bd4aa68f815daa724", - "03144f2c89c8421ef0e8fc6d43bb891ea7455ab4eb030d21d7c356be512e49ba38", - "0227c0a38ed5a708d4a06182642ce0fa88af36405b39451e2262e94677ab50a691", - "022c09bdb63668f82283e380f42a700de15f9c71a85d6f3f8fa01991f50c3427ec", - "0301d38eb7473a1b70b3c2f531e8bf38a9a0930dfe7fb7127e8c4630377db6d5dc", - "0211d571391e52e99d244789e8966d1d18ad2033a0a81dc2e40c1f3fbc39cb8949", - "0316e9a3ab79ab62bef51150adf3eb3b3a6e3d44365df4da99fccdc80f0b55e1ed", - "031c2d699c8dd9f2591dc509d2551114b4caa91d06173f330dd9d4bf3549358730", - "020cc768d62eb05e410ccead7613ba72734b57eb9fe52b3042817141399e5e1100", - "032898e76812d7ffe05030586f525d686b30f884c94b35f36f05520fa9ba97f913", - "0212c71b5248ce526ad98a71d03b572c4e01c8706445550c3f88a206466f79cfc7", - "030e84d5c8a310a5a65dc5577cb95697b3c367470aa8223f13b5b97b5f95902a02", - "031790269cfab70cafe8aa708c26050f4879a53ebc381ed023853f51c3c1ca35f4", - "032c6e0d3db9950dbee2a772ccbfb1e82871f4cb46019347ecc959f73cc8927dab", - "02005fce1088a7c084dfdae19bc1e4f4e0cf95b3fa8a913b6f060fbcc42032abf9", - "020d15109fb978b37d323885717d9a2904aa7d1449a5fcffb78cc051b7cc73b895", - "031d8b277463160ebccd43c2965f7cde11385bf7a9da0fd12366520456fb959eb4", - "03206fc32feca45ae9065dc36081a89379b01c6f2e29e85cd94bf782618dc38ce1", - "022e31ee8263266e2716e683185df1446b5ea5b5d32bfb5ccf42fb4b33d9d9e8d5", - "030fbaad75ee413691a78b2fa00a7758e9ba8d94691577d347d9425f065dbc4d36", - "0219149256c82480302b76be73ecbc1d607a4eee136a4a3dbe6eb684122824b5e1", - "031926181c2213895142ed334617973d82a379ad7334a380aa4d5f378a258c4881", - "022d8ae661e1a17adc6608935d7648cfa46a55cf0ec1dc73248cdd411a792cb3e1", - "0315a7dee043b4759e8031bd8c346a3d35d48355a631d16f18a5dc871839f6ef41", - "0223d623979987f43c0d9d025ba5a84dd8f54d72c6f09582863ec5d2dee7d46f9f", - "020ab9b009bb698c1c72a436db2dcf1602468295016acae07786bf2c29eae9fb8f", - "022fb3324d00284b2fee06f517570a1e45a07f802526e7a872b6cb9cf8baac7aa7", - "021b410dc2d6f9f18e15c32dedd218440c1be01dfc3becb091308163198c890081", - "030e950402e8293cc9fdc6e1499455e6dcb05be39ba836e1696affb538f23488cf", - "030b3516d6903655cfd314fb03113b4f24ca41119df2a2e64f38bae4ad01ec620f", - "03122716da684a391db33814d95a12a244eac92d8bff8eada124db44f13ec1ec72", - "022d28a72786c4d55536311f17ca6fa5b6ec095cdce892ecfe0c4cf748bcbe416f", - "032ef6584aaeb367557901177f43172365edb9247068d2209a705423a8519042b0", - "021820e083c51ed5ff8088237e3f3c7e3608c3fc18bcb453e2c7b302c4f181ec06", - "0227f3898aacd1104fcbe3875f6e8bb631b1b9e13987755dc477c696354cc9abd7", - "032daf2b8f3e8ec475b1fc22e00f9003dd60391970c92916e4a5df1fa471ebe1d5", - "0317246768d81b17fb9d963878d486e76950cd5f39f3d11b6e087a1c4626e2cdb3", - "031f6029273100bfe0f57f2af64663bba84606dd7fede26cdb0b891f449c72c6cf", - "032eab493b38009c5edc3beb6d6ad6893d05164a45054736c485dfde0d9c04f723", - "022c8d41657d701e05ad3c892b2bd372746982ab419d6e08a52093d737739a22f3", - "02201d2a3db44d985f72e38df5708305a0d19de4633580e2182041a97c5312890b", - "032ba3a42130e21999eaa42f02fab256b925b9b9b968fd818665f0cc3cd9cd1315", - "031af57ce5cfafbebfa458136a8689ede034f09c0c855cfb1d8d5688bddb37daeb", - "03058194c496babfea416ce80e2aae00d8275789e0678768a62f0e2e004a71d605", - "022e93c3b011ca2073b31c8969b5f772e639d2057a4f0632e03fb86a0dbae4485f", - "0201372fec7f3b6467b5d1386622d0aa7e2856b28d641b7e3a150c7b7303cdc817", - "030b92b4a88a268e7f98c89997e72626c5e53e2cc6021511e0c297f06ba0bfd3ec", - "0214da3b9634901367e41d5dc7cf482ed38db6a513dad43ba6c05bcfb3627ad483", - "03053e98507fa8d4546a940a639dbaa4899e88aebccfc25097717e200a02e8bb5e", - "032c2a82488bf8aa0902f8d93ec4d88f1fc7c0ea7e286def01f8e9e9f4d83f8233", - "0306459e3da5ab29b18cbc766ed994c5c4a4dccc2dfe243a883c1932a013b53396", - "0300583d0634f091add12d83f00352ca7885cfd58a29c11525fa1ebd0641756715", - "030afc1631abcbdb7dd0549065932a15f99084d58d8c2bbda1e2abfcd5185c58b9", - "031a32a82b94e7ba7efd7f2d2dbcec2540d021966f05516aec141f107f717c44f1", - "03168f6c5f08da22004bca9cc76e1ccc5a27ff7dc0c3a7d28abbf37c73d6413f73", - "032952fdefe0087695f393eaf756fec2eb859afba75b6bb86803db78ab1cbae85b", - "0217c0a4d5071b5289bb57b21ef32e66cd1dbf8a5c1de7f41bed37ff9c9cda492f", - "020a1c6bf95d578d51c8d1ea284da6a101874c5b47759f1377ed3a12e280a22c65", - "0218cc8071fe086aa1939f5dd551bf7bea0051e85356f66a4e57aad7c5dbef5b9d", - "02036cfd5f0ff35bbc6da22127663e7bd7f529333abf628b9749bae01b01f9f329", - "0210439e136a3f7a53ff41bcbe603d09b10892aa6f2b17d388540923637efed965", - "020bde04a8cae50710455a545c3efc27c8213d9794ec1c4eeaf02bfe5e378135db", - "022460f2b111ad2caef0f5d8295b32b8452ade2ef0a45e5974b055d4498d37d0e1", - "030401c8dbd12a9acf67209ddc78262d3f01933c7c8f48ad5567b2d52639fb3f47", - "03050eebafb375bb933676b003506de50348070fff32ed059960a6c8e45d7f0c3f", - "030ce3a5c2a766c1f21b378bce751e3ee50798a2665306612cbf25b3a628e9a659", - "032218c7887fa8337bc4745e4832a78290c240920758ae293a220fd55112c91143", - "0328c93d5e69a1ee7150b08827d80c2f1243f0c9841e12a77365f28b8be3647558", - "031b28986fd6ee63f597c9b2d1cced2aa4c32339fe6ce98caa2b4c4a430ae0260d", - "030b6dc1f78f9ed91bcafbf9150082fe9beead06246af4fba4d0dd9ff4d7c3f175", - "030567e4b801eefe8129b74aae036a3f7fb7f6c6a385190191d721043cefebe1b4", - "031313bd3edefc4acbc06b434ca6229d0f80524bb854327c66adf9ceb2f768c0cb", - "03267cde41dc7099039735d9176d07854ca8dbfd209fdc6f26b2097521421a7cbd", - "030038068dd27940f6cadbe9e7ba5d71ccfe3c3e1d30a4d03f38c5fb7d6ca85f56", - "0322cd0e413c5e4fe72b3b02b7823e6a1b43d01edc01a90586f2fcec67efc2b18d", - "032ba9d2fc862974e81969ffb7bbdc1db925907297e8d4f451b43ce68c6ba787a0", - "0229585dd14c287a150adeeb847e2d1b530c021f1b05cadaec982e34a0222c0533", - "03119de864d79dc05fea8db5c656dcfdfdfb58df8a1aebc4407e55f9cbe7e12bf7", - "02029f0200ede42e8905ca4b7e7344716996e98c09ffbef983ec42ac03316c9ba2", - "021dac13cd364a16a6e9fe97d4bae2d084854d88e22d41c7080a9b36766cd6cb6e", - "032890fbb9dc9c46d8381bc62d028334ac1c05ce704f1e648773fcbd6ecd4aec28", - "0221f17cde20b1945d95b3032cc0d27ae1a36dc0fd40b9014b8b6e77039922c6fc", - "0206bf8bdb1f4e194bea9701a9191174b454cda6cd3094ddd3ed62334ffe8907d7", - "0212230aa5dab5c07822e667734e18a047ddb5ae2a88fb70bec9d5b2aafa3e4bf3", - "0311e8e8a098a9b08797e450051a24e79980c7bab80ed6de4b46a9de8956e6baf6", - "020b98fc8f2d3b9d5001eeac0f33d3e78c58c857c452fde96ae16376ec092d83a3", - "0302971818baa316d77a61acdcfb32fb4bc051c771f884ea32c11c373f278dc56b", - "032d5610767835620d67efc6ee205bc8c38da21682c1f12e431deff05eb060011c", - "0205347056161eb6c28be18a59864427797ba2e1a245bbada89533c98e313cac15", - "02134de1ff62a266c6d772f9fac8e7c38980a9115ff2ddf1dfa18f4e9d8a004d3e", - "021c96537956187c1c3485e716cb60af42c940649fd799f474b3cbc3abe572a5d7", - "031273116b498706e5782993a988da405c0bbd3b524396b38ad0a5fc493f5128a0", - "030a9a3d9cfc99917f46ad3bb2bfaf8507795bcc6767d7db8ab497db3141eaf5d4", - "020770095c81b677fdcd3d8bd9cc9f092b7b03699a1853768581142006d8d51bd4", - "0212cfd643e4eb3de16a03f2c5631821fd71bf38d55b13468ebd7493c34831d66b", - "021867971e589b4ed7c84409edc3a8b1d5f22cef3d57dfefe4566b9fd2c1f59631", - "032fd44313fe5377920642806b7e79069fbdc705af1d53a9588529feb8a39694af", - "0305c68c4537702ad6c74a7f0cc9b276d5b279e86f1d8f72378e561b6a5cd93ed9", - "021c73dc7a7f1f0152380b053e7884d719ac8ae842818aa0b14daefd351c6d31cf", - "030242b0cd511c65d3b59a197576d01079e950946182acc44dc647a902913c40ab", - "0229227da6db242ba6ba6cd008e30b293dfe5f2d2adf9f42fb3389f6eb9abccda7", - "032976fbc3d6d034ce807786d11fc2310100dc86afc2c4d265ce115afa5c6131d3", - "0210ad5b475544fa591351f47bcf461c5bbbf4936f4cb6245bbedf75f75c28ecb7", - "022fc48d5382f31adfe2fa46e879e70ee412ad323242b9fe6217a13ffba3ac8741", - "0319f04485625c981752bd4bf91bfbb18d7019c2c2ebb2102828c85ac621e029b0", - "0305452c29e46de4b319a8be997f6279fc1d547793b69e087aa5296980907741f1", - "02070595063a86b38bf5f905742e2d7402699cfb9b2476b7d6f79bbc60a4d4facf", - "021cd786afa2f3b5a1c485ad99abcd94e640d0fc4d49f8fdc34f70bee07350991d", - "030d1c6777b3a8b26a48d83e2b54c3ad12ecf3f6bc85fa3c2ceaf39efeea8b9925", - "031ff63b236949acb2e4f35fc7cfb5540c0ba02fe0c8355260419338cdd3a9ef43", - "030c28c6268ae8215bf85f3031317eea2c5ab8907e42e44450c65cc64b162823ae", - "0203c1ff7845b7e1848782c4f6ecd468cdc5373fe077a5477c061662222f2ab780", - "022ff4b4fb8e9ded1358e600d12fc23296b3a85c0fa39f68cbcac80166cb25b8dd", - "03255c27ec406137ebdf6173732483a0b5242edd598edfee99a3067eb02ed1e9af", - "0310d8188aba2584618fbe482ad7cee57ad2328c02f00bc0335e10f974d98b5580", - "020493c71dd279c3c28da128d260273bc2f4e44cd33779eb851db6fb7d3d94b41e", - "0328ae2a4d7e44761c9ef32317fa5f185471f8323cc925722b104f7f17e18640cb", - "022b03717384fcec3956552af997c80ab63a8e76604144ed1947acefbc1c604bad", - "0311b1b0cca4e559d9fb5952f0f4924fe3f5b12f37b85e8a8fc5c5b2ac09a0f9fc", - "0228f86d0637ccbda28057d551650676600b8814550159a354753e208206000f2e", - "021a376c8d891c8ff6867a5f25080791ff1f1d44852dc9a81b988cc4f038765fc7", - "0207f75f4e5c954734a66ec9077ceae3a679fd670946c1d387708dad70c2352016", - "0321ada451aebdf35335a8d5568d8a7bd92b8691e54979293a052604b37cb3c811", - "03172933cff0030f48c3d0a166b66ee3c3b7bc1292f41d48b356b516947d9abdc7", - "02176522a6efa105e5b41e22442582e7e4d7415493901852f226019329248de481", - "0323ecf206a579f21a9c1bb962656a050fe90506cfe8ed9299f6081d1fa3019115", - "0212b4c790f6a41e7f76d4105a3dc1c806a2f0eab36579f8c4360ddb73c1003dff", - "030065d1c766092b2155664e78dd9d8ac3a278e9dd2187f58cc2bd73fa964fe474", - "02231751b82cbaf25a79fc816dfbafcee88f86e3be3cd3f4a41aae9aef4ba06e5d", - "0208502e591232a07a1e498af7d829d8699a0e54936d3ff346dfa8409b885dc6df", - "031f6b5bb70c51ff876e89f59c05515bfa53a9765a116e05995a12d6d8e4811b64", - "02167b0845f5b96d9a831b9c898a86cb0ee05e3943afd47d36a226c890a837f039", - "03087346501dc2eff5e47daadfe74270b0753d09611f63de83f16bc7a558c77d8f", - "032d4d9936c61c9ced368af4ce19ef71361d2fd695dadcb6a679ffd7144dfaca42", - "023012162d302dc6440530d5a2d8cd9f518bf779090184b7448bf7a71644661ee9", - "02062233bfbe1b97163cb72416bdc00df3597192839fc12a0e3b9a7866fb6fe45c", - "032164001b3a8a0c7ad84a0859a3371b53573259dd434ba5ca70b859d69b5b6aa1", - "030150b5ad9787c1493652e8b5a0a40e3dbbb2739c3bd1e3c7f96f1dbc5636245b", - "020b4ce65a6c7a5c175a8d6b9b2f350e77e37dd57e6bcd94817fefbc0b0cb73b68", - "030d88724384dc5809dff2b55e6c1ddd17d60f8154c4427cf842f08497ddc23768", - "030ca2546a93da4c0bf503dcfd7a53319565eb8c83421b3572241c77fda0f07924", - "031d35d72109fe695d96c416200a00785e9d8ebad6994d7a449a212498ebc561a7", - "022c11b7478a1d32ee2017f8d65069ccdb450c4105a6872ec6054895ab1b745f7c", - "03098e12e224d6c927632a4a0b9eeff9f624fa45d95b50eee4814d291e95b170f6", - "030c10a27ebcd16a7681f33cf3eca145c6c14dc865bbddd0f673850fcbf232c60e", - "031ef1eb7a5f1d32fd6ce0340c645039b567c7a22242088d7f65a71f239b7e2e80", - "020b0811bf2358796ab8f6b648152be514aa27d258707243eff9fcaa07c078d8a8", - "0325dd34d2ba3c37b7c581167cdf6eb2523a6b8c9225c28237b58044f9b292c24a", - "022f9c0badfad6640ae4d1132b6f072d5392b68fcb2e63049f4468d8c3beb8b98e", - "0224e1173f75d3e3e3d7881e810360c6fcf0efcc359524ddfa9849e55218077981", - "0309cd4d95e64888fb06162abbdc80eedeb0970b8a76bee96e5aaa38c027b8a3aa", - "020db3e6e0759f7dd117b46a3c24abbc49af2fbd96caf03cdbe4e65d3afeeb3458", - "0308802461e21985edc014193db120e29a8a6a24496a294ef73e4c3ae2e326898a", - "031ab4820001d9d18c15a6cc83ee5041fc4ac06bbe495ed1cdd45e6eaeefc79621", - "022120fab30d4bff7f5d660c3f74ab218292d5e2fb772b2853d13346d59e7d4bbd", - "030daa64c1e3935887985149225fa13172b0e77880d2450deb2d33a3efef6caef3", - "0318eb3ae264491bb9d6b881797e442cb1c1a4084799d54c404a18eafa700a96f0", - "03193c3d6700fe6217173b4d2dd293abe83e445859eb2d6707018a004a4b4b2934", - "03273304e2151a2ed06645359f305897d5dd57141ea4bbfb889a0135df05436e68", - "03056ef82ba1f057c9e79c70faa4b3ecbcbbe3cf29d98dab5a152ba1bbd59b82ab", - "030e1b2fe8f620c5a1a8518eecd7b3d5bf3f36c271fd9c18fd74a2c2b8b80b6ec3", - "0216b221f18d22a18b30e921505a66b97e642035a2239ccc935e1245a410e01316", - "02259bafbd11a8f50fe2595a6857bf271ad1e64f5e4d4b19585269180d23d73790", - "02235ca70c6e2ff8e783600719596ff033daf82f592f7132268b6bef0473a1cb25", - "0322f7cd358d42d987212d62db9b4a896e58b1a71ff1b63efbaef53805945f2a8d", - "021c6a3de3755873bc87aef5b7c78507471bf12029c0222409a6afdfdd540fe47d", - "020b00b292a90a5eebe8bf4f90372bca7201bdd2e82b47790095319e0ecfeb859f", - "0221d0654bdd62149211e038525e9a12e90164a41de1b3b688a5eaa37e1198e441", - "021cb835b6dc4ec8c6ca4e788612fb80b609b4e851ee8921c1d46d3f1c59c6f334", - "0226baff48feebf4cb6c653567137ae09d2c0059e776817f3c8c5b916d5620c4a8", - "0303a3eaaf0af8f73f0f6810ece790dc4cb3aa54d71567805571aec3543f28948c", - "030e4d7b56ff26e7e46f4f1047990d9c4af647c6c9d66b0a30c0ee920089071782", - "02087886390bb605a684de524554145793b7ee640126ceb02a169571a1e34ea860", - "031f1eb4b034750b36c2f4b284e26b83bc61044c44a167d2799f11ff53fcccabb6", - "031752257874b58f3a639e7f41d4ff66ac97c0e819bffc9e7f0abcfd72c34cae20", - "021d65e9ffd518c26bd3321a584912e9d61512a8c2d1c594743cb62fc7950a5167", - "0323cdebc3cd9b51751369a69bc43ad81aefd95a6140ab1a474a8560b050e0c78b", - "0310683ac3db287324697334d614bb3d52d260f83ef79dc5f4e7ea6a53e8b21493", - "02181b2a005aa8f7f0642f0735c436d7ec0dd341174bc179ad9973f430826d10be", - "0222026fcfc89294689e0556f20fc11eb350c295fed02f148e6a15225bc146a91f", - "032b8c0e11623a06cb2e4269f987edc6f10f10c62eb72ec8bfd2c11763029785dc", - "030f027878286ab6bfef6d3ffc4cd81920a0caec8ed56e934c08512d6ea01ab6b6", - "032baca2f76ce830d7f00bbe348ce141f5d63f487ba638547a2ee1067685d44f04", - "030767419b9be04f921b68fe5d9903e24721255e6536d50e428546b902e6a75238", - "031d03db7c3aaf3700f83c9e3e988c79c7d46f7a883dd2788c64b784da9f6cc1e3", - "0205bd725c933d23e74060cedcfc94d31a072e61ed15b4afc0da64d8074a179009", - "03232bea0bd138ea1956583ec82891b42b67e8b576d60bcb3325f1e9aaa330262f", - "02171e3c959abdcc9e3cbcd080b9be3636475840653d492a48016d816fdd64eec6", - "02008fe5e1d1f033efe9fd36885a9863099b4cc7e5c52603e8da2d39f9133714a3", - "020f1cd0e1371070d5845a6e6459209f2bbd1ee5b5ae79a6473e5b6e60a7a13082", - "031bf54a2583edb9cc091821ee344bc2df840e81cff67a7de517e9abfd83b1f357", - "031d4458dd77abb4fa4a307d66e67ed6c2dc4d2ec1d6f0408c3a090b18d376a17a", - "020e1c4a53d89ccfb456654b57effa479920e9924032d4c9e72b7519c9c119d19c", - "02088710731b227b9f9d6c1c82231d231afdce181a574c5194e159cde6f4674d9b", - "021ed04555cfdaccb26d5a45c450b2acd0b17996d0d556a52508c12bb1c178ae15", - "022017e6c018622fe0535440c223d723e5d83b45d6c969e55992fa6522fae512bf", - "0310f9535f2c5ab9c5d4b58959116503cc5e6a0effea5ef82f0d22a87e881aa5f3", - "03255eea45aa3d3adce74d2fcbc7ab3599863c849940b61999005550ec4b1eb154", - "020e3f2a5f0148969e18d58d2371830371657c2be14d4a519f63c3de7cd6d7cb6f", - "0201148af24f6e96f5b6cf1f1a68e0db97273ba90c48fab3ad245e3383a4d188a7", - "0315cd614ca982f01d8cb604d8a20d245d3fc77586503c1c77c6173372ec523b19", - "03132b25ff1d4cd83579697b8b12e8881a31eceb518fad4dae3f6297044f48bc02", - "030b73bd19677fed62f22d917ebea419f211212362994498670c817087d0754972", - "03120d17a22c8656a8ecd4a2626188d3eb6101285cdda37b7d5ab5e45b565b45fc", - "02166a77254d5793b3a03b345a535ed106a4b73768fa921ae67b2128a3c0151318", - "030becfc007643c3319e985a165a2d11f1d02fea89170dc6811c8ef18b69408a3b", - "021352e326ae730f98189c50bd31a62808b78b0d9216df752a7388aeafb813fd26", - "031a1a2764cdd04a31727a170710ccc0652a259153e887d5b412be63acc0f28e4f", - "0204cc76a47205a07f21bd63526ad1a589787582f48dbdf9bf1af01b2fa7e57f7a", - "03024b2700efda6eace9ee7c904d54cb10ecdc6a8c2073ccc5d222cc790f3d7c98", - "022db4d1dd3f16246ae47680d52c0e0e73b21a7b050d579ba757807f07515188e0", - "022fdc4ab20689716e38ed94588f46a260018a6459b77fb8bb760674becad477e9", - "021610e7fdc1268fa1ffc80e4f073bede6c0d650b10fd4b1de4ffee23843b506b1", - "030c9809511240626dbb10435a78b8ee117d4c750c086baf2ff545e917753404e3", - "020109766ef3b666009217ee16773828b9f14441ef43ff3765f57a0c0dd7c78d96", - "0220c71c2ff3ef57cc5f1bd5f17381623051f0472ce83075cce660faa01da514fd", - "022b1cd334bf15ea9cc7bdc3e13f64e979db3347a6a4c9c845e229d239583859fd", - "032d9853cd9625a53eb687e7bfedc869ab46e806ba9f7558903ed117d2e02215b0", - "020b54d5bc3e2a228ba7b31e54b43414215c29dc172609a2d244fea20863b47580", - "03297556ca91b1d4915d87c9d105a90dc0044c1bd7a3c967a3b09b22dead1461ba", - "021fd671a0a53bb201360dfc3220ef4f10f937134ee9823b308934bae63ed0c224", - "031079e09f75ba4e71f00f5737a5b17e2281f6e6ee6b5b373b0358742c31def61c", - "02303174190a49495a0548b12d7f8aa8ae48ea9a978d19eb78bdb6552d1a6551de", - "0313232ae52a3dc461fba71814757f653ae7c6774ca4534eb1a5578b0e628a66a3", - "022732a260a018ae096765fbb41bef8f0e216351c9c48c35d6ec075c4bfa9ef628", - "021c673109e3e66bb1d99ceec1ac583ee79183d9103384c96447de924dd0e6c661", - "0325f50b5dc0b97b94cd25d1195fc24dff5b9814ca67121aa1bdc0d9fd11ac508c", - "0225dd8636746087929193f2940347e6465394516174484dc9c60940f0fd484844", - "020d18cdff6e1632f745fc3e46ea765f179cb690dd3eb73ef55f204428797c0499", - "0324ecb86ac1881b2fd26ee9d1f66943abd9351f0a2d06a7c36ef6db4c78e5995f", - "022400115bd293c5c2f1cb318c00de56a3d4ca4d5b5f9933db7f0a483418817ecf", - "03284900c6ecdc54426ab09edc6a6796b8b67648d3eb6a240f551598a6bca1f71b", - "02113ec35dcb2c20a41eedad601a578a71a34e6f1f3646deeb59e1ce209c587d50", - "030539309e1af76618e18e82f448a2fb11754232ae63be32a6af3b67bd8040a148", - "02042afe9886ec17cf372ca0e8a96c6c42414afc24a24ac4caea3ca4fa14fc24b8", - "0302432f8a8566184080f3db45f93855f6ea65ac328403dcb201bab92155818bb8", - "0311818e78047175181f0928fce8e265fe5210d6e1b0a08c174dce84d56d99fc53", - "022edf2ce60d1d7ad523721562eef9d20924a6b4440ec9de8b65fbef4eb05986cb", - "020bb9310a99b617431ff08bca2659684e9ce8b241bf6f49678bd10e1ad3b6aac1", - "032b95f18134805960361e5727bd3a3e1c45e72e0e711a4366ac8b4277bd4ae4e7", - "0302b80527d97d999000daa45112bd2ba97c3457fb40c783d4a987e71767d688f0", - "0316c93837ce86a3b6a87e7ac177d9b23736fb0308d97fb1095b71465e4d0cbced", - "02196535bf4789199ee8df391cc30bfe5f1197e27560ceb2d9dcf9833687a80e53", - "030fc9444a15b5df928f664d47425038f743be4ce3cad233a0da755f0fa83183f5", - "02004484fd2e0b1a4cdb8a41bb15511f9e5a644f1f012ee1d7c689d617e1a7b3b6", - "0324c84ab1a1d76bb6fc47125b98b49418b556b36356edc5da1612036b5d26c45a", - "032b346ad58c9d933abb09d6a541bdb05a3c1976959dcfa4b2728a0ee040ae3743", - "03013c3c75800b7da714fd3e153fd0cc6ad774373c7c37fd217abad82edd970d70", - "020ff998ff94ae9fab049e9376e2c4c34d071841b1e650095fa0620de060237b37", - "020fc926d72c454ddd346cba37a96b990d3973dfdef215b7f23222882bd94149b8", - "0302d83259611009b3425d0dccd9571db5ffd3948287a196a53c5a55a3b32f86ae", - "031e431c2a74d088004be304d428638181a34bdd84637aad4d6631ee83078b221a", - "020609a4560d742f334dab179588669f8ce2e047fdf9b9ae8498ccd1bea9713b42", - "02151c839bf2ddb7703df6bb9c848cd28349a892155cd3860d269fba458e199b3c", - "032ebbbe4c6a70464ecc04e445e0f4acead12044ebcf9a24d8d48f889a1055750b", - "03187657cb017a6091c6efb23b06d2341e582503d038be6aa824b1d86f32d93f35", - "021392dde4c2e8bef053a58d4aa2bcc7b25601a23be4d0e2c2bd17e297cb9b539b", - "0325d8159c71950099a1878efb6bb49d76581313817dbf7038db92e16ba2d7bac7", - "03145ebe69f60208dda1dd1a4c02ebe6a00eb8ac2c79e7a09c92a96e87906d0a5b", - "02271ab3bbc0b43c149fb08f5f6fbeeed24c00d5377b9fb487f857709c0a7ba6d9", - "02127d7ee03db630c85b3db5ac9ee492b3d075c2dd3985b24708271b144e222030", - "0318401dde0eb68b5c73b15633bf132eb826d2f873f3a088137862062ef088b27a", - "0316bbf418f45069b1a3f6cec3b75f5660ca5b3962f99e27e3203319e8aed0ea20", - "03062433b712d4ee43d8702f8fe7d9a09acff45d2c54bbeb6109aed8ec82f6b4a7", - "0313d8ef9fd865b93e963103b5b717dcde890f215bc9875f8c7976510b0384c5ac", - "02159009e9866256b020a769901ef3c6d6edd22278753a819be92972d6aec6b3a8", - "02072bdc7a8ccc59546f915b6a6c78f8d720aa7cedd5e04442771c6bee07c76fa3", - "020bd4fce70adbc0cdab2ecbab76d361b566528960ff8db913f6d8eee7245f74e2", - "032a1dd59a2be78f3b8cfbdc693c2fea28ca28e4d536d836fb02a5107dd7afb016", - "0211a0547744b8d8b62a8277591a24437c80f5dc9560621c41defbaa85862e1aee", - "021fc8b75a1b1306f4677e72d8ce1cd9e28b5ab6b676cdd6752e54136801081fb1", - "03168abb9aa28708ce2015fc88e2f8db5f325bb0ec65758583369944d208af0f7d", - "0308319d263c511e3caa2666d822580d6183310afaa7d88ca6ff5d4ec45a7f4787", - "032d255f73cbe61649051f397eda38daed3b6f1a23914a22ce819b9e49fb5f8574", - "020a1170b45cdef3443d1250b1a9c1e94c0dcd86046b30d6e58d47ad97130c841f", - "03231c86e35bcbf01ee0a6d42c4afe680524ebe30056bab10cee8f1259c44bf38e", - "0328a9fde3706146c5ad215ab67ad1e703cc01a5b09bd7ffa87c28fec2d94eb0af", - "0224607932fd5b0a4a1949998c96711cb0d2638832bd86004aad924de3d7e4e24b", - "031e6b1fe5dc265d93c3b3bec36b246386379332bd0c9223f71c0855296859db57", - "030f08f0dd2bab2681448a878d004ffe2c49aaa4c5e350a07f31a5ca37d3f3c944", - "02164c8d981898730700ad02d8387d1cb21d5128f89507494a574bd356bb98fed9", - "0323a359d0df28462a4a4eb2966f9fded7934f049f380f19dff7f84aaffe33c573", - "0304d285da66595d645b15a8ff81aa9a1bc4e7e6a375448ed7555beb70d4a7d259", - "021564f791252ca303077b268df6420c6f4c100383b1acbb7c10af659acd643e80", - "020a19c0f139e9568a2477937478fb45e645737c372246719b29cfa16771cb23e9", - "030c2eddd2beda35056682b8685eb8aaa4c5b11e193b8870cb7506c6b2c6ba1d9e", - "020ad63e4f36fd0af28bc81b627b2908d0797cc1de71ab7785077a30e0c1ed5c47", - "03294a2da8c9246c2ae0d8769c20673ae55a80739d2faafe826a71bc7a435e9a49", - "0221179800a1e272cdd68959865c6a77658e924481e14da302edde8afe56c82c3a", - "0315ef3d401c122b979dc5c92e8d108fbcd0caabe9ef3a920a7937bf1ce1196c4e", - "020068c01ca67ecb0933c431b10adfe5b4c38dadf2f6eedc0a0d0b9c2d3a822810", - "021043a8c35bb7a4b074597b46f49104b764a4b082d957cecbb2ce0d4977d2d97d", - "0320c3365bbf4b3a1687f08dc81a0bc27ad112d83999de08dbb7783aad82487a02", - "0320b14d2223ae41b46a7b21310c215ac627aaba5d99dcba833e5788f127851579", - "032eab4db468b22e96dc76428e67366c981fd9b6e5c2bdff7b3a2d54ca56613e26", - "0201fa18e1e98861bb4926058d20e4a046ebe83da89e5c2f69a5e7b55df718cb6e", - "0310b802266306ee59299fc75b613e5d9acacba739bd14811799e3d036cd2789fe", - "022e64933fd7c61e74e41320236b1e1c6907ccc363cacad4a7f2feafc4e623554d", - "032a212c8f91d4bfdc730846a5ef1f39ea2cde50df29eed86e0e2d7e7e6eea0360", - "0314ab01f1c7b3d4b9db6cfe3c4d37aea0e2fcb77d6b30f6696d98f65fb60356fb", - "032716b96d5578beee36dfdb05c744afe62847258a21826b020f051aaf1c70e8ee", - "0203d98a34046707a75cb487f97fd707df644cbd23b7ea7eb55f8e03e39defad8a", - "0323317c139e815da8a818f85a3e4b13d20df6088387fadc4626e1887e0df7102f", - "030fbfe989c2ccd99bad428e7f5239500108fca37e52df0ec54245c7107adce490", - "031b4a8198d20b6648b201890b08c1313a77823c2a2d189d11cfdd5d3ba2af14cc", - "0205de694b74a627ed6d014964826d195c67a9a4f810a2a943954ddf0df1b87482", - "0218bf2a2f2af2aa4c7cc0e882d292ac7ab7eea2904660b95bea5a31a5c70b2123", - "020db9692edfcfb7040b800cb6a97f747deb24d01196b974497a327e0262b8a2cd", - "031989897711f545ba83b2db2466999aab2d8ed619acadc9f8f1b4aab0184aff1a", - "0324e76c257458156a31aed0db50c7676d4a24357b56112d659e224ac8261968af", - "0211ee5f0c499b2e0c6f184fc40eea509635910178331cc395c0e0a9a08acd0252", - "0323e85786ded271f533caead230cc9a80bf3f7dd3f1f17fa66ad33b0ed7ca1273", - "02037aac7c0301edf6a0a27d4318cfae4cb423760dee7a4c98dc39f5216f254819", - "02118589f74234ff401bc50053f377fc6227a8f3ac600aaf9fa31df8d763ce77eb", - "031931e57c403edd10e263a1b68879ad7b8db03d40b1a9cb5f1b990325e67c28e9", - "0229e1fdf3146e371870c47137baaa061ef37c689b0476ca88f21be153d468fb8b", - "02286af25eb9c2769103e861a28dc5b74cc4f27723b987bacabcd3780977a6942d", - "02305b2b2d2b26e9b214ba276f4112923a7495571363e074c4d7a8796fc8a51f06", - "0307320c2f27811d7e6685a83716d4b13788f53802979b777d38b06fb6cabb1cc8", - "0322a84b532f08ba753b4dc814a669633a31658964088b1b73570f061da2dc7443", - "0320dc7f1c201b006655bd9e012119955b8d8d3648df7ae77addf831365ed59a51", - "03102ea65e118194eac4982034fc758dc2eb38795d88bed11f853fe8bd1302b79e", - "0229ac8ce055c0677c72ce470ae2cef6ed56edbb3cc66a31f3b84e761e6e1d3761", - "0323e273ae8c950ab0fad7bf1ecca88ff6c3b328ffb05965a7c9ceab0bb1812bfc", - "0204c91c4a4f7aef1712af35f2ec9428a4dcf71ccb95e1367b08d1fa1de03f0cd1", - "0213f1919160a7b627cdb1f5092574e84a9ca7681e15d2a0b4cadbe16463d67548", - "03182e147d6dd3c9da32c3c682410dd14cfa25fcc73eb0b1c2e48986ff932d3d35", - "030a00882e321ff6bb57fef51af430f48f429d4f1bc0e1af048182e5ba3c4952f8", - "022ca22f9b85ff3ac3a118eff3a6aa52579a0e4721c8b6cc746bed089227f41b6c", - "031f8e27a44554d3622e1f9e173a12103806d802c1394edf8c917795d0282fa12d", - "020f6d96ffbd5b6cd444587144e4d8be3687586730ad4e77a10cd6e449cba7add2", - "031b500949276d3f8c6c75c1152006c25c0efa9c97e9e6e3f39a0e11c7acfa70d5", - "0217542e7ae2457300603fc25aed9ba23db47c79345e8ecc72b7e628a6e3dab5fd", - "0313e31a6bf77cb33ff9b0edefbf1dc1db67ef8f3c7e3f562be9f843d464c31b5d", - "03296181bbafd064c99d7e29e90bfd94a8528f91230910af53726870415c11e878", - "0312d24af2e9a4116a8fa31936f62ff5b4ac018e37d7f40433b3aa3127fcc289e0", - "031dd1f462931f2ddda05b5724e1ef00078c9eec18a7832529a13dc8eaeaf261f7", - "0304516a519e814711118a3a175d775c879e4e23b35a844ae8b55dfc6a47972127", - "032ea150deb9f5bef2ee28054b64243321b3c4e5d7141363cdca58a2f4c9860b85", - "022e0e9adb35c5ec9e12fe3e5d307ba89b6fc291b44fe5f1dc3851e34f595e882e", - "021cb2b7941a4f24f4e5de29bfa821fd1cb39b1fc29aa92f8869cdb9b5b61ac97d", - "031ed5d353f9d53a6ace3f79589e777419a4754d6d94e7eaf24310ddd6eaab8e79", - "030a444095f711b8b04bfa670b5c28810f991f9aeda801b9f855efe0a976f28af0", - "032a9d345d6858c32a9accf9c47b991085a2183ab925af619194a1363cf396cd7f", - "032221b9c896860edcfce20a7a91150fd752203c7f61d675bfa863d8988af30023", - "022c86c4f15f4ce74699cd1155520ddd796016ba2327b5a95e04a9fd4ad7e92fec", - "0211e6c44badfe870346fa96c77905c5937575f9acc44fe7a220a3e0deaf95799d", - "020a70f54910c4dbae62c73edeff0cdf935075a86238511fe88428b43470524871", - "031ccf485d7e8658449781102ebf9beabe7f8596680f3eb77c3c977ba7d614695a", - "03037ad25f3fdec43f61ea098c89e4057a54383f4f91d233c25dfd9b1ec6c29299", - "020b8d4f8c0243705d78ac5556eb56bb47e93e119e23bbf5bbc110dcbb6c34f1b9", - "021c081a4717a96ea9c45c2f4fd7b59705b642e33fd70f4d921d0d463babcd0bf8", - "021b8b97234119b770398b5b65fcaf520ef123be512b2a3362367d9df2c2417075", - "031753b299d9269d3818d4725449bad98740196c90311117b484cb3c2d7ba7da7b", - "0227414fd801eb0b56ccda18b5c2eb6cf48cdd2df9735c2070dd19262e01ef80ed", - "03188ec7dd45701712375c96b3dcedbea39da8e876ba3c2bd3c4f81f5d25fdb685", - "032235edd60eb1c67b26381d7f11947bff4a19c6ccc75aea14b0dc5f8ee6a1c409", - "0215241d19a2f35345b58537f3899259090e8d7bf366e68ac53bf20bf9e5a9fd17", - "0322d44f5c5eb155c63e7e56d1d20c2eada75ce19555feb7de4dee2bcf208dd4b8", - "021e3f586a4095cd5d88cce8e38c56cda379971b9b61ba5a4e26a42033d5f7031d", - "0318111bccefd3d4bffb76e988d63a50e76068dddf90b23915edd358a3930a5f1e", - "022244310100d3db79f676341f32e4e7ac060f45c2bb56a2eb7bb64fd400462bb0", - "032bd1f2582760391368fc64aac94c7360aec67db0dd2975436fae7b1352358d4c", - "03064232abddd49bf3cfd9b9c6dd47b475a89ce0a044e30aebedffe62fee085dc7", - "0301eb453a41f1de7d6960a6f0ee5775e98ed5d97f4703d089022f19ea956339c3", - "020aea755d6b7d8369e0104502409551b024216caa3ad05fd0513511fa43ae90d4", - "020e0dade65410ed081c5abebc0b1a12b59ed35c64c2e89f5dd4fc78a0d2b1daf4", - "021be1495ae9494d17d53059d6820195d3c4e1f453cedf20fb4fddc681686f4279", - "020a3d453299ad030f270f9bbe33231cdf0063c1b1818ae8b41c8cfcdeb2fdb8c9", - "0328efd914236870d19954aece04f523452c8d4ca6ddd3c48bf921e1e53b6f430c", - "02149fb7f251e43992341d07cd7f2dc19138a313cd079f31dcf38be39dd4c07b0c", - "022cd149426347da6f4668b994cb66e4bd2d2ba2a7564ee054db07a8332a2ac229", - "031b20bcc4e5b9ed16ff14e51676993cd9a74254f3ef8b766f0d114e4d7d99ac12", - "03305d45db8579b78f4dbb9312ec8b93cde65ef8d327763f7f0cad4f1d95cd1263", - "031b480a1c45ddd02a01a01727380797fb4d942db1ed4f24a1a6e7d25c2ca5499f", - "032ce08aed516c442e12a417cea153eddddabec55500fbeda2332951846b5144da", - "0219e744e44e9a888b27c142f5aef181c3831838ac063a9cf035b0c195fc15f0cd", - "0214e6add6e3501aebe640148f96857e692da5595a6450b6d2ada26f0d3ebaf6a2", - "021a335dcde7efd31bc49b291d96b585cf96d14b4850cb366cbd75b443e4a81e33", - "031eb480be8505af715e54772a45aa4d18e46ce271394d04145918577a6859479f", - "0203a42b9cb6c224bcef560173eb34035b90eb3604a6d6fa74839d438991077328", - "0313149caff42a166c1cdd45cfa9438bde430c91a8c43402aaed7e8495d9e5c9ab", - "03189356c6e152801d7ae3a8ae7d193f99d87cee26c9facd4b0fdaa17489dad371", - "031e70d95c1c2fb7740435041d1beb5ae47ad2f275c490694f2c8ff8a0568d6427", - "021e5c92668787d63263fef41cfa31f1213649b3d6ae17f1b0ebba33330df0f13f", - "0214fdb833f081e193e81fec21daeea8163d9fe71f5252641689628479e4f84e34", - "032c66621efdf7e0a0ef18026e4316d8c1d7152040a5d789eaa8b3a4fe4592d093", - "0305fa741965a572fa1dd4a59db0d855146e7b54e8eb66059cccfb7b6e50e7b1ab", - "0305a12a44f51a4aa55f95e3957181ed9abc92ccfec4500c48ff12d7ea6d072c36", - "032eaf6d049d29a045c2de051dc06d7739ee947b10d3182baeeb86ce16db89cc15", - "030a1f770786cad79f4b7d8942c936a074d45d5dedf8130f9fa69d8eff6713cab5", - "0326c1e3d90cac56b370cef3684c26159273eed6f3639cba86685793f546269454", - "02121caf7fe5a69b6034b120e4883706d03c6f728dc6a2001742fa9942284612b6", - "03102f9cde8a761fc74e51904abc587c200220291c363b65a7de6cff7eeee7bd8c", - "03189565b46ce468980c01e9ea94506f047f399386b505b6a4cb485f2e2c4f5fb7", - "032f105df1bccedff6f3768a3eb21608a65b3c10fcdcec58bd1bf842d058ad5941", - "0329839851f733006bc4ea86c1b548d56a23ddd398dc5016703b7e6f980223ed8f", - "03036a6adc745670dfeedf76bc6ebde6ce39dd0659193cb8e6ba333778617cc1eb", - "03101fd2259d8502a8d907628532eb65ed02b73008bba2ceef7c984d0114b987fa", - "022a837ea10b6daf33e8eeb5047573d34d3fec5c53cc69ec59fd2c277e6a13b2a8", - "02070cd9cf44b08834344f5053b142d75bb7e897e5fc6b79941e1f40c2843afb91", - "022fc9ff57666687ea0b621b9dd78a5f3762c3603ad6c0be1f4c121d12b29f8867", - "022671bbbf3afdeafd8cf3b91230e5a985b69b973d1840a4c28ee9ff0aa8315d1e", - "032835d990b099f192204f1952a9707838419bfabc976bc4a7595ca2b5a3a90dff", - "032d7e91774dd7e48134b0ed4d96f97508bb9a8752e131545fb2507cc01a846c1b", - "030dd5fc290f9c5a76547c1e9b85d2393ad762f32575a65824d3ad919f42fae586", - "0212937a0c8ef9cb2f98e2935a270b10cb398c10dcc9141696ea0e043efb283305", - "021703e4feaccd0bb1f6680b1c548e6ede511b8819ae5283cd98aa294f54689a59", - "03267e6a048d3aaee3899e2b725df64f14487ddc3a4be58ee62bfe8347b40af1f7", - "0328317731e343c113d4f61fb6b1a4307911a74a7b7e658187150d8438403cd38f", - "0313df9e2b5d7cfcf7de87a754a93370340336d0ddcb1da7f17559d26f621441aa", - "032cd86991abaf35681ba040eaeb4057f98882b8f2f1fa8aaa5fe17df3f3566e50", - "03150c96c8595ee98257cc6d26888362eb2f46dbea7e72e84e0e7d2fd99255eba6", - "020af42533e26b9d3cbb67a65f6dda9c09e9860cb7ce4192f7a6754f26f2b1f5e3", - "032410b2eb36ef16b573714514e81f69141489604324ca7933a18ccf8a95196bfe", - "0327cf38fe3c1235f03b1b18a281b4c8575f88beb256babf71ba9c7ec8574a49ff", - "0330418c840e1ae253c2e243cfdc0b3fe7e7a3189e00ee16790fa17339c25b16e4", - "02028867722e92e765482609cc50a0c274e5c9970dff5a87d031ffaab26eccfc79", - "0317d1fd7d4abaf1b2296c0ea6741c9338e7bade11c75e84772c9fecc6973bf18a", - "0317d7c29e4d6bbc4e490cb4cb92ada8a47517d75e3c968dba940ce8d9bf123480", - "02175094490b9e5015aa2660d7db7880521e4b9f8bd0171c4eaae681731d972257", - "031cbf4500bca91ea1252626152a5fdfaf8e34ed7f5ebe2f5c26039c555e4d57e9", - "021bc54c35d0e4fe59993c46080aff1d3889184bb1fa4ee34f8b0d2ee095e426fe", - "0319cadc11c9c3661da3bd127525bf3dccb880afe1a6efbd9b4be8eb5f226ae852", - "030d5596016fd5f8d344ef1dcdc39d0bb2fe4cd35b61ca48d8394118c3d8f856b0", - "0219d613c63962ea7c12b421972147d977a948c3df2153f8bd4e93cddf6ce6e556", - "020b948d280119fb8696f1dbb647dd706cd8b3a099baef02292928ec0303b1c666", - "03290a22ade4b556297e96d50289a253427e03b738f389fad28f009d22b9e23c67", - "032330474e0a7a8c5f601c377c6367b2101e8bd44c64af90e7bd9dec6d341b652b", - "021f766a9e58113faca4f7462914c558994785795f9bf327b51d9a8d5de15ae88b", - "02172f6d4d725360d909e49663824eadc654e3fbad9b241faafacbbee534ee659c", - "022664d281fae61fe11c26e066dd3f706391ce97dc87c14b7da2662962e59b717a", - "03199735d06dfe3049364ee1decd3dd50a810e1cd19ce940c45ca88932fba92474", - "0215a92738e6dd96394c1a686d08f5300e692a8aba00ed5c044347f4e2d35e2c68", - "03136bd43d977c8b2f0fbf5d44385acc3922f047eae2cd36ae001e1a1acb072e37", - "0221c1163a9fbc588962d202a184cf5a0dbf65ca3ed95d60386b0ba6265ca9afb7", - "0223547f8a2c7482aaf2d645f8b6c7cf7f6d41b0d2932a80a543785201c23a662d", - "030f7da92728ec74fdec964f847b9f342f65b856796dadbcb085b5ffd461ebc4dd", - "0213974cfc0c777c8794055ccc98f8d982be3fd4cb96c4301c1c65c2a863ef058c", - "0308a863e36186e9f0192ebbda5a8083d1947493b2599a14feaea01960238c04e9", - "0315d6973ec6e4d3b0870606b61eb43c4a39d2337d3744373db0f69f891326db6b", - "0228ebb9ee9d6e320cfeb892ab7ccbb5ea20ecc91428918c8c0cd186a54831365c", - "030e20a6b845e523601786876b4ed5805e7aa04193bd8c14ee926fe1e1b42787e0", - "0310ba8d26d8c30a591367e11fa61e8eb91b8a10ab6345399a054f67977a21a673", - "0225d8fb2f42ec970498d185cf5bf889dce0c6b7e83625c40ab80aa0dc76b768f0", - "0329dfd08a55659cc91f846c669a99a1d7f7b5339cf55f4ab4acada96409702b01", - "031b106c4d6f8c261d7f58536eee179a67fc0318cc8b4a53117ca7c67bc66f4efd", - "0224e8f9f7f91c505d338e73bed582d0fa80c9dc38d120a0844d9fc87dbd5fc539", - "0322e80083254055fc2a3932603500f809a56c1879c7b793b9d70ab13a4ca27303", - "021d66483a43d374ed8995ebf15b587c0e336e26ab759e4adda3ff39bf0f83837f", - "02246ca81cf60ee588bc95a26ce7e6d880463d9ad53148fe4d4dcd2874dccfb1d5", - "03285a109513310b1e72b5b499a7fd218c2b5dc95be7a83394cb96e6ef711e2941", - "022e45000db86a8ed0d2dc84244e2b78729ea370d05b453e0523976c74576d9439", - "021434c4496cbc79c514610add8d6e3d3ebda26900af4bf3a182d8eec78de3f495", - "03215846f2c874aea56488f7e3598343e0caae667ccb69a75de2c9bdf76c0738ac", - "0226c05e0139cb78b339d6bf7f1063b9496b27632361fcf2a9e039998f30731c40", - "021acf24b359e86bede3b92bd2de9e8dbb5d482bb44ee01ee08e713038e880ccb2", - "0221f6d8c999dc4a4fee49dd2783c20347dd2b432de5076c57f18d340b46539f58", - "03187bedb73ac94ae9f68374ffd5758513aff30d3e56aab1b2409bea4ac9f536ab", - "03169da47dc405f3a8542be5ed756492426f92764c7847abc5b522dd2b044e15cb", - "021b4450d2154d225f7dcf44cc5d6797ccb3d12971937c63a1b14b9b1f8657baa9", - "020297358fe709fcbe8188e0934339a5ea910251cad554105a6b78b40057f38522", - "02070f1cc8171a6b33560326036fa109a60854e6a17d63cd03ff748ce406f3893f", - "0216e226abcc1f42e67e6a4d96433e744217cfc5888df134ecb11e5d94058127dd", - "0229c97c7c48e9fcd00161c1eda653847300d214301bdd753b2a77e7c7fc85b28b", - "023019486d3dd8c016bc8ff0e9a7370da92629b92ee18d06a3ce630a7d22275cbe", - "022861ccfb899dcd1ccbe72e94a5e751091071e02c8751102c0bfb4088a54f587c", - "02036c4bc06a5fbeb0a581af1a8914538eca634d642aaa2dab0c6e836e6a412b14", - "0210fd575bf7f71eb6e4c75754cf8e18b1dd62377a673475280c174bea20b9925a", - "0304da9e66b70cf7306307d047867c44b51f3eef8ff19ef99e6d4c6e15dafd9f78", - "03099a7a6ae0734de8e9b74835f623594a28d8d7f64a9f05a83a0279c9fa5cb1d4", - "0307b133fb702ae1cd103343787981db8c897eb63d7fff7d9fad4bfb60ffbc9c73", - "0224ff9b28fab83c44c6a1d942d04ec6095d29edca91a0bf48686ab366b38a9096", - "021e1f2b6a5bad0e7078ae0298bc00682a70710ec9f488242228aa251a11416e65", - "031f4fdc06b8cfe6aece69982db18fbd2acaaefcffdd04f56adbfa306894d07aea", - "031dd5b316fefa41a35e3e8a32c208e6dd74677ea45b8de7df6bc8fbe3148ce91f", - "02091ea3cce17aec78b0ab4ed6dc0b4d2e574547eb29429bc9fd71b82ce36bcb38", - "0322998d2a5f563344c12c16557b16708e1a3e2be79450eaf535255dd02b17b9ec", - "02055bd0c9aab64b4695e5f4119c9157b662813c73ff83828746b40db6df8db547", - "03190ba6eafa481c55570b153dad27c0709b20b2b185f8b36b56046cf313620a1c", - "022ea08922e52f130eb7aca5e82d8ce26dd2f018c93164fde8d1a1f2e7186f68d0", - "031c46726ebffebfbeb69683a42127e3ded980d6ad85b058e04bb5152277d8435e", - "02240c9fc924e75232ce00f634fa34de4673230d9f665a0d7f8c9cba00642f1cf2", - "030b80ce0505e89d4c619b2ffd1af681907b6b1378ae7f285571220100d75944ba", - "021168694b85493039ff83745b5bdc7801f1f0cc77450e878be9b0fa64d99ea037", - "03096e5d0e784cd85f320234317c46a8f0bd86605e00fa2ad9f4b4c6a57135a0ca", - "032711aa5b312fc1bd3620848a6a85a34b46e123538e317efef3a1467561a631a8", - "02110f6fa93e689776129dc274d42bdbc17fac6c0e4370c1803a4b15ac0a6a8172", - "022bd2e0159ab689f77b0f174aecb1eb3e16f1ac33b769499200c2e7d12241d5b7", - "0202e19bf0ea396ccf5454c2bdfc3c057fb61d3f625fe5a2e3c2a12b6e502818f1", - "021d9cf31cf40b40557e97cec2b3fecbf1bbbd7ea689ad79b9e5229ddb8346c36c", - "020e207bc0d56e5b562416d53caaf2fc6c041bd0a5d5d92bc05a99dff479e695d5", - "030fd00d02e4aea2357331f9146eba250d592c79837dab3c5120d44f7b48cfe711", - "0215d17647513b02af6df5a3a2a61f7570134ca60c53b3178528e6622011ed921b", - "032b5eb62570501674c1d0e0f488cda5192dd99121125bb154790d909b350b09ac", - "02067a7bdec248e005d9755c516d70b818865396ab38277cd8746c04175927e30e", - "03281880a31640c53da45b95b155288b6cb8af7466bd48a366025bbf53997c6cdb", - "031b2e8e73de187292e83d08713d6ce407c6e81f98efd8a253c4be9c279e1ecc13", - "030f9b4901ef29d0ab0c6b3faef483c989608a8ad93089731dad4e456fa4146722", - "0311d8c6d2588ad8d4c0f24d4d4f8ef6d0cda84fc5da786f173843ed085c8d2b6b", - "0322bab0c97111016df9ce4715c77f7fa3fd8eac262807525b66875ac9427ddc15", - "03029d1621c6c9b76d22b669d01cc5b8e5619e5f389b9ad4b48be1e72371d70c37", - "0327135129ab8a1bcc2f9702a8488f27b4c54d199391937e29a55f4dc163702978", - "030c5f1315edafa145c8d08cf8dfa530ec57bc065a42c8eeeb03abb61b38ecf479", - "021b6e295d29901a98fe42bf6fdc115a95a3f22d493f38a63e11370e12c44a3c0f", - "021a8fad7e3568a7760504f33eb37d71ae363ac265a2e510f3490bf638d546e28e", - "0213185e43ea202ed0bf1b2035519efc09ff60e9d645d0d5b98dc1619ff79e422c", - "020c082b65cddfbdad6374faf6af64c08c9bac248f8beaa787ef0a7af7b6b646a2", - "032a5e16a2cad0454e11066743597d00703db3d7b4ebda8d6d745acc9a7574ac3a", - "02002562cf7137e983abc5006768ccf93dfaac7472b730f80824ad0dd30281ddc7", - "03058e3bc7dce3932c6970c7cb9f0b628fa4a8b11125080b2f13a4a09c1a8be4c1", - "0308da3b0b0ceca66f53b49fea67194d79a8923449c395b91eb93eb3b80054d358", - "022f7faaf73652a3b1269ad61fc549d125f85018a4f2127bc576b7f951366f6d19", - "021fe1652c41db05cf7d6a4b1a0d4d51ae64ff789dea30e3949edeb33ccd7eeed3", - "02175f3cfa55b44e28d2d202ddcd6ad8b1b4943870f7e31426185ccd1263d25ef6", - "022c02f69b5c05454db0f748cc1f40f2d724c88c002cb65079f4c89993ebf0bbfc", - "020b6911cb35e96e659ba7c5194e7562530f5f2477e8224bb6c77b73afcbfc93d8", - "02124cc4da053d897e8800d53be7005f628d0d12c0fb07ef28933c1be25cccca7e", - "0206e87073de2cfbb663a6b197d19cef8b92168a3acc5d45f8ee1b0191ca6c64ff", - "032c18d77d18614e0db120627f768e1540599052bc8c94a46cb66cf5595ef8f230", - "022ee28bc6f3cfcd6e4f0bd92440d1813ca1666019a5833430f82d91b1d9ad2dfe", - "022444800368a689a384d3e7305f3083d1629f6860e9492da33bd7999c7f78542e", - "03005337ecb27713e657b75695eb29e5e93e9af43dea3d941ceac48b89e4b419a2", - "030201d1cd3043f360e7f36ee9abf6eb8f12f0e3e5b51f30201ab3b50abd6c4eec", - "0316b4e8cd98a87092ca65f647393b641dd591d5cd488c6fd0074650146869aaef", - "022fed28dbef2c10897781c77bd6005b896ecbd1a38b1bfed09d508b69807acbd3", - "03248e6de7ce8c7a9ca015ce2df63d06e8a7063fb9776cba2fdfeadf9ee0ccf5bd", - "0313f3e42a59907f0b8ea4c94d6eb728808055b06a4b84ecd67ec5041b0b201d2e", - "030be2fdd7b554cee27d6e7c52d5d0dd56d3157a4c275e8aa67bb46e47792e7098", - "021ffabb8974caab31e14a25545640842916072849dffb01d8285a8876137e1b91", - "030148d900563cf43e0c3cef1c6ad567dbc5b23676812d1e8be4abd14594335257", - "0317e8308df9c0beccac71b5743f8066c5d41771c69608792cce9e5ba4be3134ad", - "0325cba228fb3004ec9516c7f3c764aa546ba19eb8ed453bc39e6d2af59603d3d0", - "0225f49462266ce20839d9302a2d4344f550c95dc76b284167fa388f27c2a5dd08", - "020712b81690a7a72938491a67f649e3cb1b287355de42678a1891a495bdcc83e0", - "03156d31cd63e7d33a246b39a8dee4b0179351e81046e71549c34fa3e3693a73dd", - "021e40c994cccc35bf8d157f317d402a7136369804c96c1e2a65109eace46893c9", - "031a0359bcd6b425a6cf98a6fe89df515c877e517983925d1476a3a2b167e6cedf", - "032fccf3b00a017e775e75b43b9544f11d9460e60cf94d0831de1820b283464128", - "0219ca17226d00f0f0e2b550e830b443eb1041e8fa3728fe277be1a507d5b9c505", - "031a3ed142d47d2c359a236f86b5b1cf91d7f69a2061d7f69b5263053f4d6e0e57", - "02099e96254e953e37f4c7f72f1e0e5468db00063960c01345025d7169e24f14a2", - "030ffbad61c51642deb9f0429d3880388f0114d1ac9945403f10716ad6507aebfe", - "022cf52321ea5183e391068e1aebc3d23ef42b2c43642e1d78a58469660b62e98f", - "03011524445029b0a6104e860c41b96edbb592224a19c6e8be81f51d1ea5edc9c7", - "0314a73eb8b040021e06e99a9264e58a65f9325079f438f7b95008c9c54ff23df7", - "03270adfee74301fa4e73d6ff9c8ec8b14037e1625daa8f13927bbe51913a0e9ea", - "020818db85d19e45b551569cd01e7e0121e495152f9e151be0f46c6703ba49d80d", - "0307d7f4219fd1fe4f6ea2b7cbab3e8167a347e683146868e659391f7d2b8e1611", - "02115ba171e399d0ee1573b23b4c2be746341fe5761a7402a2d9ac38c54a653e2f", - "030a2717ca17dcc07e16cb6416ab658716a59877ed546986413c1abdcba02bb47a", - "031b531112f4fc11fe4088c1d027e7ca859ad24efb6350d79d3f364349a558567c", - "020cb7e8f913e6a60810a5c83bf71e6ab4883057ccdd01acc78044377629cfc73a", - "0220934218b8329874510c1829ff2baa33e75593da1a5acfdaeacb6b3a93fb9b81", - "0325ca15df3a9eb0efff6f14e5d6103da7b6642bc729544d67af4781a6cc35bd1b", - "020731926d65264f830e2b7aded79f5a4a183bd69784295cfed37472644e00da5c", - "021b133108c436d2af622b1027846b5a4808e7e65b0c062b6efbf8f5cc476504f3", - "0330152b4dc02e6f899dfe3286891408bf8ff1f3af26cd79e997e6a83dbf9bdb9a", - "0215e2eac7e128bc85892f49a370dd1b46a836baa5cbd7460ebb6821317777051d", - "02108f799a1b00a8714c0c66f59263b0a9538e6a38a0d297c968d9f68dd1ca66e9", - "03129ca8832ab5228a110ac4a4c7e21059635629523753fcf87702dd19ec0b524d", - "0301503ad208d8965c472a27b38d6c5ab97de303a6bcba53760626412aeeae807e", - "031e03183d99c88ace630ae7d6b0e937727da2f5447648c83aef0b20f1ca41fa69", - "03221a4b631367a5abcb7b3c613f9404070174a42a4b00c64bac3995cfc2f60bcc", - "0326961844eec65bd41a11ad1a9a38d5cc635682011350837fa4ccc54e8394acb0", - "020e1f015f678d1b61cb565b793cabb448c1ad4b50710f6e9dfb42775700da9d06", - "031c30f35a0a27ce0d2a02ef99e99132ca4293f9a0146b93f498659c52d7afac00", - "0209200ad3ad2e00b6db54364c26c2e5b4ebfb76ec64eb464694bd983f4c210d60", - "032586766ba37f4426bacbd5923a18e3b61dd3322f56fcece3b3a8f7531193ea2f", - "030511a613e87ef0716e7b7bfece240136caabaaeb67382b25b196e33eef63a950", - "030fefe6eef94b32289deca305524e5f770fd15d991abe3cfcd7b534f529a1889e", - "03148c87eacdfbfc57437021ebf9f6c6e5ee587bebbdec07a5df3053301512a17d", - "030e38522235a3ab235c3f643a71f08cd09d7b87543823ba961282c138aff92ae4", - "0328eb122eb649f8afc9505201af4d758d90e683cba7613f6009a61d9ac7ac9d13", - "031237e1964ea6668ec53ca872eabc96ba7c1411e337d45c480b00a455e9d36a52", - "03135fdde9574f7afc8948ece26a78bfeba78cfa7f5921f20c754cbb45d62c63a8", - "030a60c0c207ace06b0b9f06feb236e753ed3b097580b3451abf2bd92bf37f7ad3", - "020aa2472ec8aecce1a529e0b1b10567cf9fd38e0edc215005a1154d8a50474f12", - "020fc4e495d72d14d7b8df8fce6cf1bad3d3bc0ccb43569eebc2a705bda53f6ae9", - "021edffae50b18797dd2e5c4cde5ddd0d54b46fe428bd7f200fdbe43c4a5472ba2", - "0203de4884047af2888f9baa40651867b2671c36cd3012ab0181a698eb671c9a65", - "0210d5bc1e537c9c806dea2dea31661ca29c811726a689f5752be4db0d01178ced", - "0225b6e2fb23810fce9d869ff1ff567feeabe8d106c1029698e27b158c1ca6e61b", - "0328407dbd96a3adc2e5eb12449ddf7410e744709bee3b9c1eea187a19281e6841", - "0314f7b769753f5a79c4520f460f0ea7f263095790d5a0571e3af687b6f57021d7", - "030a0c03d0dbdd3248aa323321e0371ebeec895ee7430b745d29bcd22ff0a3a14f", - "0324db22e65b58df71b1ab85dd3b8969968a4a2a97b108e45488252baa0167bf3f", - "0220f0d0beb222dd221583fe518adbe7011cd4d4ad462b8530c84026812565ccd7", - "0315bd09287dd1b4a3721be58bb3c151bf84e6b35d2f3e3b7b2af09e64f39ab49b", - "03201bbc52ed3afcc82ddf876b02d08e6c506b040943610ddfc467ff207c94c74d", - "032b9b59f4e065300ee8335c905a295b3e7e5823ac8ee12c55a695e32e3c31df61", - "0205a1f98c59a2b90cf5f99f883ddfeb3c45aa5e0ebd08b7c4bc41b20fef047f5a", - "0325e0772c42a5f22426c0ec094aca51cf71a661283d44ba1a744e78bdf74b2c36", - "032bb9f1bea6922f8bd0d47cc07fbf2ce4c63972a096af9b0af6d057a44c5f5cbf", - "0225774b583dcc8c83e906ce5fb1d4a029611bd97edc56274929b2082d0f52e77a", - "022c93e8414274516dec4aebfbcea492579a2d305ae186b77991f77258259fb916", - "03021b83e8ce1ee2ecb676dd42b23d8cb923712ebd804d8b1376bae24104c35bee", - "0300d471878c717f3dc3bdd861c85e13ff664654c38a989f7cf44f514f5d9ebec7", - "020c01c68747ea9c9e032fc62e44d1b8e40ce9e680ae635fdf3c1d4eb76b90c7a9", - "0229c03e674bc8acb5c0f25099e759cb2f85e006ac364b963faa6364712bd687f5", - "02156d1abe77ffffb0873a094d14e9c8bfe2608b83eb88f1b0828710d21c1c795a", - "0209821f1ab93a9d8f0e319eee7298739bfa1917aaff38033453081a8337594706", - "0215ea84e3fc9d35266a3b3b2c4d49f33937e3f9a644db47c0ece6aaee946330d3", - "0206e1d792cb37b5b9359a1792a18522dd9e87d6e4a472db1db549f435bdc587fc", - "0225600bb4a2d906955d7b8dba244938d10ee566979dfba606abf384c7efa20072", - "030e8c58e13deeba2032b8cf69c660c7321d6f76b96b299b75c1afc1df4f8755a5", - "020fe6cbbdaca5197509e58535fd88d173dce2761bb28a79ed2065683df2ee5b3f", - "030b0ec71bceb4540a40fa6d286f4f7e44c1de9eece54152b81d8207ab64e7cd84", - "031b014b0b166d4f5e2791ab54b37775316b84292edeea645e71762d38979263dc", - "031dddea9b92f1f4a98a52bd9ee36c009b2cbf85b5eca5b3c06acbdb64c4794924", - "03189951b87a4781b0d5138898cd089c55ffa5f2e27c04888188c79fc986bbef6f", - "031433c95e1ebe68ad535aa08fc4881d4d759dee4d4afb699b796c636bd625ac60", - "0206a75fdfc94cd7cea211eaee67585dfb383a9a0484578b9eb057ed2cd22edade", - "03197511bca54857d414717a0992bc3d7c717453ff5ba8d13ef0fdf3c0f1818e19", - "03019b51a5ef1a7e0be5e14a9af4481621b337799c184fc39c701af60b95d3281b", - "031db550b6cbefde3ef730df343afdc37be44dbf22266b0d1e23e347c188836e2b", - "032af9e7daf354479f9fb86f7882d8a91aef7f8696747c16eb42232f8d9c1dc794", - "030cf959bb4a87677a4009c5fcef75ca24e33364011637eb3fba1ad5b39faca85f", - "030fc9bfa75e5b4fb96e16872020b678e197749295e239fbef0f5456ccb26c29c0", - "0201cfb2d3322038512630ecf897bf06e15e13fd95d93da409a49bcde2cff4039c", - "020c1daed0fb1e1be4b012bfe92a2ab4ddd4c6e2b304c42aa8d10fd386791a57d9", - "030296333209cdf68457e8021a98db437f4dd82e332bbf8f87b55464865608db07", - "0312f414278131202aa7712aa19c601b75abc221154cfd38e32afaa7211f5faf4b", - "030d429ef3534532259957785afc9eaa909aae113cd0da24e6ccb7b579077f1562", - "032b8461db9b2dac6bbcdb3031065aef2c4b5ecca13e0aa23163c6322ee8aae7d1", - "0208d3398de824f17a3824e69f6eb8720db406f040ac80e759efe3b0f82a094fb0", - "020e028fea4b7c089fe13a8cc3732b8eec78e60cd93e2816c55704b9dd7ece994c", - "031c7d18cdd2aff7292dc2fde39122cb1d002a6b103a9d89d82b72d871789b77e6", - "020aef82f796bd21cbcbf008439087d69d3a8aae61c43a9c1822ecdda65187a336", - "032e89cc3807dd31faa7513a12221e4293d788c31c453215a3078fcda6f5f94654", - "030ab6ecffaefbfc82f6d068bc485d6a85dfbb27ad648f9cfbd2f8514c03f3caf4", - "0315a1990bd2f76d8be1c11875566ab838a1e6351c120ae776d5e0d2396daaf899", - "0215cfc950ac8589301f65b0058beca592369d8e6824d02fabc0d1cd0e1349e9d9", - "022780c5b3a1c2111ab31e3295e193798bcb81b32e4074674148e6e8a66f435cb1", - "020c50c627b2ec85c7f666f46231c1337e027f5617b328a07bb2e64ba84e657cee", - "021802ffc38554bdb3efbcd813b10a02dbba76722c74c5909ea57425162099d1e5", - "03121affc84d5a5b07925b67ea517f7ea5989d28dd471e6e7d7e09cca56f07e11b", - "0302cb5fe043267bb5bf112960835c4cb9b0370116fb73e4bc433a2c69f039a711", - "032646fd310fe3c4a2b5f3013219810e32114c4ec73d1d35f9a1bdf25ccbd262e3", - "02245beab310880ea85be86c18cf1df3ee7ddbfa129167a5bf9e96213d005476cc", - "022f212b62a31828418116da6f62544751823fa402dd5c664023877f527f122afc", - "0308e2cdfb9ca64bd28dfe9518f020216ca4f64660a595b278b221f28256c593ea", - "02201deb4dcc6f9d4083b51f1c1a31acbbbabd28ccf58a3a5447be16fe1f33fd99", - "020593d0e79fbb519c1394577085517f781aab98adc43e46fccb6342a4ce16fde9", - "031cb5c7135c2013e7dcbeb0093cd8190210784fa707fe5dbf35214d0a5964cb88", - "0213dde760ca37c997fe2229d8900dc6b516e0370f598fe4c6185c71b440da0bb6", - "02092de120f98ea2ab072bd9fa232d594e8075a00cfde050a6361309d14fc75b6b", - "02284287e1ba65baa680800babba9d07f66293304d2104d97d326dce663aa882b8", - "020ba81048971c408f105eed96374e7133a70e037797e3e4fabb2e6669f8cb4957", - "0218df4a2c8b7dcba5a10ec009617c5d1b3d5c55c2ac7b5c9e8e1e5db6894b736c", - "0307565ae7e50df1fdb5beded0f353c34f7401b4709a5f5201536c1ac0e131062c", - "03087334282ab7843d5389c5f8589da4e63a144ceae779a6b1e7a03e710391b9a4", - "02200d1ed89fa156b28efbc93d6b3abf2d7df83bcf1d7f9ed5c27fe48778f1ac03", - "030b7ae5cff6efed59dfd3e00c422c117d3401982eec986db1f75fea4d6a9de06a", - "0206f92ba387337f883034e98dceee4811188d1ce6b88b9798500f5e665b7dadf4", - "0213320f41b28e70695faa0e93df7aa89e41528237651dde3b83379ab9ddb14bf4", - "032a8e709a94576615f9f91c1d12521600b4746809c965f4a6c3a1e656b36ebf57", - "021c4f17706fb51a1327251c239ed213b92ecae37931954520b142fde1491ce273", - "0322bd800d0abc615bf68f0ea2f96005940d1a1ed697fdedffc304fd10e979048a", - "0313694a93eca708ceb10fef53282febd526fccd279a180b2f64b508eb665439da", - "022b445025eaf79491d8ad8217d9ac9cd74172b06d7edaa4eb45772bc599874de2", - "022f3d787582bc48aed397098b86054fde333de779f73072a6a1a5f393f9c8b270", - "02164b625b80710168309ba8bab130eca39a6a9aee6ec49136df777542b9d6ed21", - "02017a34d16480ef679423310d169cd1e5393afc11c7f63d111d3e2ff366966d96", - "021725fa3b283f27e90855b4aa23a4eeb4af443858e43a076cf7cb9ba4a25a3410", - "0330210a5c772f1ecdaa3e6757c0cbac6e4f40280414e006d8823a44d31bfd1436", - "0203084d0fb92306f83d708962a9374ce32d8e0812c047136c0ca1021434de3bae", - "0224a5a9f42fa12c088845166922de50869a2743bc12371d7089c519b72ca3c752", - "031890e27923dd87a0b1f1d8d5e19c5501a9404959df321daa08e7fd29b4c5e902", - "022550a2a34fe1f6db7e7c005fc13d4d8fae88c2a9594d1aa4233644df5d8f3f89", - "0326d88fdbbae967d0a4f142404cca28b1eec6e0742ad788c525c01963c7971b2f", - "0326be06bedc54d5794f4f367786500a8828f146d6975f9efb47b4b1665b75c818", - "02119bf0a94a349914e2dac50a951f1bced053cd0e4e661a9e8ce5b3f7e36b474a", - "032d48c6ae40a2bc5b5a6c61993eea00ed267be981da261a8762c32ab49ed98643", - "0201047bfc74b1ecadaa45a282fae7c4ff5994b3137f9c89d52fe4f58fe36ca97a", - "020aa3cf118992b87ebdc18890dc3f4baa50413c70b013db4012d83c8dbdf3b3a0", - "020baac77da7cd961787780c91c4394d4462189744f79776ac29d113871de31cb9", - "03009ef4551f8f902833fda5d71cc4d60d8b8c8893f751af211a4957f2019e67a7", - "03140024e3875eecaa2ab9a39fbc6c7b282393ef88a776016879c1b60d6fd41655", - "0325acdffbe0b8834e739cf763d9753e4accbb0cdc1731eda261ddef2e6f67bb64", - "031bcb0923e4e10e924218c4e7db86e8f686c3d5c449681d2f1fefa51d793694a7", - "031a2b958993504afa1308913faec4c159d4baa56048a3b2ae48b9fe6e37fa8d8e", - "020f51e270d41aebec3e547a28bb4a86480ce810dcddf4a3b38aa0401f98202676", - "03004e9530011d8021dbd7bea867f16673d81bd61fc0c70e1c3b83dcd5f1cc7794", - "02203ac03e5d766ba1e23db7c229bc3fdff4017ca2d93cdfb9cfc75756893dcd1a", - "0326088f63f65d1bdac1bbcda9bbd2b598f6cd6a4dab0db5311e180e454fce31e8", - "0204be672bfe0d5c431bf4a2ba11c86aefbabd16d0a64836805ea0c44fa05e67b4", - "0313fb8f540690c7ce4e78e9e0c73769eb6228f44fe540fdbf468f4672b33112c1", - "0313ff4460a05b832cb666faec05a8eaab1ed4af7c7d33c779d26d4a55dbfcb888", - "030dc96ce7396e714accdad52090654374140f06f1892331f3bd8a72fb095226cc", - "031385b79a7988442321df4e76f93a2142b63cbc738152f79cd1d8f57795d991ca", - "0215e6f0ea38c4f017a82023daf3f434764ba882ce00b80f12f0588258038abea7", - "030955745f0a5c865e7492a0970cad87e9af567eac7a51599c322f026ccee71fbf", - "0207e291954811612f4ff91fab8ddd411d68b9e4fcfbc0fbe79d8dca0663e54a62", - "02207c433ddcdea7b69ba1e200e54982d4498d978b32c7f38453095e565402d832", - "032494c2966be7b78a3b4acca1e4e398465d4cbdc06236f3ed3ba1376140f42eaa", - "020011cd871b4c702812ef6b57b04dfe2b86edf93685decb75521eca7f4640b733", - "02159a5bbe4cdfdf4119bd0e96419748b7fd601a163e69c2b2de39cd4790fd3141", - "0308ba9063d54ba5debd59426263603d96de08e61e74d95e14f9c82d79f37c3fac", - "022e1566b6f43280c489667786c18116e0710dccb24b896d7ff6d24ec77978905c", - "020ebd157c7841f9bfddf323bad1482b51e0a3302cbb7b793f0a6014df2dd2c6db", - "02133ce1f95b94e1c074dd6d65e4d6115967f97999cc9b2f37e6c450e3756d63bf", - "0319b345a1c751788b5af93af635df5213b82cf5d8556eb243c8547e26a8e8eb0b", - "032410b2b964bc010d5e36a4708ea5979c1fbc1ef714be9a7969c787728ecbfc60", - "022983b023274654bea25f18a0daa1768b4f761267467a07c0b2de2c7c95313e9f", - "03095fb4d1fd9b65b9b27484407ca1a74f0502cb609c3a2c581a0d87008c2c1e2b", - "0216088a92458d9b05a982f9cb741f2c52b778d51a226c12c2d0b36319796aad4e", - "03063c28b0daf3eab1bcf8e425461c4b09354d1e905d3ceaa7afb09a73eb89da92", - "0314605a5f842416b9bf8c91d48018504b9bbc0b23bfe5751d2d18e6f68a1c3cf2", - "0228d28b33a851d953b0cc6bed6435cf542ec3a71171026855be1075e54be331ff", - "03014b7b5ac72dad7132dc32bcdd01ee933b06c7b881f9ccb08e82c2af55d8d29f", - "020f8dce9234b4303b693324d6ae7012d6cacfc2dd5a94dfc76844dc05f3090a63", - "0315e686f29f0bf2bd54b97bc11e2e7eb28471df6a92ff3cfc8a45924b7c4c18cc", - "0220e5db30e77066dc4ddbbd0c42872364a708cad0cc973bd4d40f308caa05b6d9", - "0311eabbed51fa14532c5717c29187180149ffc8cb61607728dc42443af100b5cf", - "020eba5dfa12dd02feb298b73de5c38c6ca9b4ad2f99fb5e9cba9ee46157800a7b", - "030c52d44e5f78640230e7576e89d2f6cc611cfb682411fa9d839281c0b91cb0c8", - "0310f5348e5c357f10c41a7b308897d2bbe4bdb13f796ebcf6ff891dfd429ed3f5", - "020cc60bfb7f3de59c28bb4a9e0fe7914dbfef04817daf9e2d1248374151235a88", - "031dc7d7859fc8c1c562a1efb00624fb0a0fac474b22403dfdd4951bcb05ad41e6", - "0314dda6cef9cddc313a606058a85b57f0206b2312ced36de2a1bfe67b88504f2b", - "0307dcc8561923039b65b93b3dbc5974f487f49112c42046a87f91a48f389dd258", - "0323adfe30cc5b4ea0ecd2655c47d90059396b7b234b1780999e66ab18bb20e170", - "0204d2360ccaf8a72cbfce045162ba8b0431bfda221834369c840cef741ee7f441", - "0303ee44d0877d82cc51f6247db38515af79d5e47dd9056e7f70912fc34e9b2be7", - "0200972dd1485dce8e32969d5e21510d7f47cc73f2d1f443dbe280339ce713f99a", - "030fbbf1d7cd6d4b50964695fe33dfb10115aaf77170561345c3974836b2e7ad6d", - "031df445a6596d9a186556c33f0ea68624f76a4f35b9d2f55560f5565f2bd45012", - "021dd18fcc80b9c4a6843616252edf95b1b84416a3a0cd216318e9b404b139ebe7", - "021ecd5e91169ba854016f688732290ecf50e3d88d2e40c7fc6f8243019529ad34", - "030baf3669f17df76fe3f166af3ba162c8299c8f29659b89cc32560ed6e12a42f0", - "020f1e27ce5366b86402347206477454187ef8f8c4b9d08d0bdc605f8aea5efe26", - "020aeb767af4f2b06624019701f1c06ecdc790cd00982986bd6ba7eddd268aec17", - "0226d6f88a96a5d548603866f5e51aa598986ce9d1085255bb0edebb0929b75153", - "0208a073d5f94e735e1b7f754c27418ad5c9ae1f36eb693c0646a99d53f1c58bf5", - "02063831bf844ccaf3b5bdd831eea171e299ebd7b0964f466c7bdeaa3ee8b117d1", - "031c134003d1432c1ff724689a24778848646ada692f4082960b371042cce76dc0", - "0306da4f448d3937d2e60f0a48510522062b13f668cb2882e72ca86ce8950ea9a2", - "0202f51b71b4f2a2e1799486054d6a9d181af10410f7664893ccfd07c503b10c7d", - "0203c21514be7b20f8d8d1453880cb11c271527d7a3a3ee27a944b94058f2c1805", - "03039935daf0c05f48c4c7685e161d4ab5bfdd2390942106be8196584a3d0734b8", - "030ffecbcbada4d9a21decbed0610c9fc1e43611905f06f5640a8a032dce504822", - "022ea017dccc8eaf8caf4957d0a5ceae7b263a873e10102f3f641cbf8cdc072f3a", - "020e2174e8cadd7364cbba266a96636ecca64d720e8c0ab089b100c7826f638d58", - "020b1ebf4c158fd4db2aafb9f3372449bb2b478040019cccc93bcb8b738e61aa9f", - "022db0586398220f67ea8bb087690869b48f7a9c02efc066240f70ed44b84b8404", - "0323937aa1c71adf3eeb12a9ac7f9054c7a403185fb36a9e57ec6c944c9c4e271a", - "0229ef1cf2c3a4a7e326ffd4013964c0d2e11366d31c9186e4d2863f59129bcee8", - "0303d0b8e94e395fb3d48c63edc4209c0cfe8dbceaaf1c5a479da98fc9444fe212", - "02081f38d2d6bb913d7c6405c78970cbc41b92fbf0ca17d88aed6d11efb4c4ff45", - "020d3c9fdc5a569f7c961def8fb3e83004bf0d43f8631b9c1317f0dee84c7f6f8d", - "0311d07a1f78ad1dc65bee5ba8fd98f981dec1601b4e1c3073d05e83699f67776f", - "021b05a2b61c377ca9ccd97c08e8a059c0382e8c275735875cd485606d263d1bb0", - "020aed1952521c0b2e58fd09088ff21ff825ad15d5cfdd93e9450f987a7fa0d6f1", - "0200e9efe588ad76d9f6872559a12eb37d4f83c3d5a8950d1755387c00add538a1", - "02139ce10989d98c34df5fef035407d92715d4ac6472ddaa53ae63cb0f496fa149", - "020dbef425ee2227afdc1572212cf6e75ffe468bac0fb01508f53c72555ff1b8f0", - "032aa54b939b6415545f69ab4eaff5032a34fcdb36b85a6a4b45c70583238cdbae", - "0230620b0ff966c951acb1faf2fb5d0f14653af80aa4c3c98a5cb6d25b2db37327", - "021783190cc944668e6b7d17d05bf6aaa7158e4e3e23ae5fbe612ea0cc78ff1f04", - "030f282c77bd6f73dcbad15606bd9337d5c567bae0994c92a79608c213e9eb6bd8", - "032ebce98dd9d501edf358bf0e01855f556029247cd6ed06b3996a83874a5f1b37", - "021e78008eacd8765378f84d6083b1407451c1b3a3f53c9d1102b528aef0e0f5c9", - "0311dc0e68123a22aa7c033f0a95a9238b9dc450a7d50944449275f976a666efe9", - "02061ff033c6f60db8e279371b8525718c7009e44ad96c47c2d7cb530f4b519e97", - "022b9587c5ea5bd495ddb29787a826b3dd75840345233aaf8b6dbe70340b06a2b2", - "03152ff830b4dd524282bda4f030a08d561f7f1d409aa3b39a73a87afd531dfda5", - "0315fddc6a2f6783093c80249c770450d0ccbaf1520f663228d01ba34a80b80e25", - "02258623b34af55c14a6fd69f9a4a5db6316a43f7fa2fb82e99f05940ad3e18d24", - "0303634dfb85bd8ff97f255f029675d2ad2eb978f09ec1371b53fb972eea777457", - "021435d7d3a67e7cb3b9c1f504dddf4f18a67e145bf0ff5a36254ce7fed72e9396", - "022e4bf527dd8d191a5356e4dd91f24fc54dcd91e3e024591c8bd2b7d4e9faeb62", - "02288087c2b0b76af244352083711a9286e0abc949cb7d30c74a97f14ca51d03da", - "030b13d9997046628aa67936094cab338ce1b7dc4a5be4f1d16f81c94f76048be0", - "032d95ca795b31882624c46523d3d2df511dc4533bbc12c7f9d7ea0783706c66cd", - "031fd77585695000e29c280dce5ddf8af4c75c952dff652e36f510633abc894f89", - "0315582efb1923b163a0aace751c41caac0532d4748171f0df2157b64e8cb239ea", - "0225fe683a727d1c73c2de6016fe17860696a8dc6ab0cf51d8ec4fffbd4e25bc58", - "02246b8c4092f5b273c9f9e5d8f3a05b29cd3fa08b74e56c8bd8269bd7ac46f2f0", - "032781f0e47eb8eacd644df9a9704014b3144c65090a6600cb5d8fac4425df049f", - "021987b73966c3f9941f64b7b6a7c4a3bd647356de55290f35d5ac8d42f84d0c96", - "02157704d5d00ed2d235b9a787edab4739520a3a315ba765bf2dd2afc10b1e6e0f", - "022c53c0286be0fb9d8b98a5adfd62f3b9ba41644512e49cae27d760dbea9b9615", - "022466cda90577c2e737e809f81223ce08d80cbddcf747dea93b1a289e440cd6a0", - "02053f132e8f1e15747817e04dd54fd51ce5eb7e1c7ac35bd0d5f0e1c1ad4d4d65", - "0307702967c94e8758224790e57f5860c37301efeacbb59e6639b6c7e2d04642d4", - "0213bf66c2811c827ae0d5d5c9d1062e8c6c855b993f48be716dd32356930676fd", - "0326d06c1a5efe5b36371380a04b275a27a67a56cdfbc4d413694e4bf1c577950e", - "0313bcad2af28366b238df9e8ec5bda29399612365958460a733cad49d04c1ba23", - "0221e56aee34dbe836461a9c489bde2e4dc4b6ae8f6fe960114f6a6c225b263550", - "022ca061ee73f0cfa914be7b32f46cfa170161c13fb3214178e9eb358a493e47b2", - "032fad417d8444a15b9e1b5a36b6b9a0c62375810bb0cd2db53fc3b7c15b56f39e", - "0217b34f6febcc9cbc77a47dfd35f55b460e71e74b303044593fac0d086a332ccd", - "021dac6202f693f78416b8b916553dd33fe1ead489f1c8efbe252852850eec3717", - "0317806e70bc8c2350452b301b66a5b3ca4a09ba1e719bf7f62f0efc07576f8213", - "03136713bd2c2e83b2873a741d22d314690991b3e8846a5be6849b96f629a01b8d", - "030cc2c56953f968bb4045cb31f3930a58645a494f8ca3fe3461f2a9a987d79393", - "0221486ee5908b534d080356b8cb47571c2ba7be4543ae1079590f4333f4f46834", - "0309de4a23c88b1f6683e6b014cf214b1a7a20c1b02225678556444e688812cb0f", - "032f27cc3e2944a1616d3dea7a112257d76fc3f7114bbef4c85f83f44fbe0fc87b", - "02061b6c7a2b242caad2f5c7a4449c985e56ee8ef6e2bc0c6969fcfed79b4e94a7", - "021c082057ffda40aac1070aad2e989b81a7033062487f3d7ddd745c9d88460721", - "0328d5c48d292adfdaef54742bd0f57fe599a331593a55cff19195ed0bac517367", - "02291b9402daee13187fb6233724516555edfd6625ea8b1db066f4550e25928258", - "0215cebbb0f20a04ec2954dbb5d328cfc770a00f000e07c10cd5498b4e91c5cfc9", - "021f2a8826ea08c19fad3d2d0d7a84f670577dedae1090f70e096105de85b9bfa2", - "02254b7874738b3eb9c0f75edfe17d30e8ce96e815d8eb09cc687995a6e574cbc9", - "020931f2628a46c2abf6904e77a68de2b33bc05b1734c5298aa8970548fb468e17", - "020d739f29c32a58b412e34380d6a6bd573cff547354d53bf7e1eb1baa5b5ad422", - "0311e668d07400f9fd52a616334c489b2ff7a328583fe0d19b50074ee15dc0ea25", - "02036ef38c6eab4e229870b66eee47fee177eca2c93e0d0ccd4b3219d195ab396e", - "0202c3e01604c338060f580d2d1283886cb42d71f1445405068bd2e8656f530824", - "0303d9e8072e17456170366920d024bfe9d8579a97fce89c116a2bfa995f43b353", - "031bdb000ddcaf8a84f1aa3e2f5ea71e312afa07752c30872b8d42ba096eafd820", - "030c1664d019dabc333686f0bb53772ed58f0494ed0f32679ee7c69638a624fe0b", - "032867fc79b0d8c487cd599dd45f487353debf34719336d40a19397d3b4a2323c5", - "03165fb4c2c362fea5118670895bb2d8456c2b8c692acbd02cc30e906e2c36fb88", - "032c0777f85a505e4786e076974088894f7830528027b8771a5f03bd00e0be27c5", - "0319d23171ecac3fb22867f3e3684f581c65e078fba2f3d3caf39bed89df1dc4ed", - "0321f4a55e5fe531d9595a4805ea333349d3e8dc9d41e03bb8ec7e572d8e3fba84", - "02009cc962b54b0bdfaeb6f42b016086238939ca1c89eb02cd3581a3024db7a3c4", - "021f8f8125d6fa7939faf8847374810d1754ba916a1ee1c75cc937f29562b4778a", - "0329cc106cee36bf6a318a9197689d28550e34c8e77e7ac4d66e8902ffc24d5aa6", - "030c44e2071eeab3d9e0034e789a87aa8709bba1f26cf553fd088723e83029da0f", - "0202e4979c27de7729d02a0f811fb175a74e6fb148459a0aa82702f9cf53fc7916", - "020ffbc9da9f4a08d52a229db8cc73a041d3895df49bfafb3a421e85f364965471", - "020ba3f9b71523a1c70f55ce68ec83f27ed6d95f945ba29c7965e1a065dc915f53", - "0229e751bc47c1c06100b4eafa5c7d38282ef57877d18ba64ebf34a364d54ed1a9", - "0313847e78d8c8bc740026bb5460a368c3ba4eff8a33976226842f5b5d058d92fa", - "0300ccacbf35c703fc611c8430bdb3147d236db1e907d0ee6f52903efa3ddfae06", - "022e4091f00ad813534147cd997135e6280341cbcedc03a040cedfb9553b5fd0a5", - "0320053610e50a2f590e52853a003dc64cb59eb0cca5bd947324a3133a47eef938", - "0206c500ffe34216ca0e01a4715aa1078bee4298e5fc33e46b8135a5533a29f87c", - "020e87d2aa06bead33f16c0d8fc319ef7889eeb4d4d0f80bd7a1f63a905491c7ac", - "0221698138384ff66b16c19b29bc6d581ce5a67a1e158cbf80db4032c72d1a4f93", - "032399005619b42422fddb31bf9c13dc3c74b7febf652f3c3a2204267d36f0a76f", - "030728743c39cf36d93bde03359c6743cc2c201e8d17b1546651b8c5f6244ec495", - "0302d346449be924208c542d630a24161c0fb03781eefa3cdb359c22ccbda59f7d", - "0318f816479526bf169a3b2114f71f5b3e1eb4e15858f74169c0fc2c27151d5e80", - "0201bbbd65915bc503a9c4e1534e58df6b57476f5a9ed933d1937f23701e35b76c", - "03164ed5ebe2f9090d15e2913410195f1c34210ac21d2df2680898880bbd81fd18", - "030176b379e37e83df2f2f13e483c0ec521817873172524017e1459fd84102cb2a", - "02121c3c55d0fdc7b41e042f9e8c10bae38b06e7e2c7faf1c1e299386d15022f2a", - "0202400b101c41dabe91c65b74b9b7decbb2ac17bcdb5c6745ebe2fb822a020c1a", - "021eb73a5d9d2107618bc8ee5751645b706a9d7b9c27ac5710998b8ad79c2930c2", - "030c740eef2b991827d946dc5dc581214327741b88c9b329e7b131bbc450af20a8", - "021a8da7fc407db9f438573899e9075cd4a3db76a2d072e9260359e159633a4f55", - "030282245c8f038d0e52661b4b4ff6c990331499284acd3dfd8ca92defc0dd3801", - "031b2fbc59307296b3d95786cae53f8c95298471209f2d3a13f9d9180854bbc48b", - "03296bf8dc4fd33b1daab969faf74ad86d80102a3f4e1605883ec92c238c45d88d", - "032cea1c0f8a14a9c57738ed244d203ff45d1fdb4afbaf7c21a4b6366f5ca6a189", - "0211af6b996ae94bb98842cd672df4a928af4e51acf2c6abb941955562ba8c0bf2", - "031cc2f50b200d2b987b2457809f6fea1f0f2c82e6b75a66d950ca06858b44de01", - "031c8f1ceb7bb1d5a43ab6d7d817f3872b93422c152ab5312a58ab9b1257fb6004", - "020a586ffc83bcdbd6e84f74b6804d7d9b9f959f6df6cb87732e67789752bcb591", - "032c235459e3ffd00acb742cf1af9fb70fac65149d684a3aa977cb97efcd4d5afb", - "0213f6c29253a2b7fc10789f31c099ecb63b143468fb052629ae21a62e92cfbfb5", - "0219a351b1846246970cc489f311e218edf307df5434b50491f95c968f6c62f3ca", - "022b94a43e9053dd57fb6deefee65ecdf785d097e53ffd13bc0f5999e7bcb94fee", - "032f318e535636f944b31f8005e75befa85ba9169cbc9ba8b48aad47ef445690df", - "022c76c35c0819526556236264a5c431c6fbe6ab53eb0764a0e03b492d0b5415fe", - "021c3dcf840c5cae3314687da6554df4add41048d1c3d68df9b0e6649b446b4af7", - "020f6c8210ec02a801391713b1a516f6fb3bcca6e00b253f4d2415948af79fcf5d", - "032fb8c8487b0b55c3a3bd857d9a4faf06e44673fe075bbb042070ae4f66c5e08c", - "021f5f6e950ebbd8bec26d47169fd5694133d2552fd42f0c1903074294b1797dee", - "02250f8a9b63806ceab888702f9f352e59bd6a88ae0ea7ad0611afbd50b9b5a59f", - "030353c25b484833d2df5d1a67ec257ac3d48a01814f82f51431e0a0180331b148", - "022e84f42cd07f85948e381dfff52d9d932230ca0c990828936daac785a960b0ad", - "02176ddb929c45179b08a7f5d8876b0eaed4eee1ec1f31760ff320947c1c3a1f78", - "030375b9e5a1405e781399a16931d55dafc48e10f8837d7632da33c6ad80bdacad", - "0217e5d211baba39a1035a72580e381483888a2e91edb1ede521262296f96b86a5", - "022fb1c534f1f2fc83553b9db3069eef7a4cac24e0e063af42fcaffa9ccd5a8661", - "021ca923c81a6f326852b658eba26111c583e05b480e22a1b72ce8c50b331dcb1f", - "021c09f987a3093f76fd453c4c0a6e86dd16af42181886beb10cd36a08ba012686", - "020949e837dbddcad07690833f4eafc7d70e423267b8670c2d09471c28b6243f3b", - "0216bf67445cd192dae0c474db63e78c44d6a933b7b370b0ed061a3ca39dd52c81", - "032f6968aeb9881f8ac57df931b1cec1531d38791b0bc40eda73c3e081cda451d5", - "030ac18fccb15fc8baef2f09af893c422b39e5d47c9417c1e8e2cc61d9b263ac24", - "03032cf09b78e7b6bb08607060f7eb736090fb26e79257e8e85d7aa3a2a88b6439", - "0214876b55723c204ab1606ba90ccb57c1d83ad2f80b0fb3cf546595fcc01fe254", - "0210f2f298cb3c64d07d94548d4dfda0ad0b5382943da384c6ffe4c90d1fbdd665", - "031f1c193ccc6a4c7a7a60b38505c4afec64eb0ab39adabaab9df7320a41e200c4", - "03163844b43eeff62ec3d15ffb017724e299928b4e531f20d008bc06dfffb4a0f7", - "032664c4b3a79aefc3cdfe14ecbfdbdd4cf6cd96a7e69c830de32c8321386e30d1", - "03255d23cbbd414491f5cfda3c87acfe36558d606144ad3c4a34fc552b01482769", - "02082c07e24ec0d5c92d9ac6bb6f4d8e46457df87c562e968c70b3f948d44cc46c", - "022fa04051aa30fda8811726fc8cbcbf95a86e36fd312087b611be615f0f8f6e01", - "0226a7b6433f683687054514341de932637f9ebb82a71d33422a5eb3a85fbe9c6d", - "021ee6e80907065c078f816643b66501ea1e3999ac69171ff47e64152f0185239b", - "0303733a395b1ffd847b469b49dfc635f405d7e2d7e706c2d29c0101b1bc7d64be", - "030fa83e773bdb627a91c9889cba13d58400620ecd4d22c34f49ecefffc5f63023", - "020a16b266daad8298eac96e3f08e2c0b4d957d3b8503aad520f7706ec00f13fa8", - "020544a33c05fa8181f7e8c517ef6b5111f3b8b5184062541d5366041b1b2efd70", - "0328ba50dead20cec2a9ebf61205e7efdf24c76e11db5e3233b21241da56f9edb4", - "0214af4bcd44f57169843820e467510490a25565794ee74a9e3715b106614c30c6", - "020853c2c24c36c804af05dcec33316bbd51ab8d7477472e252d269c4cf12c7018", - "0210dde992cb3275470f6a967f4d75242ce755884d2c5c0d3e6f9caf5778e769d6", - "03128f12d0e454f5ce63ae6a2ebc0ec4d63f27f0284e3ed0f624db1fa8fa3e75ea", - "02072d8098cb618ed489122ee81af65aa6b0c1128923fd43a4cfe0d1d836f9ac04", - "032c3695517697a933c7b1231db70d99234d9eb0a4499c135796f5e68e56d95a5f", - "032fcdab982653dd2757e61f39e0cae4aa828e4f8a12a124fcdb45a350de569741", - "030d6a6095ea7633e0a0af0a3371fb6f2347de45d7849d88b25822134dff0f48fc", - "031415ca9339c225f9a95029fbfd153346813cd5ba8c8337163c2fe0645e992e1a", - "0315b251a62cf70c6da7450f269162734956126f9239fc7fd15f92453450523f8c", - "0219cf63b188f3919491fbfda8c5cc66cc716da0c1e1cb44cccb22a91fffac86e9", - "0206a60bb920d2a17ee97b310d2e86ab7b0d7d872696c3f0c4ad9cca5424964acf", - "022cc6d94ad2c1c1b771816d2a567987af381a8537454e7b1c029ea933ef88a905", - "0317ee24ab13b563c226b4279c8fd349ce23680ea017496c9392e80702fe8f4f29", - "020a6e99073fb0a587b42e9d84240b153c715207707d83da12c67c6893fa0e2562", - "03026728ae0b1eb392d31a4df49fcb7db653f4a36120df838eec9bac5793ea97de", - "030609b8851d9812915e6702606a3b05b99f4cadde1bc4829cc7b1ebf6a1b26d1a", - "0215b8e8f4f3b04147c18ed38f2fa6c2bf44eaff458f553b46d5650fafa7569682", - "0324d2e9eafbc90a828e79e3b946115ff2bc67d7882c2f2b2a1e89638d18ce4ad6", - "032bcac30e0258214d93f63b7a1d60d5e26aa49e0ccd731b80a0e493900ba2b438", - "032755602e22a6a76c6842695a88070ba98f02f2d04d24870c80be1db107446157", - "0305a65f17090b29f082203c4fcc133acf8760f6b1c6142b508e10ba4612fb8870", - "022f8cf0c89bda41744ec8097a47d5ae30934e6fd3d7caa6fe83a3d8f9600d2047", - "020b886f9111fc8e43ac14efbe21526b8d179d7695765235c5a80a8e6de433544b", - "030b577f8e10b75d776feac3ba525dfe41a0232dd3c64acb7b65dc74bfa9792c9d", - "0301df78ddbd8b940f84d4d51d2e8ec7eceb46e2bc16df8a5a05634901f43fb4b5", - "032f1009c13dcf2838364132ceb41b9707a2e8ac69f76e699b9b41d12e0106bcd9", - "0318e0a93122d6862669ab5ecf87554e4f9b621e0806b987fbca159bbfef2bd16c", - "030ceb6a1647569d914754fa672eb31ce314be019076dc4f5819aac1aaacb80ea7", - "022aa2dcb2382637d60d33ac4ec8f6cec8aa2ae9bd6867e7bb22a2edd3fb3eeb0e", - "0223a1f5ee58dff95aa21e0cf38d279e985f9e779cea5326801d3790c7ce1d8b74", - "0200d75ce2b214956268034e549576b00d07be5881d00df3b6b711c3c7e67050eb", - "020a5a9c4d89cc91ecec4f3c269a54c57852516324f1fe06d9198dc8177556e4b5", - "0222ec1b12f8d183cc0cb8f5fed94e90fdeeaec9ccb7cf54e1303cf9722485f89c", - "0219bd9f1021cff039e3354016707689e7790c8c687bcde54fc5133fe0d084c859", - "032f094258b21dd690fcbb505e5fab6131f2e04fe1d896f3961e57d94c0b0b85f2", - "022cd4d4251d4ae564b03988c6436b7b4a89458b6e66e9fe2df64eac269274d8b1", - "03018d35a864ca09e1eebca4672f6e00878fd1aee9f499c99440eaa707d359ef70", - "0227f5ec9aabb850bd59598ef58c3ec406c2ffdcbd264780471362440ee7d9bc6c", - "0324a00c6d75fe748ed78b9a8dbd3b0f21b19e69575211eb26c77296e6a43246e1", - "02167f186c93f7d62c69122881ccccc474e52c1bf81855d1582d851ab5622551b4", - "031de3f68dade79f4a9f9062f53b57e0450d479d457dc761d74b8bda2c0b3c5c0e", - "02138d77f61ee12137b19e251ba320ecbc76ddccdb6d39278897992336fa798a88", - "021d4daf89aaaf18749a7167a0ee48694166b68315894b17cb0161ca77049c4a47", - "0204d90858b6d2147fdbeb413b476d35d703b9fa09e4820f35c03bc8cf16750cda", - "030af78e78293410bbe7adc72ad778b4f4dcfb233aec8253c9e0d38762ad56f636", - "02260ccd666b2f623a070d244c2ae8f223b3947235f08a74f021bffe144f0624fd", - "021790619a33b7e09b002f970775647b3bc1bafcca55d8588097d9e59d48959fa1", - "0301cad8111a5f42dffc6b5319c0fb161887ef91476b692b798f85f8f702013892", - "02120ce971a163bc1bcdf2f12acf49dba753060d2658f109bf2f2a8b32ce7fb79e", - "022c0af39890ca02c0e6a016b078ab754e93c5e325f0669810dc0042bdab3529f0", - "0203ee44af3a0eadbee8949f2898303638bee9d0250888521fc1260acf9291103d", - "032273c742b3735ae1e8ed5ba27abb21b6aca224fdff558b6d6ff176ae96953cff", - "0310b48ac599f15a0f04d55ec688ebb0b5fb627e13a85cc099ac3c701c735769d4", - "0210916116a101acf1e37d94c121adbaac4c71882850f714eb94843ec59464e18f", - "030763b3200a7208b91c7868243ccd75b551bde2ca0c32a204e6477e4a26ec6730", - "021c5fb556218ffda2e10680e0deffa9bb38bd76e968f320e5bfbe18c858399d90", - "032aae4057ae674b0f4f1c003f91456c316596fb3b763d7fe5aad16365bd6dc4de", - "032070f8c05c53233dc5f88ae7f88e38961262cf8f48ce98b52154c304b8e810c0", - "031ce1b4fcbde7af06133c78a6bbd9f7e9bd987a7da57b7895af9eeafbb2693c79", - "032940fbae0ab6cd9a6f40a20b6fbebb2c4a4a31632931a7cedaddfd7ae2303c39", - "020b52bf178ddda421825776e4edbd3fa382426855333234cf630c7102e1c4e744", - "0313c3abeab186d79ba8909ef9e77c5e3908d0bf35f844847719bde7fea0f4441d", - "021cd4d02fdbc5c2aa7dd9f2bdb83c8adde947732fc70c2d5bfde90b11ae489f17", - "03280358a1aa35f60092eefe63aab1203d29d9e711e629caff034695b4e34f8ec8", - "0210581c4a37c792524f3db2838a307919a6f7afa1594ac5837c2e820071e61527", - "030e87cf21bb8243eb4188d68448ba1e4eb29b5229c78a270706e910d546b1598e", - "031897cff68cc29f9800801f06def09b9e09998ba2391684fa7d9e76e2660bca52", - "021ae18ef810e1a1208e86676bd250b9493b129da35fbcca734c71626736cfc7c8", - "020088c1f9b5a0e917730f79e40fa51d056c31cb7c954bc13c01811ddad0c4f878", - "022d536a1881517d4e7d82fcea17df137193126b473a4238c7d5f929050232f25a", - "0325a01a560bed4637c6bcc1cece1e520caa746ea415df506f05e0e0d72d25f47a", - "03129dce4404e989138ff2427e7f72aa24ca2055164a174f5bdcba70ca264f9821", - "030c8da85189778eb97da35cbc5443d216bd8e3a2ad033588e5a75a9660d57349d", - "03020b1c33a16805f8a07009dcf80710b4cfa86608213fbc73d9a43b53d4f76e6a", - "0208964207e864bce4089c6869bff61fc7c68cbdc17ed993dec042b381c1c6f18b", - "0317c3d7359016a536beddeb9134b339353944e2ecf3e346135c2e4a370b881c51", - "0330462e73d06f48565df79fd5c2c83f34cbc22513d156ed6eb7ecbffd31fc603e", - "021b3b815a740edeefe6d3c40a23162b387a9c97e1ec2144802139d0d880de8db2", - "0208c4c05455beb992f2609085ad6d81c312ec3772189d66519d9313bf76da5674", - "03132322747872357bcac5d6e4b86aad83afd8d1b5816586310d56d502faa84858", - "030382d9d575b3c2ce65f315ff9059f0ce964e134b64161876ff9c6113490cf998", - "02171df41c6514ce4b61005287361a9b2f510e022208bd12f2108e5474fd638968", - "031d829c5bf9304aed29625d7436b51f15ca503d52cb65a6f73d5629a2f5eff754", - "022587989ce2d0beb5735b930cd69650f832fdd3d01fc93cd3381423905ba1ca2c", - "0221d2d27f3022a210adb9b71d1bf47680f1e09d0a5543c36259c686d51b45fbc3", - "02288fa6dc4e8831442f26fd800a6d088161d0a1124887c8ae3981f2123ab2d0cb", - "03042a76efe6ec55b83160387b6c67ca4302ffa63f99a41296b0de362f64caaf1d", - "0216cf0074569b147a7eb782b3feb730d31d66505565250a8cb78c170e03a5bc14", - "02294a7179950294b7d32a469f88a1394aaa0be7a371ed194c1770897c3a70c263", - "030ad52951e9ad7652ced513f5b2e8126f7ea290017504266a363a45f35c19c775", - "0203df0d0e896f78cd9a465bbcab0e95d5d606a9dfb475e683d1d11b0ae0394acb", - "022b65a5df056247e4e2962c49e00e1b7646a2e48f8c863a042a747263186c92aa", - "03273d4fd9c667feb40e3fd40652c2da0517d26bf1eb0718bdd1d7b821010bc375", - "030d5393bb0219ec2739ff66277dc94c09b17e504bdbe011821db3b956dcd8c191", - "0301fef8f6732abb4d94beb6b08e2c6bae90d67aa6ef95c5592e62a755d66c3f84", - "03224141072e95cd0743444db3b5110278d10cf8927fa8ee129b62a60017278df6", - "03117d8e17799297649579edf45b1867135787b96b70666d5aa0f7e10fe0dbfd0b", - "031bba6a76181865de456718bbc895a062036019d5906f57cfab94a95ca5a0aeb4", - "030cc9f4903d6da8c3425b171c2c980f21f0f3ef3a24602814467c1edcb1e6419f", - "030629d854e8e2a124ff104fb3ab5720386c3eaac8d41f407a11822f424f05f248", - "0223e8e1bcd9edd3c258bf3f2cb3210a624fb916f5b503c875b85b25c88572ba86", - "022d95ffdf99801764fd9f7ed22537a2613a1ea96958c8614c49549eb216639f6a", - "031c830af007f59393b313507c4ed66fa4e6ca9b1e9c84f5aec70762e93381527d", - "021dfed56032f4430554ba334819686f277ab4cc48289be50367f2b97299372003", - "030f6f400d4a0864334f7b5a0f2a0cbc79ab09a2eb0a75bcfa6aa6d401dda70adf", - "022227f38e36419bb01a4d6afd5f91e5b78fd84d59f76f5c8df13e87dceeb66a91", - "021cb8d006bb911ea382c5de2de548e81ac2cb84f25eaee23d309d606de54b5fe9", - "0222a8f28e144e93b0ba74d2f6b12fce9033731660edbb51f4ea56fd9d264c84d3", - "022460d8ec38ed9dae94ddd25b3e9da8cb27038694f62273c2cf84bda28b516a85", - "030721d251afbf7a7bd5b4dfab0750083d026d0d3251f90d6c3b934bc8bb0b6e4c", - "0310cefccd789d7b05dbb5457d78ba035256c463c54fc9e17e5014373f21fbf76f", - "03280beecb035848101f2e5355ae4539b1076d2f854ae803b2827539651e1c5dc9", - "0309c0f5922ddfe18a81f0281ffe2eb3ce7d9569dc71c2ba61339a59f7a6bbe1f8", - "03251f8a1b1151b13e5125b7cb65f7917b70a050d3deef83fe362f8e305ef889b5", - "031d716c30592ce7195527e9646bbfa17525784cef3a9b6cea2cb2a178d8e1e12a", - "0211c928d2e7e1512c5ccb9214daceb1e6e0bcb88d59ab9ba217500f1dd8568368", - "031ec4b045295887226443d654ad191748ef9639a1aec04034265d1cec10a43e92", - "0317d31198910bebf7f9f035f184bc596f59fcf68bf818b042c899b3a17680ce71", - "03294b853b3a682879822b3ae32a8cfcc2661f1715c732f94dbaefccb7dbd7fcc4", - "02120bf5d8ea78659a055ba98e92cdcd52ce723f6d507ba954b82314c78f260194", - "0213b6e6bdd2379f26e89c9d4671c4f9173bfcb817194a757740ce6f0bdce3cfdb", - "020a8d91590dc2f57f32e574e5a5f3a07c70122a55612a63668d4d719909151fb0", - "030bd44197b244e9bba7ea7052053c2acdd8e5ff37d9516d56b22d7e127397d7df", - "033048352b37c259010b7b16e9464b0fbb8ef9cf980de36ac502fb3ea4aad615bf", - "022962c862a371209bc9b30a90cfaabfa435a61b5c28aedc75b143239b62ccf8e0", - "0310082eeb4273658df1b1aa42bfbcfc58cfb8e6b0bd6d38995baf5f1d3562fc49", - "031e34ab46115c35f156c41e26e091a752faa6e149ceaed2ff36a71d02ca5522cd", - "020661828c8a30c2f24bb38d02c621b53bcb8d34c16e530f783c9f3e36a3b40b12", - "032cd20b84bc9b88c65c99f0b05646258f87cf5f704099c212a344e38b648885d2", - "02204c5661847c6179088c3af9f62bc6cbd19413de71d933a8d2ba1f67a1c9030c", - "03200dee1636a1f625cc9d5e1246eebbeac943a98c621837cc7d6ee885acd73259", - "032d96120930cc2e16ac974b7003116e778bebfb0173e0daff2eed310bae6c493c", - "03047111566b7549a53ab04d34f3f5f534785acfe9af355717afdb95989e64dc09", - "021a9da7f9921f8eba7b0c9f9f2a185aafd7ed4b5299796e699595888235a313b0", - "03219b2961fa36ed4ad307d3b793234aede75429ccdd83bb1f9eb58cb628ab759d", - "032c1e1a29f944b970b0b2248afe322794aac37a96246a542c5bc67fc0635183f6", - "02126c4e3d2a09a310d1524ffb76ec40b7785d0dee08e9b23402a160f0378d811e", - "021f2d6c5adc9cb113670da9937f6d736678863c0e8e939085fcf7270f4f3e78a5", - "0222cf517685ec8cf89d40ef8b2d037fbb77c546ee796267f531292238cd780394", - "032374e8cccd40be67a0d8839325aea1bfcf1c8e8b943973445ebfbc9be66ef6b3", - "0219d4de06c1c6657f708b8c9a12bbc99548d81903328a9f81e596bae32333b705", - "030ae4d42fd64bc31d1bdac5c527b59835cb83d8eece26de6c0d39e172590ff889", - "02168c36e90791afabd5a3dbb597c0488a38259e13bbd5f75e36ab0dc6f6f59597", - "030b6abc0f5d6b328ff19eebf570a0f65f8efb37207ae6b54c41aa8827e9ea3a55", - "02197658bd38430a567ed96faeb7ab9333328d929a315ce528eff8624d6a5ce781", - "0312f0e38cbd05c968c9ff54888d28e926fa8d38652ca2c481fbc118cea73df097", - "03261d86fa53a7c3801b4ae6da8df4c7b6431b52c4309ee6b5b3eaaf55d371f330", - "0211ccf53f9de64214fc3165dfe0fe64bfa6234a155a07af5dd566213b588471dd", - "032089f68a4c095b5c5d4326166e088a61be09e04852042c4f21e82f87fe70cad1", - "0322315205ba3582e9a3b20502523b360ba0d5f2ccff015ba0b168a7cd2189e29c", - "0325c755a8dbef440c36ff6661a440f5c404f31b3f87f5d1b6ba26f0ec57ad4025", - "02297316ddfe2c45a4ac7a80f4ec5d6da91c719a1e1eb1315dea4a5c8364a4bdee", - "02078bd602ad6b69a8dc7b0381b9d73bf370c1483ed502e098209f8cad8e3a2f47", - "03192d41c1f505ea2f9d40ae195235a549cab0f53ee98f8a5d4ab4246031fbbf39", - "02107d15ac2dad79056fd56ec5e1bad736ab74e062a9a636150c27ca845e27d596", - "0207cd4d6751c95b79d811b09034852e23ccac11c33a3cb0f6aef8faacf5b498c6", - "030450070a0aeb78f2a172a6fac6979399228540515873576ba8d8649787aecad7", - "0308fd9569bd0495cae7bf310d296dabded242cf27444013ccd4401f32c59bd3a6", - "0318c4505b34483a5a2a570dcbc3e5fe91269ee1d7548f25d0f511f8f35a5f8fc7", - "0201acb39b4e71e3c9d94691bf66c559c7ab2fa682908100d4dcbe17d5f8df94e0", - "033038dcfab3fefb960e78e9f68b7dcdb245342b8d9659759f109315e2a88e7af3", - "020a995db939b9997fa2674c336bcaa09feb25b4bccc6168b354c66990bbece66c", - "031574fcd7090ac29710ec4eafa1c21a4cb6ef20760b34c5ad60f814fc6adc438f", - "031c78f033c908757860207b5112a379e64ecacf4ee79d0ffd62e2602ebdd62ccf", - "0317a8c184fbe335a1c2912470f05c651ed43f95a1fc4c052c51dfa846ab23b95a", - "0322ca6cc85c009415fe5aa13dde271db15e939fbb3b88e9a4f20dc3b60a4fbb07", - "02028ed6e68e15c674cf24c07cdc7e7ccb45adb129778474d6ac5981dc0ce93ffd", - "032080201c4a81221c0d1f602514928889076dbfd1650a00e7877344f04b8f010b", - "032cfef374c050e01c127dfdc4cd079c88233752cca94773cddc92dae5f518b36a", - "031e8b2df765b59edce702416c88e39051d3678938318181b1726c742e312fe6f1", - "030d595759f4885342eee6cca157f314d3a242d423e97f407ae501d909211d7a4d", - "020afef8631f5f0f1ebb4689e5869ad6a538143c0c2e4f20edd88bbf9468ac4b55", - "030b92019f8557ec26409fd15a0900d53458cddacc3f610c0f15964225727f07d8", - "032690d11ad086829060aa767d9e2ad78a37ea1a27c55ff55ea36c35300eb334d9", - "0307ee85037620d788bdd032bb81c7aeb6c32f29ceff08399c5b415a72403b5f23", - "021273d50f528737202dd35ff5d704d51456421400f010794e49983aacf923cc0e", - "022f942cfb5d3ed206f3fec3a468d5fc2e511701c86c74e394427486a3623403e3", - "022b91106f26dda38846bbe8b73598459a77055429f42974b55d44f534fb8f7dfd", - "03026377d2620d5ac30ba397610207b751b25bcd9f6b2a24d743cc529e27d95c6a", - "0306b554161b1c1359a23e8b4f5d14747ffd40bbf7586d392b8d270ae85af159c7", - "032e615af9e3318a910483caa3ff9079cb24e22ef636bdc58866aeca0312947bc3", - "030ba3b60bd21748c6113ea12880126a9b6d408b5e69ba1dea84327c259214d371", - "0318c1559be696e3315d351de4cce0ceb09f0871bb89e53504aecc1a4066540cb9", - "031b7e06b2e600389afb2b8657f15e8c9c672a0b0d06997763674ba31bc41022fc", - "030f0681c6f555a0b0ce6e419e3aca68585e076189e7d40ced7f56575c2b40b8ee", - "030b6fb1eb2de7b51979b984b81413ad34e3633d84dae8a7271c82e9f3779dbb74", - "03304d4e0e468c724a439eb534ca83cab322798feefd8b1e0e4b0412db5738099d", - "0215f66189bceb77bfc475b258e0e6edec471af92d9e9fcd0e058d327cb6e519a6", - "0200b0a104a795d815652ac1744c847a4bda0ed7c06e9d56989595819630b4fc21", - "03132ac82111ce7410d565d2c78592385dceb23895645223e1065513c4d1b92592", - "022aa250fb4b6c1252ded2ccef4c2e37f0e8a81f08649f874f4f7327acc8fb7ae5", - "030296fe01db807422afebdac977a9e62fdffc9c4704728389a725765809ebc6aa", - "02162ddaaacab76c8a29c25035fd376eabd78a2c24a4c55379022c2d7f5c9c5193", - "031ee76a3b98ebd99c23bb3f156cf56261ff1c1cd84c7e4dccb8c035af75d4f427", - "030be8ccf5f3bb627641d0d360e3feb4ac3dc11d16da05963e1a574d491f78c9ae", - "022bb06ec7d07cdd09074373861f639d9f925c3af2fffb270b989397a1d4156a75", - "020ab25aae8dd63d6986b9e6e174f24a4a77db64fc0e61536e425950d77c425e3c", - "02197782d1f1e82607f8ac5860cf549cbe6ed83dae41861507f958dcc544a92fe5", - "02129c6e59047412869b91e1c39eb0b1fd16ef66c9989284c9a3cf1b499c8f374a", - "0304c4e3fbb4ebbc9bf51999f5bc704ec3debcc3e041ace3013f091596f97d0eed", - "0223038670ccc1e6d503eba2f85fc49309c0461a27b63302890624c34906bafd4e", - "03265fddbdf35b36c4bd068e11c02573c0aea77a54ceca82ed63a909724b9edaa8", - "031bcf1fc332e2dc90c63ea618f50ed830fbfe449a2ea6f608599b67e510af2bee", - "021bfce60450c370d61e814b0bb0f8f26f3188788f0b66547422c04ed688541123", - "030a5e4a934ed8420dc3c42777c31dfa76132dd203b6d909562a30129e0e371e53", - "030818d7e22745bdb944d9de7e0a05a61a84e076e75d7b73cbdebf756417c79122", - "0208dadd1f158af622063a008a64c942b50cb4fb9f25ee5f4fb78564c5baa1f3ed", - "021e5f2840726333a33859a7234b023b5410aeed44a15728a28fb542766e7bb141", - "02153a5efed376a36c3d3d06c9a3e6fdc433bc309ba208d970bf6ce98f932c58b5", - "022cc7cfa112545917ebab810748b5ddd6910bd01f2ad5de0e15783ce96e466e02", - "031a39e20a1d40e8fb181719371c2b3ec86fea2b3ade0e1d30b08afcee6e2c95c8", - "0320b761b23477a88d2f9755de1fc777e470f31806a8b1fc7767b4a5df9b47d7b2", - "020e86989ce134722d9bda268006df53392f558bddccb974f3b2ff25324c19b003", - "02197eec2883576d647cd736c40ba260bc4fddeb6af4129f102067a4acb5c1f0ec", - "03034435ed0cc37be98575fb7096e55bb846cfbc41644cb7841cee7225bb84833d", - "022ff05a67d0360317411c1b6e1643131e72a8395ed6a832c829dd2d76903c0b87", - "030275270389ce0887f50020b090fb04869743276d5601f32e6e429f81a7d69ec7", - "03092889f7ab4e98cfc40bd28771b48a593d383c14393b93cdd83cece7b69c3ce9", - "0204c51cd2d3105749e513683f48103fa60f49e9da68d17a3048f6418b25c6acfe", - "0227b46252a702d73295ce932c8fae3a95b7e0bab87a925e6517942a72c85bd89f", - "021ad6db9cf84b45c8405e273b2517a490937775a5be42c453d0208023f7f407e3", - "0327803ccf24c63ee5537a539753d91fe518c0a17710be33df649af2c69f4d4ca9", - "0300abcab3751e27930311c547a7e0492b3fe98f816c321e138f3e1d6082849c1b", - "032ab0bddcbbf9ce9d93e38e5059534e585cc9bf89646beeda096f6d0d1aa655c0", - "02061483f8118f172b86c6b1bef81a1f9b2f07516f0394175d626a79d5cbe51f08", - "0324ce2e4d5c00e7cdab3e737409cd75712f3f2cbfff9bf0c7daf46f715bac7e4c", - "02159b055003ad5ed6524f2df1bd781d1293252539c60bf0a4af9d5e6786aa76ed", - "030abcc61bc049fb315c289d313b6e44772a9b64bfd0590051479fc82cffe683f5", - "02282cde9ad6759df1d02e82c51bd104eeba65b71855e6ebfdc922566b2b067145", - "02172bfe7c2a6d87657b600d45a5e03736090548f296da5e30765913ad8c5922c0", - "020cc4edc231598efd75c83328d4c90ddc746137a42301dd8c91bdf9f53cbca75c", - "031e32aaea0a09549b5f9a70038ee0cb57f3acf34ba4d27ab3f376b87695d8d8c6", - "0212450c51ee3097d58926c21bf6b77cb1cdd08f9ed7b7467c639110972f563532", - "031fdc2678a3356a6fceffc9690fb920fe23418953360e45e21418d710f5704041", - "02254c49f3f6a504a818b81492f9a788366c3f1d030d2a19e1c1bee777520591f8", - "022d52d3eac9ab1fc38912489401ba2ab143914d67ef7e7489423dae01f61993bd", - "032d187c1549ed981976699b125ec722ad16baa38868110cd6d908d1c68493ac5b", - "03020b36cb5841ee32964838a2a6ed040a1a3dc6372947cbefe864a52ed874e68a", - "021055c8dfc7605905c87ad377940a110eec41e3ecc098aed12b15389190dc0c9a", - "020be54077ac5bcebd299c35c2860d118502b377e210855eb598fde3f6cef14446", - "030faa050fbcf288de5177f373eb24f6bf06c171f2ac0dad967585b1903aff527d", - "031c15fc3490ffb0ac5ca93184006746dc96ef61b2a4646dbd6145fb3f45001d7f", - "031791b8452a91e7df82fedba933fc81b8a5de3c77b5b8349a6bd84420c80c0ec4", - "0324490da233e3205da7bdacbaaafe6a9128c04c5ded2abab2bdedef6c1044b9c1", - "0209ed90afbd273e387027a9a8f6cc69effc9213d17321eca5955e62dcb0e6f605", - "030261ed89673af38103c84ef7266930c272f83312dcdab4392eab2d7d41ded03b", - "021ac315e5e0277dca4ae766fa8797044afe9b38640a03804b842d74391e86fcc6", - "022c6f79bb3cd387cedcb51a5a8563bb0c9c583c7ab038df2648b8499ac725ca1b", - "0202c66292f4d939712435ea3d22b5b4397cecc469ae082b5ffe8b77db2692de73", - "030510feee29489acb7c4c686451720298fd7af976e1dcd02503ad41a6790484d0", - "0306802341885432c510faefc532b4634b9a207fd5e26d3d36f57429e15ec42ca1", - "0206512b709e761ba910bfc606d7f591aa511c54b3e9b596d02fba44b04beec119", - "02213a3ae4b60698d35a228b2fdaaa3e7588c7eecf5f72224deff678d23f8981a7", - "0300da83e8068653c1c87fba9e99d228835380818768fe6c6b0913f9625702073c", - "031a680beae0c3f962ac0e2a8552f86141298302213a799974abbc7e7cfa46a32b", - "03169e31806f48f7c32b019a6fc6ca58ab7930e20ab1a95a61de0771dd39f7e34d", - "020117652063935e2bfd38ffe42c7b7ea185a5189ec0fe9fe93970742e58f14ebf", - "032fded9e47b9dc82b9f10ff756f52a44d68ce0d65cad3eaf7fc9b7163148977da", - "031e1a5aef25ed05adb1419cdf8d002707f586e0b9eee4375ebd22f33ac365df47", - "02264556a191c250bba253c3cf07cd9add6ffab9ea3dbeea288a22d72caf3f33f1", - "022554dcacd90a52daaf57eb1f956f4c721a106b40ce7d02e5e937a2830c234733", - "030cef523ab45e88240460ec4b52b5ce2a1f82b590ce9168f2659765d9a86bb70e", - "0316ce512ba338f720ffe083e6210d729755bd090fd9943e7a47f9e41eb731f8da", - "0220d498763e077d8cf93e6c02cf2813461d38ff44dc49f47446dbeb260042a16d", - "0310305e5bc97be11464c123b70768b6ca956a8c49ac67e10ac3a0e9ded1574b00", - "022ebf91c527175bb96fbd826744e811bd3b3972242198cae928610c31b92d8a10", - "031869ba6e12ecb70b3f557406d3ec7a4f4a14d80b260ff2faa0ef1a596a0c1ac9", - "0321e1cd9cd5c2f36bc9cecf56014322da8db2d057601ceea84228b4aed0f99d3f", - "020e4ac79d6c4a26821d1295e2a88855730800e63bf0540a6db94e8db010d11f1c", - "0321ef1eb57d8f3081d324d96c5be1c1aa2c429f5f02987b1cacf670e03f94a970", - "020a7b47fec5b7ca3203fc6d3294617c933bd7146d7cc1d6e7310b71bb943af8b9", - "022cc2fa4e0fee8dcad8d0014c48608ae1f0ea01a679377e756e93e6587221271c", - "0208351f5b18958bc4a358e7a4b05d8371952cdfc39f231ec55755ea05fb2f503b", - "0309c3c1aeda6c543fcfd81dc0df95640dab1f22d1885fc76f2d49662f18a93db1", - "031daa52fc5c93c3dfa138d5a81c1511e610477c32387f1d6ee7d7ce20e843146a", - "031b9de316d05344dff7a7febd741f7c13d1a359a6ab6370a142cb4c9263238afa", - "021f3181e6e45bb1812021a5badc30209b1e7368632349e4950ef9dd599c32db08", - "021b8443d63a6390bb425b603e2c6ee6885d90041c813090ed0f4b78ce297a762f", - "020066c409715d5dc5de4613906acc0ad08eb38088da6c21464752704a98fdf69c", - "0307ff9a645d45d762c13e3d3d349da6804e60fe7d377af1f77d67368a95ac0e4b", - "0326e95db2363e4ec9f5e0b29933a4eef0041851e9a6bf4efc066bf6e3a1151e57", - "0215a77ec90638180f6a7e60d9169368bb7c0ce3d2be955a3750ee5f36d16c677f", - "0311ab9c72263a15559f6b2890ea2f934042a378141e44ae60883281717371bcf6", - "031b7d03ebae2ce0117693c7ca3bf7421ef88487d64dffcdcfec381b9bdc62af96", - "032ff0b7e03f90c7fb19456065405cc99d50c20330115dc27a3d8bd19c17b850d4", - "0303473a3c3272576424954ca48579f3661e746a40d64803bd8b059388cb17ae95", - "031bf82c2ef5335c7afb49029a54294ce1ef6c060420d05ef2dd56cb838aee8134", - "0219884e37b9b1fd0df9fb575a6de5e7879e3de4226648f8b26cd30d7d4d3fec8a", - "0202878aec6458b911268c1cb1844d373a84ded81408c8d3673f152b9bacf3b49a", - "0205d9055302b919c21746c4153c31a5c6762a984dd5f20922ab4064f1c53a6465", - "031bf457513404654ef8a31cbe16c83254aa0aec50f84e9b399c7d8ba66fe4f3f9", - "020b1d14ec1f9948a35b05ba6dc60754e55135f00c7da5e6412077b0561d54b4bd", - "030363571a56a2625e746c5533690e71bad5f60246f6e205c104a9a8f44129b50f", - "0309b7b71cfc74bdca514c76f58e0bb1823ad68c04664693e2f3f8fc636a2afbb4", - "0321256bd8f222561d70a49f5510f5bc8887efa542a4024562b7d66603ff85783d", - "0220fe317b40405b3c4c5800d3008c6d9d351e9904b869b31b0a3e97260138b9e2", - "031e9b81cc504c1e282fef4773d1972ee854815d46e151c783cee9d8a1dbb7b48e", - "020f99928f042b219e44cdb6ab7db6735437f3a976529670b9e987b1efc9737777", - "0312c06cdb0e9b17a0f3809b6303560a228398a3b937dc5c97c9f7bdcb0914c237", - "0306651e847e9aeb5073d79bfaf50eff7230cbedefdb71aa64c5fb67ebfe03924f", - "0206db95d3d4e0612ee9f9dcfb7837328b9ecf41ce1352fc0a5805e3a5f8cef1ad", - "0206af0c2b5e53f092c3cbef007eb1cc4c067c335e69de54decf410e6ae8a37f07", - "0325c5db81a8c646e8473a6aefb51b1634709940e062a07245d0f50d147a320302", - "03130c5a83664dcd01a291dbdb2448ef7b8612ea835ac5a3509f20ff0968c7fab7", - "031ab4196f0b8716998f7c9167327b2eb8093a36cfa9a25df8208847c682e24051", - "021738dc1957c22e74e8176fb56a3581d09e1b7d34aab2c4b768a0a76d10d2bb5b", - "03207d99e8642f94557ac80848bf44f4aa95975df54eff9a18aebe6dc79b511ea6", - "02269da5a72b6a067506c24ef83b59aab6f1e3bf4ab474d76e1f932b000953f4d3", - "020dcc01b6a826aa3163ef0b2836dd63956fbe254c9c9ee8058027688f23665164", - "02141af2a8ec6ebe0d2deb4460582e3c2d01326d45c97de4099e5171281782e828", - "021f5a8ac68a7ba354e18efd623423f666da2a8b417a97428a2d8cd684d11b1cff", - "021f50cb5882c9de82fe8642763094d9b5962bcd461d9fdb84915b3918c97605a5", - "032438888fe551f9c94f662bd49c71aa2e8c08ab5d63d823abffec0783418a2a06", - "032e9f94b22b9847f68d585949d27ae253e88af8e74214b4cd07bc0441761a1b22", - "0304b8c3ee50f31300a3a64025c0bbe0a0de3a0fcb5cb885d02b8184f57e575deb", - "032fce3e89f7cf04a061ed15cab2f3ec9dbe41279005d99171c414c4427b34903a", - "031385ce3fdce1df31ff7bb1d82c77fd87b7431b40ea7b021c9f4fea17efe7a3d7", - "03227d0bab81bee2768518603f509da04bf2ef3ec55eee30be375352830ce50b8f", - "0201c284c4466b95ab759536ba5af93fec30afb13b7caf8031ef3b585120d4462f", - "032d9d8d6999ad30aef039c5945c8487e004de7d654cad99570848879bb73d1ff5", - "03218ce510a8878beb7bed7294d555c6e54cd79e2b80b9b8e102c3071ade063f10", - "02211aebb7cfd002b656b0c74073eb018561cb81ad4b11c3e900c3a0d0889d4ff8", - "0322a810934b1b82fab027d3ec287e6412f547e75de6bb4cf081dc152924b1e456", - "022ffcc70fcec197e78bb5cf472cbeb4cf72e3747171d7fc2e8fbdd08493f648e5", - "0215da39a772689b841683954440d1206bc73358b3c63afa205be71fa580fae167", - "02303a20c8500abe2c42cae68f48aa2c48d7f0e3c834dc0e1f8230d610a65c90f8", - "03025c0fa2088a79891e9dffff4b5f4810917deb19fac404ed681f1116a25d04a4", - "030fa3ee57b5afb97707600e7a9da0292127505aa1b8d880694bfdfc022296931a", - "020c9c3928ed284fa40bd56ef15c6b1dfff895965a2636c8aeaa22934291c43efc", - "0224773d0e9271a49dc6e63087d86b18b2f60b876973f1245455aaa11a00efd149", - "02079c595382d873666f5d25382168f8c6320f5d62323ef3a2314a79248894c040", - "021782eeb07d0eef142db7edc7950d8a27c8bfbb5803ed791ae88902ebb91ed580", - "022a3bf6b764fcf83ab3a0c5d56924d5fbf6661c8fee5321c4fec089cb49471c47", - "030bc050e52b9c03b09a8a37871048a6a6bea3acb0c352963d39dffcbadf0807e8", - "0302635bbcf19013b268eaacdd82445d264fb2b4bc94f011f7a0a12f8ecd5b900d", - "021f57fc7d22eb26b9ab181bce56546beade2d1b84104c5f5e64ed0c61949025a4", - "021989dd288dba297537f578bb510d5a7b4fcf72a8b79289579285ddb5b3e32d49", - "0216c075570b532a281d26375a59b3bb010b7e97bd20e1623164804a285e440560", - "02191e440e40985c653c48b774f64b5f4ad0559c0eccd3b6faed32bb3169350391", - "0215b6eba63096518a71e5b9209db9e89e3b7a20ebbc0de5b776a306c9b0b7731d", - "021810f36b764ac22974c8bbd9c52474a373669887b3baa933981844bda68cb7eb", - "03006589dd9b98b4d409ad40edbce387022e224b4b958dd2e05e5e7bf65b131b80", - "0304088707503b5ddb1c97b14bad363145e11ba96efba0027a8ea2f9b59f79255a", - "020ae006d3248056bbfe3a0f352f6add36266a40f24b2dcc27e66caa58ec157cd3", - "020c65c3eb010a9e44c8b0b8e1b4510c367d6e30e296d5a7be6debbb237085b41d", - "030ce090a369a342bed4bf1cd2518fdd004287e3f92d6262a19cd97c94feac61d6", - "030892a6cc5b875c8b58f0e93801ac67c3e1c5fca9737baf3e532ecc748574e1bb", - "020640cf6b93249e7a41998fb8f4762381d740eee3a4b89b185e51ad23c664d799", - "03177a5ad2c7db484e0f12cac32d8277bc0f40a4511b2f20ac8e045b2d9b482a0e", - "0221845f6246624950460dbb487d5d2ae524362e22991b350d994a34bf91e8aa9d", - "0330455b72ee706527b3861091cdb2aca5f323530013a9f623bff3cbb0200db076", - "0308e6ee5e99ddd1331564c0684ee4fa6b6ddfb9713053d60c95babe5ba47d06c7", - "02142710dd89d41c04d10d03456e1556e56cf92dd94055e9164d80c4d12971ee25", - "03044c5e6acf61b448472305bd04e12bf27d32b996e2f50240fdb23d31fa494464", - "020f975a62156707166b39a4f7149e60beb7f20a6139dec97ab44bf0c21a814ee4", - "0325b0e705f07fbe75d2b8ab2d108aa4131bb5e27cd01718c5bbb4f5820dffb1c3", - "03271ff3b10dfe8b6c419ede129d053c028391727b3fa49afa3049602ee1d153f5", - "0307fb02f4ab3c9bf341fb19bdb05133e517642cd01d40b98476faad616d62be66", - "020a9da6ab0dab1151cab978519f70a2d310ba92494955c13a5cbaeeff90684fa7", - "032e02853fa0a8722d8266563f0924da82c33737fb4e83669f39112cde568d8718", - "022b54a2962ae5b6e18aaceb431ab2fadc3c1588f3c8af7fb7df10357f11e8c0aa", - "0211d67bcf2b87f2e25ee942c06e66de99dbdbe45f5ecff6066bcfb4cb308d5f8e", - "030dbe7ff6225805c792564ca3dc1dd6fb629f493d527fc6193b2a475ebcf98fbc", - "0307a601f5b4e1915f6eb2443ecc431512b170d78c466263cfb4bbfae46e9c6937", - "022c723c3db03604d636703088868cda0f140853e45740c7ad65c5394ca6bccf2a", - "0326a13ec64516ad271af3ca6e0798f16ab7f0ccc5e09ef2feea1f3b0ae23f62e2", - "0223bb35883452711f0dca3812bf018163462a845d0082010d2bfb7e6bf2cf9c2d", - "02251c369af4d5e8b4bf4ef2e8ad492ff684ebec1262ebb1dc83052519c5af696b", - "0317a27982cbc674601a41a91d51d08c8f61f95ffd5b5c691f48a2979736f05f7f", - "022e8977b1977f3ea85394d53639ec0a9ab322a357eb84587601c91734d63d9ce8", - "0308345c38055ca4c540764232f8ce9839992b9d322373ac57c13a225a767ee548", - "020b2b8bb6948e300d725297fe9b50193b8b2bc0e8c0a0103f6a5284bdf5e590b1", - "022f6e88f6e59792da0526ff98f6c4b56447edef695c9910e4c3aa67e1295d4e9e", - "0204ea1727bdc7ddf6ce25c87d2d67c04d6d1800069d52300a4f42bbb877efb694", - "031a2c1dc572248b6a3c3c758951d99d7fa28f3f44e08da797d0f09eab221c40d8", - "030e9c0866715656790ccd25646c73c46cfd4c7fe49b21a4b900d83247d596db78", - "03182028a0e02bd682c2c55dced243592e14deaba034bff9e1cf47e5f5d7106e09", - "02216a889a2e552ae11207ad86ac2ad4de875b8615e5ce185e6f1982866b2bd177", - "020377dbbc640becd4407bec67bba592b2af6018e957cb756fb3f86dd7ff446539", - "021ba2fda8d5e261a74797a31e6462b18b59529ff2a4eb0841a2fb787ab1416259", - "020ad074c7521d93e4d561c38e76051b0e389303853bf0ac419c1fa866edfa8bae", - "022cd2404650f6f9a5ef18b16246abd85eddb83b0e3a75dd1185e2e86e729bac44", - "0321d73d74d682e7def78dc3f6e2acfd5f78e9fae3fcb3cf8767d85661f8f0c907", - "022a741d93b033f49b7cc947d71112bbdd97fd766fba4ada75990420c739a094da", - "02178ce971ec9bd3819475ed2eade91f3e6b808a2531b3f9289ce861529db2ce99", - "021aa7c41c6c57917de97d257ccba4b4d917241de9dfd4cb4c056f4eb6f7c63924", - "020ecfc66085d75194fc1665bf2040ddb2591e42c246f81b6ba0349c4e8f121c03", - "03119195881720bae8655dde41bf7649fd927d47a188e63f6b7f752fb7b463ea9c", - "030e423a65dc8b6a94330e7a2d811c87e76b3f016418b4fd22eab00ff520f663d1", - "030794919c78b07a900897da2c3aa9236b37a4d5c5527ab7e6d836fccc0fca8faa", - "0201e7568bd6a3ec9cadea409c11e4188e98968833890d3f452595dc30cf2dfcf0", - "022cb4188533df90ace5d7aef1f2e55fee709670c90bf8a0599f550831d0dffd5b", - "020f391a52c4a7336d09fd3b1022a47a2f3d11396a0919f034f98579ae3f9c6b6a", - "0225fc1bb1cdfca3a0b95c55629f2d567724af1923b0d582559cf17276340be223", - "020910ee3f2ae91566147f542e99972833e091d2f3accc22e5392e163b5d754790", - "032a8ab28acc3600a6760ccc6c76f195a5bcdf19c4ae91a628751fae49d250e523", - "032a03c1b8115cf08c64d430654851184657443eee0b6e731ba64c831997a7e973", - "030ca0ebfc5c852984663afe1c0f6c569c9565ebc35710171024e0af50f5635f3c", - "020aad0054309fb352cb8087b93928b85962f04018dedf04497f4026ba32482226", - "032c836ff44d5406fd687c8185256f65b9a33ba923be1736581fd4e63e34e1ea90", - "032e146c42838ad886d6cec0f516397c8dde3b58b7ef67081c1e93fd767c9f0a7d", - "03008b6ea8d35d2be153e1c7b5c08ab943528f93e0675dcf6e914e103398d06a29", - "0314cc962af8a21669e1d7ee937190dfe79b582dfcb6ead6a0190ad4c55498780d", - "0214ff1b1704d3b61048335b922be83909998bb980c02ac2b946664cb756a697ff", - "03275caadfcc5d14051cd04107173b07d19a803891d698d4f496ea57766373cbbe", - "031e690c3a76228b75130a9756d6723758f10c185d5b6368d9069efe13519e63f9", - "0216e954039626c19eac7b559595680f453438c66eb523a24a07cc03847d2e6c9e", - "022d2d58858782a89803c14da44b7d2272a116e385092b3a3645b4e5e3252ecd5e", - "0219bffc9628d8868cb9c63872d83badd8723770cf87128b05e11bd7b7a1dcfd37", - "021b526f9999dc2f2946083a1074d18a38a73aa0951ab7035f1f6056999cfc65c5", - "0204ba1f80c9a2a832abdf5a1b7005ab175ddc811ac84fb33b4b507ea56db81ee7", - "0309bfcdb4876301659cfd9a5386157c0975f44a9c034aac47bf7520f66856f42a", - "03259e68f005ca904946a88421dbd3b39859a22a4c79ee86ca57456cef21d22b6e", - "0300c71aa52ca010d4fadfa65c05cb7f098e6a4b367b2c496ceaf4c2e98fa45f97", - "0210cb31c3f6c9dc5d6f42fa7005ca237a38ab80d0b5ebe2e2b84a29eecd161dd9", - "031e080e821d7021bef3f891bf6918c7cff9128f7c7509594626a4d5067e52bcde", - "0314af630d90734ad3d5202f7197f124d3a17503a11f6c44b4a56818c0d67d10b7", - "031abd6b92c07c269ce6e4ab2d7d7d2203b78c7181f7eec95673f445c273dfacac", - "020641b9fccaf7d6d40394768d800952b54a6fd279ce6adde77f21c3aa1cd4f0ef", - "03277b470509e1e7b08ef64e8a2cef664a7695a58926090fb534767d3718925bdd", - "0306a7a573a1965659383cb7f3cff2242a63e21cd5776a5b43b9c7cb0c0f18dbb4", - "02085928842cbb22f2475280adad5f24dab5974dee70863a16a332771e9124c5cf", - "03147d50ce49669dfb5503cfbd31df8e1970fc265f05ea6aff165c58b66fa70d4e", - "022f8ea7786289b07af24b5b0ddd174f93213b520e58bfe7de6eb4ba4222f905c8", - "0307a816bc7d4ed0cf4c593cf72d640e3a4a6a9bd742d075916f938888dd7cec43", - "020aba99b5a0551c7e0709b19288967a7f8b67e8595dec06040a990301edfe275f", - "02282b040e4d5cbec03d0fbf0e9c1e5127393cfb89ee1ea9df55bb5476cdf98a8c", - "0322df96daa39945dbe139de155f77096a3e61144576368d77cc9beb97dcbe4e10", - "031e95e69f0236a06c4b8ef64d4713648102ea51afc64c9b9561e1541a6a2d96dc", - "030add14d15c3f73b1589963395ddba2c7d73944b6748dfad295969513ef70dc39", - "031df395354f93ed36904d0bf33eaabbac00e3e460d0338f8166a8079a2aa5b4c9", - "02176fb45b6a287eb09b5a01d070ec3b5918c61d9c031814812ad98397257270cd", - "030e63f93c401b8925059ce8d0980c3753b3d90e6715f9190c6d78464b7c3cfab6", - "0208751f0d842d4738db3bfd26629012096395d335f3fa7e41c287ee064b2ba5af", - "03090eace15ec033989d8a300506fe628457d95b008b73fc67991efabe83c5969a", - "02244027d98729c2f875fc9015f6fad02aa181b068102ac9ca42db77ac0a45fc01", - "022edfb1dcae6bdee39b60ac7c9a26568b3d3b634a3f59826709fd47497bd2aa62", - "030e511b608c6bb7071a9140c818a0899ae6d4f848c39ade8e2e94edab8868609e", - "021cf2bfa69519b42969ecb3a3764604fee0a7e08f4881208cad2d3a3951403278", - "020e21b28c07d22381e4507907503bb1457f1b0c07ec49b0b41e53dc6402766c32", - "030f7a18f1cd3aba7188537354e5beef2fca082ff5047a6b9ae36abecf9fd00126", - "03112a835333cfeeed7820a6fe326a583fce0e9d42ae4a11a24d377117754dc495", - "022ecdec9f2c64248348ebbd1e4de3ee2acfbd5e0670768e206e8eaf52595270aa", - "030bfd73295590a66c9f8ce5d887202d37cb4747e99a3980b481606b07b0ef23e0", - "02190b87699eb0d4e003d672244a8cdc06f93520c729beb2ff9146092f6dd89ee0", - "032b8424c95b39200c66bec6238f5438ed4dcd442ef146a3d92a447e7e60bf4dce", - "02120b92755488b2a5fe9f65d10d9293082e4365e1631768409e77b6daa36ee156", - "030d430d787e0fed12889f013b012787858a13c16466e7bf12cca3433a31590cb7", - "032255aebe097bdb7d5e8302dca2792c07feb89cc4055cc614be3889c7893196ca", - "021937a20b18745a685dc70de658a0f8f9d3ef266c62d2ef0b4b78755baed7d2c9", - "030a35e6f059e13cf48d0ebeb8537cc7c1faafb44e23b70fa1e0e1ded181b2a3f5", - "0307e2c7b35bd6480cdeecebe63192bfab92e245bc89f1e820753a37a5a2f33510", - "020ba6e079d58a379ae4082d44b8e1dc6178db0c2af3e29d8ec6b555a1b77d7e90", - "03128923daf088ea9594ae89d546cc855485febe0a8b86309c15a888737f5abbe0", - "031437344e3ed66bf46db07c9e06adbb9fd780099881de14156f7b34809bbf8e44", - "02212f3edc32c812657aaf49dbbdcefbe34ef85e31eb185120b71f9ec1fc7eac95", - "0226b2141330045c7ca35eb304e415325f83f0be1d314a0dbd0a2ea757984be44e", - "02030d7004f1efe823315c27f06fb644eb762764f03cbc6f24b9e895eb4a30b639", - "03277259418e0f5ee6b722a5e7347bd8662a67e3620c9d098e852d8553e2e68cf5", - "02071886e8cad2438ae2885bb837b7e64e0c1374369b32a862f2e3397a526f0c2b", - "030dd5dd52df1af69c1e5f75e848ea0102add24eab40a068b826b5982580a02472", - "021cbc7a0d660b5ef5ee535b2255fd942ef455ab8a4486efec9ed2f367bb76fc62", - "031ad39507409107992df278063efd4c270b3564e28dfbc034bc846dc29fd6de57", - "021f4496744b44e05a6f4c634ee533c3a22648775c73df028021fb3cd0a2b3f15d", - "021ce69cf6cc8628bd81c49d25a5ef83cb41eb9c1faec4636b004018afb5f9ebab", - "032aa47d0303869600bbcaba2215956de0964c3aff59a904e4cab224bb39aae61a", - "0214f8f9852c8f43e830965c171bc69b4f02874348b48447e6306479db1c48363d", - "0328f647fa6ad60ccfcd452aec80036825ead184711c4f650e9e0652b1a1ee16fe", - "020da0f85c0ca1691bd1732afa1fcedf3da60d8276f2e13ac2d68518069365ffd0", - "03088e9c3d9de15bcbec822676b85f98b7dab0fd29a3a995cdafc8bf90ba2cde69", - "0214b14505c9338937dc2cbf7b780218ccfb52d3ef059c2cb3e1c17bf691a27736", - "032197cb6cfda31d6ddcb294a6def022cb834a29fa8d29a48d94db408e1f0023bb", - "0225990ec8b93d0995d5820e8fd72a2db36f0b2a362825e431901d4fa555fcf483", - "02063b5a9416341dc6fe656e5b38b2f86b3707875601350f40f6e031bce584eeb8", - "021a2064bd2fa5ad456b16e5b179f2122f3f76b6e8d65ce68f5a0417f3db9761fe", - "031bb5d219142cb2b5d28bc75561d21378e7e9df2ec15dd8262b062e24bdc44872", - "0308434b6909061e2bca61ffae64a4e8495cc5e182abcee065429a30648ed3cf5f", - "03106c16e0cf768b0e315ad89421a87b33f6f1cc7b10f869b27f49f4653a6677e1", - "0225f6ef3962e2248778b0d269cafbfb5f1c16e7584ee7a6ae37d849f66020370e", - "0214b5230bfc3530c1bdb731062b03a8ca0d39320a1485d07274af74c8255b8d76", - "0314add86c8943d3955ba07370f653b6056edf06824d4b0e8e80e22823c63010da", - "021f57e66c090a0bc33f8ceec6acb576d686ef25f76e7db6038f476eddd5c30bac", - "03216271e12099e5fd2f291201ef6606a1b89d93088ad5e135c1be6754bfb712c7", - "030a79cd351c0c4021dad3eb661129497832e20abdaa57bad3c58c02f4f4b3b273", - "020b6f5f8c7ec6bdaed46223593c58d26f3b681d018b9a7f484aec58829051f112", - "030a15087746526e0dc5bcb41c8654507d6d93dbc315b2ffaad04e8246e2a6ed22", - "031c2b9c1f129da7f84e6ad521da072b1b974b3c1d3f7dbe859e90453149154acc", - "031ed8af919c9a66766a4ed451b69ee2f6fa5eb8730edcf5eb528fda5f5171b824", - "032dc7fb54fc03291341e91ba003104aca3c4186e8bb9b8e906187be3dda8b8db5", - "032642ffca902b4979b001c7a750bb81d924e486d1c85087ba82029a47b4d520f6", - "0327d57f866e45a841b01b9311d089ef433c2a2a85ea4d988d855c83c8fef6a355", - "021ab6bced2e252b2baab0e14afaa3071a74e18837d206f809e4b9a67f9ec4c0fb", - "0329e666f40e2b15074630d4986d770f6f36fefa14fc20de8c4d1041cd731fd4d8", - "02012c1bf31365af24bceef9f665e8002afb9f055e0fe7c90090c5d8e0035e38e1", - "03145683241ddaba121adbe7936e544914db972f3423774fe29a520b56dc9ca7dc", - "020259765f84d94b32ab4c1395416a93fa77fa69b9ce9216a51f8b8e1eba0e9cf8", - "0321287dc32325d362b488acf83a7014e73801f47ba063633414d035b3f76a6a6f", - "022c601c1dc72aae928c79eb5b6f2f4820792206ac55ac822aa0660f86cf780356", - "020f797f8d334feb8929c3cf6833787fb9432f2853c05036b4e02c9a15052ce63e", - "03106be1c705e657a4475b676cdceb8682f17f0f0309d9cd216e96d16ef769d0fd", - "0229c208d534a2ffc6bd24ca8023ca7ebb89972c9bb3795c4d7bc76f4217192250", - "022bee491c132115c9a9a9afff9f7f0bfeb98ea03a155c05ccbacb430ccf2f2cfd", - "031b215218d63460e13da1f2139080f1df792046334639f5cab0d1124f54219631", - "02216573a5378f7cedca2be1b04f5f48ddf6bc28594a39d067bdf27966e1d5ec6e", - "03210da06c5a31ab2e1095a8a72330d0236fd2e162a8b34ef2aa4c000544442ec8", - "022b60982df81c14f7b783bc06206c94a07fb2fc1021309a4650a4a6ac41a793e1", - "0213b2d2c95365a2e54409c9fa25ebaefa97220ba27b4c5ee00eb0cbf1bf7e029e", - "031d2a4212c4b24189def5f3a03666939fa1351182bd8db554934310891df2e729", - "02298294ce6a4d52e9722dcc154f3cf018c2efc339aab63f637bdc79fa4817e970", - "031fd07e718c2d157ec84b2b2a69d77f2fd5f0e9d2ecabdbedccfc96c93336ca7e", - "032573b6c835b9d6e8239e3489f106518136aa73aa25a955eadd9dc35801b11399", - "022a6a2c6157e733645bf6ba032350103818583cb04d4372d539f787c88ad072df", - "02152164dceeb3694cb36de496e7cbbfe84404663b6a9ff85b8efbddc7daca979a", - "032bce151cff3f83fdf5807569f8ea19441f38c881704bc04d82de409358c63658", - "031e866f8cf9c4007a35b7cd79165a06c8bd004368a3b797a04f278f780f275531", - "02270d4df29b892c3042b550347e790d4acf5a0df0c5bc2441cc20cd624a64ff40", - "02094f184fe63782582fd83a75b17c0e6bed092927684facf0a443dbf28d87f5e7", - "0214f7cad17070ce07706ab5c99b6a0ea9939665559b761c643604dd56e686c9f3", - "0302dd4948eeff31f61f9cb57f305252dd791a3669bd6f92a33d93a2f2a6537dc4", - "02176069085743fa38c26265a7984eb228cff3584a04889b2e6b4e21313c7bb91f", - "022cd6dfe14e0462cdceb6e0bd43cdc188b6d008ad306f68802e874e49cf53b7ab", - "02199e7be06da4cf097a20c3aa7cd8e43fe4d04dd7cef2fc0397ab0d81cdc54943", - "0224707dde39fb5c9d1b6c28d85313786e2b479d3375ea5f67e890a8d3cc165cef", - "0325274ebc45636c4503b3f2d56274dda22324291c59e989e0478dcac285c25c8a", - "032543f3b9ef02c06fb8a66b2c6f9bfff361ea60e6689a27b59a68a022ea187de2", - "02094d6f2fc6a1baf5a9e5bc157089607918d4afbf5f3b01da84959dba59cfc337", - "032239b5b202013b70083dbc5c681e477ae52214265063f46d39c5eeb8d91b384f", - "03234e635de13601306a1cc9f01d2563e4fd2179b392dc2f2a46b1e2ba1e0d838a", - "020555435a3be24086f69a57637e331f1e7d1158453c021b65474e8df82ad7ab12", - "02058410dc21bec6fe07ca6aa590dc6982f539d547d719fd9e71d472c2eaabf696", - "020e420e5a4f85a9e7852ff860d0589c602719f45c88b8a72fb2762c4985f96e26", - "03230be7c3a9f53e807b881cb8374deafc383655b5f3ce6f34d187b6aec5ec933d", - "020b2ed87733e521f4eb01cad393027c2fa763fd6d87e436d830cc26f5971c928a", - "0315d7606cbdbb9c82cd9d63b65983303b49446810af4c28ae132e33c0484d9917", - "0304b534fd57ba21d48860654f17eebdbaab5a42eef5d63f8cdc07f64b02f97bab", - "0205cc1297188fa316bb504a88ac1f8a2e11eac7249119effb7caefee9ce4a99ec", - "030d98c3ba510c73fd9ad80695fbd1402f85da27a4f0a60550900c159231f27517", - "03060947b5cb8972bfbddf8e5d0c822c1dd2c73936a269b1b51c507fc3e3b9af21", - "0315e13b18cda9f8114445193d789c9eedff19001e423aad70c61c9278f73e27ce", - "022ad016d5f0fb7b282828102f5dd955b5b979398a7e35ffbcc0c14bc8b139bbe7", - "0209a2579bd3d5efe0af7686cc733ad318f54df179c5dc9103c889a189f28a35a7", - "03158e95901cf2e7467d2d8b353ae12255dc48563c4241a398c1a540f4a6c77ef2", - "0322e5542b40353f1169306c12b607757632df614abde56dda660036dc840ed89e", - "03193e62b8f68c066c053b49b931f02ded794f2b9c2cdbdf60847fac7f0868c40d", - "032a12c83fa454694b23c53a43134cb04558f60ff07514baf25bc4928b2cf1a057", - "020c9c6a966e800c7df73db9384f1d24e43cab56818d4c6ce5ed313f427f1e0616", - "022e958d393807ec6cd743ac9bab838d5dc9db4b2a9be346a6f0ecea85c422b0a6", - "030a6d1b2591e4138ef102d85765fc998726339cf0d0cfd083cd775f026241c69f", - "02011f127db39e9a420e748413aa51d3d48fa3f1e1ed913a246f7af91bcebe2f8b", - "03182738047b97c907495265be513129a7296b494b0aa73c21063d96f7edd02d9a", - "02090376a6a4493b134c0f58665e3a78cda57ad79ae8b19926a6d8b26d62d95dc4", - "021a9367b3e6f450e8ab179ac8a5cad9b98d2ff9271a0c86c1632406f73e00c7ec", - "0317ae289efd6993ca42c941c7873d4f91c5863efe6339261e41bb115d7d516549", - "0302d7ccd2b39b5cbcbb454960d25ddc991ca3107423a65630815ab9bfab4a2630", - "022d1f5200235f62a73b4d9a2e56720f1e0992f9e0a8a5a5d72e21c502e7b8b652", - "031f6a4d0a6bc005b4081e852fd7f159334aa621d209798e998e5bc6683a3a7903", - "0314dadd12e93063aa341182434442e723d0d1ddaf8cc31993c6bc2270329d6787", - "021e106d8d40c32e1b1d087ca7e654f04866e5d9610882df0043e4bedaae5f7a1d", - "021b8b66bc925bdb498a9d6be7a32da988306b68f2d8090a2487e611bab5ff7558", - "021b45f07165bc03f3fdf776f30d7a1671dd42f7106ebbb68b075d315508f3e367", - "030ed0f42c3ff537df3e49e9ac305e6aef3ba115034a9e25099aa08f25976f6fb6", - "021576fe0e197ba86b3c51bf51560fc1e53c84d6ff738a98155ba221bd7f55b12f", - "0213590827de6b89267e70ec86d5b416f402337f79ad98a3fe005c8903d56bbcd9", - "0303cff2735d301b38edbeb38ba6f564dc550fc07c1ada6a03755fdc7e69b7f0ce", - "0223cde427f65e0db9316c0fb6d1681ee734fb4bc94074bd783c7ef1fc272ff4dd", - "02053288cf248980052f0d67b5f23dfa256f6a3afc8042870de175c165ff8eeab2", - "032f6436952401b5dbff35b2f6fd7566771e9e63c0c5ebe29ce5424902bfb0508b", - "0212294d2c983f92f4cf2bdebc6e5f25983e09cf6dae7000ee3762e217518acffd", - "02260c20474e6b6fbf15c7bc845657bf8360b483e3673bbcc4d7192a9465e66cf1", - "032cec49f499f8fa2b5295b89663364776cbc0e346f9a8ff30a990377b9e6236d2", - "0300d6eff74877f9606bb62a26a2f09013800d009f105dc052ba9990a78154d2cb", - "0325a0fdf741b534fad9ceed35425464a114808013f1cfc67a718df3a74db5cd43", - "031a6fb1a2b998ab13f6a97e356a564fc6a93e39be19a7fadf9cb05c1dad63cb20", - "021cc6df63a31ef3e5c703850712960e2caa326d34419d87b6d421ce96a3d62e11", - "021a36d0cde377c6292586f589eec93fd4558f06a0e0d837aec5c8bc60e472faef", - "0202caa081220d8ec3639de8db06a162ced2134a041074a56f93e6b39ffa5ba07f", - "0303bfd50a650899881fa383a6737774faa978c086daa965aa5cb6181fd6c54eaa", - "0326635b0a32ffcb9c4b81f004428fa004ace1e24d6b527704d31c01ac19f30ed1", - "032a93c97470ce70e43b05e0b867f1f8a3e3758b77b84f93574481bb5881817dd4", - "0303314099d139e490d8bf84011dc2b1109a64cf17452af22efd7b8c0b65af2958", - "02164fc6cdfbf33e8caa4c952ea69f60fe015c7abd1d699325dc8da8264a592742", - "0223784f00c92264dbac810522ff64460f5084b0b63e975e9e19ebf6026fe1a9ff", - "0328505cd03e9199fe4e03022fe65e3861bfd0e70860fed022c7a8d1982269e1b7", - "030139963c7c62f4938a692383b44b0636da7adb89c1d02ad433b492ce5a7cc057", - "03094ff7f333d70885e45dea4e386a01bb8476797b11cefec0d434047778c5dfbc", - "02017c9ac8b8a5594db318f80807a29c5e07a4e9b4b9f0333ddc437b8a80cb1f57", - "0308c2937503b853310301be03584834882503952114c6a7429f54b8ca3d0ec1fc", - "03266a970c622a95e8dce3fad6bb00cf4697ddd329c434b8939a761709aac884e0", - "021585a1903d8282d9591b71d223613b700f09981f56793c50b325be2e6b4d0f41", - "03006a224c4d0de89c2acc4343097178f0867df44de6c30c7213697ec4e21a0057", - "02043caa7e03d41d56ef56ea46f29137e94af1424a0f8b2d7a848c7e1e8186cea5", - "020cd7940c928c3153841d8257340ccaf46e8e705be602f252e2b793ef4206857c", - "020c48f163225bccabb649cd2a9737f08aa7f406674a56d98ca4d883e077382700", - "0329173215116c6e1de98b205edad4e0d703a6e6f6a70944e2f66aaeb5ed40340f", - "032ad91a702492fc06d924962ed0cb7e53525a9df96b5f6bd5bf9375909bc4d8ef", - "03129d7c97c231c5524ac2ed57039546ad97f1da2e8a815c9c0f32ed5dc5fe9448", - "022635ea0d76507961dd8ace902b3815da2b65caf253983f3b80b05c4ad30a545a", - "03152b3408d784efd58bd04bbca0fa7556805740fc9101a38c9cd3af51c6bfa726", - "0202d6ae584fe6cfe1d68efc509bb111e263069eff9364fc608673b305e435340b", - "030fcd601193517b0aa618b0742b6e8c2510d5799228276fa373f062744bab589d", - "0323f4be9d6dbdfc20b681c668c3d8ce3bc11286cf02077b5d937d28e9236bd9b7", - "0303f16651697561e31d544bcf57ebe52d09d3e0421012015a5fa386a364f8ae98", - "02149506158c4a83b57325d8029e4ecde5d8e3bf2cef84e0482e294d38abc382ce", - "032488f7946c411f60fcff243b39a16206a04ed2061666be704065debf328c7afb", - "030207084f3a40fca0cf45e5cf5773dee5a5cfbbc700dc50aa61e2774edff5fe25", - "022f1ca6c0fbf79277632f3cb095b20663e37d0e2cc02ff440188b1ff87c154c77", - "022ecb357ea000f912ac373cb51554039a89563411e3fc7611669533404580a79f", - "032a8b6d3cb9ad18f477832db8408abec30f816e4e78a2ffd869e9981e893f1dc7", - "031bbe064f9a2faa1dbca857b10b19295344a1d8d577b7904dea14f0e6d469fbc6", - "020efffff462f7cab5da28367975a62d8b4698651bdef22b1e64af0b9ccf713cb7", - "03138c5e317579c92450da941b28ead69d4fa1ecf2fab0d4b385e7b824436adeaa", - "032895dc60e91624ecb6178db4b52890aadb2bae22ee0a408461e91543c5515959", - "0219ad230d258758a399ebe295da22826bf9460c7ab4cdb2cdc9be253bf577eb72", - "03172cc38d1e104a326a611cf2565d68c9217711b0c9d79b5708900f3d2302eaff", - "0220a0408f1eb12f7cbf571c4a255ccebf3976855793f8c52007621e1f05ea8658", - "0215fcad2868bbb47aa3abd9b25e5b0e64d9995aa183c12f192d53d03e43656e4a", - "0320e7472a38b69057a4bfb74d1a47eb04b13b63a244ef064d3647bdb2b85a97dd", - "0327e0c1f78e1a467f27c1072e9f492fe893aae9811d607196e90d19738cfc509f", - "03251cfa84a09f1d7a7748a89ccf61dc5497504ff73cc1c1871b8112a624f52fe9", - "0221843976db0e749921388b8c9d30028e74c72733f360b61af8bbfaaae6603d16", - "02052e3e11c046b3a1921abbbfd10ad71a07f3042a4cb9f77d17e80399ba4942e8", - "0327df46ca9e98ecd3ad23e5299af5b87708032198c05835aeaef5c8263f476f63", - "030dbd65a3e0484ef28d642b372e83f6f8d8732b77b6a2723be0d332d242eebf6a", - "020a9bea69ff09a2837233f11f9048fe72b395de3760831c77fc1dd97e59ace2b3", - "031d99810b82b76feed8b148c295fc434385201bf42e7ddcdd1f5d0e38a6209a3b", - "0319f25478cd0f2e7c166fb8264c710c0f89ccf75b93c375853fe1a52c3f7f11e4", - "0214aa482be14aae7c16ec2e738d1abd01ed6242f07e6d516489f4b2f0e3db4300", - "032e5128097e6ef646291baa457ae21c21f1e31c6511f42868a2d2b0fc9a9d68fa", - "02096e70fc9a27b55ca268868716d9e52795a9ab51d36976ad1de88ba6f0d6d5b5", - "022d196feea7a4ee6f14c3cc41fa00bbfc5646b35a06d29f94ae0c757983c2290b", - "031b7b7968dc77176fc34d7499fdb1cfa03b81bcfde04ec49fe98aac66459b315d", - "02100f7a913d603694eb2c78562d8a94d62ebe9e5d1d4e05fb0036f67f9e29bd63", - "030db6aa85ed6bc1ab9ba7bfee0d2a8f020c86287f96ab544581133d356ca8be96", - "02009e70bdab68662c72ac4d06e8b38a12d38055ed6ceae444af0df87a26540e70", - "030c604478b455285cc084e86ec25369da1ba009fe1db30fe596a3a3f2c1b22dc9", - "0310b64f5db3a734232845ecfc68bbf8b9abbf30b5e0f16975f1327aac06719ac6", - "0226929cf4fa1affac300767eff690ba609a00c78277f1b6a7babced789560c99e", - "031e8ead494c4811589acf7a256248109c6bdcb957ecb9e123ddaa227e233740a6", - "031342a689bab82d995100a74ee695874d74ac60dd551f188e154aad88ab845056", - "031d527032586948c22de09203e5624ba204f6be383a2039b5cbe8b756283af99e", - "02262ef6fb9635cff62739c7e2c5dd70ff3b25a4dbb36e77e4fa899e28f3999dc9", - "021962863ec1b734aac0ae229295181ebed4f9701a8fe2262282b2deb0c6fef81b", - "022a2932bd2242645c3da082c2fa9e2521b9eb6c46e17e36d562519d82b7eefca4", - "0223d0d814070bce567b23c556fbef40a913d3a822248e28596661b7b9144029d4", - "0311e03a03a90884f4c1d04463b72867e3f346d2d57865e00e3c45b12d6d64c033", - "022e9315eb022a050ea0886fd20646534700eb8d940255848f39b7496ef49c11cb", - "031d062e7f1fb64fc6449e685d495caae72272374e5b05fba338d1fc3c8c62edf5", - "03305f148876e3bc9a3713004fef6a51a141e73b0fe9cf9366dd766fdca737bfd3", - "0321f9c23c31b6cd77ae5abd1a0bf25322cc0261b35705841e3f7dae00827240ef", - "022091c17db93e7f8ed1ee56cc429d943da26f8aeed75545bf9071b9885c9d4d12", - "032882df2f827c3938dd4aedc3cfc53131763a1c735bf0cd810739adf3683282f1", - "03069bed967ba33e7585091051dffb30d3674a39d38550eea413749da3c171c3ce", - "02065368bbd1f7e00f5063a5280a8feca9ce7305ae9648e0c028a3ac5a6658cdc2", - "02140bd8ed9575312bd97b0cf62e2caded24a9a7392584a0132b5508041aa9bacb", - "03154eaed913bea1af30833607bbc89a56d600dd76df31a099fd0bb8e972e9fa95", - "022ff4452206bc9920f11321472ad30ff8e16695702f15f617bcfb1a7d4b4107b3", - "032084169f6dadb0aaa42b27abbd3e7fd89c26b22f9278a39590512d84ef5ff87e", - "032ba4542c86b77ae51390d6bfbd972b20d601210d17c58e039d375ac74641ecb3", - "03097aa8f89166e7e07f30e4f1398c26377bb5c8d7b178d114c58b45164633a01c", - "032b515dc4f8c38c89814a2ea73237a70fb38bdc5b67148b1b8e8003755cd15cc4", - "030bff91d46f4980474a333f20b5a8a716d44110bc080c9d65545cf52a9c12b524", - "03218e9d4e4eba8c0189c53d10d31ea0038cb0242be4ecc81c8d5351af167eb80c", - "030ab7e91d4729d66252140b2ebfdb5867f5778047627256c9cc0c182e3657fb69", - "0301d96472242e021ab31efa80392c6094084f7175d81dd6006af878bf71039398", - "022f6490a20fec33b84edbf658a444e25ad6fb3c715b9816bfd9929eda42b0386e", - "032111d42cf21433e99223f87d734222b5b7d0a783bf075a822455e93ed8560fcb", - "032712e467f2a8df6ff780ea9d2d5934b0e8b0e4da7b561a049dbc9ec3837422a7", - "020f947b6a98fc9a15a453843358eb10c9af6443723f4918a8a5ccb2dfcef0d889", - "0213f28dd1b0dbe801d922f27885c736966cf48aa56cd3267075e60f2cda63dc16", - "031b3bdce39db7ced7838eddc8203e9a31d2906a5904892346ede19706a6d967df", - "021838f3466e1e6d6b3eff5f503646a2440e156ef9b093eb49ad5eb72f1a3ba360", - "022a7452d470dc9d65eedd518d36df238d4bdb9138312004a4828a89193f04e3bb", - "022fa2a267c8098749af56cde4932095c887c70c3f94ddd90a931aa7c96312d5e4", - "0224b4293f67d323cd42b85691de9a6e6eb58efabcb08994356eab779bedb748ec", - "020797ae82f253d422a8be6f2b51378fb76a0939bb78a7bc77eac77a4b3daee1cd", - "031f63fad824eccb80f5969ec4e41ef50760ca46225d0b390c26b95889ef8fd29b", - "021016c8a72a3738e1565582c89d4314a148b284f91114d4c2feffe1b1caf76aed", - "0206a7eb580f5a49834b4c96dde4e3caeaeef264a152c7f1c3d22f82576bfec6a0", - "0325cbe73364c6f14abe601c3698ab55743b54b575bb976731d9dd8e148453d66e", - "0320a0504b9895df3fbaf691fb914e142602db8d4c800de83ea301d6956d748e0b", - "031eca8890156c17273523ff78e8190c0def1bb682f05c6dffcf77f9f41dfd66c0", - "032eb2bbf36273c833a9a070313841f667e413ff81b2a8aa0fc513e3e40764aa62", - "031725e8a7e78730e731c63b0fa30e1d27dcfe9a759216c2483bbd227eac5304b2", - "032a6612b8cf61707b5171ec481dec6869875bff84a65af567263025183995c1a6", - "0210da584a4451015ce9b33fd3b0391010e97ba3d98bb1291f1b516b8afd864e98", - "02079953865c5f7ef20b99529a0fd9fe49467fe339d871642dadee9b876f9635d6", - "031a469312bf86bb08dfa9031fadbd27ecb8e8318d7fa6041dba1b88cc120a8b69", - "020577c44c598e61acdfeb969303f7205bd9685b921daed9fab188b6a7cbed3ffe", - "020659b39ec693e2609cd5dbc0e7c742a170d25d92963fca48f15311408a91809e", - "0306ccdb4f35bed4699eaadcb8dd6c76ffced984c24749c4b6e378209443e19afd", - "033004f86604f3516936224306af800f1e532d7db5e5ee4ec2820b62573abfc0ce", - "0309d23ae8a1fffc4076abb83826866ebfa422d993110b7c8be61bef8fe42e7671", - "031f0a16e2177ba1cffb9b65e66d51acab91bf4025c5f2b4c9fef42b5ce508fb7b", - "0304e45ad1be734ad2bc2bc7e341af7831767c6f0c1dd02b345c717512767033b6", - "021ff78d89f04731406f61517445076cc17789ec87aacc31f247fde771bb127e77", - "030bba73df6577bd5f8f5d7a991d44e449954a5a0645f139b2c386b18fea25318b", - "030ad44940d6559dfa05998ceedc4d3224121283d5c18f3f311bf90804443d9151", - "031a82dc102509bef2fab72b274ecd5ed0c6002714ca78581f120e5351531d3834", - "022ebf0857e320807955b5f12ee77dbe6519fb028841bbc6709f29cb91775788da", - "032234bf79aa71f6db985ac42c19807ff4739f5656880a768b934e15d48a52360a", - "0306e16458857a41652c7cdbac8787df6167b6683917bc8b7f43df675331f1aeb0", - "0327b5156945b569d492a3c1335e285448249b218938a26e8480f34f9271dc63e6", - "021315e5a7e5fc5c2c0efe0edefec2560123b2ad8fb8e524fb04d1c464f059a6fd", - "021dfd73f37ebbbb4200b429f09da9d4e278754d6b0a6523464e276b4e047f1620", - "0228642daf74932833882eeebf836c38452211a34899a02802105d4f0e7e3b70fe", - "020609236286fa0e1e572201ae63b578f45339ab2e8cb693e1c8d9d51532e61cf7", - "020281c470367943035e394c51ab67d4f93b98b2cdf752683c610d0e825a616fcc", - "0223f09284f98b2af37e93d3a8b8fce9799a5c1f68f19d7690187ac7bde5ce9695", - "030b8d6926444e4ec7026fdcb499f923a3a9562433478c8d92e89fade2efbe7a9a", - "02098102a660a88557523d8198c16ae79c41ac7df89f674299f52d5f64ee8e7853", - "02243d83bb8abe042f869145a38fb618b544971b3112f186c23062fe210ce8277f", - "032c9d3e6df291938a4e6004ef25b8d729323c8a556da925c9092fb85686ef703a", - "031a3b58566813ad29ea041c0f1cca36f97fcd5043e8e1caffc6688d30c9fd120a", - "02140402cd5a6c24a6cfc3ac3d5472bf09cd129876f73f202d13708357d3f938b8", - "030bfe49f283da4a0dc177973eaeb3e85eed0e1dc1d62a438e2983668af1cf299b", - "0215168668a63754ca024428490e01d5e5a6964d20de7f377b43e06c7ef7d205d6", - "021d1bce60d4357a42e7a95ace372754bbe17f94156cce733465679c83a753e7c1", - "03114749b5b776a9306e4127e144c17b835f54fd5870fbe742bf35b352e2620ad0", - "031cf9b803dcfa8b794ce0f0aba89be24b914d3bf0bca56c1e3a6a291914cb5731", - "021218b7032abf723e07696dfc603da5374bc470073a8d6b6c359e8bd462ffc485", - "02140c17b6447ae0465f5920e67ffa255612556bb9c7e432a23de377e0370280cf", - "032c93d44f1d675381ee8cd4262195fbeba23d88021808731ee9779d9d653306be", - "0301126a612aac3bf09e4722c4de18e8a3892e452a228bb38128c289a83263c5f8", - "0203e1645a81d18b24404d705f600f91e4e99ae3e2313260a445e95e9c250ea5db", - "021af51be1ccebe863b537c31e4972de10ea0ee4cdff5d87cc9ac07da59ffe0034", - "032e5a25c27190e429e204a347e0db96d6eace28b1030033230baa874792f69d86", - "0206bf72a98a6eb7bf2ed46228da2db5076549a4679c52961c2a37f68f5870e336", - "0301d42fadbcf3d66b76a9955a05128ab4cb67800348336a0d87ec5d5e60d93e18", - "022735697cbc877826e58c671f4b39a6b753b3a32d90ec97b2d26eee2e6efeaf29", - "031e73bbfc6c1f009d1b697d47c8d098df5c311d4277e08ef80f1eee3645564ba7", - "0204c5668b85299ef24ba3e53d8ec9edd910cf4f5457d4fe501b48304a1640aa4d", - "0304b9bec204439b2a6013bd43903c19a91cfa4e3cf80262eadd91f71b77ebacf5", - "020b87ba4885382162cb42e74ff62976841d1c7dce6eafe27a5a7377c4be0b4379", - "030fe80156d3b51084bb7be0214389655ee50788715edc713e3774f141f0f3d168", - "030b0f19b77d09b809ae8e3feca17a30de59c73e1a838e51d22aba7f23ab942e3a", - "021e0967617f1322406c28911cd1b6a18bf83f067c8227480fd5166b981344f942", - "031c185d97584ae7498290f4438aed570b3e03c784b96b2fe9f17943c4e77c3cfc", - "0212274416f682ea768bf3bdd65b4ad8868d290f48d2153cd06a0f9dc72e111d5b", - "022dddb7a141a9cf67bd92bc06b3cbba6c37a9eff5f98b22108db9fbc447790989", - "0302c3a68712dfbd4bc3bd2df3a96a0d95177d7ea8af11b0cabed61b6a26404b30", - "02067b853c03237d02c50921ea1eba240aa688ca91a7a2f83eef3d20710b339961", - "031f158491fe3efbc41636a0e74cf755d71eb08942599f17f5d9bf258b6d8cc9f2", - "0210c90a034027f98c95bda5c793373340eb392a36652f6baca91c02de3f5dc48d", - "021eb6d180eedcdb746dfe9da87cd72c8b04a709af00bfd50caffe709ce5c7ff61", - "031d0097f5326f21b62df07cdff348f640241d9d75d3cf597daa983ed07c9acc6a", - "0229520fc4e6452309fe6a767778bec3b0dec0291b3911fc62c6448e1f6ecac9c0", - "02132b5d58a4524bc736d4a7f1f14f5e49ae10c3abc2776183ac63fb88f59de3d5", - "0320aada9f6abfde2245b39f3d9f37c813c88e0a4dfaab8040b9d2b6f12f7da5ce", - "030033552db12bafe1b0a1016911219b352fe800bf7502ff3c84ae42a20194061f", - "0224b18b8500dd47d306c41195cfdf23a051b680b295ac04d8e4cc9472415b0414", - "020ad01c16a928a11a48acf1a0d15004f6b2b9801f49a383e30b55b8f923d2001a", - "031358de788416f139e9483699120d4ffaf2ed459ca8a26a3454b30c94461f5cb3", - "032aad58d7008ac950fd5c894fe12000f867718e40a12c66648880db9c687deb5b", - "03220061b53b64e97d6eb2f7aac879e20dd2b6e5b664bd2ea6ad1f7df30118918d", - "030e4c4f70dde3ecedb5f9e60909edfe74eba61520d70365ae324d870740a39120", - "02250619e07209a00fba9803d1f6a92aed3b435ba204dd692effe85dcb79c4970f", - "022e4cdba69aa2209e56992f2ddb527f72ac44019c49a2fc4aa6ba9b127fba0c14", - "020336f9c06edd3e7bdbdcf6bbb5d04b2a97eba5bffecfe962491b107e6991c075", - "020aa05306e84e5ac944477f5c6eacae3bee9e1acbf7e6ba58f320aa6c6975a940", - "021bad2f2ebf006601419968405b2f68aa80cd17fbdfed699c0c73345073fbbce6", - "02112f068115dc0b51e2ec1825635ee9944f5bd378e3d679a3ce5072c20d413ad8", - "0222e93737e0430a3a21bfceb37d8f6128c1590f904825f71cab0282fc43017cd5", - "02214de7a630a900b28c7778c9755dff0a33f8c6a39431c68274c4f19f99fbe303", - "032521cb322b4e7d5657fe0bcb0119b5f82f5cb978927695268a9886479a3c76d4", - "02295f56d59cfb893d2d02bbd86d0f8bfc7e9977de361744d155775609f01f90d9", - "030d2c5874a8a69dd4a42c978c4018f927c4070462571c4a6a400ba6f0793b574f", - "032762963545aca4c01d385cd16362f7012863bda1be2473da3ac38e793765a908", - "020c6c86dfb6b678ba212815069cddbae9cb8be489a4ef769af3dbfd6b98eed4dc", - "0220b08c8bd2d496edc4e88f3d65a46bd0b7e990e46a35b00e39071eb6d7cca701", - "020b1dbb8340d60d66bf3f834072b742ce0bff6500ac3cbc2c190626d3d33d01c2", - "032f4a9f445ce18db3dded25d9e087473de2158b666ef3a6694e024e8781d76284", - "0328ce832bfe22a455e6d8848a80e8f6748e4acc56fa8c20c552a03b78b12b5477", - "030bd19718e87aa3e4378e21772b77e527f9019672ab6d39ab3245846ca4576159", - "030037f0fb29f801f5900e596d8249da4b76798e415a25a7f4721c114904c5ea8b", - "02249bf83b6b2b1a1506c42e755b0e0b4db755758cb71ec63431c1a0dceaf10b1c", - "030ecc4d24245b588582103aac863755168061c2c0d0aa48fb619ef1fcba3a7234", - "0321be43008c479c8c405c7f796e41d1e987e811808c85e0fe178bf302ddef13ba", - "0212e0148d95be4d7b66a2c48f9845e751fced1fa675eb01983ece638c88ac8db6", - "02215e7f5c99b0854a3d4b2e46c9c56633c1beff333781fed654fe609601e0856f", - "02049834346f329fb7132247bacc46ca98604bb5902f517edac852113c0f4973ef", - "022cdd7887ad88b55e618e26635a7da813dbc5cc97c0715371db4ebfd28f9b759c", - "032155f425d4c4ec70e745d73d96f56d55b88afa6171a15df6f271266b86d7c258", - "030906ab758051d26b5cdb46830803e41dbf8624cd0f80a5d66aa041264e374f67", - "02134d8beb19ae6f10c994bbd9c4c82cbe0318bfea608beb23023a019b1c89ac3d", - "0305bb8d1952322bb6548624fff2a3a4b1549f2ab7616c8215dfe0d3966cd0977e", - "020fd7165d7e968bfe3e5ceff270feb2fd7dcf75eafbe042348424bb1f892c3987", - "032dda859c683e61a82bc8100d19bf65254bd7574e4e7e6f2e27b72899c74a115c", - "03277af3253dda57705d7f6e4d76044e9b81bb45939adeb4aab15687a607eae36c", - "0322522b3dad98eba7727fde19f4e8a2544cfc6b3a00068a5d213de323d4fea647", - "0209b62b4b6a2c7a00149951b09996dacf4a025c6c8ef4f045a2d893208bb3c1b7", - "03081535d10495931d9f91eee564daaa052fdf5b3a00867065328c8078b906d6b7", - "0300c2b43744369aa28ad8e8465389fad7024a9d90b07b7aa618263d1e8f67e0ac", - "020f28ddd0d059f4c6c92655190d3a5f302fce90f0b065f2c6737ec650dfcfc33a", - "0327bb520c99c7c2491c9dcf1893a1e4f36f1b2772f379a25db4cf4613cec87add", - "031d7c1bec84fdbba28b86a2243207b2fd1526548185f4028310e2d3f775c8fc36", - "0200b199b7ec066aba15a4c8b9e9a48f6dfab05e57161ff152a692211ed78944fb", - "02051340196b12b826dbd5a2adb5d5a73a61766ea479bcf8851e3e5faa3bed43a8", - "020d5013d58d3120c482019c0d7f4ee5beabc9838dd45374bcfb92ee3057c65862", - "022702a990614444b39e125afcce3c0ed8bdcd2135635ed421fae0bf6c09cb4e5b", - "0220d93141ea74510a4b3eadb4c364cfd26a9b7247cb437ade1539d79af3ac6169", - "032e9db51bd1874315b009f6bdf2b40a1d1ce419cb381a9aeffcd5d13180e8037a", - "02302949c009fc63df56235469c6fabf3ae43996a83cfec4b4b071e08c4ccd6ac0", - "0309e75719b230bab5497b9bcf86b2bf7bb3ea2df1db6f64b1748ba32958a18381", - "030b1ad3de731e6ea11a685cf033f78431246239db2c4fb590d80afc2637b9189d", - "0213704fd791536b4fb0fcf8dfffaf0c1870aeb28edc3f4edfddb0ef239541a510", - "03222040a73a71b916f01e5cfc7faa4b51c1a796b922aa4a3914ffbf97b6df6bf1", - "031230bead5ff314a7d3c666eac8e262e011295c45da62726471cc23f9d753ce65", - "0201258c6c38cb52d3029a481cd3b56a2a8b06658ab84266b8580c9b66507f805d", - "02183d6b1dd3acd6b4409661f87a25ff2978ebc3f1fc05163e3259a1eb5896437c", - "0307c6062dad17a4c4a61e096f6e630ee7b069d639ff02f61114e9b89107eeadc4", - "0205387eded7e49e9c0d0f6d3dfae14048b18b38ae1dda61b2a47172bee94fcb0d", - "0321bf2ecdf7b4359af7d2cdb83f9634bc78d6b2000207b7f4afa12a2867a469b2", - "020f2416fb8519dc233f0d34064c5fffb888689d669d288a8e2a5ec109995ed107", - "022deb96f094cc31b1f2de0350bc953515d03399dac022ac1dc14afdf07c9c81bd", - "022c7df1c1284daf4ccb5ab436244ced7cb012fada59b6b5a9f7a44fee04d6e107", - "030839f0bf33c0a0e96fdf797b800269fa4b1e8f37400b07d92964e6caaa30eb47", - "02018bc60754d31787119b1bd342fe2a45f41a31f81b5a177c88f3369f794032d6", - "0227fb4a1d8b883b2d1955b55163b80c675d418cd613899c1c436de08582a8ccfc", - "0219666142dfcde5fcd9e367db835a36cdcd570549043a71ceaa5cc49e599e1e20", - "021a3a798cdf66e75da4b7aa1a24c71019c6f117f6eafff6d1032030459473cb1e", - "02295f9e13395fe32da9792e53c0a326a3ba19a76cb956894dfc896c06f85f4941", - "03166e70ce9a0d875eafc269db35562b2b91ffa2235de383b43a3b2476db7ccbe1", - "030054cfa49df260de086759a3eb384bee9d7ff89068ae72510202db68cd06f615", - "031c4492a66ea45f83a317881728150847dded21f8d9276c73ce616e1aa0acb849", - "020ab1dbc65ee6aa92a41fe894a82a0029d893c90712ba0105c7b5b9bef4c2b874", - "022c18b25f818544b35be029e5cdb2be0f32a0871c3cafb29bbb1b55171ef8c0c7", - "0301a8e436a0b646ccbf526eddfc6a73180353c4d583e808f18e96d19cd3170905", - "0210d0ce554bc766b6a8354ad42706307e52e0374ccb8b3a59fccfa7b5a2cf49e3", - "03304d99d792b0d4d9512709531f52d566a73c677c8600b18486ce67a2ae51c430", - "021c02d691902ed933d13e310e3a2b505dfd359cdfba1f6a0ec27ff270da301b7c", - "032bc924033318e0c5cd432e248a7bdd6554aa58cc002ec89a4b66310ae16fd315", - "02000cdd79c7a2377a8eee24279c016d24d29847cec76ee7990fcad51ddb27ab7b", - "020c313a4fb485a3e8702b7a60be63a0d63a1f717050454653877a540b32bdbcd1", - "0209b59b8cb8497fb7ba603566a26bdb1cfac31cb291fc442414a526572957b7e5", - "030bd09efbbb92c630fba0807571a78ee9e8ed577c6075af92e8efb80476943adb", - "022a43e247491fa038902c82f4ae93ac288ed29e3934a4105e2c51d95b351be207", - "020025c7d00eacd64b09b23663c943c9d4abe5ba2ef72dd2cabebaf32c17205847", - "03074dcbdb58e7975e6ceaf5879eb8b70c7c6367e5c3ad101fb8ccb40efa346bfc", - "03173d1f5e75c4457fb381996efadf53c73f1d908a7fed1c531dd22de340a6cac7", - "030d0191e0021c681351d6f75402baffe5ba853334c292cc3b8149fdad461e8610", - "021a557d894987c4d148627ad0a0da6c5a836ab60c64f827cde1d10d6f6634248a", - "0215e17f501411513f5c49f8deb90d639fe24ebd7c407784e2e7c07e860575991a", - "0227ae947601e39045b2623bc1c548f0961ee567c34e1281b3136c9c7fd2f28dd7", - "03051efb6e8f495694abddce2143e1702a73240a28f8ce6bef18d8f50029304de6", - "03287494b1cf9ee1fb5571cccff78aab006676b1f60ef9e5a9a57790ed9ce6c531", - "02071c70c77c7cd5f63933fc649d7837c528dfd62e7ae8003dc006b3a2ee21f1ec", - "0202bbfa0c528b5a6d57bcc7216becb90661e011df1521a2ac230e66807a7c5069", - "022a7450d42ffe62cec4519d33ecf99f98176abdc1c762e6ce96a3aa133972c4a2", - "0304531956453a96ed275e779e07b6e40f511c7b406bbc257e61af9b975eab0c92", - "0305f47a8c749cd28c2b067207a702941b0f2fc31b7e786a9a2b14e3e8c47c87ef", - "032102cc5efbbba0470c9360318ec5c021cb9932e780149080e212f16b1611d651", - "030399cee928e666b0bd7964bea9487fbbaf3990dd9b57c522efc541995735580c", - "0319ce3ff9a880c293cfde58862972a44b15183112e2977fa2b088f04c60b6b377", - "0301e1ad4713a47bf0e7c58794ff9282ae5258c2033d1f0c63c9674dd2afacdac4", - "020b76ddad1eac83cea7958e40a3af45e8bd13ef4fde8a6624491fea0815515cb7", - "032c366d59ef3e8e6fe8073d4941881b518877db1892f1d53de5dea7f86cfb76d8", - "0229806c8b6833ae3852dcc246f3ef323cd217231c5df6e02c0188a0ab027803ad", - "032a99ecd1da24f25270c315047d364c723f33e92e8fe9e35bdb109459d126baf5", - "022ecb4eacc551e587d5311effe3d706e0f7658f139b8ba2356ec2a7955f10282a", - "02303f443483b241379e6ffcde3f05cbfe3556a6e87cfb61ea842782f8d804baf3", - "0330615ec0908c27dd5285bfa899eb55fb37a7224c8b3595f8fbdfa9706b85d538", - "0219e3c21190c6b440be6f0401a29e7b9228ca7eac952794a79b6121cd7b35cdc1", - "0208c0ac8cf36558645a56211efa9e5bee9e69e28cda8492368a7df9324067e0f7", - "032656d533289223e43cadd0df7d58cb704412da4f0d83ae6982756b96b718284f", - "03216ba8f9822741cf4c83dcebd890a86fe3b227ab36667aac1e1f1ae71ecaa9aa", - "0326fd2e64bb04a3ab11cee2058754b0797d5575e86959eaa4fd2e626e9f028396", - "02024d72a4385f9a8855d7eb9ab82537f80a02911c82522da330b1df998967a91d", - "031296a196ddd36c50fa6901f65bc03682b009e98824c445df2779d0e77fb6de5a", - "021311aebba8c696ae7c44c103e71c28a61bd073ed759b918d91771880fc581158", - "0321411ada8e216fbea910f6a9d6f320155f5d8400b070ca1304a825158ecc69cf", - "021d76402f34a27f435849674dc3d64d348ddbb24656e902e7b0b4dec23a3d9da8", - "0202042eb9720002969a6e2e5c014554e3d51681fc5428723d4f3512fc47ff92aa", - "022fad58a0bc0d29921ef58daee7e17953f3658f45eaf1ad05027c606825a4652a", - "032c5aece480e14e9a9899fd21da013496308fdced13ea93061213052685b31266", - "0215f4456eadbb399f7b1d2d1a0830fda806022d5c86d878690138a428301954b6", - "02103fa1e0636342d42ab904f9f5c851210223215dd160d2d6a126ec4b5faf0890", - "02040397d7ae6b329e71db4468382b2c0254e731ade7905cbdaecb12f748d91b9d", - "020f4e861917b77c824a7dd832cfa0d119d9df2eaea5a73363145f3587b1c63622", - "02277f2f8b163c5857241160f0a1fa3a73b789554c9f6f52de39e64f6302ac6805", - "0325ba8c64bda3b26ad265e715bf3f311ce33109dd20606af4b85c82cb3d0add02", - "030737251726f9275c2c51daaaacccd0d920bf603a31033547051971dcf5baed11", - "030d861de2a8598aa46c190b1153ddff355a593c35ac340221f7811e0673cc9ee4", - "021385886a21365313020ad44cf63e084d2f9ffaf2923df2805d26cbb0ab25fd23", - "031f4fa3612bfb4ad6317a14bdbbd926c9c322ecfbad9e2b2ee59f5465837b1983", - "0225a76cdcd0226ffb7a008bedaf59e24afc7e58ff39e7125f438d6f7e444022fe", - "0218926a560ed0855e09657f8b4a8db9cd582e7d832f2ddcd0ff2fc360c599fefd", - "0316fd8038d6e431144c4437484806b35c86f59b31663e525edeb8a8e7220a2ba1", - "030d7e1ed99249a722601adbb8eb54e167097e4a3a71eccff8a198ae8c89b2b6a5", - "0306b39384e998de81aa0631c0d807c4a29c8a759d1be283f612f259baff046579", - "0322b2fbd8f1688ac4018dc9172e62a65d7e72a89d942dca71931193afa1bb99a5", - "02006401ed5400012d16777cf6193d79daf4f477d4e27aa537f5ce43f529d1c6d7", - "03285f467dc51d18bca7dd3e9c0db3d2e028bce6231d109f3635eeba3d8ced6a89", - "031d13f819a80b1d7aaa2008941ad368d8302e11571c52c7736e3d8f914851ae13", - "0314bb922f9bf69eb24947d8523e03da7718b045bcd634798a8dffbbd116fc7af6", - "0207264a181065a0de17643bc1bf03749dfe0a1746064dab12a50e4bd9fa76b697", - "032d18de48ffafad011acb6fd735de46cc4031225f353a0caa7566bd406af2903c", - "02151c7660f4ecb1840ffdfcebbf0e5a61f3abea03e9fa89d20af1fd0f9a0ad554", - "021ba8a26a92cc09b71829581bcb7ab964442e27576fdfcb8efbf9271c71b866f7", - "03273002cc8cc32cf6ee730479efdbfa875608b5522470637ba0d7afa1367cf0e8", - "03153b62254dca9069f5921c0123e12894c06e36ecb15621bc7cba4235ad7a967e", - "020ce821bdc3d8ddcebb15e544238de2806879e8457aa150d43f973ba83f97cc89", - "0327c647e368ea1bbe61202e97f99c6479cffc0e976057426647ddbb70c08de7d2", - "032f101596d26f1d8bbc55b06452573d4dc71f34874b70faa69446483ffc791ec6", - "0226873c1ddcd185c7889989cb65f40b6d562b763ce71b61edb3d47e731edcca12", - "030e653066ccd743f6b86e2ce1dc05586dd56f5b5b962a4867926e55f1d4f5b4f1", - "0327db79411669478c30aba8f1d857218e36939af7d335ceb5a270a4374451adc6", - "022806e29e7c551dcc74beaaac5de5b6a1bb910adec78c6dfefba698c37f78d88a", - "0209a2430db42758e927c1574b7f88545ec3dc39e27f9c810ba4becd6b8f36ef44", - "0202fb0b5405ee1f6fdf59e8c178712679b0bebb2731f98533eeba171ff243a025", - "022ba4e539af962e8dd972d2b095199355ce172e8b4bee10c3a0156acb96c171a1", - "0322927d23902f2e8b39b5aaa9573b3ba2c0d4e2eb7c560af2d6dc9ab9a0ddfcde", - "0209b3c53ae505e7281cf2c36eabe10890efaff8dc3882f19f07f572d71242fca1", - "0221b9ea69facd136fb7f952f6c761f3bcbc0be9e703dee6fa9f169f5d82933adf", - "02179c53c50acae505f602515b53bae6bf75909b8e30829ffbf278417b94d99149", - "0327d04941fb5e7c4e81e22a6b2ab596dc875e41419b3581be5e582768e2297080", - "032b9cd19f2f6edddbc632d069bd6d1addd05b69924de69cd4ee519228d6315051", - "0300818a50b7c0ac593ecab997c7e999a04d71e75db43f59c33d81363a7a1ffe3e", - "031e271042077a8ed2b7e110b68fb2c9224538eace4bf676bbcabed734ad35bdd5", - "02129e330e8ac31b98da221c1aedbabd77f852cb50fa7a5e11299249ecc34c259f", - "0212777085ac411e00d2baecea28385cfff9a9196e69e640328c820526b8099fef", - "020c68880a22c3c91ffc5358ee1ba5d50e92733fb35befe844aa5e9c29bfc88b4b", - "031e766b663b699d5f1542075444de98d5adab3d77fd59211965d83a0a437f2bd1", - "0201ad41312f3e6a54050dde52263426e69984c2a0901ce6fe30f87e86bbe75102", - "02041ad2a1ca6b8fccf72c1b2393818ae14f0500078fcd4969bacc5ab0cfae83d4", - "03032ca65bd98a0dbcca10abc007884218325d40e4058758b2e8b3f234cb4ebcce", - "02123c6211714f7b228ec756d63dac8ebf13a6fe656356010cdb1e324812665c87", - "0328e2fe1875593453d66e9496467b90b9cd60be63c99acac4ac90b7fac63d0a77", - "022805c5bb154fd8e6e2214d90f110db0df2fe3d66952aec20f3b551163be6feef", - "031dbe90cae7b68daa5b25a7d716edd81690803e1f207ecdaa5ed33774855a062a", - "022560dfafe7b0e75062dc39ed5fbce5e03b83cd569ebf418c1b6e58c2c053701d", - "032de037a481579f91ab98ca7f1be2df6a83138cc01e7cf508057165e10c462a22", - "031148e655623b8b1a4adcad98804cdb538d8481ec1f15e5a2d4205045bce90723", - "0212241488c7f49a3dce6cb0368924359567261a43a8c9b9e08c47a5f9c86e9d11", - "03026ab4d55b9c825396bd32506b5aaba713ed72ef9f81315d59b4c8a18b122b0b", - "0302a464c6d7cec23208ff8964ecb5a3f8ede956bd91545404a00132ecb80cf52b", - "021a8b55b758da84506c48f50dedd999302cb807764a3ca23586cf993fa5f9b44d", - "0203c100a001edaa5311c746073644c2722b5c5f85000ea9728d89205be1807d72", - "0307e27e774922afc9e7924e4437f472007c29f649041233c5148c7d684078b643", - "03238e91a669c4ebd3ff49bc90059a2d3d8d84609c9a3c224dfaaa72a43201a94c", - "021e769805762d24e429042250b47dab03e96dde386f6e7525968b6c89a7058a0b", - "022440d00023ca547cedba0149c2d93ad380726f30761e0d3cdac03f70fbd404cf", - "0230487ab7aceefb81f5edc150988b39ec9fc9615e92744469dc279aa8d91dd0d4", - "020643b4423363cdc5cfc9e284f4b1bef27517aebccfe8f80c9ba6ff2715f4f8ae", - "03261abe5bd57dd73ac059b78abcb5e25a62a78efc5d37cdde6f0e72991379ca7a", - "03273e43f941de59ae7e6539a25d1821fe412b515ecd2f545f61ae80dc93b68d36", - "02076f6560c30d1f5926d06b90fcbb9989df6344604879537b5893aed8787bb1c9", - "021f2cc43ace801666ccb6149fc8a470bf6a0a8f21a93ba7e2403ffb8c9a99784a", - "020b37ba90720ef74aa8fad41da77920bbeaaa6dcb600e281c73bcc10f3a9f9069", - "021f38580f018054ae06761b6185771c2c3040ed67b72af23c252fae63df4b9c18", - "03127be428cbd1a030e57d186b42e2a9d55298f2e7a5d634d56a6d72d26070a47a", - "030a818cd42fa3dcbe8c03aa6ba1377fd91f84f01e5e6b2d4a1a4f302ecdf213df", - "0200e87e2c87809a4bf9ee72f300525a485e94de5af1ba1e7b25360c16027c691b", - "0319132cc0276533ad032f08f88e30141e97eda166e056644f658016a1df85cbc7", - "020d4562413738dfc82c40ddc8bbb6c8da3836d8e1d88683ad363bfb41dddc4f3c", - "0316ade8dadf3360e26eabf1966a5dd4bf2f981510a8acf4477a6c102f9cfb46c7", - "030271665686efc7233596d7126bd88f4a2c3b6175ae462462f04cee410b38b479", - "0326686211f17a91908fd84f9f68ea3a92c1ebe0c5b6f7d1162d130f4c5810cc18", - "022c775a6df417c4f5b8831c8441826121e17b85a8439061d55d4f17fef8823f3e", - "030d179eb649fe4d527aed5fb472e1407075e598582c8f5fddb29080d6a0ccb087", - "022ce2b3c2d91b940dd6bb2daafae26b69df89cb0557d1ef301332c20ef1eb7e51", - "032966cc70ea2a91f8fc8bc17b269e1890d0fb96f8cc4cdb2d93187f1173e74e80", - "022f013792df7fdbf7d619a1fdb2182ddb8805902af948c5e373247808e90c85bc", - "0221b64ec36854a6e202f949c352daeb254248be2c67e14aeb9249fb0446a9c880", - "03028cf8054476474c0319a972a6abd627a5e7031fd5aec55171b331d5a408ec4e", - "032249cc4519ccfd1d112657c952a5babdb22765362075155c2dbffb771c397352", - "022a53fa226c4301a11e30c1d792678f62be7eee63e5cb4c5e8f41c71e4dfcc76a", - "0303f6482df819734e5bfb81231fde9b60c10fb300213478a9258426bc22f1cf54", - "022277b7a667e735b91a125cf9530bff3f50718749290f7072abfe5cedf93802ea", - "030d475f0eb17effe132905a065aba551bf96991ef8fc406df12bc77ffd19eb0eb", - "03006ef17ab7bc9c42c9143fadb03c131a69a7053393d0bc6e34c1c82375ada86e", - "022d51c6327e38372a9a64ffabfe0bf49f40eb8afbd868a5ea532853ef245942c0", - "030da6c8d18b0596441604896b144d1ee3d389007b1d5c219b1b47c4ab3c45f896", - "020fe22579fc394986f28d0b9ad48c3a9d201d8cd7df38240cd79e14da0820e842", - "0222d39c2b933878d5daa1a784090d0f014fbfd588ffe5ef17fd8a91c9ae8a73ef", - "03000029d8f02ffd5cc77f542d576700b401c1594f853e1d191d38b6a27a4ec6de", - "03072b7c726d15a0979ea7cb25e85bc809dd3e040f9b338139a2ea7673a7fb111a", - "031c930a7aec038d9c598ba81fd17eb968fb9b4f1d800e37daf7ff61d8365fafcc", - "021aa83e8a3cf7cd1791057d3a89531b4d381c289b177c3d46d8c6c82eb726af4a", - "032f1e0bcfb4e636b8cdd4dd993ce548263043df0a4a2923d324f202404ff2e894", - "0319ca27c626b7865a237b16e704e118d28542c6939aa51d3548cb7a4ffad0c905", - "021e2ff9763c130204b5f767b2911e899704ed8af6aaf871fe9f77e937a0b8d180", - "030d34dc90d7a39bc0de5020cc27b1928f44cb9594563b71c5c020baf657294f1f", - "022bd601d404d127072153705378251521fcc70d501a491f82d89739da6dcb4c01", - "031ae5478319e59aaeec6defe9460232d225a56ada8841209b5aa589707ed8f835", - "031860572755e437a26fe21ebe757b61b6bb7256b80b8c1542acf83f1fb839ee19", - "020ca4c7a7e7fd933aa99ee235e7be6cc9f71ee3fb1d417df371cfaa20cf9e3628", - "032f602af7c5e1609639400ea3784f0e440f9c064dd60384a70c729e4d628f5b21", - "0301a3aaff4a091a660afa8e21f51c2f7ccd22772a23f9a7dc4f74f8c646974e1f", - "031f7c7a889c47bc47276a8342b5b2d86a31cd4c0aea7589b0e9453cbac5a5506a", - "031d5eabcf99f51e7f74836d6f7ef0abf35c443e2476445a20a6d400fc701526aa", - "021e763dc69d3ef74dc6054ca714eac38227caeeb930a2be4fcfffcd97cd94495b", - "02269452880aed31170ed92b0b69d4f8ad1a57a83cf043e960f8b3e78f75b812e1", - "031e1f9e6be806864c123c0dcb1623d7fc96c2d2f1e1265bc5e70f1578071f5561", - "02238e29754e274ee715b3098a4b450c0539d931fc8a25323e7a2b0499add3cbcd", - "030a3363c4b0404b40cdcc7966f069f7f72c484442e300fa45a48c3554821c4049", - "0214b9891d1c2b2c6d3b250c67065b69510dd47fc7f6befdd4a9e32d09119a6301", - "02046191b574eaacf5441fa177b8262b9a402484ef38b8b24ff4a7dcf7f13560b2", - "0318ae80984507a2bfb78eeca0111d327e6edeff7f3921f787d1b7bed8f3101c84", - "020934ecc3d451f17f6e55a96954edfab1f7241de439713d5ba706c3f46f1a8c2d", - "020dc768da3210d0b7464689b76e0015b0313a2e940a71f017d99a263782284729", - "022ae6933d443085a38789b91084a8a2c19612a554e11a7346b0c6547a70bc2f7c", - "031cf1702284ae20bab87292f754680497a1f391310a12ac22f1c6548871ec8fff", - "030aa5c1c5cf2b2bd341aeac7405cb4a801aba39f7ed7c193facebb2f6ae00acf9", - "03189568dcd761ff681230dceb90f392e0a477de1ac0a53b01cbcddaa1edb03fed", - "02113b1001cf1d0814bbbe21b1e8c3319bd88c243f55770798622e9382679ea53e", - "032a947047ed18a80b73f42015de0bbf1eed2e7e0fa9f02554cacf52ef6b14a4e4", - "0206dc44739b279e11fc6f63b027dcee59bdd0b91b9fd38352003d5d07c9b6d81e", - "032c7bdcebc84bf096c701b9bd39d745615c1cc7aa03b9ac8bd08f9f14454e61fd", - "021accd7c23bb61e771a8a4297cd64f4d616647247fc433b7ee0b6cbf119d0340b", - "0324c1b95141b72544580a85fec913f5b28caef17eded0a9a588f074ce05c8612f", - "021c7ed42f4466bc120dc05572b0db35d5fed64f30ff43e438b98ffa0398c07130", - "0219cc1776580c1c3204d4ad873774d3bfeb0c435cd572e4e105824354adab6fdc", - "03216ff44cef7f243a3771100f1f4ffe496e1d6a21d34a706af4be6138057ce815", - "0302d7e29e734f0483578cc73f2bf71b04941f21b2f37e0d74678a6db4b2ec3b8d", - "03301bd53a909bb7298c35938fc4dbc342bf4aaaff278770ad3fff5a815e9daa97", - "032e91b1a6349e0c6b2c51adbe469b818a98b60b359b07f73428896e5b8841c514", - "020de30ec58b4e6ffdcd4d8ab6859a5797875fdc8e480ddf16f940f57c46342e61", - "0229ef9e2fa275b6a60ece7c7da8c5f8e18e182ff053e3d083bb14fd4779c1aa22", - "02273793a3bf9eb82a77138379d576033a8b4ebcbac713940d11ccac02fe592d79", - "031c9d1deceab6fee0e6805baaa103900f8ea81b2ab2f2ecd58462200f05f33c2a", - "0312048f16d7ca26511d8b1699402a16a2f0d30472551afb300a337ca0f5ee179c", - "0209ba4dc6f6ac7ea985d9d5906449b391f79663c5f08ba4caa999962b0aaf5841", - "0207207001c2070d21a0a3202aff5a7b34d576442e129e7034703a4ccf76736b99", - "02297003f77b42ed2823458ee8c456ef3a683bf81ecc1dac89f67a60f302b727c3", - "02107a7eb9d808abb60b8ad30f43cc551a9830d15a4e87c733b3a5c11a116d84cf", - "020e0e25eeb4282a05c8c68474ac2b8561aad7feb4a1e513835e9aad8930f8f767", - "022c3e79267267454ac7d2750d23c9a56ac4dd579a6baf80577f5bfb31cec0f0ae", - "022905c49d758b6c13407f5b69c9105a02e6e6d5dafe37dcb613f0e0784aa4c73b", - "021c3ddbc8e295f929714d8795124d30c7ef17bb1585a29dbc5934e6b6e7404370", - "021133e0770f801de987b972f427e7af7681b38e07a3262996c7e430d3be83b04f", - "032f7dd9ee07393a7f2c3b7697b7d1abed694e3dd5ca5b5ba26c536f1901281bd4", - "022b56397e2b3d54263b7880b58e25b759a810d6627a556e4c4806379226d7a85b", - "031905db518232414d667a5eb819ce85aa742b0f1ae334c72d19fc29d1b2dd4b12", - "0304253919d719e73bce67c0ce9153f28697284fc9b747e2fb4a93c8ede2ec6a19", - "0204fa3b8a66416737d30c4982b822b547623fcea7c2afdb3b418ed271b6253419", - "021bc83d6bd3d4ea773a1290fb89bb3a39b955e5348f430b384f15186e8753fea4", - "020dcf8ec3e31473920a533e5ee888702cc862b9ffa3be957fa5f168b745bab72b", - "03201a7e49302d625209a528b226b65d756e34211f30f7055d60fe42be7e3ab297", - "03015efc4bddd428987f216fd4443fbd95a53c73f1c3ec77887bd8827bbbc3d5fe", - "0309a84409712fb4fad9dc22724cf3f2e4edcd7e684a010e0721a59b7ed0e64d0b", - "0225acdc4c581f3e205e9c8709e7261c4fda9eeb235d8da7bfb5d13d7d90ffc490", - "021fbfd6cf15b5ef251dc7d8bb104359507f5ff0f045fd18bf2e933657d93c3ce8", - "02106ac6e4cb430a34751e715b5f3697d727caf5dec8a07519c8db68301198583d", - "022884f707e9c48b275d4588d1658ec4932d64d9e251fa27ed1a8425b5b4617065", - "0210ea4f99e853b4f675d9e457c03970d2d16d6d1889a27cc03660aee95d95e7a6", - "0317ac4ee47022f91cb13406d508e35563a728c5eda32c87c4de95666a6ffa2a61", - "021205b440316e52f560274a0efa1f7a10040688ab0c30d637e8eb026dd84df7ad", - "020b1295df8b27dc6581db5d869b56e6996eabd0dfb95fb098e215842a116d9755", - "02062b1ba19017dd16e1abb990de7793a75f92651d7b5a2f9059fb0cb1f959baea", - "02113585dc0f47a837cd074dacaf6ebaef72c0d4cc5b6550666d5e0dab04e0f19b", - "03066184fb8664cf9bcf25fd4372fad5f0a0063f091b272edb5d8be2ad67ee6bc6", - "02110b68bbf8697d0616bc75b3642df3c6e43f725b6c3635d9e94afc7e1bb121ec", - "0225bb500ef7a8ff736f608f82c38355366b9a6b6757aec20d08ec59775583c5e3", - "03042be754a6ddc8fb8040e5c723cc086ae63bc52c1acdb6d533277b1f78f28235", - "03222a59c39a2a41162bb93b9c8699b95bd219ba1fab2fbfb248ad9d970e814a75", - "0302e505fc7fa0de7e46a7fa4aa303932974cabf001171f5d596db57b50d0a19d1", - "0207f4b6271f35502407eaf6e78749ff28e3873575db5127d4586761174179a493", - "0218f6991a12d44869440dab0fe2aaeee0b9d62f2a6e4b2922d0f6072426d2cc14", - "03182f20ff9e31e12759878bfdacf9dad01dcd374eb2569431c38aa498e83923a4", - "031cc73719127b4c5a0b396b7ceeadd84d60db3870e72930c7b2227051f6d56837", - "0305dd7cb0c2e57cb6e24b18db8c7ef371b781923778c08c8bc732ff4e296ca9ab", - "02088cf3174c007e6963a63a9b91e9e1ee7849c28ecbb6e04e60a98a4d0b977b77", - "0303c56d4f11528c4b37a8b76d2661717244a16bed0d276761706a012614baa169", - "021bcf8b446eb7f9ede75c7f5c19d4d501ed25aa9651ec4bbe4dc8e499a7e0013b", - "0212518325a8728aa232e8db0ef45bbb31c3208a7d721130122e1bd16bff8c3646", - "031e0e7983c3dbf435eb552a401d8e7ddac24fc00fc42f973fba14e773af57742a", - "0328849847707c4e548e3ad4d027e202a23c0bd6279898d72562648585715fcaab", - "03029cd8b61a2c4ebd7003f5c272c96b8ffc2dd1210bf2aaf7d1cba7923d0b6709", - "022748b9bdcf92e309fa88be463e27ddbd62c2c1f397bd4c69024da67d3871237d", - "021ac652c2ebf28a17eaf96721a8febceda18e4710124bc56955941362821f32e6", - "031f2b45fabb984e8cc66dba981bb54b745e0693f63bf71ba2bb400cab2d32d407", - "030a42b8b2faba80edbd8256d2fb1c8dcce1c99fea046ca4dd971ce408316c39f5", - "0222673093d75062bc086e4b843f33e44e19dfc345e4e3021803b62a495f295c44", - "020c74e1b2cb9b9fe551e6a19251b77880c4cf6ad06db003472accead37e257277", - "020cb814674c956ad5980c9ba391277d590f7b3f8f1d236ce143b44197e3a5bd69", - "022b8ec78c6f4526c4f950716459b89fe79669409c50bdb2e7cceb84dceaf0621e", - "030ed4f3bb1ec29c828ac08f67d71d5c2d0fa28ef37f3a1afee4b7c9b0a73eee15", - "0221d68b07023e4b944f50cabd71595e31d0ba452f857ef0868b9926cb169e4acf", - "03265c1071792de900aa2d59c924bc6278b8bb1bca9eb2f23256041696101ddd39", - "02140a98ad2b9f453cee6537d464770a16ccadb2ba44552db15afbb80057176cb9", - "031376935d02173aa8c49d46d4ea1a06c44e0c28475c3c0160948b28e2c60dfd9f", - "0319cb1a8cc164083747a9e1ce57e08b9b48d638d9b1100b455ca68eb9629bbb8c", - "032b2b2873b4ff8b87f2dc6a2df67eecbf7b48b61f9f963f20a795c87481e4dbc9", - "02119a10cbe5126e02b142b6d5e566dcc90f72b68ce360bfe7f4964660285d6165", - "0223dab3ed7cd3fb3df1cdff68847898dafa87200e208931154b94865a2b04efa5", - "02131a127758ce97657e58f8a66f7e1ace5d770429bdfb00cfd9258cf5c8cc922c", - "020556f3093df06bd459a64a26d4c862f8df3c8821dcb37f09143643eff1fb94be", - "0329b0e9373301663634b1f922b87f111624024720d4cc9f7c1f0ad192d687f6a0", - "022098e0169060197939e396cf624afe59c93c4a78e84344fbaba77bcb74e693e5", - "0209541a2089eaf34ba0ad94463607acb62d864766ff02d01dce4eb38c90ca8c69", - "032ae414ab9b5372f607e75068606f4ed2912faf4c189dec906741fc876de446cd", - "021918772f716e37aefa462b3f1368fcab5b16bb5863b4c2ef4845393231038981", - "02126c31e4ca74dae12caaf4dcce02b8a2e28ae64613e5271cf44cdd1007697334", - "030c077f56c944838683d3d9d9c31a965441eef2bc86d3cd0e08cb75b32a3ed75f", - "021d749f03fb05bbed89e2825239bdd22b4c398a937085bc2b494b7b099ead08a7", - "020b5ce0a75bbe6f1caf8326f9bf90cb1199f7d362f25ad5a06c3ed793837a207a", - "020cf805e62d88c17ca952bf61291c8866846cd9031d728fea51f2d342b981d1a0", - "022c7ea4f22e628e69fbc3e4a2db945aa5d52de43b7fffe4c0589856bfe04555bd", - "03125c3f97194142147b754125c3a6ffa377dc503b63e380b136ef107ca3111ba1", - "0222f1415275a07bcafae1c04503ff5af9a209e2313ae26f75e55e700b15803783", - "03237826e8025ac29d7d63cfa2c0d254b4201f31b43c67ddc1131bc888b555dca1", - "030a3826c20e474891300a6f32902fdb7bcb0f8c36e6f7f4f7efdc6cbbb292fcc9", - "0310db3eccd254f40600b0ad602b65ceb5322be2f50a7ed6232ce34e8d91a3e4d8", - "031635c7df15b5eb31a5b3a2874c75c4f8bb005ed9a0411b92ef167731a3793bb3", - "021a6ade3c74cd680b1c8a357dfbd8b37a70149cb62f16dc28d2237d19096160e3", - "0313fd3a452a2555769d132d86fefce2277120ad5ed4e1439cd007b97977782727", - "03094587e8337cd7b85d21eac07d83911586670b9e22a1d8c4ae6fe59a3956511e", - "032c7da5355b9e97201b1765df63382f63b98868595fad10c84bc8798783f28ea9", - "021ab12bf08358d9e9d1cdd8cf646d538a5796bff4616808147e939f1d8434f5ab", - "032572bdd96f12e586dc00e66a3a3fa57fb5642cfd848f95c0c805f06179d49fb8", - "03096937367d32c67ee31e67798778d056491459c4fafe835eb9cc8ec7ada09815", - "030b1486466e9a6e2e451e455b520590023bca50656a587236cc0b107fe690d3a3", - "021e378265af64895b8be768c025b7934254eb84c2ccc570843e624cc2a1c33f95", - "0206b033e7d843cc5aae0093efa9fd94210e136275044385e1b42de928e8a11534", - "0326a32e818610b193a2319f7168e902c448c3c0322decf6d62cdae079e7445501", - "032606e1f1b3a9385b65555517ba350980c1801c3fd2245540827cddac9b13fc8e", - "0210a314d35bee00a1bd29d0743bb1321daea59975cb6730a620fa833b0c8567df", - "0307a79e9c258769c01966d45ccbc07a0a05451415526dec08a6ddd1519c0acf2f", - "0202d5041382099b496464580c70728ae83b3bd490f33e6ae2f941d395685b91ed", - "021b3d8244e8a68afc03cfd0e93682c37661ad6daf9a5dc329a366e1904fad8411", - "02020b3497a7c3f6c01ffcabafc586bc5c65d225ddb2895a59427be21c6c3386ec", - "031ea6b7ec9f56536c0d9e0271264f8921f57e8f0b1d8bcf55c198bfe243b40f43", - "0225c33cd9d7140e788aba7147a21b97a620e97a098a8e5489099abdb116ad533f", - "021eb7e78542065324f3ad8406fbde768d7654d56063613cd11f3cf8df1e909c35", - "03074c51dc0fd7a0308bf98f5f18d1d5622d03aaa8e033cec8a9ded1bb8626de3a", - "0217e1a79e0e7c1a2007e06f9345ac1579b2abd6d0ecb50b290b0a6db35a566c84", - "031d36dcfb65e85939e326e817a9a21d0132922d36648ddd481fc02ccc45870c8b", - "020321d45ea3d3eac94dbec002360794481c2994d7c608f0ad94f5a8d4eb558763", - "0325d8540282d1157c314b98fbc8462c328601220cc7acca0e0d65ec9ddc67f8ce", - "031da815c95dc1081646785e0ea9295e7632b0e24fe4747cc51121a9844e3eb67d", - "02081b7a6c97d3ad39640e463fe00532e2687b7c6fd3edccd8f1d39ead5deba268", - "0224eb4933fce0414bb6e7b4bc806622d5106e3a4c47d9023be64fae92759b1761", - "0303d8ea07deaeee2669e4fb46827868959671a65cf0b960f1ee4381b615fbc90e", - "030d6361c3453cf72fed65015c209de718e72e5f17190feb27854cdcb37c3ca3a1", - "030b7224c2ac6c030588faec24c800c1d399dab616eaaea55d8da878b3688c5216", - "0327351411cddc006f1c9c7a73e9863cd67117d3df89be0c7e49dd27ecc032eef1", - "0319c78860110bf4a10888df3024d72df1b90694c2e29680aa7f131686f4c5e006", - "03163a675689aa1fa90191b9ec109de6038d17ba2ae9cf53e91f9c317a6e27c3d2", - "021a3b7b0c934bd8c6dd2125c0e0c7a4fd9ea237ab8534a10290d96f66d47a78cc", - "0222fcddc86635df09b422d042c57f2acfaeb3758f20b216cf0f8522014994ba65", - "022fec2b619a6203c203e016ad6b778b67a56f579942b75c164f989d6ed8423eff", - "03109464b4871ec41aee2de69df8b9be70de64291ecfa8faa5b72b8e27c366fa15", - "0300e3d80d840736936fa3afb624fc5d536093e1a24b6a8a0cb69370f7de1da4c4", - "032017cb12fc34994f40134f3506978771943db5b7e5a836b7f3ed780100cefbeb", - "03199051338ce31524a70733caf28806895dcdf221653daa962e4b77872313670c", - "02236bc8634adf85ed1a02ec4a90e8a8d6d529598d5749f3e84af12ee3b1ee9845", - "03277f3da8e861b061c630474c7983d142715b25f2d299db4a5942292b402f1f0f", - "0325c963e7a6f72b1793d7596761c50cd76cbdf82cdeac9fff0b0b41cc48b2b211", - "0321461920f8188dd838ea1b19479c55a01567caa4fa5791b7f8b7748ff2822744", - "030bf3311e10d4cbd571c63e7071e8b1f5483ce94b9a1151ad55f3f3a6627fab57", - "0302e43762928c171c9d973ee5651107f672ef511af553f831c8872720046a4312", - "020779285429e39f4f1d287fddf98b66677ac6fa62269993b91e04b0f70e3e0101", - "03203ebd4e0c99e516d4bced806ab31ac1be9e5b61198492f733d0765ae2eb8a89", - "0301bdf0300ef8127ee7481538c4c9716d667e831d633100ccd989fbb7ee9ad4ef", - "03269e429fded41f63a4bd303f53e4743f3a02dd6eb7d1e2b6d2ced5def2a2fe64", - "0304ac8c56fd9bb08817b3e782600791cf59a68e9cb6e1681f2be149c4ec71d605", - "020f75d8aae62be588ee93426be6fed47923b38ee2dc76ff27429798bdba0de588", - "030804597ea0f13c4b7a5fafca8a0a0ac05a2d0737ae43577d2e373b324203e268", - "02231f47ba42a587a9722fb023c27930d717a563cfc7bed551c12536ebe993faae", - "0307ee2f3a6a4410321fd3393382fd30015e279c0a388af2e434b2d98ff7b5a0f0", - "030d3e2ee3f3bd5f2befe9f10935531d596717b00abb7a566b7f4374bb7d200a47", - "030501e9430aa55225d62f67e3b3a6e2cb979c89c16815ca193680a71ea6958900", - "0220032b23312eebeda761dd361a69ec93c5a5f2726e69cfb77ba2eadafaccfc71", - "020bce208e5467bd2ab3787e025f5b6d3397b182bd399374687aba242f4e78a204", - "0308a0c760f2bfc77c18d3d9e3873a62b6a57daf720308a319a67617cc3d2b7029", - "031b50ffe919b7ed9235e632a82bdd49e318fdbf93c8e1fc9ac5c3fea5b6d64ea0", - "0206b8c21040d7b52e8aea244371fa30412d6a1024554e931f7e1e11f7d449d756", - "0315c8fc3c928225b574af09ca66088c86901b8fdd02d2b3b258cc71ca45d6ad0f", - "032cde8c6173d06bdedeaf40cde44cf04b56a3306f70b5564de7eb75657dfccb08", - "020bffbefba7aaf33565a26f4748300aa4ef26848b56f8074707f8bb236177ff6a", - "022ec499bb9d49aa2e5c11a2cee6a73154ba500581d2d4afe4bd7730efb6f89054", - "0310df048930cfa1ca280111267f5f4f84666be346ceaad754de5c7a18519ae6c2", - "0324b5e2f1704d026d5be2833c33ca55d7adcf9370acea532385c2312abba11473", - "031cf3eeb364fd0ee0204b6c5133dd55ac4fda3528d52e8daed310722f719382dc", - "032f0cf855882c3baa143095ec32aae82dc1a48cb9f95007bacdf778d47df3a1ae", - "020ef30f70b15826b91f85864b1be634ce4998a4baeb6dffc5fe0acf16a5c5c1c6", - "0214b1a956ade32bd64b082a4b37d383214ff97c2e8f95a08cef9652aec3cfd39b", - "022f6894bf87c0d9343f1b8b124911cfa817f8a31a1273732f840ac8a8e3d2259b", - "0207fd46803b8e54d0fc0c81749683d54e4e9a32d1c3e449fbf7d35a3c5151a705", - "0325554fffba26074ebd0c30591de9d8fa977b358e4d6cb14ca19459d21a5718ea", - "031c253786e3c445d3b3f605590f2cd4817c5c01439f73297b778c79e562b4c404", - "0205ca002ada1a0f15d40371ea9d7169fe6d24aa9cb8f59dc052d03b8379ead091", - "0225a675a9417328330c4b3840bfefad4af69948d085dd0ac20b333b4c9efddd79", - "031ed5c12b7e5a95be9eec245a2c540470526f62d1e5c009a869da414691c025d4", - "0200295803a20f0d3ef5c7ae1fc4990172d7ac0036fc05f8054ff74ea3b8b16535", - "020ee32d9bbd094eb9e9e57b9fb00c1558dcf8061dba76af5021f3f907ad0decb9", - "02039220ee7d004a4f9647403b8bc7007d66952485d01a0ea4abc96f5d9eab648c", - "0315f5fbc03ba5bd9a3e0ef3ff0b1b6b60f7afdc88eea3a41652621b18fa3f4cdb", - "0327fb65ddefc4d71a4d7d0fcafc990ffb0839476e59636294249d83672e1664c7", - "0204be192d7f5c725b7d28e97e2b94a2e088ba17f33fae6223ebd5ad8efb43cf0c", - "02155cfddbe5cba13cb2ac856dc37f445b2586bba1c7d054b70b67d23a68a6dbdd", - "031e72177a1ba228dd3b3e91b17dbe1df98ce159d50e2db53f3ca08205adf24220", - "03225d1c48235a85f854efcfcb6f903e0c3cae7ef819af72bc1d23ebff88503568", - "0302f3ad6355900e13388d3b356a126cfaf4c4aa0741466d5d1253143f63b9d43f", - "031b7114e8982394c5ace61e25e4ef172cb994bf248dbee8863d78cb9bddc1712b", - "0300f8509e09d8152dc71f108d9c7d6fa7c68b5ef428fd3a385829d520b3274cc5", - "0200fa6b5542bacb401de2e32cfe1f98c0381fcf2397ffca4c81df5c5d2c6b7126", - "031ba0e6b02735b96583fb34b3fd3f711cade2e44d8794436293436e3c037d5182", - "0329b7848eb1b5f3a3fb5d68d6f3e084e1d493f603083a7f5660c8766b70b30dce", - "021cd8cffa0d4411c8e215a452d12c3c30d3fc4e522ade9eac5c626229d276173a", - "0218ac72368318dfa6fc5f8aa4bfe3645b9dec8459243e57400113bb315a4652e4", - "020dada738f81660fb3a1e6529f604bb786e35d95a8ff7a3a636f68ee9bac0fa83", - "031f842142989d9131c23ac33e10021836901f160871836bb9329137ddd8a3a0a4", - "020860572b288bd34dc2a4318ff173afee1f5a4e71fbaf9a6ee93ffb27c7b23d83", - "0210c82fa45c6c0ff25d9b8e4175de5e775a8a05ded743eedbda59aba2c5e8b405", - "03120230e8f2a7c1ba80055fad8c3f7683f5f78e5711dd8568792a12687956fc74", - "020dd3083ff7ae7eca540616405569e27e75288c714e5fac45f13879934fb42286", - "02012827dfd2896b21278120e0f9be0667730a8b9573383d9f8f175b027bb0864c", - "02258d015cc0dc584cf0e5eb9b12e3215acf48f3547968884a409b0cdda59ad6d0", - "0218a17e652a2b2111314b2a2f27ac4345335e42cf0aee27d44f387f1a92690412", - "02168f592d2a0f69db7874e29f88f62e5168ebfa8ddaafc79977f38aeeecfc1450", - "0201b34b6336748c3639af1097eacfe69c69acb0c2029d2aca3a8f15c2be4910ff", - "0214a47e8c6eb9c63288550d12d41b46c64f599e881c236d76a3ccfd3f519d8dce", - "02060af84b1a7be770d91ddda458a6982329015fc692cb2227998723904b875ab9", - "021f7ee00929927c08536c579efc6806e7fa470b5ea5f113043485126f51c8f534", - "032347bdafa298350889d2dbe73c5105e90aa8506a3ff69ad7690f0332d8eef315", - "030e8e8e027fc09491a19103958c4c48da85e03ef7c1e4c8f446179be6355d73a7", - "032416a9b7ab150a637271a6a0030b18798c2ec1a2ad31e60de6f3caad7863328c", - "022a98beb8c1017bce2be2f85d35e134769f43a65ab4fe655a4b4c8a24467b1d85", - "021bd2f618b06d043c23a8a65476c20de26f56619e1b381a7aa8fd876820b791a4", - "02025708a790058d5b713773b4cd39a35cae3ee6b54808c6924288e805a6c03d49", - "030cf82897434042a929c69b56e3f1f64882427ec3f6a4badc903d5dbdae850feb", - "0220c6f5f1c711099725b8b205992e934255ef61dd152e512fdd85eb23b4673475", - "0228b94af222c9e3015598ba4ae1a03127ddb61af4213eb10ab6869c63e5844854", - "022663ec0be9498324d102ce5a579033a7712e05a1448a39d4bb887d99f7b91242", - "0321e56972de6307d6e043a8bfcd4992c7171658a16707e162bf5b1455e69bf270", - "032e4c20b86f5e10077dcb54b42d80cdb79507aca11b70b0bc7882b0957ebb0d07", - "0315906bd865c117d0548d0cf02a63cc8c99d8eb9cc5fa65d6866be8385c8516c8", - "020bc435cf2dcaba36ef8a7bc212ae0e35e22210c016c5225eec64842f9a6f92ef", - "02122b56b9a5d48673959c9fa9073b1023b946632e034c38a26a40d554ef8fa278", - "02099906bf0916600491a870274d8129123a58f7407626b272b93fcbf5521fac3e", - "0326d9b16d383fc48b00909832120273c84d95e8fa70e3ab6c8f68cdac17bff60f", - "020609ca012378cf5933a880ff1bbee956b08cc87ff05e4260cc0587edddfdfda6", - "032222518e0769e3dc7bce721166f71143ee16292b4f8414fed69a66d11de710e2", - "021c14bc6235935ec80e4d6833aab5fbe8dd1d53d5c0587b76eabb5a6851f7eea8", - "030eb2984c4c8e4b5695ad92fe5204db8e1e22bbae9e77906c9be91bda75907aba", - "022bab0eb373ddd49c1edeafef1e087e49d11d2bbd17ae44824f54b363e97e0ad7", - "03161f623c1a23fbd58ab9daefdf2cae6a502d3b9936e81b2c1e54499fbcc4d2f9", - "020db7f1903160b16aad43b73cba8f1aca13829bc427712773827d811b282caf96", - "020503a5461f2825ca1148cdf2e4e9608a287e84e5ae5e16b64fc48007e5c18879", - "020646d697611b254473aa279e6ebbc609b25beabc061cdddba14210636bf163f4", - "0320758091443151e85820a60ede6d6d4815e9d94718a2c532cc1f836b559b2677", - "0302b7b79f2c8f8feefcd69413e9a1e09430a8e3526d4b540aa40f547ce792d45a", - "020068017a8ad23970d36e733ffdc179c41cd49c89e1e1f13ec83859cbe90abe06", - "022b5b7259311cadb86472e856596262397445329849b947af8b010a8625a67f1f", - "0221e61a0247617c291627309a7d1125423c0858659fb728eccc13e50fa3866d9d", - "02245e704f89a0c759ca55d5f47fb4a8b975a8563c824689ae7eba4b7e7dfb2e4c", - "021deaecc160b6c7292fe91d4ba9c53b0b91b2df30517b8055a2ee129d1294c107", - "030e5f4fbbf53d0550bc95c9202ae0ae872b86b224f52baf020188c77ac4cb2480", - "02078543443165238b0b7e687ed486cc7c4ee3991e225c8b5f6d3c2c740123f0a7", - "0207e7b0ba74d12c7a436716b1ee76a000dd86be35eb03a414beb899ed6ae7c5f0", - "020d5efddf6d96b0969bf24222fefccd85708c58bf945dd7cc21f259ee5eccdd7f", - "021e99ff0219beb945479bf907b19848d7ae215be5179ad182372fa09c8da63dd5", - "0204f35c7b00a766f21a9df20757710687941e9d1b417863e76b937012708e0834", - "031e04fa14dbd2dc12065f18c2a57492eb520abe42700e8b764f24891521da4268", - "0213f2169f6e9fb2131a96e1557325046b08bfb48803a371c2b58d6cb64a9a9a87", - "022803ff6989cd350fcf9ff2447ae1a2e4f6c98249d2fbbbc34344fe79bc42340d", - "02298cc2adaded47bd7c23199c06752dc549228857829e39abf69c5750598dfb55", - "032e95cf26c29b1b30888db69d3296b3cf0efd613b53b5308133a76fc5f970f33b", - "030d8701176a509fb143bda3f5e5a8a3be5e6ce3825e98a0d2de482a068d5e334a", - "030fde6addee18687fae42c3802983d70445fc7c51fb609da9110923005dc999d5", - "03027d2e44476d498d9d26373cdaf72619e97d2592ff0271661c4a3b690d7fb433", - "022d41b3c995ba2df06a682da4bd45df1180e2676b51be03a1fe32a4105bbb3770", - "022117a2f8a82639982f20d4724dc3a7aced55d31c7974121e45239cef5c90fc7a", - "032054091963c0ce1595971eeb28ba576e7660b594d79fc275baad38346d603103", - "0319b3609f337c2227c30e59a910ffaff7266b24a09ef8b5ae39f85a70bf40e05f", - "0205bf7e4ca900390ab504330b6b66b4e5eb26be5d371d191f897b88c5b38e98b7", - "0319578a6257f6b97d18989727dce2fba582b8813fc7a37aa6d91934da58814e92", - "030f68ab4595868e9237fa02a6286a986feb745b490dd89351ca92f0c891c88a36", - "021e980dcf90228409bd8f4bc6ebf43ae2b615c79586837e2c05be080f713320d5", - "030e7a62979d8e4126b7c6bd3b900d593f0f890c29608c369ce924d5aacea940e8", - "032141a1c23505c32c509072d66d04e1f6e76d80071182ad74d56761e37edddbfa", - "032107dde83a07a2918e773f5d0fc14dfdc29b720563f7fe5000014c99c79de24f", - "031086733bca0d02e2ce27639734c2c42c28df38054671f404bfbcda21830a3f25", - "02286e7a7ea6f8d6a49dce773ec81890d7781a74276fa232c8bd5c31dea92fd7f1", - "032bfb4af6635e9c9ac6478dd0cced4fc00882c5824634b0d36dbb8f5849f38977", - "032b8edad16e1523a8c559ac83f9373413525b77fea9290109f67caf83ef18aac3", - "03087bfa2bbf747eb05dcf749a844eb520b8738fc3bceb346e1a25bfc5a71e9ca3", - "031924da8e96efb3d052183ffb07c86a7e9a12beea25c473e1c54a74cdec55f777", - "020b58314cefaed50820aaa37c0f0d425c877b693e0578ca9b35c9e40821f61140", - "0324797a15105bd39f4bca651310ef99eaa47d34b5217f901ae846e7760f7fba0b", - "032fd369a108c570b25c2125a8382b28ef304a452977f4d72d470823bdbc801b41", - "031529987b5de35225d64cf9e068eb99824d03ea78f52a0fe6ba0c6814c794c113", - "0213d3d3efe1fe04a6583161113a8d118ae8e096ab1632b8a85faede359e0efb67", - "0316b321d1bc3cee658ada5358599a40fa2942f96f4c36eb4b603bbaf4d7449d2c", - "030545d1ef82dad9f17133699788d98aca3a414a53044947dc91cd661a5ffb1dae", - "020b97962c0394563473572472d988e79d1c9ea3aae7bb6de891a293cd29eec1d4", - "0229f163cae54f211d7ba04ed9afa42ff1830fb53705b949d10e089f9e7b78665a", - "0228de379245a9a878d236619b0e3e6b955a983eaf9c5132667a89e88fd3d0d7ad", - "020a842a4183f2403d187a9354b9743b0297216cf7a151238bc6425bc168a9a8be", - "030e398885941d2c18f98f0565a923f835d7252c927b57993e173e47e51ac01a7a", - "030f60940b1980b0d7a45388156c403f839e91a9202375558f1cce27ea201353c0", - "0201529f9839b47dea1deacfe50248cfb735db11098abf11316e398077241b031d", - "020083a35b87fb2abebae14034ba4bc41a76a9c5c4384c452480f13d6de515f4f6", - "03258d9e4fe6662f8b8e3f88d6c9763bd756de90ce0728f31dc49427d674791484", - "020f1392a41a62eada012c5165f2de7365589fac351a59fb6ec8aa617cfdda82dd", - "03239f8de2898d0ccf262801d38c5ec0d73a1b2dfad0f412cb2c0f043e85fb60ff", - "022dd1727667ed6df066afe6c682d3a5b7cb2b2dec5c5edd7d3d49575f65962248", - "031dff32d8106f37dff4208e5df830ecbb22064777d28e58ae008e49cd0066a73e", - "031fcf48e2e39c8a58cd0d8e387ddfe9a2a07abc484a491a523f4d0093bff87aa9", - "021f78165af0a10454c6b6fdcca094f62014bb7ee9c2057a7e8153630c843d1748", - "02129a6638b1cf40312327fac0c8b7e7c1a209c7b193303f3686f614c4a7b49e11", - "022d4e0e1e8b93942293cbd8d259d9dbe56c944a358c3b2ef2320022701a5f4b88", - "02172e63f902d8931009ad09ff699fe38a5d000485ccdb0c5bd8fecf152131964a", - "02050536470f8be4ee13d4dbaf8294a347becd95afb15a997a4dff2c5b899c9ada", - "0303f48fec3842d7a50cc34fe80193ccd0d3f3b16f3286c869103e07f613aa4aec", - "03256d88cf9cb17fa87f805a475f9c841f9e0a36202dddb5af4712bd264c767762", - "032aa64b6f7c7309a311defc655a496a7551d91ad579e2e08e07dde1e4f8c5af2f", - "0211acb46b00a5b95ddb9110c13c2dd85b64c6175b5041a6e3068717943fb48abb", - "0217d3b55a45198e6234a64d1e1998462a2ac6874bfd1835664c65f08df2094b0a", - "0228f0dcf12cf743d3465a0eebd558a8e8d3215f1c49671423afc986198ee6e220", - "02249619d390bf192e3b78db51fa872e9e6888341d3b9e77544e63616af9ec2566", - "02013f3fa38c9b9acaba76e20f1181ea2ca3dfcc4c1ef585231390b4da7be4af27", - "0205c764e7b300701bb672f546186167f479ab121f582813487535a7bdd4a83b77", - "031af8c4a53aaa32aa6528d7801bcf15e8711acccdb8480e755c1861d8b3f29fd7", - "02282cc08832810b9c3e1a478527502ba10f4535c5a0c142e72a7d0512bd698a5d", - "02150b6ff076fe8ae5c89d42483bbd12b4cdff215063f6355ef6c955e660363fe0", - "031a1e7406a5b4ab18a5bbcac1a02e48cc13a4ccf9a8a9c63c267c4e31cf4e41fd", - "022c7dd2fc0ca73822ac95a497724c39dfe7791a37b844fce2d6ddaea788fe49ec", - "0223fb32bed9f6f9a9ed175e699e163ee210f732ee01f2b52030d29271ba3abf98", - "032750f36f8b616e1ab3b424ef656bf861d82053df702861d119d6c843f31b0e38", - "021561f7f4868250bd0c337bb25b7364625401fc2418fa2d5b65cbc1493e23fa68", - "0308698476418385ed015d523ed00d7244b0c9e0445b53af816930a995dffe74e0", - "020933d5ddaa65aacae34677d39cbd2a3dd56c0d98c9518516f52cd8190dbc796d", - "03173a6de01a7ff7fb28366704d52200892911497b2c537a5f064a4458e1d01b00", - "0306d02613597b09ed9daedac93e020fbc80492ff88b595c21274328efb7a030f4", - "020f2f3a8415d657959555c3f2581c77d35766438952c32ea20533bd933df1e9f9", - "021beaa6dadafd007ca056b48633fe8f32775f114dd2e05a8356e510b058938c03", - "020e078515369c3fdb204fe439197bcd3a8e9ff2459e4e857689843ae731c2e699", - "022b3a34307718237f4201fd852ced4ec1a4daca0e814161a833769ef66aa387a9", - "0202a1e6cf20ded0a33c9fb9fcec577397502dd89c3a7ba7b9a9e0a6e6ea1ca8a3", - "0320472eb80e35520476200939d8f1fac67bbf243eaa3f7e3ac28de74c33af9b51", - "032c51aa07e5652698eb5e41c158e307f8f7fdc9192f41910a2209953f65995cd8", - "0305e03d477e49a990b22186f2a2a5cf050bc7de146f8816b53c6c9a9d8ffa2f31", - "02251c144301ff3b27685d00c8ceb612f2fc5c1f0a29f773fc59d06d8fddeb3cc7", - "020129063a4d92577aff9fc8fc5bc202826bcf4083c45c639aea5101511b043f3f", - "021daac10e243687c525d06d4fd40beeedf074413a504464deb25aced74ce6986c", - "021715e5769df6850ac4290d2ca77ed3d4a92d8daf994ff72e7f2fd6f58226d76a", - "021a57a69510b13379b4a0d548eb07842c98323c4e6614058d3b1c934f5886fca9", - "021aaf51a1013030d84bd3f5dbb4e1e57e892b5f733c3c2182c2ec45842e5dc949", - "02243e474702c02c477bc0e8d3f8c485c569cf9e4e441fa6e7b9bd05918aebbe5b", - "02133ae86c3ab44c19119bd5965150470c3f0dcafa3541964660907118a6a5ad78", - "0307cf5b7a72990f10b0b0d05661aa9292473ef746a9c0a5e0e6ff24e9504a56b1", - "022de4ca168b0bbad63ffe7bf6a510d249c76752a55d733c923096dde4f222f0e7", - "02151a52de120f59816f91c2e1c0826e8e00196ec9d99df9980f29d63002e23c5e", - "021830437601c9071fe1c33eba47e4de160c7ea70bf50d91d24a88db1f8642b840", - "03051598d1ad5f5e8ad13fab7ffe57b45c2eebb5ed13745b3356031f7c558f3205", - "0307482780cd9d59626e06fcbc1177c5be322ef2b51fdda98bc83d569301cab233", - "030b72e52e33504af2b5215b25d394be6e82f1ee47f438f94e55897ea3be20445d", - "022e07949480617370956861ce91b334af6a10bb22dc2b41dd5afa8347b852c1ab", - "0314bf579d25b3c3e07f1ecad8c2df494faa7fd0e12cb760d048fe444baff1f73f", - "03131030ebeff5a896ccee004f6c8bc42f68f97950ec34635fad43af44f0a6cda2", - "021811993fd38a512a6e8855ceaedaf78762c6990c336153bda844658cbb5a2d1f", - "03037a5cd3827ca68cd2dec25b696400e44429f614ec8b15d9b04bb14bca29c04f", - "022b0ee5d88454428051717b206ecbe4f11e4021ce870ecc087fb57da407c36e64", - "02231084ef59aabeafdc8659ac1a48641471b9a2029b8a0584c2d05a1273e6185f", - "022e78d8b93a23120670291626e44aa51b1013318f3c35660ec40711910fbaa3da", - "0317d27f3afeffdf21888f31b34e9b86a5c83614a8d5f6a7157f17785183b20493", - "0200553a9375c506cec937f9f328a6519b027b5d4c306ea97f573a916ecd90378b", - "03104b87f0a50f463b26cefc65c1b22eeb256bfa12eb171f9845562c9f2476d498", - "03156aff4626e71127dad30be79214b4b33f702883dff6aa65d65e751e967bd246", - "0309aee2bfcd80c98c35673f1749a9f1d916fa78a437dd9851f8c475a972dc474b", - "022537aa211ffa5a31b7296a7178a1cf8b636353dce5ff430b1f4c046edd0d44bf", - "021e0b41213e18d659077560b9ee7b1e16283d92573e897e6c16d43dfe1935d1ef", - "0217798226f3df3e9e1a94e84686b286542ae58653df83f16fe57a4bf9680cc5bc", - "03050e14ac2410ac57cc23b7050d90df6cee4f6e8a4f81d561979f231a162093c4", - "031eec0d74595343c5212ec5f75d6e07d15bc8a2f5067e8c9a6f5e2ed2e78ee11e", - "020fd050e61000d091e4678ff5f0b5cfc1d48bbf30c9aa4ac2847bf252f5bc603b", - "0324bf3b999c55bc8d1a334401dc16263e3e935344140a7a1ed4e6435c2cb8f913", - "032dadb1fa77dba22f0acdec8b8f0a4567ab3033c28b6347f878a06445399c0239", - "0224a08e21e19627a1b488ca2dd2e8a4901658574d6a00b6dccd84165665ef146a", - "020166b02c9bbce70c5202773fd02bb1281b9569019f087a7d87aaba748e1737b2", - "032c82bf78a7ad96d9a8f6475040e665fa9f0294a2638bb924ef710382e7cc15cd", - "0300f794e3b6b5ea3ba55ca815cd76d98a8407d4cf27b60764f2c94f0dcd16dfa9", - "0202b4ef6f89594830a659bad9273d37f3360eb647deb084357f89358c3e44cd25", - "0318c9c974f15b46c7634b7d8795af78bd8d56d213a45771ecdbad711900a20ae7", - "032eec6b37e8257ebfbd649129276d0ce2c1fd12b99ce3c5b07d7d3cf310f6c435", - "032eb2fadc038c73f87354befecae719e5ccb48a36746e23a9beeac71a8d0f1bc9", - "03291e9fd452c6c69dcbb669b8683538b0040695dad37c6176c538e05d8e3b53b4", - "0309bffdc7dd64fe8b51ccb1f74849aa8105608163ca3a51b7c5e7ebde0f3e6609", - "0202ede5966ba5b1c71281f26a2a3d57e24eade701ade014ce08c94800cf01c305", - "032c5ea969656529f2726d86a9e756f57d9960a9d7d27f2941e7617656c6d57e63", - "032e96afd17bc2c0bed14053fe31037feaa663eb71e907adc518c3a644057a7ae9", - "0214da475f88c7d7a2b6f8ce1da81b1765e010b5038465327e50f5cd3d76da62f3", - "030389ce27227f4b3f04e7be70c8ab1d40b847a0a69fc1de7f0ff04770c038b504", - "030e87afaff3780d12f7cb28cc6aaa685d992a9915167d5e7f5ed4bd5746dcbf7a", - "021fdd56afa2db3660dbdb0d643c3656901f1082ad120d5f1bbfb38b8b83bf1cd5", - "022a71bc723554855b84e1868494496472ff3d80646379452f41514731bde582d7", - "030f1beb53ea12d32e16e4faf5e640926e548acc7c3572e3fea1eb12d8d5658c5e", - "0220d561659caadd539cb191bb07fc7a01212eba8de94d9423b225f3442497d4c2", - "02277e783cc0919d579fdff72a10d6123db7dae7ff83409d3537d7cec920b512da", - "0329f41151adca621de6543aa57303c0b28ca5ea3e821115acfb1550497b8b1ae7", - "03248574cc5ace85227d06df0188bae0eee5b3fa7254a210ef4b0517296e94dc88", - "021bb73be74f2b723248ff4d6e148dcf483978de90cb18d60adb1f039a8e497f62", - "020ff89c6150e5e9c05b2be55365d4e7f30552fc053c33f5a45d87db38395dae82", - "03258f726ffda89b58de7e2c891354e34ec4ed5f8df601fe824fec671199256759", - "031c3b9fa44189b1e4bbb29aceb7b5cb0cff052e7b0d8801a354aad1789a31aedc", - "022cd2f32e2355314dad01699e9da39e5255a7fd3020acdb348f0e6fd919ab4427", - "020342929b4c9c54801dc0dde77b4c3f9f569fc9bd4b440bc146bc79c7c088792b", - "02183d970e2b4f25f192b8cc1e4cec67fa6d84bbd01c8750c187c70c0cada62d19", - "0326954ca0a996c69e6661c978914797375f59b6e610161d801f3f5318ade53b66", - "031cbda63bca9180a525f9cc81a93a102142e9aeec5eb355428122821d98844d7a", - "021473e18dd2c9b898c32a5ba5d939bbd4cb091a69df2384caf639e0013289c9be", - "0306c6c6a7daf7825412d9cd97da29a5b603c83301b6185854fbcca8cdc71ea7cd", - "031c48b658533e43c5f0dd64cecc0b7b5ba77da20768609150bedd0f89d30a5c5f", - "0311dc99b8c235e27fe321bd604b7566eb7e1b5efe3c489527a51321c801762676", - "031fa0e80418074c3fd591b72a39450136ed2ceb6fd788ebf62511f62e2345059b", - "0212ce500c8b2fdb43ffefb68eba1410384d1476be4ad9565c5b858167b358e6fb", - "032dc2f53c33d56df9119468a0f7b825673e8c2d620025bfb6bd97092a82e52e4a", - "030ecd1f9d5d46119d803f348c2099e91ebe9c78cc9524514acd0bb216d29d7884", - "0301b21cf7cb986a25097a19dbef2302c7ed32defc68701b2d9dff54237f71afd9", - "020880252e6453dfefbfdd6e9959442a54649865d5fa0a7ebcff048bb40cbd852c", - "0210f6208f75a7fb67fdcdbf9824a088d25028d4dcb81130a97deff3d9fc88193c", - "021da43cd5e540a683411c5bb1e281d39da9d3af49475b51e79ce307cace522a90", - "022b3969f42e55f20f19145a9d777f8634109a15b90186ca06d3679fa56b3be597", - "021c04ff4c040d0b704abfb359a5a8be5aee21d05812952d64fc7ca7f460780db3", - "0216284ca6a455c6c57ee9293fff479bb68e2ae7f45a86092de110c742df6806cd", - "0223f18f000992220b56f75082b829026d37861557c04cfeb4c09607cf75943bf8", - "030dcb1959db4bcdcd861bb3ca6714cb6004a5397aa237459bac0b25d4a77f5243", - "0322577ba33af4855c12247c5385f942ed3cc7d4a8cbeba188edd8d6ba873fe29d", - "0217ccfdc4f8af15263577df068e5f03764c3e8b30feb443faa3510d70eb561cb3", - "02191fcd83127030dabb11b5e70eb6ef2775517e478a8162e27504c148f36dc2ad", - "0221fde71ec6c0d92698341d8a46ec6cb2a859e9afd70b0f23feb541193ec9ed76", - "0314146af264ef4f04e571d10b4b178713df689ac98752c42e3e64f2b369ae47d8", - "0307f47bfa2bfe16115ac6618414c8fe4cbcda6f6f1fafd09843f067abd04cad2d", - "0318467825b2272951ec433f03db9313c13c8e8ba463b5f98a9f6a9694a5b5328f", - "02120db02fce28acee02aa4d06b4cfeadc0b99841d6abe5709546c23e20feeade1", - "03255050eb818a10c8be031dab6a96c1fc81a0a99a1f751e3a7b046f5d469b08d2", - "030f4de500a59e655888d99024834c311ab5ff5221ad71817a3cd90c64e0340adb", - "03167b54d9d6615b8fe91a508742f0ff9f68969427a3d273dfa8ab64b88edf2d55", - "0214797f7255b594caae8afa2c89089b72f0dad0d627ca77c32e53f811ade9ffe5", - "0319ed6469130a643283b589af6491c2d024fb91aad8d09642767820fadd1d4f02", - "022fa481cd3a863592b6117bd405d16bfa00bbbe6d6bdbb9839efceeaeee83b894", - "03244324c009ce74c3ce401e1b11462d22cc1802a882d77992150b84c05cc6cffd", - "031cfc2cb01224cb55896d49809c8429aa95f166cdea3d9d7c9eb59520c83cbc60", - "0224fa1c6d74cd02510f66b53285586e545c6f9c109b4f76034bd3e4af24e4dae0", - "0321eea1ec813d9dd0d0eb11854fd097dcfb4f235e7fa60cf6b2c17fd2d191d29a", - "030789cce7ad6573813c08b2b70837d88bc150909324cb5ebd77ef93c15f64e1bb", - "0315034a12996662611adbb95754847d95cabae8c529a87c5e7ffb4bad7f1ac1f8", - "032e6526ca748511a23772496a25d14275150519a599bc3d456ebe3b4196376783", - "0301dad1656b905ed2cf8ca02bb8b5050ea8be05a9747a606adfef5392772fe1d1", - "02283f1ba1d14657d4edd69a55e10e3bc2488e6421d1f1a242ceaf345f36b115d3", - "03113b926cbbf76b67a35baaa62cc9cc71a72f1b987060bee227f368c618601e61", - "0200ff51754b977eac0df189363a3b7ce461d461bce6f649a300d08a9c36b8ad68", - "020f206e0bdb7811a0fd69023299dac775fdf41f5ad308fa55591f3b3d9a2b02e1", - "03231fbc600a2dc1bf04ac22537142570177f11bd0fdca24efd6ba4dd3268dc001", - "030384d35551dfd155e916cebe822ab4cc027cafe393b5392a9cdebc2ed5a7a5fe", - "030a9751ba4e158c8d527b908393ee1ede2201b279d9dee9e5528aa84f968a5884", - "031845c62ce9fed7adc715af1a29fff5dd17d20d9e122b207733f96d193eb6ac80", - "030462f19230d5d6561386962e69bc0272c43ccda89724f24a7f52d7c4f5ea7651", - "0223032e8c917abbdc1b7035d70123565deb0e4c4fc4664c7831dd045f31dac025", - "0217b95ff4b85890838518b195e77d9fe25243521d70a0dfae8de227d18059633e", - "022703e61941e095be92afa5191b4b60c8b5013121f1ddc5a428fe9b563ed509e5", - "0213ceb5cdb15ff9fc0ce41919538266e87ea0beb72867a849c67534c512d172db", - "0223ff3364450d91a3bb512919182f3c6270a0fbe8bbc805bde70a3c38a08030ca", - "031b6a279a00ae010656de8405443b9a3752d77e6288e4fde75c839b576bca65fd", - "0319c6f90a01ba65854aa8d4e7467d2fabf06a348aa737dde1201058938aa3f58e", - "03098450deb5a9a1d8ed57118add83a0692bb63933ec83226588c7c134c908fae6", - "0214c3201909ce54fd7dde078a68b68a371b1f809f1f8d281a407152b5c359618b", - "0214be47b6bb97c1b029e4e7e4f21387f4403490d819c31f437ba91c93850a811c", - "021c8cccc209e9dd37e7efe6cf4ff9ca267e358128c74fe3d9546402fa852b5386", - "02267a38d04725f817a7dacfa5337e9c0e34590161f2fb3d800d7e894ff9cd7f2b", - "031a57af77f8a47a73462df03e74cf4ca353be2fe52b788e9bf1811a59a63422a0", - "02265682d7d45f3712b02e19b7af094cfc7d172c43ed615379eb9d9dab7251b635", - "0216cbc0ef30f2cf4b484fc2094b6efcf15a05c4aadf520f798b9bef4f71391439", - "020a301332c625a418fd80023d38d3d07de6bd115f6af945a690ae1c23b46683ac", - "02023d809c5f75e9e27f686ab8ed8073ab7c253345bf2c34cad632b08d4ab8922d", - "0209cf75f87b6a10d00f1a3baf046a36e53927ce98e3c2c6c9eb1e1be160d5d8b6", - "030dd0e1ecf4eaa6080c2fe2d6a30af0dfa5b50f6cf1f903194c57fd7718c91990", - "0213acdb092f8f2694d932826c2f4ca1176660b113b945b5e1d01a2dafb8eab87d", - "020ee52633dbd8565ba3ae347f95261fac47c3d0ac5d52ee38b42601e7c64264cd", - "020b79ba695f18a932dbac5884deb7762c8f0be36c4f165a61eeede0228b803d8b", - "031006f83bec430573a013f9db9654da7b015aa0759b960390580eef16edf235e3", - "0306160caf9e7f679dee7c4d16e98c4dd91b8da43428373b6d23c02b4ff1d79d2d", - "0326ff2e0f88e8510208acf92267a6daf7fb130fa5f00a6e6a21dcb3e635e52b1b", - "031c0470f367589a1a4757ef373048b9538f4901a2c0289e4989f33fab50aa6621", - "02110b6d625c81a994849339f72c259523861557afebba20a957cef76ec0f300d6", - "03084c61fea8e81d149fffba510b70fb267696fdb8ea08551dca4bcd07ba84d258", - "020eef97a2bb9715a477db5382b8a98cb9e9b4e9ec40b8847bee8cd4ef3d0315ab", - "0200aee6a662f00c1525d09318e9fa9ac38a831b97f19c775b3f1269cfda423883", - "0217ba270685aea695896eb710cb06008e25b1a239d2011d7989ad303a528deb8f", - "02076552e161444843c9123587c501c3e376c943235f0ddea44e11510d1790b976", - "022ac510785f7da78e4ef751b69081c07feb16b47f8d50055d27087a1e241fb715", - "022ffddf7e5d01a2db545903de7ed2df14ee6bcf7b71d73f5dd479b5551f80caa3", - "032ea49ba1ad4302edaea7b7b4541fb4cdde32c0ca12f286b47cd7b38851a87157", - "0204621d328e881b248a12534d11d0a7a137f045804c57140961cfa260ea43a841", - "02104bd1b3be0b6eb00c43513ddbc82c006be088a72bac1ab891fa7a09646662d3", - "02046170a889d0316876519894e490aa56a88ff90ab2b4d1564eaa9ea9e093ab6f", - "02191f0847efadd89eb61991323ddce2ce64b428c804f570ce555672f22c7c3e57", - "032637228524db50c72f4c5d886e6bc7f81a1e363e8b62c8ef7c8c3e086b7fb10e", - "02037068fac1804d80eac3e0570415e48f50d1a7c92ec4414a07cf12c51d06c19e", - "021747548ef9afe8deb77de4b09b6d7ccfa71d417ecca14f296b10ff2cd7dc2ad7", - "032e726c6dff1d1e56a19d228e809541095efd896bf9fe23e27415feade3a1fcc8", - "020850f90ea5153b6cd8e419addbf21663d2b268685d39bcdae459cd30e0b7e589", - "022729927f1230b97b9edb813c63e2a1451771f658afaccb03a403936f71546eff", - "031f32ed00cfc571d4b961984e7b2682c6db9b7bea5f91c54e0046fa978cbb1197", - "02138265f747c74715d323f698b720e37bf2b7e02a46e403711152219c853b87ee", - "02231e00c96257d8ee39da10a392b4927135338929b1762430fbd8403f393d7e3b", - "031c8aceae926db90b9083da8855a6e77c47db936a2dbe55613cac44e8d590de19", - "0202b4b88df647647910a14f546fea6e4f9d72fc5a1775c153c5f55288e64aa82a", - "0204bca7a08dc17ab3fa8851d3cd432c9f370ed6546f293ce2df13be412f4f85b0", - "021ae9a3ab89c3ac4b09a311b7d937da097adedb8a8c3eb0560efbcbb482613c8c", - "02032d91a49409224df6554afbe69bfbc027f3e420c0925e177242f95d4e3adb55", - "031b0a564f898ba051fea290e5ee01bb512d7ca70500dbdf0dfd7a340130fd4437", - "021c1ba100c528f43837c945fc0ab27847a17096a652d79042d9e33afb622d0ae3", - "03071e0e86f4788d9a2984a1ec7ebd34ff966bcc15fbafb3297c567c27f95cb23a", - "03276d0d8775405f804856d439aea1c27bb10385d32069e2e12e3f3b97af70adfe", - "0226adfa7d0217d5cacf8610554e39c86defa82cdd2940366077f4d92e6d3178de", - "022687dfa60d52ec91b23b89878beb1e0d33e4d79101cd9783acb79e99c2877953", - "030ead09117da22efbe811ff0245c10c5f9971fd9e50ed4f06436ae7039a50324d", - "030b25adc0a79d541852714bcc86ddcd35ffe42aabeab17711814c49f379d945d5", - "031c5230112afb0c0d14fc2364301a59217b1b14720dfbc52060158ddded1eb10a", - "02194e74f189e9bd8cab49ca5008ad5b8771b5b88ee96f3b1b0e9b153347c3b471", - "021cc8a6cdce1aa5967e481f698e36e3a1aa482ad63e886ed95c15565487557fd1" -] diff --git a/src/test/data/g2_compressed.json b/src/test/data/g2_compressed.json deleted file mode 100644 index a64cafefa04..00000000000 --- a/src/test/data/g2_compressed.json +++ /dev/null @@ -1,10002 +0,0 @@ -[ - "0a041c9de12293571fffe51c1c4c73f5ed5cc9d71fd64f6c9a74d704b8f2171f619b9176fc0d6c804f76a50c3d01a69fa0aa613f0fb4d0d6c3e6bb9e329456c386", - "0b0543e4f2f99ab3ea63b143d6c2901123b8c0cb2be755bd83641b0155e1feba5a5a38943b97077536ebff6eaa638c1468040509beaf006c55425189ef0091b66a", - "0b04dbe35b8a3de15d0ea2bde0ce34085ad53944da1bae37e6f8c08adf6a6cb195ee0597384e7ccb56fd9188c41a166a1fab6cef813129dba5596f69f624f5c883", - "0b08b5a792e9641d7c2e7d2de70aeea2921a7bde6c8db9307b62693e3a98293b512a2c56debb3d1422d0b4f4e00493e6ba32e36ac0dbf1e5810bfc4b70c7697914", - "0b02b01975444aacd25fc3b1531eb9b3901e767dbc3f0404d58fd03518f40609e890583863e16ef27bcba4b9313c1528cda5793c89f6f68672a469027b0333415c", - "0a0035444184e44c651ebab0698c2ea7b07c925b6143389766f5fe790b23d6a0c16d89febec36de90a83871e3e7bbccfe19092cf7b538e3140bf562810a8e7e763", - "0a044a7d2e117491b12535518407629d95f57419c0acbe8f6782e563925b071961c7b010be79ccc991c4f327ec03fb7f82c20982d1fab5da30f3620c0adfc86723", - "0a014f5db8445fa119c82a5cd5c88099d0d74b7b231f569e9cd4be4cfede28fc489c4263a3c984e8c0510adb62a7e0e70bb475236f7658b31c3eef8e565366a60f", - "0b03296f518d6a25ff508e7ca9ad31d93f1b7dc921e27640363bf45b6aa90d08604ae65307b7af7917c68f7828fee22911ec4cebd5b8dfb79b96842d047b208620", - "0a00f606e24d1845f32c9dec897ebd64057b9a99e66b97caff1299e5c6f8df8f1631a6f522adf0bbedcd9f141ed8dd1d98d397452845d4d00243c6bc5efa1c435c", - "0a0450be31ffacf99913d82c78bc4ba2c5bc1b64650b9dec3c998e2af345a01ca71c5e3c740d6c6538c554370e717fe2d5dd9675d0d77f950c9a36f2909e5ce8cf", - "0b084ffeb748a04742c3b633141cf9547e5ee28acdf3feeea7b54207234a6497266d8bc5cd007529f7e8b972899defa0c229cff4aa9cc50dd6ff9f3be3504b9c0c", - "0b000be1dcaeab3511796208126a1b5fcbd7a5c2ac4f26ec6739c714873b7e13349d7d7edfbf5424f4916a039431ee4554cc14c05ee7b0c25a64e63a046d3f0c0b", - "0a007bac50a429b3f0787c16fed8e439e7e1c2b6a023cb6467069a6c5ae3c120e44a6b1c76956234fd0a3cc88bc16dd5437bfec923f5049eaefec51bed511092ad", - "0a0598fd91b9978d7ff66dd2713973eb09a77c5ad39cb57f357fc093f16afb503783cfd2a6e9dbacc12228e051a2e8179a071ac0f5657b32f4d50a8a09b97dfc93", - "0a043b72faacb5bc3cf6c9b9b923d03f8c6366e8a8bbf58c7efaab1d6fe922b8ff690b1c61185becd892ef98168de8764a80c8459a422723bba9836f364eb07f0d", - "0b054e9f29cb35f719727551e821063129d25aee7f3d642ebf25369edb7c5e6713561b5606675a2073c2fc6ed979f1fd4b24c3e8ee2924bdf045e6d86c783e9b5c", - "0b03bbe747a75f1f88307ff2cf873c04c3769df1ee1ff1558481f913fe74f1b2b81f37a85de180401c295d048a5d136f71735efa05c811c2ab8c99509ca7234e86", - "0a091573af3781b686bf6fc73809a8f54084ad47d5c1662b06dd3246c76858a2f5e90588a8cbcb01cb9e60c2c2123d985c1a894332ee901877f1b47d12fbe2273c", - "0b04b4fea1c27c707499a40ed66a48fef02e2b3ed4143a6a6cdf8989966c4fa7db5383720682ff073682663dc2119c9a86c331c01b562fe91312f3cf56fea2922c", - "0b04fd6c04b3a29772dad9de7189f84c6a49f379713c7837cdf823cbc6bb33472ad0059dab2be6b1ffbfe1f6fcf04f82f95ac948bab6b39baf028feed0ad11b2da", - "0a02c3aad46931394da1961596f4f9a4401b90b4e7975f798f136f8ca56801b0230c7b36f186d37d650844e099704a49bd95d3860a5e3ead33dd9e0604315a8a0f", - "0b02254c8eab5bbc53ef1381702bd6185a957d14071858b8a05884af75fe1da7a7f26ccab0aa65d070a43b9a6dfb52568525611e8e1dedc6d58633bae7a9d4a451", - "0a0556cb1cce70946e08603930cb15b521fa9d805bb21894a17ac548b485c555dc627fdb2c1218b0cb7f032545ec892ac3927fead91c3d8bcbae4e82ef63a39b0a", - "0b0747f75f4d78125ee57d4ba041a2a65c5ab3ba386e804f01d5a44961ac8371c1f18fb2331995c2179a92bab7de4fec17f89eeb49ed365d85cfa61f01a9a01eff", - "0b024e437bb596525d15e68b38d280edc57876203eb5bc09555b468c9f70c2e28ada022fc62258e360bc9af4c79b31d27ecc5b2681d63f02ade10ec5c8ca053eb7", - "0b08bec5cdf23e9bb19dafb8c812f3ae25f09da168c1dad1186d801b1844d925693dd914faa554ccccddd545c1118bd18d8c7b5503cda1131b8e03140a5f29f1cc", - "0a052b6bfd8989015974de7e62605a6e371bc1f226facba17f0126729a251d0efa879a14ad26a71d1ce7130aef1410c63b8da9de1d2373916cfcf2dbb6070774d2", - "0b0719d4da68b6b65aa19262379706ed37465071361f6a7320ff8acb45a78cc13817f3a23c60d809a3e7433f046cb6eb91eed9a48a1eea8d34f1299e18509277aa", - "0a03e2e0ce8d4f0ed6cacdd1965539f2ff36d3eafd550ea92c8de954c5a778f7ce990ca30349e335f20d0c067135b7858e7e9351c2dcfbd6cbf698485b5b45196c", - "0b085e7a9a00b10ebb10da05da0b57d3e1e12291833919de598d612889f5616dc9b34a97201adc5221ea247adc566b1638a70954b749eec75dd897a157dae7bbcd", - "0b04409f8f5831ad8f389bd3d16ecb2610bd40f0a54272a6a2bfa2f1a354ac619997d72888067ed32ee19f54d45c2a464daa36a17ad79a5aefdad9c21ead754df8", - "0b0352553eede2b9fc325cc0966e1bf48a673b170558b428e601285f8df96512892d8ccd1831770cc8d03ffe1f5f03c2f0f22ec65a4f287b0937f82d078fb27db2", - "0b063abce5d72dfb9794cbd316c05e60f001cfaf019101c6d40c422938b27116c040ff280dcf7f4ca4e288aab3b92071708b90977680185a7e3a352b0278fcbfeb", - "0a08b998d0e436f0a00ac55c5b0b834a904a8a0a63aa880555f7ce6b33f630ed1b9609d43408804359400d810fff6f27a31d5e736a6b32ba386f92a72c72a48ec5", - "0b03274d5952917f541ccd83641dd99abe1ea0dfebcc2e34d453b16cfeff5b7a37c43a7f0128c62cf39ddfe8eb46ef45a752d7fc634d1c54e4a39d7aa1a4c66e13", - "0b067520a44d30283ce0b0e474558e5a012bf6df6f98dd0d274fa6d10a7f1e8253f53e93e48e4538a7240c395956827256104a70b2ddcd4e412019422a338ff2e0", - "0b02bae96e7a21f308f6fd86f896ec62115356a7c54d3b696cffbb1b1cfa6adefa3374af473e0e874243d2105e24b32617452962c65ac915358e72f953feddb908", - "0a01c0fbc5f302e45a98a9ed479ec99ef3548feb77aee3f215f55a19679addd7a681a57e1cde63d5a89e68c297888fe5e1dc3b1ebc004f94aad018ffe9c7db2628", - "0b050ec8f818a209261f61f848a9914d34315555a76e9ed5f8fc69b8d255c710fbd5a492f3c263f3799519fa10c13360f91234d2f280a879e6cad77d6f55e6673c", - "0b07431b6869f3b48c45508d4433b217d4e77e2b8dacaafdd3eb4045009b60b636fc997e648d783c07e232f1e723ee40b7abcf42bc1683904264cd656cce55ec24", - "0b02d64c9b08b4093d0aa6819e145de721ba2e8fd83092e1c29c059140f1488a1e920b6794f4c1d164814bdaed965c32761def53e55f23f088107584515624d856", - "0a0658dabf4577de6ea078df2a349c769c0c0d45e98837017ab0c1cc8399797f695919db59170f2ae6192757d010a46d81326411be4feaa8d5d3e26f504cb09700", - "0a07e1e49c8620bd35dbaa72afae8fb89a350fde9b1dc649a6762c2e475a03f9d92b8e293e3ea2bd80100cfab73f4383373db9f9c1a83dedeed1bffcc5958d51ac", - "0a06100a687e5ca9f731a0aeabfb6ba23db55749414ec2054cf17c67ec8e460888797ff5d7c6ca8453d1f629675030495272da83da54aff7ce3112c7009189d8b1", - "0a06636700911bd847d2b381692023b555c4863b574a566dfc66905b1ee4231c1052217f699ca68d38e332b41fa134c96ddb58ce49620141417ee790f5015e2394", - "0a04b422a0051beb7a439314b420808d26877d8d1e2f94eecb274914aad8e103ed0762db337f5cf7aacf0c16a2531fed9c5cfdebeb8fb30f101245eca6fd1d32b3", - "0b06ed948f213c52e3d40fe95482d2b9bec5aaff0c2d8a95f383e6326467194a69aaadde991911ddc57530684f784d8f4324d034ceecf6c39598dce6cae14aeebc", - "0a0021c8bad303c342ea8564bf60b28b7e1461fc3686dc8776598bccda03e5aafa2b600c6363ddf2e4d334e5daa08eddeb63063431ee204dd98a9e9f039162c0f7", - "0b08b16613ea2e8f73fe2f62b0db690febbfa137af292f7823e053d5f91ee2397a8b60fadb1a294f8982d5d73a78f14e65b1e3362e81002feeae9f53d15935901c", - "0b0601e47c2ece6a7510b0e9885b094fe51ecc7e1726e49fd25f506519652390c06fd4c68d6d57d02fd0d953176e8aa175da7e9945dc420f7bcb203f5d734b3993", - "0b0805f6c53516d1630f44b69a6fe6bdf881c917a3c79aae88a5ed8513f0c024613255ff147262cf67889e3360cb3d1f1c5171e3c47dafeb663a041014fb1c2afb", - "0a037d07d0c38aa9eecb42c198a3a83aed1beb1eee6d6fcaa38c00aa8b2a7ad2a0d4f075cf0e397355392a12c11f35357a09d78bec47f20e90ed7d0b9aee268509", - "0a032bcf124d59435b7b2d288ecc520c393144b64aafed71cdc38ae1ea2565e3f06c3f937787b83333cb5c6b2233768c1a391d701d9939bf0389a64a331ba9a8c2", - "0b06ac1a559eb527d9d1d5d3bda5bb22238aaccbeb80abcf9813551bf7521084c04151bef35e53915a59832e343d5d1fd81d603b0d9330070f09d2f604ac971b29", - "0b00f34a8e049160c0f81bc09405bf9be2bb78226dd6f2bf86126c45fa2501b9b830b76d7e8a0cfecfe19d523fc0ff2d9a447f09bf692df823f1e052d02e08c3a6", - "0b009b8b823d2c9a8cd802e849410139af9d9576ea01fd90251131b78eb713abc17cecb5912e0318cf907b9c1443364633ed9c6ba376f00ac2808d99ed55f25c26", - "0b05d036630a9e285c46ddb99a501531c779d9cddba181494f8203693b33d95df6d7a53848154abf53275e5b63c727d6b67c4754dd0f2f223313eae6ac3f288d45", - "0a090770702f3f618b46b8bead90697e9519fa8e441c668cb3f009c6aa296818457e3822a43bd7ba1ce3c4592297b7d07b8ca28cc593e13c5544baea51c4f7e0b1", - "0b08c1695bc9afc471d9cf3fa70c3419c55a14b8296d09eb5a692ab1fdadcf8e5ed33e847e692e69053a872d5da02cbf3dd5d883133b238818721e5ec25e7361c3", - "0b00970943b1d9f601637df49296163b15be133807ae4c1152f249ea343d54de4f9570f3960d4748bf1ab7b4a36a06aa533506647740db66a101aafba30830227e", - "0a04b3d56388bc900f12ab9df2c70744870172bc02990aa3e849ce01a001c991b84a83d45492ee0c3cdd3b4f962c7c8861919ce5ffe46f84406f51df7064bbe495", - "0b046fd0201021f1f003c08c4e7ee274dd906168a7f5abadfe1da0aa7ebbedde27b82134225317124dd2e07d51bedc08dc5fbb96f01eb689252432fd4e500e8767", - "0b03fd7f8cdb1c258a4c44b484c3edeca175744857178f54f186f83af91ce85d348ae35ee79d24456a5167cbee0889b3abd17900f24b12cce4638b00247ac4c534", - "0a08fd0ec1d1c703cea4f1fa54a5a33c53281bfe3414fc6f8f26543066a8daaf1a590f8a782b9035954a86dedf7a7a9d40b2432f8aecc95ac3ca856e9bda33983f", - "0b031b52e7091c399e327bc291d9bda11981eb40a674947e2e15d7136dde2b776dedf7ca0d7d8c39e9e6906efeb714bc922a0029cd4171ea72067a777477766789", - "0b062e683cdc07d4a7b5474a97a4b8d38439e17c30c30fb2521a600eab575083155cf2b35f8dfc03ac596e6ec97a2c197aff58e695bb7fee2a9804564773c34411", - "0a052afc405914f1e30a49488cbd3543e1ddfb82a17419bbf5c32fdf3e0b664446efb4fe50fba0f2a110ea9a74f5ada53f384185ade89dec4225c6b435e06cdaca", - "0a012b756344e359e15586f4025fde3021b7ae44246663a515ba9ade0fe07fb66dfb8d19e7a1afc20c6f4cc7408af5101e65785aa31ece563d5a3b70105c0a7f21", - "0b05505cbf51e14c4891ea767e8ca2e4462fd5da9cb58c4dedbac883088a6256cab1993ee5542508d5e86371cec90d31bd64ca0645485daf201c47c3bbd39f1563", - "0a08cdff7e0b4dde663e7d44152da27bb209503d8ecd2dc49725058814c5a43794dd528f67b8b7ffc2c040961fa9180eb68b55da0d6905b4e4acf52c0a196c293f", - "0a07f6225c17e81e99446d52292b949acdc7a2b598c8a41691879a9007cf9a976fe22e4fbc175ee1b48b0b9549e05251ebce72d6d409e12029186229e15893c867", - "0a0005a0d536c7e815a2b8560c1e737f459e7fd32b2ed52cb045e6e2e4e7e883830607e568b077a1c019f01234d6c2ba0e48ab425ecda7d226d27e99fdfa7627ab", - "0b0429aa532d29f6e561f691b84a6c46af5718b7c14aa1de6249645cdd3481dbad20260cdc189ddda9ef994ebc552e36820d81e41b17783db04de03e27f389fb6d", - "0a00b4106d4fdb53db8dfb9c01ab12cb0d0bad3a5373434c1dc387cb55d241968702bcee0afcc95f332e35a1b27ac96a11896c8c623e894589bbc862e39d031908", - "0b05cc4a29945ecf81e8202c2ce2a03efcdda05951d7f0e127bb78d1b942ab9ce3075822ab08b5c830b4caf33ebc448c5f4556c10a8914763a38e697df46c284ec", - "0a0559a450a8b5d128715fc012f56715619f4635b6abe42e3be217c23669d7a825c0a46f8300925b3ce63d81dc55ed5c54c5ac8bd1e50cef37eaa79b780770047b", - "0b0111382a34f8927b6f3250f2615b4e7874ea872fb6407cb6aba1ab4d49134396371ad1afe1193953b08d668e13a11126e24b83629923778ce920ddd23c0fc65e", - "0b02443b00f80f705a12bf7030d848771e67189783703ddd446a0f8036551e3c3e794bb8f5082b834a9a8097aa09cd73dc5d5a068feb13ff6d40de5ea8f66aebab", - "0a07de166e9aa77a1507af4758020c8547f44ec91288fbb5be4dbc7c6db8bca501baa1f576077b98ddf4ed5364716360b05b979223d8204a91d49c25d1d2d2fee5", - "0b02fc697b1d4a0f92647a42b4abbbdbe4de4451d042d1049524786727e3f2df93bc3e9268be2f7e25febeea21e10c48c7e3e8eb8444d1c64c4e1334ca760c0204", - "0a038750cbdae420ffa6e6881febc35381ae64d040a80a081835e96233c043da397a0db4f5a09916a335f5ffdcf4e1e775f85a98a2766165a829515e8ad3e50553", - "0a08af1a01ead30bf9d6826e9a794ae44d0b425be27fccf15c0a87abe19213b83108842d105ad30b2d41ed1b7b5bfb323ea10377890cb7dd60b4de25d108a5e62e", - "0b051bdcb03c6fd9445046106890e8ac0400118b220b403a03de54dd17d6297f8783d3bda8e0e47e033c3fdd3f15bae31f4be6c46d9c74d610c9538fc220dc3050", - "0a06ce91ef9dcca382f462e6470fa4273fb8e20f47f5d2ae0e015672e462e18161714c2805cc00faf93ce3c3f69d697a6ceaa7cc5044dd7e10eb7de57a38e52c7f", - "0b08c3f8ed53c399110bce75f5f16c0e5e463420c08b142017892f6770020e354851ed559029f7546ca7428bdeb8989d13ae9ec3750627cd0b9e8382a1367d39cc", - "0a0058eba89edd5eacf2848ced9405ae782f77e68792c3e799e7c165b8ab728691c2d9d921aca25ba69abe835e03a6cb22eb001af9adb56e180ecd456c429ab435", - "0a03aeeda4a774601c37564e5d8daa2445b05f6ec116ef9e34b939aaa8941f53765ce7f96306058a4fe714dfea6135be07385da03c7607f635933b6dfffe48d452", - "0b047dfaa563f7af3f9afabf81d8785d40767ae1ad72c7ed6b7c045e12462c31de56ca7d796e8577ca334074d0113ac47ec7f27245c8da4a8ced65c41070f6b344", - "0a058a462657ca69d88acf64ece6aa8d2965807277bef0933e8e39ddc9745afc934c5011968f9d6a3885d8bf292b7b07835e628ca3c7c6840a6ef52dc2a821d18e", - "0b05bca65db65cc9113664f0c789fe16600b56a0852da367ffb3ec813ab08e35c0178ba87d4073414fc0d2dabbfeceb698e580752ccb82dcb6be6adce13fd69972", - "0b03f24946ed15f6e14076bb21877592a59e779408627d75160beb92a8949ffb02b47dd78000335d859e7c1ff694a59badad22a0dd1ba0146b1f7fd3df34fdb169", - "0a07849735b01443e327cc2b85c912b84e1d97c013c52e2ecc62563e9994f8e3df7df22ea29326fa80f4171f0aa77972e23d66018fd0943d3a859443080bff1131", - "0a003aaa8e8a844d47dcc40028b9f65d426e024841ad33d022a132f6e570f48efd31996fe111da01c1ded875fbedeb553fc71d1f11697202a4f116220072a1727d", - "0b011064a68d769e48585a3f0df44b8fa8d51076128e182dda1edcf3f55523a101d585a24525b6fc13a7b21af48b9adcde53e1651ee80ce78f784f193249036c8e", - "0b004703b5ef2abd2f88b8ddaf50804b98a0fa2adff1ddcd6054131bbfca273241232f8950d7e559aaaa8f79b35c5a5287447feae774cca317082d1f1633d7c7df", - "0a02ed962bdd60c94d527406d7880b32b2123e0d8b5fc6f92921f3ea60097cbab79d0090c4086cc31611e67e237dc713a47829e77b5f6fa7889e946ba95438019d", - "0b0581c19ac2a83a9af2211c4e037b46ede73a820246a162dfb5f185b019d6cd2dad5bf16319108e64ab1f31868f9c5267f84528821bfa490ccaecfd1ae414b8d0", - "0a042032546328eae8c4935413d127a7c29aa2d367f8c72f6e70590784bf3d280f4e0d9b66a202e5d96b108cbbfbf54a1479092dd766eb602169deeb818141919b", - "0a0481a7192fc1a1d3711fc74e6afa250e3bb28ca5461a0a27657a8bcf7e18da9ce37ad02986fcaeab047aa1bb531bf2dcbaad8a09a0595bbabfe303edd740614b", - "0b087dda0b76be5abfca7f7d0614881f0785d14e791379f25fa4e188f7be233035862b4da4f4184e52e2432d1242bae071706dd1d5dab401d38d940038bcb96eb5", - "0a038376dfcb04a2d58e67843f02d30195895bfffc9521fd57f982a975f0a3ce1e2dd5719ce909ead34d782b9b1590cb4b5d43e682bf1794d3b59e539e15461554", - "0a08909c191c973d65482aacfc05d54b6de3c7031a7504a2dfd829508428c3c265f8f7eba2afa420d03cd918fbf9080e70f9adae7166237dd9ccfe353b35fe1d7b", - "0a008a5fbf5199bfa0cf8036b1fa108acd9e1063d6c705f720c65c50a13d2bbe56ef24aa4f5e591ab11ef637dea8680c039e7bbcba934882dcd43331af9f48d0dd", - "0b0315a15d4d7b752c9c5be389b5cfc82c2f1b5af3391dea5b41bca4b19dbd968848a534a84ec96dcd162f7daffef5959430ca137d226e438ad3f0fdafe67a7556", - "0b019949e09d7cb6b7eea93267868aeca4cd3e92a15e7714f60cf46bba1fe56a0ff3d89a259c1ba3ae5a588fbc5f5764e80fc368d9476cf33c159c8ac35638f677", - "0b027122f18cfaafd51b64024b44803520a08c9ff2454446e45f4e3a338a13e3668d2e3c4cbd181691ee2ec4d71b32d2834de8d460b43676f370213bdc32605977", - "0a04d7b711c7278a04cc1cec2f0d8fed57127b4aa9fceb3564a541df0a90b8de45aef80d9413bb571240b46e1a6cad9e94d70762b2627633ed4b7b014e1a79bd75", - "0b01a47b0477275bfeb291fad5deac621003ab1c30d6e0ef5939482eda5f840c2fa146f3b6866b7fde1abf0e62697755329063ac834712b6be690cdec2e61f203f", - "0b04715cefdebd84c89580fe5564a29accd8d004edae991887b083122f954c53f66bda2f04ab23c8197cc13236180f3dfb6a74c03ab2175fb48bd3c63c10ff7d2c", - "0a07e5285cae76e9246a4675cbf8f3bbc87e9fd1d017827e86873f2e669111abda14a0047fced0d2da9cdc43f361df026871d13113df68ab7cd1364fa869882131", - "0a0706153d8e38842473427b29f06daa9ee76490cd1cd8965ba52a04f509169b0f6058c0c91e8185476c924cfdc3d71d4e1573b15b4e285021f7a72e06c42eec71", - "0a0008213cfd66de5ff7aad8313cfae4ebb268df4eb8c2b7c3d768b6dd8e8858f16f7bc54e47014c26c9422747af63a22e4f3406ea4b2a4ad3871666851a5a0118", - "0b0716312af6c7b2496aa166d67ed4ece5945c7967e3968b889c2cb13396d40fb93f6cfef7b882fb24b3e1336ee523a2e70ae4bf2037ed0851251ab078bcff4c1e", - "0a0779dc5759a866a816aa2e58951eb4122796d78fc7ab4ff3fe0ba097ca639dea749095340dfbac7436ccb95fbba91b55ec8236e35285a1789dd389fe5438d9ca", - "0b0169c2b2ac5ae58b40072d24575c1a35f0644b3a4b6f6f0f9946d25a7ae373640c5e51d3da95f7e5197d52e8f3841f7a1e25733449d00295c28611fb876a91b9", - "0b06b844bd0cbaf6a6febec27d4cf50b6ee24c6b9a29adb5c55b8c443bc4e3757f1f1e49658d485247a8c3050a854096fb5d41c071fd037fc23f32dedf229b2f30", - "0a078e6c9bf24fc2024a17b1b477fbc1984869cd1ba21f84eb4265f5a457ba5e28633596861322591a1ea2fb9034e95083204ddaf5f2bf152e2d6b9a9d6d670aca", - "0b06e112d9e1d9f3dd5037f81b7a6864712ab35c8e758fe4fd50f0c8541f3db10ecff198245bc2c8b224c40457d4bde6a6426de6d7be7db38e02ca44ef961e27ff", - "0b0168940dd5b4ef833aaeebf5b91a1144984f0881c13aa9e8cb9507f6a945e9d3671f8ccc2d81bd9ffca79131ecef92df42a50febc359099bbaa5373a329764b3", - "0b0262942f24c933a98646ed43d749f82ceb7cfed5e0649fe2c98c51038213da3c252cfb855d7df939f442cd160e2d1d2dd27dee4a1158d688022fae84f4310186", - "0a085793c55b6078b48deb5ce1d5984c3f8515e053b516a296f8faa1d4fbf8cd090dfacf6d0727354853b5145db7b713b121daf9baba73edd97d143f7b38598586", - "0a017d638f2d1d6a35090fe5b98bd8406462c7737cef734ec0f2e2822988170bcb3e4c210470eb1c88a85ed2e6c5202f6ce24c309f865f221c0373d932add1bf3c", - "0a05d70181447aff130dfa2984d75862de6e5670de4a4198a2dfced41163cd4a9f99551a4b08164a5b4b4859cb4cc0e2eb8f1d56ed899f28784a0f53358306889f", - "0b00f22f523f42270f38ec04fdf10b458d0089a7eaa1d55d1a5723a922be467006214f8fb55895ed9515ad3013c9850bc0f1490b0a92a64db3b3a5592de9905c97", - "0a059ef198c112a2c0d7a4ef77e19ac2760d83ca468a4bcdcc1ba49152b13631eb0ce3271b2b3cf17ad9c06d20f5123167dacc145ac4e06b604bd71e389cfed41e", - "0a05cf3d8d7c0ab7b91d2a34fe220132ce55cf8d3f1cca990ef36e5211732fccc3b0f2b8c986032a58e12db90e4fd877763e5dfe4b124fbc089046c93a50a200b1", - "0a006c08602e8bd9f4e48ebcb8f9d67ca6debfe16da29f783465236eae14b466e400d7c381f4c7bfd5cfcf440fb0fb168c365c39fcd56e696951d88109b4724e4e", - "0b00cb264d013c76ed90deb712274bc2ea45af11da111a0906b3757efa11e2156e88fefbc5b4aca2f0e4c269b28c95223758733fe6a0f06475684f8ab919da52f3", - "0b027460ac40a5f13bf5792429761fd2b0438b34b8830deac73d6a63f658ce3616f2648ff5ebfab9f1a836679818e03acf04727738638ee8f6246bea3c646bed62", - "0a081f982245c123051e06ffb2535cae19110ab2e6787fc24a713ecdb552ec02b0afdf25e44058b08ab9713d041ea3f71256209a6d98e6411b9e2ef6805008099a", - "0b01cdbba4d584974e4f301c94bb75dd3f0ccb292aac77e1bd8041d86f654c6bda2e6e2c7eac64ac2361ec8b7956ac7309846cf190053aa1ad83ba904e07eea29f", - "0b01302a3f48edb87666cb8a06856a5bdfa45816afacca83c3204ee83a3d63efd5790ae54926423e569c3fe1d47bc9e042cb455edf7bedc180d286853c87f73e49", - "0a04e1f7e8b2b6cb1b8b20dd55b9bf38986820e50741e58ce9694e541f7a6cb0975c1100999a6dac821b0c19e453fd33aa2e958712e28ad11026d92ad0c0ddf262", - "0a066643e4861a40c9a6636fae4f4b0b8d0da2880c4fd2ab8449ad84d2dcb2d58e04eb975d5c98b28b786fdc8cda4df21f64df2dd11cbba499b8072190bc48c7b3", - "0a05f68ac97ec72bb95c95ce8ebab8c40b541246afb7fa2e420b8069713f8a33d5057283b22a9500a31f52b5801637e79edf2635d033bd617ea9dcfd5bfd35df25", - "0a02b0513f33651b766d5ae3f83d44e1476ff5116b18769899397069c837a8132e174d58c36caa73352f09353c252d728f1316332337d0dd1baabaafa9b12dd7d6", - "0a03a907e1b7ef46d5f49422ae87e7dae054e5469ca270fa93a5e441442169c0e000aaf2400eb9a7df635966bbad1defc66c11835161988c7c97dd6fc29d2a30a0", - "0b016a239674bd43226814df5aacd7a57f0f604cb02519184c1183a2de1b53632a47dcda501d4f61f5c26503e0969bfa5bf706128eea7af32c22a5369380b3af84", - "0a07936d1889a173c9d540cedc37ac8367339d802d867e833e7948d5a8dab2d69ca6fdc8c79c40537bd5e9131a0977572defd3e2da122612c15542a25eb4825ac0", - "0b0273d84eb8477faed15061c4e673ba3d18808588154dbc2cb0661ac722e624fd4d3dc5f0a204c0e0cb79896491020005e1f0f4e2c2d07205479b5ab007a516fc", - "0a02333d552afb4fdbba9cbabaf165827ed36a0f6268edea2a5707dde41622f58cf80686a0031f3e23d7ba2dc33b5528f87773cfbbe569c8c2c32b76db27ecd933", - "0a01943b90901d650f0160629104210e71609979c7410fb04a3636362eb6fcb233f21bd81c17335a7314d0b70428a1c1312f48c1d88c213f8645b98e0591047fbd", - "0b00b52c5acfda89dc6c9630412f3cd1eb69207ea2bb46e99ac6eaa9563e4abd8a9314465165fa2aadc8d175ed1930a980379b6b5590cdb44b35952fdf8877a2d8", - "0a023601b85021a9ea7bd29d86fbcd46bcff5641c8552d55f7dea40d4c2b2906fbe7ea485c072819351923fc751e3003a1d03a12315edbddf7d5ea379c9a8e0ac4", - "0a05f2fded258c9e37ec989c46eeee374f8f07e8de94b295a1b85b4df9f0f3b516b28da25cb69a6fdab06996af8c065bb90c52c576edc181646fa7848da9e0cbb4", - "0b001f06407280d02ab33d0a222c07a37d402646b7e5fea1c3336e1eb38b9a32afd1c31d1f14a0f384c13d951ce7d7b5e06d5751d2c529aa04d48a46f32f80ebfd", - "0a00d0ba6ab291932b0d7f83473fc7ac77113d475c3106e81a65584679cb8340fd84c5687ac96304ba879143a9cd8bbc8d5e76da1af5531d77156899b80216d861", - "0b04505ec47fbab443b91302fa6e659e9fe65927e76570c8cd4647c776e2ee7743780a9f2c44c82bd6e079971b4483553cdac5a807121180446b33ca3ff91ed5a4", - "0b079887cff6c636243398e8eaf51ded6cf359dbe3c8f6a8ad50843507b069a0b97b3a34e6f0d48002c484cdec636eb8bd9f4af4ba507bc4d487c90b7fe7182af7", - "0a05a915b318da3c67b2a1c74d2e74969bb781c81d34c7ff9dae55fbe24424a60a3c4559d17541ee3bc094d2292e7e833e9ee0f6c6147b3d946c09c694054b0df7", - "0a0471ff07cfd23399688b776dd87d4f247746b144dd0bd948bae1a0ca2e9507fe72b5ec068e3605b38a3786cf2b18c73f38d4d62cd7ad25229c73d8202cc0d76f", - "0a05007d0c8c40ffaf22811a8fee3b093ce663d9e254de5f0726c85d40a0841f42b56f8c99aa48e2e6300d99adb0a5e2bf0fb904d81bd20b80cfef183b63f1d0c2", - "0b01ea8ea639ef6f78203c2e72c288696f68e36d85f3170abd1fb6373b6e69104df08bff086dfdb2239e309d133b12df81a50521d51205f6725ab857dc3619d0a8", - "0a01f3055622fb2d2ce2095d62ebc2d031dddcedfa3560e37b9792c62ed521e2270477e5d56950e5c613405a7fc67fad59a921dc75d7ea50359c641942f38c6e49", - "0b0197055725cdeffc6637e319a53b98b797e9102e36a1946a5ec29a61bad8dc1b05c48c69616eee42ca8403e38e16ecf8f84e473e18c6e83870bc1fcb6377f55d", - "0b010598890680674156a6504cf3ac573e0079a060a0be4b2866c380e24ad5a89a538fab6121331decfc1ae774bbc855ea922c4898efc3906ff1257c1e82dbd841", - "0b0442c86e2a09d274b4e725cd7dd230c5ce898c84b4bbaa60851dac33233034431d1ef023e6c5e72198d43b30acafdc8f79615488c2e16b51877999da59245c5d", - "0b0415b201182826327d8a63776f77b3473051c456cf61a87877b2398efab10ce70d6cc1af0ba3634632a4cb636dcc657cf82d097f7a9a44b34bce0d32e7cb7a89", - "0b087d6a985521f06ec40baedc10a9651819c7a13581751bfcf99d41f7058894909c2e2b4f224863bdfd46ad412aa4762dbd7001f5c2a916607308e6ff1d501859", - "0a0652fe557bf49bb1090ccee368b116065e2418ad5039c0607f3526b87824759923c2d7579de8ddd9f070915987fec7a906d9ed6a279597f250be994fae527e2b", - "0b04037fe03f69f8b14a744a4a04249c5231eb2b4652a7a6842d3af1f508bdaf15c4c44deba576e6ac14971caa210d38a0828c2c76f1444c08e7d5c7544039fe28", - "0b07a8010e33c0f4d3f01a15ed88684fa08d983c3c4aa88719c5e5cbc9743deadaf8b1921ae5114ded5f990942aa4876b25ac6d540b27776a82faaf649c2c3c5dd", - "0a051ae4d4b9e83662535588a14a33ecfcbf194be201c537099041f056bdd2e5975a18503b918318d21fc3d1ce741591813b3b376b22a82f8e5769878f6fd93204", - "0b079c5fe6a4ae99f06ad184111639b2f886e3762f1dbc5b7c30071af9d669252455ffa6a8e701af4a94e2d317fc3ebbd550b2da3a9905f850a0feddc3ad104589", - "0a0060de4f80a75c5179ecf2fa78985696611cc1552813ad10b935d204d26c49504bf042ec665faf7cea2b366a35eccc88825b648726dde3b07758971994124dd7", - "0a05902418865be0181aeec879ca9f64d12fccf94ad686990f46ed7a4f9fc9c04d244ea2f2ed0dbfafea5b3b50fea5d9eaf99e080efea7882bb1eb4a9805336f82", - "0b03a108b18ce8addc9e06aa7e57a25fd85c8fb99f9cf10ace32f9827a1a38c2f781476e68ec0512ebe5f6a110c338cac4ab0b527e753e224f87b9dc16c4c8f0ab", - "0b00fe88d5a65e3a302f72f185b13ef33e2706bc0c8661dbb4bca7b714e2dbc29c075da809dcc57c32dc61fdb810f5073df8a1e0a1ba6a419bce5d102cac7a082b", - "0a020fb91107ba49abad866add56c3a2fb08e6e35ca1427f6376ed10a3a2e49e0440319dd4ab651ded1a112ed1c7952bfbef45ae3658ce1cd867a13d9e19d1f6be", - "0b00c7333425578d4ffe1f0da99d720aa2ab6b56a75fc89205da5f41e954c0ae340d264312e657f1062fe2bb47e7d565345b8409cd00b138d72e525e0cdba53630", - "0a001e68c9e64caf2808f44a66d595a87c029cecd2069d4a7fc6babc76300aa73431dcfc9de513c3542182b36b387dc12aabbec5481e3186d982da389ef6422c98", - "0a029b27e90715fd82ad10fe8edde2da021274e9dd94dc0b8c55ea25f2ad18e871e68c1deb368220eccfc6821eabf475b0918a4be537e1d4ac0226ba57ffc1dcf4", - "0b056be6fdf26f352a57fef9f3fc8697945de17cf0ecba0b0bfb32fbe093826cb03a27c191375f3a8636b8174a675848f8f32549d3ac3cfa227d68599cea052cfc", - "0a043d56d51e28f9e215f8512e143447da21a4a815333fd56a75f79760bce2b59cb655d843c5b73fb1784e6dfc215ec27ce2d79deb5924ce478fb9ee02ad42e4ee", - "0b04f0dad41e412a373b85b4d84b862413979cc58748cfc7ae8a5f66c046d48ee128445b1fbaadf0b0914ddf3e4c02fd3c94af32491957b6eb47c8b2acc50e0caf", - "0b04dbf3ce327bc09993bfaccab67f9cf755dc84eb0bf49dcf47d0f71c16accc61ed5955949e41b54c73ba31815e7fcad8ff3942bbaec2cdf47131054c0fd3896c", - "0a062707e54a39b3b05e9fcfd2d204eb2e0e064e1bc0adcdf31992d2595b83cb386f1d0c3e3fb4b4775c1ebf3c57f485dadd096cbc905a5f99bb9341ac32372bb9", - "0a04416a8a8ea917ac1b408702c0452a797814948fbcc6cf58d389d882f8bf576cf0c68fc091db0228577f70c977ef75242209345fdd8884d339ab72a63c896f00", - "0a02fc8e9f2fc1b5a8c79fa0fefcc09512e9bf2a736c59ecdfa0628b3e9b075011f66a90b99e724712796e69fb7dcc54bb53ac6f0fd01d824da84ee312ba25944f", - "0a077f8312d16c7e1851005c54d95c6f55c1120c3dc4c880a655298964b958aa498fde3bfd528ce572617eb3e833db197f8fe52f5c0b2b575047af9941c9eca5ba", - "0b003cc95a1dc500808406917dbd9fd2f6eafdaffc5212633b5c43d1ec1a9f358a764429e3b19ef2933d293a1b894de1ee002c7a698f8633d51ca49d42c44cc946", - "0b0831a78d2fd11b880beec8cd17ace5a0fab71da7f627d0c9ca051737414e909ea6e6afae9ebad9d61db6db4667fd3ca58f6e39bb4eac89ae96b9722ed30f922b", - "0b023e5d223927c5f48e7b25afa021a9eade32f493f1c0fb29d5a1fa26e5962aea105f980942e6f3942ab894214618fd6f535cf68e851a93eb9321b310ea98d2be", - "0a02737397934339f251928aa0a2fc510387f35d0c8e78c4cdddf842ee09063a2889adcaea8c72ff04c86cffa98089dfd4bcaf938636acd63b269a781a00d6f946", - "0b037e83e6ed8e7e201c8687f436a44c06af924d64236ae0e8c899203995cbd97a6f5051e08175cf1712d37fd3936ea40863325a0609d830b5ac93af4e42e294e9", - "0a06b976f656c7d1f6f1cd7300c4a311293d732d23c51c95a12a6c8217eb511aee8ab6f44980ca00516ed2ce1dd572246f1c9219bf54634554ced238b26341aa87", - "0a02f1070f24e0b7916c51c42a1ca66ca9cad7e078f07278dc7b18af9f12d1572e5d533ac25e54724006d79c01fbdd8a02f7faf4c13623804935b947cfbe1d71cd", - "0b01b4a673717f306abfc4d647097c1d4ccb6ef169a14bf7494961a097f8f6b9572d99ae9ed2a56e1d0915e5466cb376ba61c1a37e5d5e7c33ece7653090a58041", - "0b0466bbb7d1cd558eeb7efe44ebb24a843a99fff790e57601313dcbbf1d27b0948580252e4289915d636bf4ab31fa731e4f798007accc0e53ca5c468ee1380f38", - "0a02ae78f1874c0440242ce66eb1a46bf4fc11d60dad31fb4f40742438dbfa3cefd58ce51ae5137d55ff100afe9fb6f72d3a2b5d3e0b318010e8a9495ad58e16bc", - "0b071761a35188cd07e45f712a5d30502e050fa76c271a901492f9802e1ba7224628e7504951e55717fd58f10a7c1bd45c6e7bb1688b651c73fdcbf411e365e438", - "0a0710a5996e088d93abe465f9caae8b24b4b59123248b062254860d0b4750aea1fe683dbae3e7a364fefdc40a89c788124c537869ce9533221263d7053d537bcc", - "0a0071d8c3b41f621139dc4dff1eeac20bbfddf1dacd33611437bebb97da09e18fdbbf9a86a82cf092f7d00ca9f30aeec424f6034df7ad8d3a153a0f9bc5912ae2", - "0a005f39191f713b71080a9e29eed04f83afb30b843b2d6903f520492ce86c75a034dcd4e6fd7320e2e282968d99de0276eda9d485263f6dda1b464899e5eb97fc", - "0b03be6ab87c461aff8d1697cd9c960e8bdc05ff524e2f16c8ac23ddbe6cfdba575109cc7c670b56653343bd90a87647239db1c03f2baaa47ec32422b72a1ebc33", - "0a0408c7e0fd9c5674a383ab6853cf5cbc4d93408e98a8c61bad09e38afaaa73d35f778984f756976e1650be9471289514c2533120f4313b7c661660bc460746d8", - "0b02c9f9adfc3f970511b4018a83ee92aba03286b9161a50b96c1996dd76d351f01c89f3f9df08c6158cf8e149720a8ce7993d8c00addcd26acbddd6be7a2910d9", - "0a0584cc09e6bdf47330bd473d434b751ad42be69e898f4a55b3e10ac80580d2904d0d1f665d8ccdc048305d9b7019fc0aa61a72f68814763373ae9daa6b35619e", - "0a0019b3050622524907c586faada4676ebe2f6e6a35166887c16770a3de442cb73105e9bb473adc5c5ba37768e7eac97f39bdaf8fa97eb38e1bf06cfc01335899", - "0a0219280ae69c543e19ff5af1b3b85b21fc42b9eef0ed3cb868298d0571040d87ccb8182ad81f23fe4d41d2db96c3b725e2fc333cff35bb273f28f153835657b5", - "0b02d0898313d1fff9e3b3eaecb530ed9c5319d0533580ceb5ee79647c2192228045120689572da22905de544248901a69ea48fc3d56a892a737f7a6d5d74d3e80", - "0a0610dcb43bfaac68277dbd3bab670f11380f82f420fb46645e0323da9dfa7b31920dd6f9d65c472f645b47401fabaa05afee25488ade7153dca44738d47a5e5b", - "0b043b0e0a23d9c470fa65453e312b7e08fe74fe0c50ab4048fd1924ab9bb4eff94804353f48fd0774cf1f6250e777a29c7efd930c3afe57f8526ac52a639c2410", - "0b08c13470cc7815b15653f79a1a2e7780f45b78538a710ba2d3f34fb2cbf10d9f07e2874b472dd9284267364c02b5e689b7818a877419a0930c29a3d3790c5ccd", - "0b01f6cf6a2c67f5bfc3f51e5fff690d2a40db8a5b56d4e903f6aae75a261f09dde48dc35f2c4f35bac48d6766b882578d60445673dfeca4b3edab5b1b2f3006f3", - "0a0873ee5ad1c0d3079c3505e1ae22c5480d46679dc8c928942728f7618756b6daa66acadb908a897696cc4c61a84ade68de3971a0cbcff6ad9b960c07306fdcba", - "0a01c691d7c912face9b5c25d61325fc9dc419d81a6db195e042e3df5180d78b6e06e1d0d3385ace6f9b9d5a1fefddf2514a87dc284054cd84503503233a686f82", - "0b090f8c41036740d63e7738c449d97c89363bbbe878870cc903f35881e644be4cd779609e445a9fbb44b8bb1314bddd818be0b82579d04e8d63e2dd08ce00a384", - "0a000206f20bcd66b1a127ee765b8496d0e2d4d931f6aba3346a563302931a467395b0f809c79b4376ad9c94250cf6ada6a6a278148189a3473ade8669a00d508c", - "0a076c8b4479cea756e04aae5f4226d538bcf50979ceff2368088240d8425d9b2dac6dfef492a6b07c026fdd0fa92fc2a986ad30abb3e6e5926840641a9d76133f", - "0a010feaa4c778b06833a2523204cc6d32c3b233a11d6506e4d359a42ae3ea66b830c058f58f2ce5aa4e14ad5d0187af738043bfd9919cecf1543e9efddb1f1bb8", - "0b001504383d1b26c5e7af2f4d691f4baf1881b96f2f5944d9f553b18ec28daf4a2738961ca9743ff611f69654bada1b4839b62eaf29aa8558e3f6f80fa8181013", - "0b03012b0d8c5d98af79369dc64a7da050f122ffe059a662ba15070cc006292cbc7dbc8fa636ef73b0d6d2828f03f9d6a4f8cfc59b541a6dc8675d42995d3e292e", - "0b02d9dd99f6559b8bb59febaf6c93f7129fdd3d2bd8710719047729e58879e8781f1d29ddf9c8df9e2c31014bf5d17e12f6089cebbcbdedc86cd05da811fb0c52", - "0a08c1d47d723c65fa99d537296aac1476def6257ac999ec9dd3a04ffac2bcbea6b3025d14272d7687c7f642a8cb1bcec5d40d28c4cd58eaed6c5de36f3f2fa13b", - "0b06f775fef059ee43e1b536d09d6ab852076f610ac227a34a33e1fb49675851623620c1137d60420eeb619e59a47326cefb44fbea8134452d1514e1ce1f310f5e", - "0a0185793f48662beb4fe895176a8431a454fb859b79b788135e593a65a657569e828cd008b6010c25875bf8f3ef0916906f87b01e7b94726147b966e79d1b2788", - "0a0389eae41c934f0d6c97e02239af573f7299d67330a8cb321800980a8a21664a6f38131da948d68edeeaa68adfb838bfbc920add551f39fc92829280e34f25d9", - "0a04bf514e26df45d4df7783097e278519a6d9f5fe356a00dd5fc391276b47e5de7af6069a2e1ac1f90987659bf2331110402c7c20db6ab09351e1f136b3942d1d", - "0a012987bd7f96c0d3b5deeef3aefffde96d0749c96fc6f0497f0f46370a9db973a75e3d5c139b8e76a29bdcae0d417b3acadd679362f7ef87dc4589a0edccb358", - "0b059407089bf7fa9b8a932a9f4215a62e1544ad0b7fbcba7829453a4f9e3e8ab7dc4c73f84976c49dcc789f99b1ac8925ac096165594f9175da6833044e75c25c", - "0b04836de034711404e200ad910c702182a054509466d3af009bcf9486a795830bdc6dca017715e08a78aed0f2db71620a8e239630e2b2187f86fe4ef18045a48d", - "0b0647f4f1b7f46c6c2d9ef7a3b00a8e3df56580541330273277480e959a5363cd7650a55b20cf4114261c5c8fbaff99580cd7cefea8e8f98bb4aa96718b1c88c1", - "0b02c1b4631b71df5a0c1deafd0a2338a1a8fe6debb07f74262f6341caba9ccca4f4361a8b3052d50654126a5fab8e421fa6790490a207defe55ee19698769bb61", - "0b08b45b30dc421ebc03a18285fe7551d8b87c27ba9482997d6e7b3ca5f2f69d3efcb839ccb8558c6fb2e1786202e30b0fe8a2b695c77ded49838f0336d40eca87", - "0a08575ab4a4aec87f4d41f2d8d76f2ce7bf501f5d82d8594f406cc92d9c773f063c555d319f1bfdd2767d3740489bbef743ba7584ec187f9e331c08ae982d12dd", - "0a083f6ee0e7f5c7696dfdeec34868406c5c6b91f045df4b0e0e893e572d3c8a2d5ef2ba3231077e9a9d50b1720cc1aeb730b69043c7a07558f51cda3b1415e30f", - "0a045bfeb5d058355a2612a6053a320dbf36d60e7b577f6ddc8a1fc3f1299faa4dc4a308c3d03f7861bc7d302c4bbbfb5ed3a52c53a3baaecb455fbaf4391ef0b9", - "0a07c71964aad1ed187c4e0263e3b815c6fa583ab5b978d620525aa06fc187631570c0b6ac5846fdface56f27e46c5e470d70e855889621c6be4c6bc99331c6db5", - "0a0868575c260954a5e0949eb95448a955faf135fab0c110a90b9b83acacb0c1994dbbfece69328e9f5cdb20036e5164cfe88707f2d35ddf2f13a2ab6cf9522dc8", - "0b00ea6676d1299c8ecaaed7d20ef58f6737d49553350898e6df65abc1f008bc0da9c6d29dcd0a4135c7d2655080bf073b2e272a8c878770ea63ca200f1c4781ce", - "0a0259dd7a134f47f44e65d11304f5f571d335fc123e9f3d9820aa6dfa5e177132fc5e9875476ab5885f15361f6adb715eb1f6c88c218a17a700e52ae8ce317368", - "0b00ef0370615e5d471eacea9cee7c3fe7ea39f161ecc844671b9db68fb88d938f64007eb64f3b5ddcb82689f456f9c1fd45786337b00b39d005b96d4c81bbb8b5", - "0a01752aa96efdee2c35315a63959529def966d85a065b23d8d3ec73872334f5f95ff917f4559d7ec586313f3f5e4bced78001bb75eb04301bc5415ea3aec93f06", - "0b066dbb4d1eda30c79c9dbb57d76125b4b53955553e4dd2d8d0f56f70e1a8ac65559e0e08676b8604d99579d1ad0b3f7b13506448c7cf91433fb7fe26b773f00a", - "0a01b1a5f32b9b054ac766e889d997681cc949ef36ca7bc65666dfb5c8929c22ef80f502ea65043568d091604c3015c6ad52c82b9af370499c297a72357fba9c59", - "0a0132484492469bb3f3e79e8fa6e8b99c0f54d97784c3b65427ad3952e1d40e988c4e5aa4f099c52f1d0ba4e4f997274b16f8a6a21812d10cde65aaa180a53085", - "0b080f4ffd57651a844e3a3ecba7cd3d697b679d8ed30f441f90b425422248f77e39c4741075d94195a290174659692eedfaa76e2e82784962fc78f276384afd13", - "0a02adb1d4cf610bfbe2ba9e1672daf39204d40b0d19c09be96fd7a392559e7604f51ab854d1c81228c99fe8c8342fe76d238eef252da77f8d8cde398200550292", - "0b0428950f4597ec26307f46eaf79529855bf3185fea479dff8cf195388b4773432ed4751dacd8149640055857973d1bc534a06bc03b6266850b764c3a46669e22", - "0b0548e515ca9fc5673fb29bafef482fa0a20f6caa6d0ef786e8696a8bbfac70818b7a5bbb775c8f4d1ef1ff45bc82fde7ca7efac4ae00243e0fa8eaae64e24efe", - "0a0370aca1247b6cc63c7149f2a2826208d12ad296e1a21afc0423431dd5a7d17ac9d008539bc9fbe32838e4f323695e976a5834e369ac369cefd0f12b29111d55", - "0b004c26ad9880d9fa3ce7400f199c3f3990a6ac55ce6e3e6abfbe3ac234ab4bc9513e6cec1c6f18cb5a81807397a2a7fdd251339877ae23cff22c0f6f6f4799cd", - "0b009d3e3f0f64bfc6af7fc63c5d53e2737635d36fa52bde91b31941b5bfc57f39ee3c91a6faeb1c7288a9594cf3cf9cc8ac386e3c76787723cd21954104f673ab", - "0b01c4b1b522c7e326078f10eeda1430d74b12cb57ae7abb50d82717a84f1671f17e6dae9e6a3a01933d78b4bcd06bc33d6751c89a9fac923e5f582c09acd74f27", - "0a08ce77dc9c6f0326e4ed99be067bf56259c67372b51d0dafb4f6b9963d893f68e50b72cb87bae7d4d1a46e8d0fb95289442517c738740854b788faecba1b2578", - "0a065c8afc5666333cc369f68ebdfa58ba70be61a1cb7971446a385c7c1a767762861ff14915a33995b54f85ec100c0d7425a034143d739cd651bc439554a403c0", - "0b05f03ff2670e3466f7e5b3bdfd428460e04b1b155e20c2387b5556a4544230230778cff5b80d4778cc70bbd203bb874ca7565178b32a2124b33a3d5cc3f771da", - "0a06727ab471e91c7fd90943903e6ef00b9d34c67a97f8d06716e702ed8841014ad984d0ebe23c19803cf61b4b2475f398636596f866c62bd11d8b48caf5c93ba5", - "0a0142ff719b4d5271b49cafc887910f063f6e72a682a69dc5a4ff3e9f774ed26c72d6930f4e1e14ff89a4218369ef46844eb095709b54c6fce6fc325b36d35c75", - "0a08da544a2aa004e31ce586907c26bfc574a96e708d7b3c4237091e2529faa5df78fae253b913693282b73dc486fe978b3133678f38953660a1cfb079c0e4243b", - "0b011ecab9b4e3e2c1347f0826427be4de5d108dbb467df77a4fa13e9d2a533114d7666bfaf7e87de5fac94d5b33be2c2158c683e1a4f4e65af809b7198dfbc2e7", - "0b07f8f1e3a45bcecec6f6a2428b731d59ea49434595bea45be904b81adc30fc1483c9ec25aaa22e8ee22666867416c123019f55acf7c217f87a07308fa05eb95a", - "0b03aa9da35bb15b84d159a3b26ddf4bfeafd21cf8b6ecfd11bf21462165cc8bce1a5a913976fe956d4b7395547cf3198e0d7fb799e9451c723fb4b33526aafcc2", - "0b00d27ac7acf5e94a67f0fc7c736dce57b209a72a08ae510aa651c4b7f07bf48d46a4ef7a58fdffa4b0359572e021a568cf3d4763db9e044970edea4a425243c6", - "0b079ed6715a643c4be427236f74e6c869a54a01bb312c7cf461323788f59c02e66e08240f0f7f1c8fbb86b1bd1e23d6054435ba0a1cbefe19eacda5ebcc21fddd", - "0b0184358e7ae8bde427d33ba71924a46c44a516fc92696a36b82f8b577fbbf005a8a2749679d7fb5ae7a96e42781b74491115fa4d2d26f49e597169eadbe08f46", - "0b0540b096814d6791e6debf51ff0b0248935a77b692d2f25166120232f5d9b53757368bb141a9bd30eec59f8a6c979fdc1bd3081ba2bd52d7564669d027618a49", - "0a04b123265755d63c4f7f8a72c1144a6f830aaf0677b5997c117b294d1e69b63c0237c0d3ef6f724aefa1164cce29d0652d721f7bf779ab1900a18f42e6f7848b", - "0b02534f46f9a7c2f68cded4b6835831dd370ceca0028ee92fc862e0c48ddd40c0f5cb8be968f0b666e08174433aad661238f1bf974ccb107ccd93a230946fe7be", - "0b06ca7481011021f09716f0aea2afa80f6039c2f2febf3504659ab3c6778acb9011bee8abd6f5e076d40a05f4e5e8a22dee105c4ac0962cd3eee0ddd50d2dda37", - "0a0638a3187fa08d11a491cd134cf60cd138f961b3f2291fe7883566dd013bd574791875e841fb143cd3e951013a27b16b0e1978410c2acf47d56aec1c30d2cd1e", - "0b089f8a13662ebc5b9c43a8865ea4a921f68c67a8e4e207fad01c3b62e38d9b643fe4c65246f438839d1d82737fd034c24d257ca75931f7b68496c548730ba5bd", - "0b025de9c418ec8640602d6669daa3dc6b7addf1d6252b9cc34205f824897464d04e14eb37dc242bea10bba1031b19ae09732004297461bf2e3180e2ff922a6025", - "0a01dad54b9b04c3b5120a59b91ace38766c1566501f4efae0eb0e636f28a1415ebfeac4bad69f3f4b78bd2172eedd35704dac2f493eab3f8ce62147aa505cb479", - "0b08412386dadf0eeac492aac0d8d47eb8747269f608a27899f4e675b665ec059c82f07adc64ce67e14fe93e91793cac3b865849123fc8d01b1336d4100492b08a", - "0b0910a0e3ab6ba079225af51ba879d997ba981e0ca966040d7b9f547bd22e6c6c5ab677cd650abf9feba84a6658bde20d66aa2de750f696635a157da55100cc73", - "0a05db34e4899529b522f789c557fe02e45b55aa4f6ecf4e975f9c2bf9a019edf2ac8a5d2b170a0966352f147c92e43ed556ec8e0e6362788c994091cb4d811bf1", - "0a01c0f657d98d6d39954d2e8df97c69b4822cadd3afe140990f4dfd4156bd427fccd1924a6e44aaa3ebdbd8b48869a2ed3dc1c4259bfda750f3472f3bda300744", - "0a03cce40ae5ea9077a206f8c6d1325f9c0e57fd605d956904f21f8e738eb19e3454790e95d4c6ab6775a7415b80729e34219d363544c06c325cbb4e67bded013b", - "0b05029defc89c5abc0fa6c811745346aa35fa39e107f62421c9db57e84b9af716129a3f54d5e0965898e50987ded7516359c1266898378cd627a57b1e7240af03", - "0b06205ee114e341452fe224cabbf1dab032009bf1abc7e3310571143f420ccfc211dbb9b6a49d58298d67ab1d713b1d8aa3b242f59310dde9a6cd5fa7e3223430", - "0b09147e1b61fe70fc0adbbd6ca7d7259ecd6bf61fa98419b4f43da42a9d0e1846ca13be22399a70fb911ef18cfff9229aacbf7d62fc3f272090f2f6eeb921199a", - "0a04d89ffb153e3a7572f06fc2383bed7e1f356728bf017693dfc27ef093da75ff0fbab0793db9a3f4ef67ee7d365d807bad996d3cdb634edc78e3435cf37e8062", - "0b08786887c85b965f08289dc5136b11eba684a56488b41e6afe1bf577a58cea1c5d361ce847580933548b3212e05767e7bc966131689f10dd3f0028a8c37d968d", - "0a048feb8655c1d5c2a02dfddb9604dcef75e10b67347db7a74e9418cd83b2073c1934694870cae8629cf1e3a35e36dfa2c9270625045d08637df8e96df6530228", - "0a04e453bb8503538318f9ef3536466553f30e0f20ab3a0a1c4bb07be74eed32051f33ade2e0e8b9ce8b2391f9d8b303b52bb4ac680c7f10ebca57761adad31a69", - "0b0603649a6a8b669e4f0a4eadf9d91a9a46da4a521004e74ef2ef1fb481cbf4bd4226b9c754cebf61ea5347518ec84dc70ae8181d7c2a95111e46414a45e2032e", - "0a03bd428ba5c83a41879d80e4d5ce3435a95a3652da4a178e79fb9a9866ea76bad83efed645d8f32969a4f8cbc860ef5d0f51d5cc9ff20caf8647e8f5dd7ccdc5", - "0b05ab85586842c805b6f3d143b738e439493a1a22c1cec935f30e8a7b19f45a566a18ef83b36442ba95e71cab8d97cf129dd03a8d6bbe2f9f9f6edd97d126877a", - "0b06d2a4e673d8c42a6954caa66303bbd7dffc4a9b2f6cf8ead8ed59be278a6665d540e3ad2565f4077697bbf4b085eb63e60f591488f5b10ec177075787931361", - "0a0917ad842c77c74e2f4e6c68cb4911e8e41e3b6bd3497d8cdb92b8b9150fa86038fb0b7385908f8ea0809060041bd5e24af7008040b9ef217a2d80ab79c8b2d4", - "0b058c94cd06a3e1c43d99562e9577f18104b848e98de73a5a2ba1436d343c9690adb1054cdd707588ba26e3536edce270d01376c9ab02a15c7bee63e98338f0c1", - "0b002e7061c8424e78c1266eb1572bf08a3ef4d09fa4f98379af1d825125510cb94547976fd6a91272466866f6c313e1cdcc813ce4d367890a4d830e3da24544d6", - "0b032d8a3a2eab2249e924c4e57202f3e38dd0f230b50b367b9d2a9784d9222e8a29a31dbaded6640ab7957a90c3be1e2ffa7bba493f8c96010cb479578dfb1c4f", - "0a0843705e3f180415b26da73ea62c806a403aeb36a3cc27b90ebb2ba2399e32a2196143b6d02c76c3638c1bcbe8ef09dcaf5aa1f28e98a0367e5b31d2a292f613", - "0b05b7d40152bad375a2075331a864328dd29e6bf16605dac6d80219008c83fffba3e306ef2abe1cce00797e689dcb9d77925745d286d74643adb157ddff6e7013", - "0b0155c231d992285e662cad5c30eb854107183b2fa6814c67bd59f8ec375cdd4ded944280b6a23962242b4dc5d88d93e833f39bc901fe7828e0c3ffcf46de0cd7", - "0b0770d7c980786f02ec9edb1d89074e814b42621107938b4e974c2494e5d4b900bd36688eeb907b795a0bafa80e29a69dac4806c98b46b27a996cbeeba2d57fc7", - "0b063a82cd055dc8bfa522eac1f63ffe74a64db5f900f8b55f124e7bc01acd181eb4420875487cf87b309f1a95670d8e4e11b4914d1123465451ced2b5e9fcbedb", - "0a02df30102f7f95aee29e03c9ac98047dcac96ec95aaa713128f6222dc5a8154391f658a74172cb3bbd7c807320e73dffd5f9ea82b6c01f8d1b955b3003b2acf1", - "0b06c9d1ed3fdf3fd417c1559bec1cb3eaeab6d3c0fe782376ef54f0d63e34e6abc18c94888493f3b4347e258df61af743ea2cd38245ce9a1f59392a597bec6801", - "0a007a0f840c1a6c40b8f86119bb690a880c2524137d11cc40dd13ad29f7481813eb8d3da46dfe1841ad0d8ebaf4c91a31896c9aaccf342bc42673eaf02022f242", - "0b00c8fc3195156ba8066d09fab7d019292bfd47608d69c79fbee2fb90c88d346db5d2b902589c34d8fe41302792616c7d8c703713881997550bcb9069c65bf472", - "0b08d77eaab06abfba4a83b82261f2736a0c322a7cd7c3b770144c2fe0c2032c2fee60808804cd8afe3ebff59da0f19de8816196928e9d847cbd2924abbea15e82", - "0a00d55906aa609f8e9f99f970adebae649a68440dfb11f9e5e269603c3db11fefd7cf0871066205cb1eda80152bddf673a0845a5acee6d96683966a4408ad6d93", - "0a070f8ccc1f58cfeadc1d1c2275066a9798257193b0c8de5a479a0cbc6c14d2395f0a11b6b0890b48dae0fe9a7b1f40e6f5aec664e15591c9f52e4e21b3febfa9", - "0a08dc87b593221ec5e95ed4c3caeb2c1df1c113b9f1d1b149d266a25d21a2aeabbdb8feac998b597b0a67db15425190687f53cf92bac07bc71d907502034f14d3", - "0b02aeccfc7eb4b600aa54d61d684f4b325d64b5cdfff316eb7e6bd246d24778f3018273685be06d8b1368e87a781b737d3bd956914721e70a7160cc48476a66bc", - "0a03404ed0d232e5139c1280f452157c49e857d0baac47550f3eb8683896485b9a581f7774e40bd050ae8762ab0062c087462ec3ec6c429eb44d4e2012848c954b", - "0b06463b2a385101fbf8751ba166e4565c3f2ad10f7ccd1590af4de25238d49ac50651e1588b6992d6aa3a65fc08edc2ed1feb8a95e3b3eeb614c1cf2168a27499", - "0a01412adba28c0ee8b285516256d1d9c21f33ea52d430ffdab606fd912dd82653dc052205f64ffb0ed5f2cbe870d982859c28aafce32f20529ab555d2a351ff7c", - "0b05242dcc6d52e83348cd0465a17fdd783d4b951e5132a540169eda3b21e8f029bd6cb5f505d49c6ee67a099c85ac11a9e14a91074958e581a011584d4fba8543", - "0a08f437b1d870d9349f33d106d94fb6762c71876686ec6c49691c0b4b5df384d3f18abb3726bc7ee9be754fe451bc8b0cf848a728763fcead147bbd4598720f0a", - "0b0919446ed6d4865b458685ee0808746364d89461e530ab1c13f679df2d3ac7a037326f0bba9cced3b1b5345685e0456d1eebf5d115dbf3e96c01321c456050d0", - "0a057f882df6fb83d34960a120cafaadb2e49f1722a22ccb59920bf7703cab45151b3dde6dec6d3096723edd5272ab0e1172b87fd33ed77287d4ec25739383ac6a", - "0b0632b1a5b9a5955f5b82f7c66d7903db868c0fbca4368d57d3b5501d4b83afc9584af71fa0be44390b9548b9c52224cb2e602dfee00a15672f0b2b8c96393512", - "0a085cb1b0eb703249aa67f7ff4e6cb45df653fe7548329cf92c577b8b8f13601b07900f80826ad60e99d17a191a0600cc0648ffcdd773bb5ae68a5987e8e01222", - "0a02ea57ab42de17073e80d97ac7d46be57d35573e0968e7b1aefa1d14768a4faf760d3425d186e1139da8167da85a9f0f02cf62e6414995e7130de2c36ba0c94d", - "0a087abeb3521d8785a160628f635de9d73edf27273da1254ef1a2f5a900e338a3af415e0b4e6ba336d19ea76e4c9cb8d12c033b85cca6576d07d9a1fe1ceb2df9", - "0b00fcf9c8cbdf33e346312f0aa00636688a186b08a8653775bacc30b979ead6f0c56ec63b0b4ac52d9e05e6195abbfcce755d1fcb96635f8c5719562a2113412b", - "0b086c1ac51d0bd2daa899294f6133a4824ebaf0ef553f9f863169661661b8c110636fcf6879f1cb98385ad45f460ec226fe3e4f71bc1251b5164917f36d1c5dd1", - "0a067f447ff09138321289ab57c6013b4df9f1d392e3a01b9dac42700712f5e45bf5218183e7826d151646703159d9c1cf3ad01c4086d70a4ce477dcc7aa13e16b", - "0a06c06dd41fd4d1e2d036b6ceaec6bbd660fe655009db30e9a80013c69280d7f708e374b3d0ccaa7335792256a82bbd6b091cf92b715d89f2eac2757a410d0fc2", - "0b06937eeadc619af715158943bd628fa11a043d66cfef34fdfbc934d69e9e6658ce2850978bfe10ff7eab902511202fa754734f714ea8d1514b763aa67eabc1d4", - "0a00af45657dce1cc5d768a35d5005725c7d9273cfea90df7d030774756f9ab0ad9463725d540dd95c68f568debddfb0045a869e067a843c1dff82cabc2821a590", - "0b00867ad8c04a2d03a887b8c70d2dc8cfec6313ec8df9acff89a71103564b096babf39a263915a44e1197e205444fd63aed80d2a353b6c8bdfea5f2e9dec26eaf", - "0a04d4edfce6f244b225547a786d69b8aa450ac4239f3ee613a75e92e424dcaa064e5d8cb2b4f63613c7487fa3db056b132538d8dbbb53a074965c22530ebb2ff8", - "0b032a83db05c5b10b66a7eccfb1bdc9db0cbe7418a8365938a529587fb026dfa96a99add9973771ac7d52209b42f3dafa48c4db94ade4e96edb598cdf1760d8d6", - "0a0906826e5c160f0303b77205e617432a4c1809ff59d2a6d0432d1df560aecac22066c6cad81be057c648bfc85e289635cdf0a315aeadd34c55b56518f9c5569b", - "0b06a957ea5c9ecec875887f215f444aae72e20f85ca6fa2a56c199869a9db6823227d7b502d7ab8b7aad2b273e38bc23825c3d264afa548b8fbb0e6532c7550a0", - "0b034ba5e3534dafa901f02f6ed0b4ca087a94b90636400c2f02fdbf2c84aa98a3c4a50501334e2fbd3a0413ac47ed8ac84c18e29195f17cf2748e8990bcac89da", - "0b075545317f8f89bf7988fdaf3930e3e3b9be8dd875dadd0eb5aee3ee54479158eda9e552199111d9c9baade55388fff12653b597312308953eb4415f64eb0bf1", - "0b0326b030e410812f68d24ddd2eec02fedecbe49467813681439574911160de7a3fbe662ea594187922d9a6028c091944b88e3a41b717c82c1c988e7ae0cd2622", - "0b0322e6958bcbd0c65e6ae1518ceb25b0f643a4077620ef4331950086365ce6af7ea1dedf745c027b8f66268c18fecea32fbc37a2879f1479aa2c33172b0a30ed", - "0b0845a35c8bb673f26738b38061aa09cca6b24f6bae3cfba6f8ad34b1c2aa4fd05cddf899356429cfb05654c8266b51e7829556121ae2c1a4c2101ae0f6628e17", - "0a04c2aef058022300f7e3e25cb4f227103be3bf119ca04da1299ca8f2c3035bf54ffd1b5afc62ea66196f84370d438f197f8f550b8e43b66abf3a52edc480c7ce", - "0b05c33f004327464f2de76a2fa612138c528318be8d36bc08ef4a216a2b6e0513109a3dfd676213ebd23e2e66c2fef7a5d2746c9ae1b38ae3fe02dbe3b236360c", - "0a08d79019044d97958d0035c105d1a1fb3e23c4ecd95098322a674819bc79b494a1c2e302802a65505b1102f3bcdc5983094fc04f191d652c73a7059ac78391d6", - "0a04a1cbb6a5a9da98e4e14654b2b2d9fb6e0e8e42c285aa84098f6724cad172a5ffab9146d5ad501105e3a0338f8d32f12b263fe6c6f206a3c0ad0f6d4a02282b", - "0b08b2359ad367dc946eb540e695333b5c8bf0b65ae2c1da24b0f6f7ea93a23042e6b0ecdf40920b36b5eefe4c0c7f8a16262702e21b8ad5c29adae4d310bc0649", - "0b0533eecad27c98ff9a745a8e0a771c9fbbb220bbe78a719a60f26727d3615077a9f71802d801d949b74c34d2ab58437e5cc06ebda35478444364a73038aee1eb", - "0b06cf3358fdbfda3c4d0cbaa48b150f30639a30567c78779915a2611e88c6272541c530db1fc383f4ace38d6164881b60a57546eb83a7ceb0576986aea21eced1", - "0a065dd02ee8dad06a8f39f0f153569ea28eee1036c231f12d18a6afc64daed8ba0ef7c8338d87094891e47f6d791f61ad4c7c85f9a55c28b509cc9c86f422a213", - "0b0806f562a3e794bd29a23a6629d9bc2be480ed7df77866d3b0000c3fd249dde08a2d0eaf8b3ac9c770f0240863617e465ce2f6d9c0558b9f26576b57f9917aa1", - "0b0800b5074854f64ad29f0d542247dcdb76ab0c7ac026182f8c02587ff7b113591de1bf0d60533809eec52e78882fa115baf14d9fe1b8a967d146e84595d18553", - "0b016f8b23addd7efd41ed21644accf66fa76c9d8aa4b609dd4f0bd18ec4754f5ad87b3f0102475e1da09bee3b8b43b2fba76ba22c4c568daa975dadd6b6ed8a2a", - "0a03fa8437e5fc33718f7b275a91e3e9b0e91c40f2f964b43e3e19ac33d4dce41a16c0153e4ae6c4e01fce4bed525b20bff0045ab320d091888eb447e52ef0bb0b", - "0b0227fec6266792b64d93e68d88a763b5f523d01d67d8d2b5a58154541cf51e075acc5fc2fd455779131e33264f4490d8020f1cb7900fc3f015149bba5879e152", - "0b02b81d060b97b1ba8e4cd0923b6f7aa9fae8cee241d94df2bef866c39e09cf96cbd0789ee2c00e506d4454b4227b2916fff0c3c7dd7e1f15874975ecf2a5b2b0", - "0b0823dcac45ae4d97a67b7608082491deec74ad7598dd6600c6a2f06b581470e8b5f4558003d0507de309aaa7d8cbbe14ebc97c6a796237460bde9b0c23fd270d", - "0a00ab655cf3fb44e1ee94790055883e2261c02d2f6bf72ec4c1ee568f3d308c18739607e912e5bc7f915b587b596ca4fd1405a553e039ac116012a7e3a7e538b6", - "0b06adf5df8f52a97f575beaec0a27de31b02670f72dcbe592f2fa99f651eaa2b020df632baca95affb8fd6a4ac6090c3b880f069a8552a222f796ec65229f8a8c", - "0a085e536ea80fc7c47007a6cf5ce0409e34b6cec09fcbfbd181068cc9660f202dd8ccb646b5711354d2f73c90aeb5936fdd062a4e649e9b40d3422b6310641c01", - "0a060980168d67bc7732316054225b536b457a86ff4d320ea01bfedb874e57d5e7eafaabc0d352fb9118c3f96d6e7f403bc8bfd3adb8b4688cfae3c65f0bc58a51", - "0b00163239aa2d84b577248a91f59d4fe447f31696392da3540804af9c678e56f83662025470f483e68eecbecd8d8a1c9e407d18ec6ab9dc82f25792736cdecf51", - "0b04fe87e8b0d710506e5703af3387ac6150c7f66e12e66d1110535d7d5251571e160a02dae4ec371e0f374915e79bbf846727d83bb08b68f375c89ef9f20ec7cd", - "0a028555e9aaad77aea80bb72819cb7ddd06167fbfc764ff463ccfc91b08a37e8c653215098312e3eed8ba40ffe661f82cd8992e85c9c30b1f219d7811c193c206", - "0b08b6fc049618b4ae1ed903bf73404141b2fb9e77c36dba95b88bba8abe5b259692bfcf4b54d4649cb03370580dd3ea0241319df9b8334267be271cbadd6c57a7", - "0b0296dffc9a1747d1c0ef98aa3ec9d0963c43921477dfa11a5ee766f7c98ac7ee21de9d91c67981e22539d3054e6d79a4911ed62fde1e9f48bb9c40ad0c7372eb", - "0b08e5a35e6064108a2608483ea6f4bf4b120ebc4621304edd34bd4c2cd0ce906f0590088561c777fb6367cdd9cc6e97e534ef5c76c0b14a7b9f633c6dd5d308bb", - "0a00e4c8e1ff32eb0327e059bb3c9e31d00bebce4762d5160fd01c1285be23e42035d5532c7ba753525b34e8bda6c3cbaab766ebf77d3824694afe44bad7593490", - "0b0269cf901ae79240bf975815af3d205e808b2689218fa9afa0884a4ca1a54517a0ec31d82d8d8a8905a4307a6f7de3b6b80c1a668731ce77cb387f304d595273", - "0b06fda994437e5c6b6e5ab32215d55cd132a5c1524cce8cdceadf52e279a3454393ef2f2e8f6e856c97d54f95e838bdc6370c84bd55f37d654dff26069f09fa6a", - "0b00c2b8def9aaaf73802d7780d499232a3f9b834d0bf155b414a9dc3a2f3620f6b0a6e779e9614372596bb61e682e436837c2193980df523c8b7e9a92110dd278", - "0b013453142a4073e2c2328fb5aac5aea6095d4a6d2b91c09062c65c6aeb75ca15ccead85840e2d7a3afc3bb6fc35ea7a84569275cc0b34ef650b64d63502ba889", - "0a04bad7e80beb678d4c327bfbc27dff512f0158a2201eb057bfa774e2e505093a929eded838285d05a416d851ce1d20742630ab8d3a1ed78347efe3e9288b0015", - "0b0103e42a240d742a85470b8986a0fb02e328a2a379d3725d8bc162a53af0d2b4ad3e52f546435e713c6615da568ff12aa2ed7fe8bb87ccd1c5d0f8d45c34d356", - "0b0697cc7328558ba3defb64cbbf53802c563ba647ca4e6f9743e09b730f790e75d21940f13e08c842420b87badf18c0ceeaaa08833db6469b6f9dc4090eaa0f5f", - "0a08a09a769c618ddb83e8d32ab3eb0552d9aaeb6acc5c56b3fe83b6e87b78d2ed2444025078f0571747f46a6126b39d942abe761d02cf5546c540e84021051d14", - "0b004e4692d25ff391b57f0e91e933c3c8e71758a5f482d4baa1132817f19bf9b8878aecc7cf31285027b2b5685a6e70eee34f1941c269557872d84dabd0067138", - "0b02443630c1584daae95222339ff63b53e6fa8fc840f7d14f79b012a01813c9142418f7127aacb235031bcff115d18952aac96115311eda561cac9cb7eddf8f41", - "0b03f693f5a9f91f3f8e9b0b14c4e13b5edcf30565423fac0e4f55c64ed28e916a8ff697a4a0160dd613826c6aa7745abac5d1bfa92dddfa8bf207bee5eb3f25ac", - "0b0644b4269849fa9427a3ac233e44e51db19ea610587c205f2048f90cef3bc4ff09a91b75553784fddbed334c18c7310a5bcfaf893c84615b9eda1ee614cc894a", - "0a06077ae151df33a7f967112347a48ad19f2fbbfedb4a6cf37b47704352ac6a3e848c439c74f00e31dd4ef7eabade9336abeda088914a3e78fe411d2d903ade40", - "0b055c08e6b8aa9f1eaa2563ad227e09f66aa876c0d9973eb9f3d6c13f354d82a1d878cceda099c68ae3bb98a8088d640ead833eccf3c572b263e7a617d019e678", - "0a05475c504da1ebc2073071fb17a2da3e8101f6aa1feb1a9cd6972a4c3e7607e7c9b9ccc54f348cb89be6aa31d85c25a6964a90e6fe186aec0004897b04ef916b", - "0a0082eb61b37c8426294096b18d4edbb157d47ee8cffa4683171d9940862f7305c6c3d252151c8976a7194a3b7d33f3db6d9bd6afc86032117bd060213fb1096e", - "0b03353935e708fb09fceb68a0142d0715adefe49598217c471b0b083a77584d5ad190cc16e033990e3b506539f0cbb0fedd2d7e748b376ee238ef4507fa2c4edf", - "0a069560b7377fc06834a5c22ac3785a517fc172941f336febaef765cbf5413c6a3e50297108abd9f7474ed83ac0a5c6e4baa75235012634ae9276088819cee345", - "0b0157e0ba42626a6eac46a02239f9e57b63049481f7a6ff5d37e3a846051cb567451629ff8f352f58fb79cca4a2e17a05c76675ccff9bd564ef7aeabd52c214b2", - "0a06728bab857b4b4d7044b3fa40fce50602ceeb40a840afcaf95708b29980ed9df92a44276f6916ed8f039a76ebc85e7b61d3e63c5872fde5139ae122013a9eeb", - "0a07a203212e6bd038cc7084bdcc1ffc085f1a80e9beaf5e3ca4a09860087bd96a33c4af4db0936b76921feb4911f298c88bdb512cfaa7a4fb36bc9d11ea3c1c46", - "0b0599133fd89db561188a14d92e48d6f976f99ce9ddfbc02adbe256429aeb250390e0294dbe24ecf6c3cfe0025e73d12fc1f7fc8a83722f9099f0c20a5fe22e88", - "0a0173afca4cf4fa5172def245495bdd8946f37270fd4e26edfe828e923ae9915594fdecaa617a7944aa53de72943dda86f8781a5919b012970ac63d397db67319", - "0b0898d9a7ea88a2cf3fedd4347082a36b320f9baff85bf85645d320b9f25735c481912fa62287cf1eb5e072ba2a46b630505c1bf5ff3e91b3f165792c31f94cbf", - "0b020c0c457c60f746d1cf315860cb8de4027fba8314799a4b68a9aef3fd769a1a333eaddd93f749432e300802d7f7ca4c38e788f9f4a4992703a7d1977f4d8d43", - "0a073cb5e447c9dbaf15ef8f5a33eb8178095379c13c53f24d74926cc0584495df3abda788354709f24bf182589537825c6dcdc101c06d60b23642d24ef3f85760", - "0b02868885a04dcc674e280cd30e4f52df31059ef200cfbb0a4d7d084fe250986f5b6143eb551701e303604fe1692fb33510f187abba980f5aaf43fe97a9f964aa", - "0a0356606cf49c328d16655638e09f881c9637fd1e7bd7572ec0bac253826a1f9690186e0def6f6386242dcd52678b2dd582246c22ec956b1876b538c7e8f97e46", - "0b0028ef16618de5821a807fe4132077e8be596494a1f414207136565e5312b90281f6e6a3aa77d15a8ed264eeced7fe5e838e642cc4a29244e819d111155feeb0", - "0a0281869d298cf49209057757864fa651ace59c8179fc0fb062caa96e8e91278a77cae5441d2e1b1c369a59a81fa36f66a3792bec80c2d36ecc005335293a9292", - "0b071b0ff473029f801fe4303f13f44b54320947ec909aaea2e9d1ae9f16ee137309cc5723ea6d864f889466c95ba6634174f45c2185ab673b7f05f3cdadaded5b", - "0b06bef6ade87b29fea3d03db4692c366c84ec2369c4e1e0b2d2b30b1fed8ba701c5b492e0212c1231cbdac59eee5fd12d1553bc6b941964ad18ae58526b808213", - "0a05e10c27182179ad4d9b7c812b5562a0a6a390861c45a6c0fabc2a6767d832b9cf5fe63f6c0db6c823ba0b7372322f1e2c1a625c30f34d97e4d306feb7a0e723", - "0a03b2698e037d69ccf58a4c95f5f9b4ddace70b46236bfc1d52699f84808853dfb2981ab7e4f6c671e70cb700fb4ddfade944da8208faf52c7dab5401abe8ee1c", - "0b00294777fa2f61601aebd37cef7e1373c7221666048e46757e82a23ce462cea8b70e674b0221762b0d18fa2845b20bd3b0d754c44d574d20d2653483e075e184", - "0b01504921e2c7991aee07f0b5a67df32098edbb02d2d7adbce26ecff7026eef8f9c3677e6cdf941e09352f799e7a321ac0c420a234da05b8a8d01ba20c0cfcc6d", - "0b02e2154dfc85739ad57c571d40c990ad6e2be570d85cceeca15dd3beb9eaea1fd0b7874f5e608b6d1c11be47843b26c7a0230cabd27bf3f19543021bb58b42ec", - "0a020c655f77d63bd1b684ce58ebf08c918fbfc6db9da7516f18b71de177c3bc6111235a6af762e2c7a2e738a9fcc019c8b2318708be9c21cc035f38f0687e32e5", - "0a07b94ae97d7972be7b6f83a48f670f65cfc2b7764ccc263d7caee6d38449a8ebce3d966e528edc189eacb3fa627f2932329234b9e236510e44653e66d7f0e425", - "0a07bab9f7627a0cb03e78d23adc89ba9834e58196a33ca076fd1f6dfe5c1fb1727bbe7e9ee69fa8beea70591c0c33672c5ed9e00810843aa87764e301d86cb2d4", - "0b03cda5e938a22d3edd4914ec9d187f6cd76f82c0603a9e17d306e014f93351a738e8e585a9dee2d4e760fa435b538363e1d8df15e00778da05b59b1f70cdcb49", - "0b076c2d79f2f21ca85c232a6394e8180b614b870efe1b09a949d24a2f5a9ef0570d10647bf5d5dfe688bf61d7f60f9322a56759dd0333016a4be51e475bde992f", - "0a05b76d96467a19510b504b7840979b03504289f93485f655da80d10b17108eb4806660e99e7da8579a44fddac362c1bdad1019d5b0be2001179ef1d857c487b3", - "0b054d92b415ee7da9c642567a125269aa72e3d169264d7d9b667cade67dfe5a7a3db51f29814f33fe8a30cb7a64b5fb3a184e9e98b2404ea80ef4c09f25b67d47", - "0b05e64b9c241744cef43cdb69947c403e72571442a844c86d25b4bbc167542a99d835fd3c60c268e4ac63bacde53c0c38c44c63c3fb957fae0dec7f673846b8db", - "0b070a8fc3e0bfc88c0784c7f0b01fc3e3cce89e5db241197c1c56da833f1bad610a00fa5e90f1cbae6e5cb56dea3b6c03d0c7ea2eb8b94f842b472315eb46b45c", - "0b027b6db6a62e98d46856c84d1a5a77dc7b479b99c12e59362919a9565f920619c3adaf9ff6eeb46ca0c8d6404fc33ba619a10f244cd7902cf5248a24bd8b48b7", - "0b06be5417cd62075f637ffb5bfa044b67fe9c17c5ff083f3eaf179f6cc15f3f946f54e53b49eb5555e9f3f0e64de50af13d311258c7a20651958661616e85261b", - "0b02e20624ee6588915aacb1e1cd39e7be1983434c648dbd1f92aa49c9c8154d5ba3031696da177f4858e829516018297158337e9807f37671face7d1f7271745f", - "0b08f09f0eee8767abd41cef705e130669108eb94f1e5fa04c9217a57b3e2d2177bdce1b601b5de3a71ccef950ddfc03c1ac4e91fe2450071ef6b699aed07c15ff", - "0a05cb454d8118335f498fd13156e61f42191809f919908452fdbb7d7766397d77131e48a5be49042512fab218d2395d24f4f4b1cc6171f3bc0eabd48ab46b46c1", - "0b04499208f97cab201bced026ab632a6de39802079152384f961d79c32f9da0d1f16c75abe64cacf95c7760a62230cc8c1506ecc838873684d3729b61bfdb417c", - "0a04dc4b952699b83e0284069dcf1e71aa318c8abee58afa7db606acaecb464bcf74741085eb4dc12f5bececb9dda975ce88453490c211ac129ac74c29fe0435d7", - "0a065e4188334ecac5a8cdb6ffcf81649a56c25d228bbeec20d43238a0f7a7ee69533980fc173d7bd9a95b1cb1c1c950eda5b970217319cb4358505625a1b7d064", - "0a0732cad98a70b870db14d24e239fa7b919a84b65bba30df99e42bd177b400bf06ed73f133215fef750fdc1d68934384577e5a85bba271133e88ff78b374a6779", - "0a014ef3225d07893f0370f786ff9f0bfe3d7d37d0532ae2fd29e43455f880ac1b9a9fdcc955a57af6104449d7db45c77dbf0887a367565782e7b66b0f78560bb3", - "0a05f4bb172c98641bc1f94bf5958e6bcc67318e83a285dbf20913d0c80ed5e71fc5289379dff3c97facdca3af6158494b1a7a55ed29ff661fc41bde694ab98147", - "0b0321b58b871eb9c8ed66dc05fb2d6a5d3a34efead8b63953f01624e2f2b5ffafe7db8b439d8816c374ee45a2fbd9506929395f1c9043da7b684f4e798f5b4c80", - "0b06da95b4886491125f42456d12e83b8736f434adeae8a0f67a1126bd4a45120aaac3bdbed221dce5fb4940e087a4cc2eb43df66e944fe84ad58e70192cfdb2ae", - "0b02cdd9c61998788574efdf5e4ac8a73aa595dba0af1010ba75345bef2ef29b354c020d4d7bd4d39f7d19661b8445b6d3ca9becb71fe36ef76d97e847bc5cd0d8", - "0a01bb53d66efe3c8fdcd052cc6cf5d0bf97fa3375d478de1edf24e4e40a74a0dadfb0d5351f44ec40d83bf9209511566102e3fa5a8327c4b3d28820ddcf07d42c", - "0a04bbdabaf2d5503e93a8c54df0ad61cfd397aeccada902a4060cee2825a4722a3dee069c79ade04b1d0d566197c3bbd3345178e3306a2d766094c8cba765aefb", - "0b051e4c69363029d7d08b30cd4a7525a441a3d26184df6166d467e2b38ead76421240c30f5ec047f90d814e490c5738fe78bc87ffa14919179304a25586d8860b", - "0a0369407865d390e24a8c7ef18be595b707afdd90f0f7297a45c57c17aec079b60c45751446e17e4f5be1bd974c511c4e3cd4d2d397aa37655f642b161a25ee91", - "0b01f1c983b10c16bdece65c49678d6e8f1044cf0c22d19163ca5994138f2ac534fdeab5d98c5cd7ec6519642e5f24f94cd2f329be61b0bd9387d2cdfdc2f6a146", - "0a039e749425d40459569e57ea9f9caaa4e7afcbfc183ee1766f413b7b52f8e38a4ad2a04d07252045ea3e5c4de836fdcf1008af86881c22d138481b8a19cbeb67", - "0a02cf2948bb770d18c8d30fa40e54b0b377e0e1de963fd0811c8ed4bd69d8ea6700fc11792970023e93826eb2129e49ab6111fb4ee4037438daa4c46815a0ce20", - "0a00231c9d3bd5c226a3bc493dcd21f36ab3aad9ac9003a81f9cfb288da61c4a925da45a66309dab4914dcefe5801a4a4299d1a58af5d37aa8570b569714371f2e", - "0a03e51708b2719f8274a23da7e1c1894bd0c075b30f949699683185204676b469a73d6b255bac3517a5f5fd443fd2efcd97242d746f1629a20acefa6f7321ad70", - "0b061c3e9b340d818b21c79ada4a67d487fc1dcf604420711f83ad8110dee99b9da61aea1ab0a0a1adebf7b835dbcb0368564f294842d68428a80fce50273046fe", - "0a057b8659021708b5ca62d4de8d34fa1e7e671dfffa7a78df9957802ac2cfd01ec2f66cd580eb9a747b7731081a54aff9b78d1a247a7b661e132149032acd1bb6", - "0a03677f7123760bfbe15883857d2ea34fb4c9b92761f20abe240e8dc962d00b5f0951ae1748612eb57938ebf65b21ff2fc6809373978fde08607516a1625b6532", - "0b03d6e9b39ae0093bb082fce51cb4e93ea1a29875ba03e724ee7916e16b4b6b3f57c4779f2ed170dc54c97643bc75586b87982f4db08cdd27ca3f32b56fa5eec9", - "0b08a67d717b8718c0398963fb3fea538583b02b85a2b2bc7c61ee9b129ec3d8d59ede7f528232ee94a50306e79f099d682c57dac801b35090129513da2e23c14f", - "0b0904f297aacf1cc18d820dd166fff980f47e12730ac6e4d67060d9d6c0615167bba16db4c8cd3933f05c3722fb2dc4a9ae357b7cb1f2d577c0f1a673a6f25cad", - "0a06d92c85f7969d35cd72ad63eb43e2aad79dd851eb4dda08ac5ca336f57077d6afee0ba702770b3971fc0a7a6b681bce595a8b2d803ed2a362976a0b37785eb6", - "0b0691cab17fb685c76a2fe6776bd831636d6175b8d38346e349fcc177139dc246e0c95ef316b8f1f3967ac1459e738665e3f669695542e7f8f3f929279d410688", - "0b07e73ff65aef9f46a7f6ebfa3e53c5a891bd0eea3c1f90b738bcfd83a4702093ae8d24dd44f96343a08332e21ff0d19f25580e1b57e8993e84370cab6ef39fe4", - "0a0661a2be56fc825c6a291c1330baa8a0c3e7d6d88dc8e292a753f49fc324a0cd3bb997f2a898d22dbe6e418e564f695a500e1c2c20564b62dba27d9d93968452", - "0a0256d7171cd4a69150f686bbdac81e82a4e468743aab322d23eb293f16fea92db2bb18d0a74623a6b19972c10cc535306ab628dac1fd83835f4c0d3603e12694", - "0a054b09a0f4a53abf70d19a0f632fc800783854b94b4fed6745abf5897d403fdac8edf0dc9b71dff5962c619f252d789caaf10fed59d2ae57d67580d07cb89d3d", - "0b069f6cdff94bb1b2891584e636ad8ab89917cb98b176fd4cbb74d33160bbf92666e3e8e577b22f27fbb6586bea2122f47cad5fc3a31ba58e45e9f12e5ede1d92", - "0a05f54f3d72bfd9d41d12ea2ffa1657049387d6f04522db39db28ebb3c458a0ca2c5cfd19df957be84c084086edb235b5991abeb9743e3fca36de71f83a01f07f", - "0b0454de7673d9a1f8464c58c3941ebe08e09e6e08f7c7a1551d3a9cec50a81891a7e0810fe4ddae65f376bc600ed040b3895c1626d820c0476bf60d539249e1d4", - "0b017bb0346bf0625f9d0201c7a7bf5e423b17355b68322064c9c937683b4475d6317a4c9a690809c399feced4cdc0ad923cc8697e4ec0c63747b7937f7db32fbe", - "0a05fd3cb8517f083fc94f115cf3667de23b3fb257ab0881dbfd3167749c03bb3a9222e146782cbcd463e158984c32db796ac8df0d3befffa8b1448056323738ac", - "0a0015ace9885d57e6133f10bbfff7feeec9598b999e0adb91eb01bd08ad7992be7b24865d06c0a9eb0e02ac0205c22cfb04c5c9b50274a3755f7ea5300f80dd48", - "0a025385eb7c70165ca082cdd5498e55956e9b575720b9cc67feb7fc0d9c4ef9af7f2593b24d4055376e8755f458511e9fe32dcd1583977bdb68666852a49559f0", - "0b06d0761879ce08a0cde200b1f6489007dd0ddfb5a5d0aaa01326b66443027a90f6ed057cef552f4f1dd8b85b6bca1480297043c031d86262643ba4cd0327e8b3", - "0b0145850ee5cd01981d87c9482e9c1b37212f49580a0021ec4da9674ab7955433d314709ed3681e86b5dfcf43cafc6772a405090ec5158e246b9b5c190a80a9f2", - "0a0225d96424596355822ab7e612072fc1164d30b843f32ae7db06147511310832f9e36912c51efc7be161c824cd3485601999060c091b605eb9e0c1b602eebe60", - "0a0835dc8538d5a03e10c1e4eb6a0ffd23afd8dc79c4ab5d1ec55b99b2e38e0a31b59225334db511850cbc629be83605f8411413243f174f040f504fcd6998195b", - "0a0350d5cffc93335b1ec670b439d98f57dd59742fc7f6dd51b3b496ec343012641ca4912a9d9856ad404ca6006f36b72b785bbb5ddc89eaa08ec897e7e2cf9793", - "0b002f94e704f98c3e391818f83f2715c53be57f36bf29618f8d3ed2c46e4f29f77fe372372823f2260a15e161e872263c21b4d72c2fba7093a3b7ac71f7bafd72", - "0b05b99b2b32a00d62da2f53d6e658e466768de433e0c4b943fe6744ebbb5d62552800c4642c810b5939b702e52e73e520c154f77e843f548b22d1e1f7ca1174cc", - "0b01381e04edb8e32b33b026795f6020ca9096165b02a2d2d77401dea5ee57144077d12374ce150f3a299c03cb150b402c17074776f90419cdef5bda09637130a5", - "0a04d68e167a2e3eb445696ac583cbbc74fcd272b33fc15d825eaa6bc41e3a8d4541f16bcbe75cc1f83e6a17f3113b001d0236ab750c75d45ed8ddc297ab3aca19", - "0a041af40f6075e1c6a344814dd1325c3e412299d4bfe2319f86e42e5f7fca160e36295be8843afa78d205555829011c91d42d03463311db7cf7d0d541fbd63eed", - "0b07749e71347adf714f54a35f911f42f32e42ef2b23853932c7d8c3f272248fa8b1296249509f6a117135875765ee02cf4857bfae26c75921ba21cf33f05b4ae2", - "0b00826077b843b19eed5251a6d58deff4b3c71f3005a5adaec3958a2b0d924f07d0586ab899aa407b8c5db17130823d61ff42aad5afc792e210dd47021520bf93", - "0b08af0da5cbe0e19d8a7b955e3713c22eeb1e1a49d3a2072b3ff54e2a6cb856ee8449e2b0a4de6de511b45ba2b4f9f8789c168784dc64981f64d5022b8444fad5", - "0b081b22127e7ead2cb7352278eb268a67d94f8ab37163d0f15de05432c0abe3e671a4f958f49edad7de47f01263d685eb735d1e8aba0c4c9e841c8caaff25a759", - "0b0665358def120f53605b8e7ced308c6ee2094162cc1ca36b75854a699aedb92e7312d8a163531f68ca828241c0f6414548027b3c1a6afd6d18e0cc19297e1edb", - "0a00414f14905370be2f591c12b30b1fa12e9b5f405e6df1521012c8a64bef4f4823e27c90398d410e0f3070107d9fbb3cd22b92f23519894a8c7a3ad0421d7bb3", - "0a0335bb73aad0cd79585c2a802e037032524160c32cf7381b9fb576acd54f0eaead29a9690cc19751405f149c5285e43aaea46138b5eb000a9cd42a35fea110eb", - "0a01437d3a398d6eee89796d28dacc67871a6160eb53685c45be944af7b494d03bdd456aee2e0fe59573b6e7d54aea087cec27846938f734a2e997700ab9891770", - "0b0543b5985393b31e0bd40fa31cf894385ad3309b199903a5132fd32aa11ca673b6bf7984706cbf8dcae8dd4aba0fcb5149119635c9500cd20e5da3ad08bc8304", - "0b015010fbdcf182f3c37939228c370b15d00bc7076c492cdd2a80b56d4cdda4ca8112ab05229d531f83444752ab07a0428b8a8b1eb2ca4eece91caa05fd57afd5", - "0a017de64839cf2c7df853d7656dc5267b7bd1fb09c129b65266740ae5c1a1e8a6cc1d17edb1e9c451602e8d699e6d6878ca26ea0874ae4e87e4f56f5275900f93", - "0a0104a155595a99949a249d34fa9011ff290d2c00d7206eef76efa7b4464c8795f103df5468a5efed7e73df02bb4e5019fe4120a1be920cbd53c9f0838c8afa68", - "0a0476628c4b23d76e3cce1d0518c75d308477638848638ec851b18c1273d7463065b6ae02abd5272c5e84f7767ddf82b0a7621726fa4488211a1aae2b5770d643", - "0a071a4d1c8ddcc679ec4268cb16560c8f095183e3f965fcc646a963d3b5ec07617d5de793e313da235bcc6646714e9deb32fc0a030178a544c55b831d20a68830", - "0b039ca792baf051df6012130b903257e4203955832b8ff563c1c05ff401b6c944b67b2d29c81f7e057f877d121617ff45a7dc5c223f4e1df8631f7b8a09430761", - "0b01b53c44d6257317ff5e541e3e8a13ad1ff1ca1e215a1abaa5843f530748aef0bf14a228c56a9f8fb387bf55e012584fdd12938ffb69e9a6b038b8bf27521907", - "0a07f1987bc52b61f88eef8f60ecf88e3b149354c1e3c6d99c916e996332252320ba795c51dcfd14a4989f485da527c57e1638f39a715e2da053688d000b8d67b0", - "0a0242cc6044d26a9a9cad2db820f3840f80e6b8c12b6e3e091fafab748f2940455fa91873e167455ed6e93c5f17bf36f1406dbe129aff7c6ab5fc0d97bcb66e51", - "0a06adc6791b5fbc925247fde35c401082a4009c9fafb5831f1f41ec95cfab7de0c12df71c8d6d8c48fa6efed9aae35b5248fafa73f1ba288ac84a346c1f8520c2", - "0b007940ea7d5ce8633215ca8b9dca4c84ab12d2b93db43da01772a725da211ea8b5d3c02a58c99661fd1c99eb46f01380a673f2acdafa4aa0205581f970d6114b", - "0a00e62372e573a097c18d3955ebf9d5e515cef798406a9f12e2bad664af305edbb893910cbceaa722e47a8d1d4d182e1f2d968ade2766d7b0f2872f5ed09fa560", - "0b0736ed437e1d5379bf46d1334c397ad1894ee1d7af556e658e9497afebc4d02e88331cb995504d5e93fe47f2824bf221840719e319b7bd41d2b153948ed25e49", - "0a04bd3b20a3f973b6e8b40d3c136e86899e5689f88b1f949fd03ff0cd6f9de83fd0397db7801007a2deb83a2881feb876f329477076f01bb958d7d55b3b1b9a1c", - "0a06537620327e65c7fa24deeec3e351ee46b0eb828e38c92ba1e89145dc9b963ea7967d1b1b80bb0ea015f2402c34033d4ade3907565141c4f277aa101402e814", - "0b05f1302084532d674a6e97552d268ffcc6c8d22df16bdfed3b89efb04061c198607f58ea46f28f036bd72d7640c9aa4be5094d13d88795871c89584d8bd1ca8e", - "0b0220475f8fa0505a70fb2c3594c0f5558c20a671baad788189de88a7a41d6e205a518248f6e180fd2f1f95afcd2ea44b2352d074f99ae8401b72aa803b35ae11", - "0b038fe487875671d5421dfdc1c896950a7d0143884c916afeb8858b5e6612358c47599895320bb84dfc37c8dcb414f2294e12fe89876bda59a41ceb470169b262", - "0a0657b940ec231606a4f186803c23c7d5b8103cfd40cdc10c3ef52ef1f59876f3ba6110d5a6c9db29f672463eceefca5cd517cc3d45eebbfe164cad560cafc933", - "0a03f11173026fc83cb06a12fe6b44870bf167a529dfdb8bfc7aa0a1e4d8241a2b65a288d8e0986f48093d84952a4747c4fcc6ae4a93e58f416c2ccf2d683c9a47", - "0a03b847062ca5b0186536db48d82d038654abed9cc77e4af443e00dc3c4db08c190b9a56994139004cc16040b11e31a744ad697c78d3231face96a7f2ed459b3a", - "0a06e164da76dc1217d15171c1193ea3e2c41c62c73103d9b7b95a7aebfc6d710710c85cae441a737f0fac45cf795de750ab546de18aec86d60e159f8b2c1f0455", - "0a04eea70de47850c046d8af9acd9bba9f0c1d7b90448424548700f6d8dbf6539975a56b08344396d7161085bb2514035103dad716e3920819d99e2dc585b5cd2c", - "0a042f7b1da210ff49cb00a33a37ddd9e0e09d18400e3f2cd743d2bee02bb54cd12e8f5f947d1c45685f30f21931642f3a4e5bcce6b078351220015b8f73bcee9e", - "0a0273d311535b55817f53b5c8a4e144ac57fdd9149c3f9f30a81d988124fbb89abfe185796579372ae4a74a6fc54c71b91e46cbf0adebcb86adcc03fef719494c", - "0b05360068e24dd4d9c91249aa9b1462851fd34feac0b9e389643244e3d813c3291434442877df929b7b15a16a7cac3b26c9c2cbfacd765c2a00a7dc079c448d7c", - "0a044d85defcd5cd4ac4abd27bb3b5c5d891a3901b053762fbdce3fde228293305760acce02d6c4ba9ce174adffae83a93eb4bafba6672ce93e4a1daeaf46aba35", - "0a073b586c275bd651dab7ed813984e9d894c8a5046442748b085bbbae4ce4b703fcb3ca7fc93440b669439eafd58b40c5abd871e1f3d228ccd7b4d2294bde5478", - "0b018f332b8254de653a7fcdfa5600097fabe165e62e753da684975fc8ebbc98509c63644b8355f6500c9b1d94ceed2191b7a728cc88563304c3611c9ab78205d1", - "0b089e12b6a5b19fdeef80ae4ea26df7b1967e7f5e069bcfb7b0dc82f89d0cfa5ccfc5f2a8b03b7da56a170095df35f9077b15219a878a43025e64dfb4c504250c", - "0a078fd6cb532ff2ed2142c308636f8f9e7b16baad5985c73a8cfc4084f9ce9ec9816cded394c900a7eff508839c7c72554584ce8f609d49d4b7695db96c6acbdf", - "0b0697ccb19ab1417abe992701d842240faeb473a6c722c055ca96407f3b82b1c48de3037bda6c17e713bea0a7e6c3948a0430a7c91823cd7d0a50cfffa5128ca0", - "0b047847957693a2fdc5100141f1d5e5e2dd6cad2faed58d0bf7484e47fd117b2e8220695aef0041224e33c9c90cec3de86528a271fbf8d5033f69974005bbe7b4", - "0b08616440d6ea2cbc30325caed806affd06894698a3e15f5f71c7368c3e05e0f2adb5d71e6e8006d64e848f2eebdbda904e33b98af15afbb4b918642a5ba769ac", - "0b01f67f8c661dea5ae1ee7294f0aba14403633e3040dd64dd9ba0b5c85f2a0956d858deb2b7c062b5f16d055e6b19b16e9d4102bebdc2fd139449809521c96daa", - "0a03e77b4e155b5b2d6d8b7de17aafc4b81dc53171096f87af5a0563ab5ff09407f9ab907a0908003b078635f2e3e9128ac52c5632b9f161fc532adcadb3ad3d54", - "0a07cf51a54b99f313a3e78e6db9f124bfed107ad3772bdb9a2482124f895b2da965d0510f85c22ac20c3202a4d4e3ccfdcdc7128c410ca3740c66c6b6238d4c68", - "0b054570af9d43401f08312f8614efbe70afa809aa184f8a09b2bc3ceb6a46541c9a47d01c8687b6731236b6442297d908b462a0fe713fd3672746702947b1f0a1", - "0a06d5ca4e85bd778bd3aed0506aff6c6edcf6caa0460defc73da5458df31d401e1aaf632c0093da5d576c7dd277601b28d037df031da8463ecffbf92b927abf12", - "0b05495d206899f58e55e9af3903101dc4c13e0f0bf277ad45579a52852b9bf2b74251cb844d01dc3569bdf4df5faac447ac80e52bb9fa5bbbca2c9cf5f7f5f7de", - "0b0504f99340fcbec0307d842bc1b228ebbfc11ebb967b03a7ef89be862f889d6596799834dcbbac56abeb6fe41f5a8904b7776e1f2c215fec1d1c8cb26f07c527", - "0b0100156c544d6b8fc2a69ae09c6127a1bc73fb9efd6a85fd3e3e3a66b715c5ce512843e4edbe7d7ccf39d2566e59b7b3c9ee902344619ebb00765cc34627607e", - "0a05b5e9591e7ac2d23fbe97b796a74cbc2bb6e1b98243f66bce6c3fe22ec9f43a102d259ac888531558379a1d7de893f3bb42cd7b56d6278995a138482eb8185f", - "0a0083b1b117f804cf0af75fc340cf56e7e63189638206cb2cf00e8e6704d2bad0b9cb7313791f7dab8292ea5f1bb3499ceb3356daea243f3bd790a689109626e9", - "0a046d34538308421646c130ed826c2fbf7cf395faca7bc0d7f28ec0c570a259dd192af628c98798a3d9e28e538eaf4decf605ae6c5f673a34984826b9be81ffb6", - "0a01c6555ff18b12e02a438a1e8b163299c4ba08ee97e443552bac03104dbb7b388ccd19c749004b6b0c5f69fbde1d0da785ae3b854116d457f8973efa59e0cbe3", - "0a07bcfa57dfb0daeb21a83674866c741e039e1d8bc8770ad786cc79e8971479ca06c52e3c953ddf344982480f078d5844baf62ec5123d9b1b917bb6b876c4335e", - "0b04643415f3ad0f2abba0011fcf378f12701ac904e4fc33584658163549f206bc59f7ec435d978bd3535d2e89765bdeadc15b7e9bdfcd292ce43d6f0a8b8908ac", - "0b0905ccacc20c38c0b8f389ef7dfb35f9cf0d74bddd5deb1b6dc891dbd884bbc46ad28962fa0b67e3f88117d4f841d109d662c9e44fe8ced1a270c95310307878", - "0a04ae2378c811e464314c4ec654f02fa66f07f143e654097d7d40520945edaa17789d21d06fa5c8a48e82b37f8b9348bfb6443a63e8cd1dedabda7276afd8f872", - "0a060890ed315761fc8fa24c7044f0b501c1557bc09191b3edd29c9d1606fd19382ccd099562f858f4b060b6fbd0bb518ad2c0eb80a685416792f125aada8f62bb", - "0a0297047de123c3a4a82322db6ad57907d693601f51dc9d01a9a2fa474448b285be842459943086aa096760407594a06916527c57439e448549f57079dd4e75d9", - "0b03aa4b7d3ec13bb1fd01a1ba1fab7f3efaaa704c8b5cbf07fa3a078356ed444c20949f849a757298d91ab625e21f501b1319f8c82f7f697e5d2daad203f665cd", - "0b05ec2e56e920d8d8cb88ff9d324ed01d577480b9ecd1adc5987965c078cd5563ffdfc452be5bf76871c35e7dd8a09614a74df042c61adb94590fbaaddc9ce01f", - "0a0784f3a343c8e35e7a0c1b5c290b810057f109aaa6a2cf07f4720ae123a4d61d8a8f1d14932609e3a5ff26953eac16d0357ebdbdb783a6b3b1347e50d72eeed0", - "0a03c39d0790f05ad849237c0612ef6bc9ba6b58d7f596fa90eddc174d47a9d8611e0bed59f72d25d323e9e3c8eaaeb1bf11eadadb2d1edb81a1db1c025e66b238", - "0a03ecbaace807224c942c225d47a3a04d5166c424ba7aec22184bd0bc9b0073675b0ce2af84107462619913d4ddf4f6fb4ded0de0f9ee266c5d9297b668809034", - "0b088f647247dc901a73470f97695184b797a665164d2c8e790a6b15627d82c61d562da779109e11bd894082328873ff7ffd683395f63a765766f2064859cc1bfe", - "0a032e5b0b136806dd47c5d132f110052ca08eabb7fabb4c11620e60ca1576d3c390313970f11440f4dae4d9561207df9a21e2fe0d94e15888c1a923687ceb43d0", - "0a076970f1eefe1d71b14472fc69630cd65a58efd11cadcc11e4ab2488e96600fece4e091c59e8d1d938c4c6a4bc2945bb27fc099b4099369e0d82da11f066e9b3", - "0a083598028f83d0db8b8e3aacdb807f40a095741e3629acc1a2d164dc6cfd71b65793be5eb479d4f0a75fb2c3b3453e56580a1adb8f3d9eac70f6b11f4f9e7d1c", - "0a0672635aa3e041f1619b8285b3b814521524d050738eabe239db76b85d56456a7b2d7c93e6aba2a1ab9b75e649b524d97d868a1d6601f3217f60e8c9f3a80845", - "0a07291b4fd946e2ce66d539bfe47fa35a67c6937c0d7a4eef28f317cdb60a99c30fbdefbcefca6782d65f52e446f8295d8c1c5fbd3098c9a64dabc4b295d53a62", - "0a04f0d663e727485b8df1ec27ce4dccf9415274c06efbfc46ef16fe352930bb6862dfee5da8d530a1b626b504e753c4477050503ca66ba03e730f06caf0a8772f", - "0b07143daf0f553ba35a9d01775aea080ce1e9d86f0cff18e6b677860dc6381532c6e72aa4e20378ae74f7c5375e1ad2d41cdca9c727baf7d44e0713ad4af163dd", - "0a0210fdb22ef1c1a032c73e4382907bb5b59c5cd6114f0a502ae25b2706e7f52a49a30e64cb3eab357833c232173b168aef3e51e66de40c652ca18c0734bb2299", - "0b01bbdf72b6a9711eed43df7c2a60ada2691271fb7d594c3750ef39ac93dee4e6339bdef7a1c332a1596f95fa56fadbe175df4681c7fa7e1d3f9c355058119e18", - "0a018f0a5c27bda8edd420cc4bdfc711f0e72936b419936829b3875ab5bd7ec5fa730f4a6db1f46ea0d533ede9ffa1bd4b7a400d7b723ba9cdfe645c60e64c3d96", - "0a04aa0e248c4de0e06a24bc50f20284fb922eaa1ec413983c7496bb6116611f474b1c870caace7188800134571fb448a4e8d8178152282e600e9146f286bac8d7", - "0a08eb39be7823b89df8ab4777553833ac16d3534ae3d48750192405fa91fb195f619ab316a90cd862a9d3e62a1828bf261edec093e02a7f7a183c65e2f2a3b4f5", - "0b00484325e83e34b12fcd5cb22e09322bc8b435d0eda5f8a2ca5d22d664217785f4229b9c6b4987bcb111d60726b880ae601dc4bae643fd811f7ff0cd85dd5d55", - "0a051e9d9d01af33e8b0f98a88f5df896b8ad5b0721284802c4180b385b4f0810745c30d047b6350383bddb74fb3eb76c7c0153814c0b7ffb3c2811f8fd376a89a", - "0b007a346b74545740265fd7c5ec3c3c57dfc9bfc5dfb5d7ea4ab4ac49f934a17642e7bd0c50cdd9efa24dff52040d6f1f648e01c13dc019a5428832392994ea38", - "0a08877f696a301b661eaa060a958fa01138125419aa47c5486448aeebaad542fba6c9546c6c365c61a1188e16fd4b2ec32f4e11048bba5db66e71cb2d60ba529f", - "0a038701498f6932fe0eb67ac9c4117043c164af287db832b7711cb5164376a01d96edf36429626381a7a80bf39d20c2a0090c65e3c48bd016b03a9212f1c6bb31", - "0b084c045e8fe51ea43295c0cad32d13904a661f42b1a8520088feb5aaec9f1cabc6c62622552d9629b1d739c22d4598c1c92592f004d20732af4e6cd0b9929279", - "0b052c27d79f79db42003ed39b0408d3d8824950ead060df20fbec4103e2edf7e65e52de3e8ef685bf580b4a9d269ce12ef7ed9c2d1279824d29d2d155dbc3ffe5", - "0b06d62be1670386c7e32b711b5f36cc10c000b87d453571cf5cd3c8c436fd04903ffaf73e344363615d655db35a1b8e868aa0550baa1bf7277ac290aeeb5311ac", - "0b0609cfcb05ee39d0f5329ad0053dc02310a1f45fa4920c4b31d80e8a820052260473058f663c79564d2d105da1b04b008fd7a8d97b04e9ef28405bed621e4f0f", - "0b00413febb0a215354ae16df149d9cba4daf40736e204a1ca4b87424bf1b518f684b5e1a0389a3e5b222676b4fafc37d85fbc9788f001e5e8b8b4db99a36ec233", - "0a006803e29425a6f7413bb037ff1d7464eaec35dcfeda72b4b23bff4e9e244d30d588929affeebbc7483365e402be5cff31d183224e2528170b85d2636f056409", - "0a084a0788ec67bd2f7403cf5494c49cfab661ee80104b4189bd07f042c64d0cd7844e5d72b144c36e90f0b3f3cb33a5f15fa041efce50ecdc2b61f2b7bf128dfe", - "0a02185313b183cd72ac191a918a35e947fa3036d9b9e910ee4f0fdbf1ff733b15586f31167c90cd07bd8952d61006e71c3997f7dca2f47e96a379c98c220bf2f4", - "0b07c8546986d9ad004a15fc4a173c358b67891d4a27dbbb39a487ee23b5bee7e31d07d32c2ad7d21503317b47dbb07cba0974041818b384ead77b19d46f2c3438", - "0b06b2447bd524de26022e7fcdec32877bd45edbc99b404e99621672fa297d78e45601c0515813776dc35f412fa20156008442fc4d0218cf327e66d8c0114d29c2", - "0a08185d5e840c82dd945f4421e7c39d3825d925d9ea76af07056550b1e3e19a9c292f160337e399ae638e926d8851928ecd5abfe9c2b224a8e509c91321eec42f", - "0b06087d96e7b5aae88d9f34d27dbe88a30c7e5e2c5fa580b662142c9fa05489d1478ed54b35c99c8f7a923578f2c931f5b098616265cc7e288d662dcb3a805b9b", - "0b08380f5214c110ec33aaeba455c98fc18e58d4cee9a076911c5056bd1552b3776aafcffb6b09dde90ce6e8c4346026841332a99cccebdf9a44d650f466f0b7c0", - "0b06ddcceba38b35d3504956c30a0523eb2064853ae09798cbc3c1c2982571e8dec7c4480a3fda6525597839fcbbec7c523b269e2d1ffb0b918a3117c19a1e4f2c", - "0a01881ee0838ae78ea41faa3b6a757db3fbdbcd5b66edd66636c24123828737a24ddd82760901507b8f2ed66cc4881c1c053d5a808856a7c7b1968755d5a9c126", - "0a03f010307d6227995fad9b04ea49ba77d37490c53b3747019c08b5bf3279ebd9a7c7c0a3ee5c530eaa982f3f90bbf7bcb09389038d34c587056f2bd676aded23", - "0b00854976840c8a928ef75c35798f3cb89bdcffdf7e68fce631f33e66deaae431b0664b88f143200d77864318e59b3d49be25a641bb6896d27af4191f029730e6", - "0a0172d1d226b022eb10e579cb129bde1f094b0f545e5a5d12eccc49c07613faf0bfbafcf7ddca944058d39dc3453f45e9901897b31d002ab0a5fb4e4e65fba443", - "0b06cc8ca5129392c65e5cf97ba2f6363b9273f50a42d9ca68871a5b23c0e3a5ce9be0e10975fdcf7ac853da0e3c57eb2451976f9f1764e615da7a353b390830eb", - "0b0007081ef4e8928c6690a91ab048d420b73ec937a113603ef714bf5964dc3cd70324e265a70962208034c70927ce7394100538b49bf6798b6f4a802a8e80b95c", - "0b021cc83e7c0fb9544a8dc5cc722c5f7a0a05c8e5b4139edcbceaca42ac29b7a2b843cf436c550a83ca93d5bdc30047b2b78cbf12c7fa3f6791a1d437366ccfa5", - "0a0896394aae23113b669123ea8bee0f3b78faace7af31ac49186556ee091890813dcc66b3e3ff13495b7f43b83155ee44ced5d08785158c0803f455b6355d1144", - "0b04487a6c02b00846e2cb8618981712f146a9cf01523a961353f2381f8d134840d02719c156ec2c451be10b005741f4476bcd1b56ab6890cdf1f201f0f7789397", - "0b03e1a726bb085b4d3bdb1d36e4642a525fac0bcfffda0e5d4aa04fca698d190759dff8bfcc86435a3c8cf283604a6d06290ca1275179148e4bc884d59d9c40da", - "0a08a064431bdf6e3e1c71d826bc4bd03e7b34e23cae3a9026a74136bc973730bf64670c4f063cbd227a9ff123e4c0d5f125c4de2ade506818dbb7d160283d7123", - "0a01f99f270023e343cba72cce0e5ddcf6b5d3e3452d4a13ac5a8e5fe7fb91b7a88a0b3b26206a3b7c8c22f82d9d6c088445486cca54a64d2a7d30bc55cd7a2120", - "0a024d36733f77fc13d9d17f4e67f343a18ac52eac512c410e327a4fb0ad68c10f1a7bbf427945b0b0417994208588c3de84cfb7aa84710a7e0b5892170a60332e", - "0a0225c8d9cf86eaf29b8c42d303c02d946b6d10f91761836e21a01afad3fa39f32a2bfa4f7d331d908d211a99ca9eecdc8f1090909ef0bb6669e71f47cc30b24a", - "0b07c9424782d2ef13c80cc5494640f5dc72e9cb015e31630a64519432a1c4e2967e2e533dc572014a071195b838945137a343290caeb16e2acf08902d27e92607", - "0b06f5abf3aec134cd1b9e95cca7c61aff08d94669eff830780b7c62482a0a7e25c432ec1be97fd26bf8269a344cf21d4ca211516f9cec084a90bd07fddc3282de", - "0a06456a0d304718fa871cd859d602110db9509995831c2bee82f6f3ef630a02d5eaf41c270ca916d450ccafad7fc90cac4023521a0a94e595ca4251dbf6175606", - "0b04ad35885b587b2fee8dfea30c03c7e9ba012a2dc576c1d852ae9305ab06cd3585166958737d76eda6c6ebab38f3dd4b7e85d1bb67d4d4552a7a66fa6b36376e", - "0a0876825b67bb4a19dc287fff86c46fa3b2b44a5233c928215763b764cfcb903541b9977be40dbb33410101682d6f4f6a0f42fccdb470229e82b05d58664dfa1b", - "0a0447c81d29b2ee84591a60a9898805924ecc561df8185e23bbdd10ee502d5a926947d92fc31328b139bfa577cd664a19a0132cbe71d5ec71f67523c51d210a55", - "0a060751df2fa3f4356b63131000498caa925f028a9951bdd603e64cd95490a9a87dbb2e1a01bcc5a506ca50717cf989330461b01bb39f22b71bddbdc8c831a531", - "0a02534ddb1d708bd80c2da426be05d7fe526c107d9f7b543601793de91ee3ad4b554806d33464683810de38ec4c5f288c82dea6005fbb647043751245c836aee8", - "0b03e5544ed0e0eeabe7bc92e4a8bcbdac2297f6c5cd92fe2f908f0ad71eef07a7ef29072860bc6560252d1c1d2f37bbc2e14b90554488431ab40bc65be0e77f4b", - "0b01bede6f193496c2ee340591c41f8a6ba650c95b3a12f1d95bc898cfba8f7a70bc04f103e9bd7899e702da0d214b7ee4e1de973e8c6acd1bafc2379582add713", - "0b0085b082d96e4147774222caab272fe565b7ee3a8b3d23972dc8fa107bf217f3504408e9a93579f09ee3295dcb9ab2dd4d82defd0b9e966ccee65fb9f22fa621", - "0b02850137d933180fa73ca103f8c9fc8e249323d469878f23f25b799324c11142c17c45fe6ebaff35c794844d3208fd65feecd922f8600ae0bc687fc5f1527caf", - "0a0184b1b31c59f14533f4abceafd8f27ee44bb2c44b49d2b28857a48c81d192d92f20646c29062c419b6f28c100e0196fb44c8a991bcb377ee82e3f00b55b44af", - "0b02002e00e2c1e4a392b4f5bd425f4f4f83ddd1b96a5eb13519b306fb81a1b22c366d518e71a31fb2e4a02535d461d37409c300a66776a01856ee93842581fd9c", - "0b0686bdd419f63d4fabc9b359c22390a418a7092a05984c85d2d58ef36145ca2f696797d46fcd2dddd0c9356cc381133e39e1e97f8dcb6bbba9fc031615252062", - "0b018eaca22899e496042f8dcd3c5d9e9bebfeca69229a934024cc1a1511c3f9c36a6c2b087aa1f09fe559767148001587c2cca348c55b9c4c7cd8f6d7aef1487d", - "0b019861a4d026ac651a2b3d4040a92cf1db63bf65271207cdbb2e99df9831a5e5a53d90179235f22af127f658ab86ba781f1af318e7a425cedbe82ee83d316662", - "0a056d920f75b02511311b0dfc84749b188d57a1bef135ec31f4d323f6e02c54f83c6462d6b19e1638fab537e5a91168194641c4639e7399cb11426e24f4bbac2f", - "0b06db96473b4a05a9335b6c416ad7be1feeffeab1bf771b8683c27eef214910594353c820d9b726788d3953d247a007bac4f75f7966203602593136637c0d893d", - "0a021232f9d353d4a27b22596cba3ad1b21c423af8d2566a5847eacf6dc56b912d2dfc524d9f9a43315f0b37f6814183c866c218032cc44d988684abb23f9ca16d", - "0a0537060ab3d75f1656d2c94d567ba68cce1e0b868f2364385d68dd30ba9c1cae2a5c05593bc4a7ede0a2bc346690c2d67d227506532f24e253886c9184b6a395", - "0a00faeaf0514463c760b0ee5ba29499c65d05f5e05a55daf0e04b152a12770cb3554bd9e58c2c07ad12fd3f1e03e88298a8123051dfa9d21e5dfd1f157d539786", - "0b075a76e68480e083cfa4e529140172fc0d930275a492e9f0fda93ec5289ddb356ed776dbf1b289cfbc713503ecb30bae112a4b815d47303a93c33058124ae18e", - "0a0615f9e90f9e9f556d98bc9d3f2375aaa7432b0cba7f262ca2d0955392d917da72548912c6890f5502f1db3bdea4925373d98cdaaf99d4a206f12280a77c5c22", - "0b021b7ef19cccf25fa4fb52c929cc288178c8dca8f8eeea81c31f4b28d087d843e62ba5dbd5706a8e5e3f8771168551f0f6253161015ce6fd9bdea9a4590e2c28", - "0b06201651b7363ad018f1407ecff8acef61404da98ded39bcfc64b19235a5a71adf3c22fb2ab247df2e19d30e4ac8bb992fdf18d3474a1de8220fa83e0264c9bd", - "0a046f66d23b06f604174de2a45e132885362b5f7f034a5976964104a930681fe3f9ab42ce4c5f7e52cc90ee07d074c6d747cfb7a883e1db937eb041e7c0d793ce", - "0a0688ef34e3564edd255c31c1bff4f9127253ab7c9c40c90d85ccc03f2660e5d5d0338ddad960fd98eb3fc28428b330404d20ef118abc4e95f82cdbff4c540fba", - "0b01bbfc2478be92940d970c304deb65f6d31d8faa956c73a96bc105325c2c34f83efd571756e46cae1c3098d25ae374963c29efa46507b49129a7811843f097ce", - "0a057e53766a0408b1b9da53ce3d47be431bdb921151780a9ea87df5a2580c21462bc6ac7e272d1a5016a73c878d3483702d379a10ef80feb5f0745dcc471c3d35", - "0a08b37865616ea00278b0626cb10f5cc983e9b11e1c88710273c51fb1649d3b1f7bc75d6b8a4b29959efd8abcd4cf642e37e7b9999e5380a2f1908a5d380872b0", - "0b02ff033a9392dc4dfe9a1b2f7abef8695666b77a431ea8cb129440b5f82d3ee97dc94ea0c2cf51ba7727f11962528910d9fd90586f97f443f19778d7b85d4d7d", - "0b01276fdc95769070495bcd67d3e63eb09bc5201491154425c411c8d964aca097c9b1083c53ef69800b4ec1db8724c3f1b4b3d42e20fa4f5f15adb91dd09a243b", - "0a0626a3d0fcf65e3419540a76a3a5a8810e09e25536310e532886f095974160d1507607bc11eadefc3500ed89e664ed1655dd8e50219729668fcbbf2bf327ddaa", - "0a06a51d2e40a5973d0b062086cc25650c55c920a2023ac5e9a6fda9dc057f6f0ddf24ccdc7a62170c1a69ba928fd0403af17d68578e381ab106155981aa444f74", - "0a01753ec32b2a32db2264ae121fb9658ffe8a3765c22fbc5eb210753b882bdd018b796caea96ef429a6562beec7fbc228ee4bcdfe68a0a0ec4b1f5be1330cc57b", - "0b03edd50a2bec184647f62f8e4fd57a160480f334cee604e14e70f485181e58080b5ba2facbac50bc06969ae2f5c48ac2fd51894d67d17c4cecd07764f6ec2f74", - "0a0089f50439049e26c337fad9d3dcc02a03aafce0b5bfb65e11b6480a3cb92951017b345d030778cd5c04b9dea24fdbb561492ed2ca2cbd775c03dba0af8e3f96", - "0a000f3a61e29f1a8363b0c01c57ed0162892d6d33df06f82401a0b342d9757f3ffed9b64984dea8ba51947b5e1c062693d652c4fbaa5761c6606e99ef79320ba4", - "0a00d624afd9e6aedacedad55316ff1a1e69c3d533c5fbe7a538c12f3f579868c9cd41c567e313956d296735721ccb11312e7b18f843780ac07c23d7b0a425a849", - "0b07aaaaa9edd469d0a56e55d5993dd1bed94b7abf2044288295b783eebbd917be3c59a6cec904eab3bc152edcb13b5382d52957e3abf36426f0309effbe88b5cd", - "0a05f82b8773d96c8f527f84c0c5e67e3de9ec00b3363d02e2fe754f2485b12a830b2f23a898ea9053ca0e57c3ee34120c76f3fc4a6ff03e3a5214824f98181a4a", - "0a05c7ab8ad29374144d8dc42fa821640dbf6e6b995c6c100f1f48511ee53062af5abadd3d21b33f5e98c5c5d3cb88cd5fbadcf2a2f72d7612725eb805469e05ec", - "0a0677ff613fe031c36867d3a99fd7761b30b0ee720d0176391fdcf5940401719ef620f3ac54a8d377511e4b6d68ae7168e3830143a06e2e451b899f1dde6524e6", - "0b05a7666893c0dd65fbc50460763b059524a9aede8f6d411afc62c0dc78036dd929330435b7a08337eba356fb55b9dddf25edb4d71d37166bf6ff82500cc68e25", - "0b0700904ad176d1819b1827f4e4e3f14efcb595a657b8dc3b4f14fbf1fcc2d2f16a81f7a5ebc7cbf1a0f02d0bf4b40ca0286eacd71048d0dd0c161f1d770c99ee", - "0b02a2c4af3919b3661189001a576a1ba8450c26fc8fe1c0e5a6d3345ab63f2f1bc1510bbe465ca1bafaac524d9a3885eb454f03e9b881457f358e3918982ef38b", - "0a01254b6b2f8980ef216a49b807928eefa2ac1fd2f755ee37a1ab96967b06e7f913bfd81c6a55992f33cf1f77f9c5e7d9c45ead905a3d98e355201ff838794bd9", - "0a02b8598e3fc87e722d0e118f79394488757a64d0e16ecabf85fc75134eea5de831c8308c81a3e0edaa4ce476ff30a388d3708b59309cff2c60a39db20ff32363", - "0a05f412d9666192a09efdf65dcf8a2c73e289f6b2fa37a6f9fb3f275855e089a332abbe6f3a41aaddb935a29493ef4a6ffc6a64deceee464df32d823d45553629", - "0b0735500addee794beec125d95013ca39d5fac002d38a25b0a5aa65390c96458ae7cacf11f6ff45d7eef5ab5f5b3c5579ad5f2642f3b38898d021d64aca97b7fd", - "0b019b5d4aa3fc8b169ebf5f90b2c4eac5deb9677cf76fa6943c4a544ba4fa0cc3c07ecc91c193c3c36813870287838ab99bf4865990ed82bda6e76fe90ec47381", - "0b01c472e806ac4145bc1ec56709087ffe8b635ee0393f721c55f9e9ac65d032732572daed210273f88b9958faf7730f973d0056b13151dc1fcfa381fd580f49d9", - "0b0155d4f7468c8e8494c52bd9601ec4f1f4d2fb8383e6c4cc2d2d8d420c4e3b45d46d864e77f19510aadb961e729dfa5d0dba6a5ec657f91729c496d73d9e2dc2", - "0b0879c0d675f3e32a3f4d12dc1b81f2247e96d4729bc333e7f4a64f1919a7566647d9c8294d5908ff789f889ae4dc24ba6bddf2a35e4376c85bbfc9bf0f9602a5", - "0b089bf428089334537705f8ab51c6e233db8264a0fac3cca70043f23731595d458fd3b98f2c2ac48e794080d0a366f5143843be55731a45c8b810bc119747f04e", - "0b043df3df012bc0ce86819bc854d6ab58c1caecca5eac2d37812c56f2a64bbe3b0cb7bb2ec14a2e15a45cb5b2538c659f71f1b32792262336c8b31c66c2809a59", - "0a0262400b7a34b57d706b433f8b5d480a60a5f8a53db04bde6dd030555771ff544daca5faf60c689d58469a107487b94357816fe7771f4d7efb44856b453f75e6", - "0b05771865f5347d92fdef530425133d741b03fc5fd5285722c5d22f51aed654a1dda6ae899abece194a018801305f92bf947ea41c152e637580bacdb2c53ca10a", - "0b00d021d005978d390bc3d10728033c1a6ee46f04e7e4a7b60abf2f1ce0156a6d79031efe3a6be1ff8e1fb9a376b13b09526c14d9de657e664d690a7c7addefa2", - "0b03ced8ef225337a3c334973e25b90dc2e4a70b686e5c5d131b053dd524a5a2986b329b14717a455fb53a7fd1e83ec4c199c8086f1102a29b1a087198bcf3bd90", - "0b062aab7d64669d35df070d72505014a27512d6a3d287122404e87b6c42195437eb418110ec0dc5018b3213320ed5c1e60129f14522025a1bd6c58bc7f8b22a67", - "0b02decbd05c79df7340d9df01d695fd2a4d297c4d9941f032d644e9e86317a52da1363113dabf67c4755a90c7df92e6752785786ad29c7eab233a435a569b7773", - "0b05aaf9632bdb236610fec80eb63bfc3268233c4aaf3d5d305a220d48ba33e888ee8e8e75802bb7b35501cf272df45de63e0219b3683400c18a71ada5215cddbe", - "0b009351d0ef3be872fb25cddfb6aefb9d682bf8e7e11aea954bab6e3dc064573cff937305a8508c2fb78054fc9852e9300f870f26a7927a4c9bfe0804c56cb833", - "0b06dbf90b392e8581749e2a1c7ac0c9acb83a62188a55363c522c08fdcda027bdb2a1e5148a0e61c2bd50d835003a68b1ca662968270d5cd94105511e1ce664ce", - "0b070a8f65efa649415e4bda9166b506be252f5403b7bb4d1eb2780d9897c3e4a74496e941bd7be58d7e1311073a9e98f412e57ea2eda5075af1619be94321489e", - "0a028665d0de3ddad8fd76f307ff94c059648ba00d6e691c6ddb500eea5fa1b7cff498ace1da3d3e8a9091040adbc54f650ed179d8573b5ecbe83a57d0e0267a5b", - "0a07081c73e80e34142dce2e8bbcce2819d67d90f99d29207eda3c44c3fcedf9df51785b2f8d4aa757979b180b570388558d8c50de32893ed5c74304b9f87df732", - "0a06021bffa1800f7f7c1be17e76f6069b24f91e742ac9bcd7dba5d32357f695be12280bcd828608f6ed8e9a2b9aee83ff168bbe8d8e4ab1319059ac12ca69d7f8", - "0a0328144e350a75b79f03f31a35e65662f89287d6663210238d604407fe5dba180915ef6304cb514108d1548791b059681c0e21807cdc9376b03e0377930546bd", - "0a01ea53541d48d8da76311a1572ec79ce6bfe492e5f5c57ef858206854bd426f774571f251c385bb719cd7c3a6068ccef7019a3232f502d8490b06b5ae9a638bf", - "0b07c3e8c0d14fdf5df6ab821dd1b70b273e2ba0fb8d0ab54c7f7f0f04c29a4f469a83b33119f92288b7149771edc68cf7f01a82d082b5a762844917a4bf1e39f2", - "0b04aeace0d47ef9ba5764c6acaf65c427e19ffa7cfa5be6d5c21d79a4dbefcdb30488bee4ecbfb57eeef5f113ac08b43bf24d925505aa26dd6dc28484b62a5fd2", - "0b0313218f33ebf6fe6102168f48e9a971da70a1e0186f612ccd5f462b8f508a3cebc30faee4599efa4f523f2421fb1878743d62ce30924c3bb575440599f25f13", - "0b0903a07aafd40e2d209f5f3f1833a5210e9e44814e79df6425872fd880baff9c73501969295667ac714e92eec94a17319d233c857b79810bdb0b436a01251568", - "0a0589359868a9c70b877b03f31af8a4fa209214e334f8846c392c89cf295de598a1b8bcbeb955e1c6d1e45340ab65c6a423cabd5638cd5d27ba2a46613e7a0844", - "0b05e9698c3570320765d458df49baac55af3e473897068d176a5630e38b138a2625e8f14c59601046d86c889b5d2d0288ca75c79d4e016d4fd506e00610ae0017", - "0b000ad3c085d62d03173e4babb02ae368b7c9b17c1a37cc6612eb5e510d945b9ea1fa563f521cdc905dfd4b1dffd0fc0e3f72467656a5f67cf2f54c13ccb7a08e", - "0b053f3e9ffca64a26cb60425cedcf964d24c4ad36b2f8737aae0798e61b7cdc573e3bea8b2e2a1e40ab9799244936c8488a5d507c5bf510b6066f94890e523901", - "0a048a852fb27a52be4b36314778756f6fb517c75fa878a1520ad7259d1182e820cca5c1efbd9c271dcdd649362cefc3854ff9664ceb9362f7bd42c15e9e12ba02", - "0b06743f9438a3f8f2ea314aab5d189da91fa4f5f5d943a43bc0e52b7f3501c804b07987f0352e8036d1c5350878c0dec7ab2017f5fb58502f5bf54fc77a36a6d8", - "0b022b1315188662258cf1fbe9d3adf6063e08c02bc229231443caa52c84bdf2a7797b02ef9c09ef40d9af3f65294d2d3e0901add396903edec917aad123ac5347", - "0b0686eb033c907b02b43102d1652296ad772f3d380e10fec7ebce199f2d61b42e85e31738550d696b906759353dac83ba08d497c3616b2f258d2eb484a360a0b6", - "0b0510fcab58bbce03ec2d453f89ba0f3b29baa2638d43b14f751533b8eedfe6a04e3c66ac1e216360f1aa2665b5abbc953f335031b51c0859b5cab44eb362480c", - "0a0043fa6e82cd64eaba28e29be9fde0df346ba1e589fb9173b5fffa72e7224cb7a5ad9f21c3476b0397e407b5622b846b5a57691514dbfc91d9ca47fd21840b04", - "0a0864643fd83bf1963180f4546e1e43ca290cfd85bb0f3aebed444c17e24705cf50fceb3f43998cdc7b6d61da0e22758ad0eaf3ca7c73ded4ec0dc8596464f5fd", - "0a048300ab3dcd708adb414fd92c6fcf448da20c437b3d249a82540c9f84845d9b348c8f037b098285ed7e1de51ee5a5fcd3bff308c5193db31f9e13d6d9f52e02", - "0a0208beefa406f863c24b53b71da4d3e06eb872168310523939d3cd2973fd230d6f15c020defb03a3269269ffd0f756592922ee7db9fc00157470ead51c149c22", - "0b067c9a7edb54ca102c0471b76f10dc65442c49ba2e737ddc2acb6310746270a5075f00bbe7d1a244b93d8640feada1e4c2efd53ab6dd8d9ab22e6af701825ef7", - "0b0791d4070af8fb3e674ae4bd93b34a94b6bc245e328279f857b4732195dd3082e1a68460b41cc6002098ddbe29595196671d8779c9644b4754837cd3ab0c382f", - "0b050ac62049857c076ad0da34b0eb1557b20ea70a6772d70b07d90f972eaf6d08209636a829bf7cd959d30f5bb8c4d158ec0acdc67f6ad10b7096dc98596bd0cd", - "0b045616eca0ca3ea348ea5c689df86f83df6dc1eebb3313fdbb460a2a6d77abfe7215007dd76667bd8df183b928f55bb9d06685a611810c6e834831ea0ab0e54f", - "0a00e56529ca45162cf4ee7022b56a71627f9ffb11dfb38049f3f29ac6e5278772ebdd99e622e86ff35529a29ebb7f1d79438d18d51b0b7bcc6a2f6cd7862c4966", - "0a07147d33b29853b3f07b3b7fd346f4b901eade0577ec95a6fb233e0c92687c6e99394f459bfdec4ec51b14fc0556d2a1e101763810fc8fe7a1f0295eefa8dfc6", - "0b02e485acf4f38e0cbdc2c081b70b3afd58aac0a289a169c0911e62037c4511eb7310bf508403b229e425ecf76a0b2b66dd9d8f1759a5ae05cff4d46247aa9b12", - "0a04fc223dae4b5898d02fe68b22af3879d2338846e77373a154d9fc762cbe341a91cf98b344be3bd8d04b4f6b8362de7c850564f6fbfbc2577294a647395aa6e6", - "0b085dcb2c0707c626f98ac3911beccbd2df5aa089300743118fc2954132c14a590a25039807e2ba944aaf87dbfc389403a3cf49e0c62bad55c50b0d299bba608a", - "0a08eea7be48750bef810459ed3ca76ef84993db0cd64d190a990011e7d32e8c88beaf4dd2ed759fbaf25c190fe8447ea678b0ef9ca152dd6b721e278608878ed9", - "0b0358c1153ad4a1486a9192604f2313db10ac5c8e72c8f9fb3864511a3b82bd10fc356dfd5eb73bff8aac2d0259fba69d4e4570e5c8b49113702284300b9144fb", - "0a08a72d5cbe67e2fdbf45eafc9d36012684b97eac75c56b9216696ff18eeaac739c195aec3c87c895db2f5a0bd35912795ff7dad0c802abb6660a0b1e4acfb481", - "0a060f3ae58ef9e9d2f148d0107b30c29b8e2b193a330007d87d420e4f0f725c40cea8b533317f50c52c240064c71cff9fc46eadb967d9e7b616e3cd805fb65d5f", - "0b074730377768d6933b397e3ffb9c37a8f11fea87e66229dabe008b74d36a4a739155fc600000f4000f02ea1c59cf3e8cf0cf363195df2cf8ea99b9bd2c46eb92", - "0a00116d74eec41a5c3e8d6a3e33faca5dcb3e8e681bc6733968856d9e302ed2f611cace80fc957a0389a4f627be76f073941daa0fe8727414b29f4e34f33757ff", - "0b08fbb9798355fb973e83b2920d4e76392cf7451df77fcb8d1f6ba279c1f96e33ce1c860d15e085baa590f248dd8508461b8f2b0433173b4d036de5cdc1892ee1", - "0a061d8125544a814f07be9361964159aa6e2e4ea451336fe0dc0cb916567a143bcf7ddc8c6aaee94799dc3d11dfad278041fee1ae41aa9a60a641c35c1d5f5dce", - "0a01052acbb5d6f39cfa4042ad3de0904bc56e304d145c42faffeebbbb075f6a8e1aa274a555eb8f8889c1c81f5f85ecd4d14be1b63286a3a6ba6f0eb9ed50103c", - "0a02373c14a3d8b7d461b34a0726005e2fe4beb5f5aa2f2eef035c1855e82b48dd18b9785edef03efdc39906209a1cb634cb02b50973c52b16fe1c1532f6965238", - "0a042a40d639d65b53b8bc167ac22b50864f16c7670b6b83a46953884cfb74b2a381b789c0fc3f7e3c4072d0737c6c3bc1fe62fac682de7a7c930a01e716b4b6ee", - "0a0872125645beefda27c1e6b451cc706745a4affc09796cc05d45273ced3b64d579e36ccbd2f3e255761f57cb611565dd217f266778ba19e80ab155250f3d771a", - "0b036209beac06569073a3b6ffa3c2218f7283b5d1c53d2bc18b6afa71b9ed16ed79d5f6d5975625cc01fcfa5ad2708c4b9133945f4657da0b8ba2df716bb42fc2", - "0b088739008540741ca3346f051f3e6c5ac7671783300287f56b4f67f24ed12ea3ef773e7b4f62bc6e6d52a83d5dcb137a5754fe7e8cc17f55c2042d15420245b2", - "0b08a19e3db1daca06850001c8264f27d5e4172124a67e6cc8bcba0f82dbd2de782ca7a61e004070dd34cf0f7d3f1b1a91b3219ca0c5a1806bc726af830c471bba", - "0b07ed40546770e6a3e14d68854511c71b2c97a5c495756199e3864dd4d76c18efd09950697f99c5424f46c63e23026a39584a183e00d616ffd5c6d0d08958b72c", - "0b06baa70db6c95413c71671f2968b5dd3a7e3e8d7f9751fe5390110679ab01dd6027eb44c98f418f46c262c63f0f902a09f75b32a0294321b966a6e15caf06cb9", - "0b089837cb704e80bece638f8f6b6c359c384e9ab12398f6fdf2d7b51048c7750e07a1c0584927d51eea01548967d9cdf1b2d531497e58dacb8ccff57e1070072c", - "0a03d257f044c9567e43bb7a7158290c54069d0a1bd7d668fcaffac654a3255c65c23f900bd3d142be411d6971e0fe45759576312a4a505afeb9e7bf28d732351a", - "0a056d4240c1e059e4a492eb0363e49aabf65e54a7ecfaec47e8431e90ec1557e9cc8d0be017e24db3d51543b604f870be4a384cd6dbca6353c97f5dcdb5df16d2", - "0a0780deb562611719a5fb4a2a8f784c177589398adadca7075c35ed1df5ca0617b64f311b801d2fc6fed0d27adb68e9ee45efad687842993987c25f7a28bff5bd", - "0a023d7031e663e999c88278f42f3c3eb313dba4c8708aa6b458548b22b242eb8ad5d8ebf83902fc517946dc203cf6c36d991ab151397c0017273d41f168900be8", - "0a01f5b76a599c2b7e141d155d312315c384f944fec8cb430d350b0186146265a5c5c1cf71d9cc4be3350b438e76c8bee835d6a05799960eca1a7f8c1983704d09", - "0b029fab381666ece10b746756ff7d7915353dc4fef25904a89975c701acf0072f390672759c7df155870c04b2c12cbbf56387457d85727f61ec03687e0ff310c5", - "0a06db5d908d586dd86843fbd2f719e4688e411ca0249ebb273d39d72e36401580c5da428da461000e76f8d984963c667830d77b25d9396104417955960f2b2cb6", - "0b005b8477210f511cc38c1893baefdb40e6b52ab76c966c997bdfb8cea5508be49edcfc429e0ef58ef1db11260802663940676d1bdcbbaa0f753ef5444cd0876f", - "0a07453f114abd558717a60dd2dc5816fd01128aebdd04a6d33f27fe8c2c7a70843e42bd5d6ef3166489f7796c6e40269509df7f2216d074c29d2c7cbbe5708c34", - "0a084ddcf89ef1ae4bdbdd786e94d4c4f40f4f52018301694f24e27ee8a6ea2a532154f7bcaef01c92ff1189cd8a9e0106b03c89884cb4a54927255814fcc4e077", - "0b063ea2ed17b7cdf573fa4fa063c21b0b7c132888dd780e182e47dab52173a20e7f54826b28e31b8e8c83e9a5f606fbcbddd9363d352afc5596c6b42d50d8c4de", - "0a03d9e54f7a05292a8811444864c749b2db7500f471a8b6e62ca4fcccdf47e656bc608ea0858036d010f391bbde8163f6e931fb6cf952373d1b1dd80307034915", - "0a078f22cb6bf3ba1de3d67e013240265d59dd6398c9e1ec86d13125c3f90abc7592e7ca4cc0f27358a04da7d9534bca8f46f042c7ebdd05355bba417b876acede", - "0b04fca5383fb3fafca5d091a424242d0bd980ce979178dbf834539004f4c211c71e943ce8bf7062695e668c6c565867c6aa387a3c5d7917479001325c1e371a97", - "0b00011c8924edda64fde0fecdb172e4269421471391bfe72089c43e870ac9b661239b7cc3ae787bf4573653c925f4820eb0ac01d9bcf942e46d21fd10801a5f28", - "0a044895523106e624e2523c7f2b73e956daa237a13035f18dbaeb07ed18134bd5ee8916130f2934e8b3f8e09ea553c3c6b7bfdc87f89beb82bf46d0e79239a9c3", - "0a01d0c2989948649f77dcd42be355b3437ea74d11bbb5f1e1b8aa00c5c2a79d5acfaefaffe73df93882a5832b8fcc2f585e0923f859dbbe1172d5505e33b7c216", - "0b0741040a3e0adb59c7ff9a0d832299ceb53bda8fbbd636f1e2582964f96c8510399b0e3847bfb61bb11e64449365b833904e32681d03b8e9ced1ebd5a051f3ea", - "0b068f359b5d41df5070bd3228b73b7330a3a5b18e75bc8590e6f07c116a61e3d12b4f23dabe1acc5d5a3836e91d8b0079bef4147bbae1f0bfb8c3ae1aa3f5a559", - "0a08c285bb3a8667546445abb3d973574dfca37cfd871f0b88a0aacae9183cff5d7f0afdbd9ef7d39000070d8c3562b8902bfaa2fc5abb20369f04d83fc68d0955", - "0b078883151be4e94c9d8e70acb7443ab584fafa99501bf6917985523598806963ad29caae5cd7f130963b74917e8c4d95e26ba7e73953f63ffd8f19a98bbf8021", - "0a02005441f3d7ff222c8cf5ca2f8dc2847b80a8324740dd81332d404041e8e9d4b92f894110deea32665ca3239a5fa8a65a560474cf24aacba82dc6c9909e1309", - "0b07eb082a095fd158cbb814d95e5140b8204462e5091237a336d417b9fc8501af41d182f983bde6c8f1195cd737f9372ed3684e0fc0f7ef81d07e8ff481a83974", - "0b05a12c5d23a3d2c22f854186eb47b2f209b0c9a0f93662a8fb7799077e98588d54c31229ef803147e20dd666ff2cdd6a138b19dabc2981cdeeac997f65194342", - "0b06627be346aa76daa14b6023afef1f412a998efa56815035d4e3a791df4b825ea2df813c58293f3b1963178dd1738c6b33a0ae5eb31cf28d48c327b97708a619", - "0b038ac683a14218238b4b746dc64b03370f34921b4bb8d78eba4a7a6e1c2081f0d0859841f898799ad2f6fcd4bb3f1df5215d81bf7167711a576b7f7d22567cb9", - "0b06a9fef51e35d58ff70e97d8efaf656877249dc8444524f72634283707663093c9dd19adbf64b999aa6fad7bf6b57199396cf126f9e222e5e94a1a416662e821", - "0b021c1bc490ad0429df12806f1710051eaae74e4a9eae78505143da73a503c77b8fbbc52e5fd63ecb67d626670c21e1a97862c25dbc5711d95408dbc722318346", - "0b0265c4804de9a18f43b4b8d4a6cb973f59562a56c7860286077c99a5faeb3b3e08046659d03c7341cc9a0a5838875548995924d498f41811706b57ce266326d0", - "0b0679caf93973ba4a0d3397fa380f040be997a57d3e7e07deda3cde78d680adfe70525415440fb0c9ec406d45167d82395ebe744b4485816c3a589e7b1957e392", - "0b06ed92cf093c6f9c733382bb777f195dd2e1d2bfdbb027a913a41b6fda6fc73cae41459ceea593159af7873c0e3464dd43b4779b462a024d89d53af573446cbc", - "0b0176e80cc6010fdd5f05c930b23a70a33466526a4991144a931967cf969996d6948119c1001f17994684874da3f39ee0efceb796ff8d18d44d73d90264bd9511", - "0a028ebbb79f246579e23077cd53863f1d23f7d226ffe97c5aa9f6b461cea29720af251301b539c813ccc2f623296a4fa4efa399c6741d915a0049fbb818644f90", - "0a0423f3edb831584b3be22fa3b8ffe24277b2ac0095f6af01c5a40ce71405886d3cb06e98f548d55460d7fdc3dabf38124ba3e57e3f6ef9f3feab27c28bbb5825", - "0a062d03ed9ef2f26146dfec9cdb15ab343641ac45e6b1324b88f2cd13c01950289f3636bed6845ccd0697c35b57ad49332ce29e6cfe4b523e84324ead319251c8", - "0b089f7561e9aafa64eb42ad497f3e1a1cccd9dde0375cd0572fa9fc6f15867928a1bb1d77b0171e74bf42e0ca6f2878572fd1f69da2192baa7b1013f0555c31dd", - "0a081d4e0cbf57d19da3f77bfcea5edf270ddfa2c968f2eea4d5468bed5a2c31383a007b99f9f5f43002a95199e5e03a3379015c1977db05da99cb3d84e639c39a", - "0b02857c2000c73df3c78f1d7df455ca81b9d6556e40b7f4e964653cb35496092984372ba25f4452fc37ca287ab3242e1de0f15ee8951b97057e966f09e57a8bc1", - "0b05dbe166403917461862de1fafb72349ab53849e183399299262f71b60e1aba3becc6383a19f07b7570c4378a34514bcd76a8a59374a7cd6cd0069ba65cf7b6e", - "0a0004c79b1f53c74b26e3ec03d18846a44c4016bfc6a70d0bd802ff2486522afbf3a6b56eb9dbd96506f09c5c260e83be95c5ddb73adb4d775ca0cc5db116236d", - "0b03ff10e2ec58385d385c11478fcb290293b42eed8299300bbb78574a95549607cf374394f91b851c1b54745139a6fc8ea85153bb0dd19913033ed18460d8b9bf", - "0b0252fe212e61d722cb8ae84203ec300379571b5778473a22d6d1a54d07035be87f2843601fb1b3b8c7be5cd2769cc7140be9a0f43c69d109b6946a6800b1e95c", - "0a077a937d58611cfb4a0a4f81fd4bcdbcad17a8ce6e5c002425c63524e2c85f6807f989db6b45293581e1afa34570af1e0cbc956d768209f15c40378ba37cede2", - "0b08494a851916f435150fbeb9b4160ec7a86008726be285b6f66ee5b540047a9c0b5f8dbea49aab677615fd421e1dd068504049be59087c382610d5e28d3f7be3", - "0b0049f662c118b3412e8340f87ff81306b8668a09a5a00f5028b265e23b1331daaad5528b21b276cf6d57a5580cf7e29eba77b3b0f819ea3f87ab931a0126640b", - "0b04e29251d77c08924ebfa414fa84d2f8ba14e364014ac7cfe8055af087b13535dd523d505174b56eeca05c1e279dce4d8b0f5d3db974831badc89998966099f2", - "0b0859d7309be8be2c32b2f6714ff3ee28e2f192932d8db5f8da1eaa6b7ee186d2030ca323e804d26a92888b31d331d66e007d4ae7a18b8ef1f369a9b6b574568e", - "0b000498412b10392c004c1f5b4aa10d3efb9ada4e58eed9ba257925ee911deeb9b350a83e600337ab494139a714509ccd0ed2df89eb1e8d54eb3badf08eb867f0", - "0a04ee983e8bcc1039f9a80c20ec689d70f7b01557b53e536978d25dc1d1764fcc62964605a6e6c9153610bf2b54083ac9e1cbe5b1237473db839a98e718d02d0a", - "0b084bebf3d33ed1a80ac5275caebba49728797a8d7d7cb4ccbc337dfd0a616856037a2663f6044f05863875c1b167ca8c48b402c49486a82d31baf8082bbccb60", - "0a02ae846d09bc182a7cbea43581edba03875e5a2b840dcbfe8a72254d697efe80ea9f973eaa299597de43c789bc160ef122b7f6bc74a0145a96dd7f7518f51d8e", - "0b01f17bbaaaffe1da27b8b110686de0f7c982f93ee4ed282b7a0039585829ffb1baa6c237431cc93655313a579001260f139a6d0912f62d980ab9e32abce179d3", - "0b029dfc625f7ab7c9f50f094f12341f20643faf7ae9fe3b475bbc9e4497161909caccb8e75ca764df8d74223ff74722e78bebe44803f9dc9b1417c124d6fda372", - "0b053a088d91fd98a2aeccb7822677d0d6856c28fb58447fa4678a473b7d216f92b33da9bb29437e9e9a00cb1a7f33af6415a3c10aabe3bd02247b22af320c73b8", - "0b07095c627e312a2e741829606ede2f2ab006e8977825373d3b4fd7225446bc1c1ef80c85ab3a53d5c506e6ff87f1386a0affe0d06e8125fa2eeff3a3782799d6", - "0a002c6c3171f881e4e9243d7be608f6d7a1d424f3b82b98721c75181124a6e9f3a76b6edc1037ea35808e0d4c815591182a13c54659b67db66efb5438645658db", - "0a083364a38e1febeb55f274dcd6877335d0d8b048cd61207513e503d5d9e55b1c9334e7862c9401747e4196a28b13942f6519ffabb1492cb9ae58b5e1a2681f5f", - "0b04fae38f9a586afbc545e7afb7e10643526a5c13b80d4eebd06f16c2d7f32df2badc38baff20a47ba1b1fa0a6ae674be349bb42497a3a52aa60530c23b41f305", - "0b091812e9181af615514b247144f2b88b64d75a719932c2f24c654e6f6a9a7a89959c82b7ce0f928b376f7fdbe6996a7930064ba83b4abf8f522cd684e8c0fe8e", - "0a079114ff63e6fd6bd064cb3b02753276fa5c65a5312ac201ef9f1a4171b22c7e5bbf51cf8b8f1fcaa813818855d223538d2df259af4977a5b1a7ecfbcfaa1e8a", - "0a0413811325ae423801c3352b4dfe902600045cee443b6c6d98e4b6f89ef57257f7f5bc01004ee13a0c135ae9bcdac5cb6970c27db09e5938db7da5fd8b35711a", - "0b06ad901de0327f771088a94173c4b69e05f0031f817394c3247c887d659d7d8f7f11962f6d5bc230f3d848ed4fa01c47aa71155bec81c67f2ab99d7aa1b02966", - "0b0764faac34dde20a9a5570248d2f0d4d7ff67b2ab68e4776a1f7c2b93e2df7492f866816eb2ebdc89612caee24ce226f3c05feff75d0fcfaa9876a20a9352ae5", - "0b031ce0645918d76546c7bc22ea99c66d0663478759bb21bc644272692190d4a30d4dc365a700a9574a9865051f3aa59a394dac87443fdfd0f54b5abc386a3c8d", - "0b075f03757818151e2a350e8b411d75b7bad95af8cc8cb902e340a35ffc70b24ce0f362c61d73b59eab16552c548f7c21c373748d77ab0a739a23591dbadc7ffa", - "0b0811da25a6dd7291f85eacf682f1559b3eeda75078ea6b3dba74d82c46edeb7bd105c7e846d1b1465b4dd4ff898569869c80cb6e2821ae6de4ddc5735864f168", - "0a0796fee15c1b00f04bc755905bcb93a404b3fb763ecd41b408ba9ffce77e87094c88dff2283f5085094fa9f1d7ca8048f46a6627caaac37647d73122f562e870", - "0b0313013e92a7018815a33c21dcd3b9d081f427a3a6b76d54fd2f9ffb40815eafb31546c90511518e3c7daea7302a4083f50bfef7c9e1b429dd3cbd04c3da3dad", - "0b067a8d69ac0438b73f6e52c9ba56a39bd8e75600024fcfadadfc53ffb3ca6b812a7362aab87c8f28e016da25be733ff3d84d18adc61de52283538bfe85093b63", - "0b01fe026f87938099aa97f4d789e8211c610158d8dc01d2a897ae64ed292d787ef24375badc36429fd8724e287e4a59e060d918db5421793876da811e20adc020", - "0b02de687e046e37208b261c3142a0afa133427fcc733b0fa21681a7dc85e1e3bf44863dac928d6f0883fc25a4c761879f3b725710d8a7aaddc3736225ae3a10f6", - "0a06c8dfdb22c2bbbaecbbd5d7574511a450d1e2ba32edc132d8670ac7433c9235f00d36caa840156bac792d1c8f76d85bccb579ca58dbbe2814042e6c045bf9f7", - "0a087e9b43b20349a6a5ab8965e033a84f338ff07214afd5acecb0b9b7598d2a9830e3371e0299ed80b71aed114f4b0909c3b4ee14b12aa1f60b8a8e8983f485d7", - "0b06a1db2aa581d4cef3d00998384e57fe8354a9b24e9c16cc4cf4bce6c04e82922cfe98588580a0f0ce7641ed844e42a249bdd046c57d8dd5fb9f235db5f9466a", - "0a00d152191693fe52ed4e6b3e65b2cbb4d5d9fdbe170cc064192219088df9432551346990db750ac88df432169540b7fe3526b2648f1d9889348862981ca0a8c9", - "0a0063d2e4ac5fb8d387908aa8e3cbb69e0b3444a89497943a91bd73d7e96fba2500c922f198ad04c1d5c7d3a5b2ccc1ec6e6aa56570fcd49d4cd5d16ea68a5914", - "0a0558bc3b5b833bece40b921f72397f9e601c5e0416d3ae97a8f77350f63b824609f3ae815a0952d7c5d04b75d26aa6c411554cf9a1c36af0597449183565456b", - "0a08f3fe6c4c78064bde42058b0392e8cdd0a58e64de5d56ed0d415c06b4fa33f8bdf8d7bc7f9041d5df32d0e03749fb3e81814efa59d24b6687a84df9746a0555", - "0b0678d4df3b1f5565815596013a375fbe06125803386fe45e82e67f80beb88526fbf42eaa9be223e736add603127976ff2d780b9d32ca2c90a353a0e1ccd644c0", - "0a0814c5d4b5e92b03f72cb907e71c734f19255944d79f2ea59f776dea376a36ff20dd65a6b7eefa7717168434a0adad612fcbc079e71f0dd3ff26b90173a3fce7", - "0b040e95cb5b392c2dd3e47fa730448b30465f65a376c3c231a998524279c771e99a4deb13d4d33c4afd0a04ae1b7ddff82a5202b0ff98f194be7e7d57a1b5ac07", - "0b02a32dd4cc8fc1b9412ad9608a9e2338f6e427f099ccd0306ab9a2d143cb5188cf008bf5ed0de20d120cdc1dd4d26bf6f67ed9e5b63ddc9a8f141615390b37cc", - "0a02b923b117fa28fae91baa771d99e2e738d4140b9e9a02023dcb194688b11b95b9e4ac0525eb2a990509f1a09721868a969bd94bddff5fd8f147f0530932ac9a", - "0a005f98838927a93d968b22c00e5d8e4006b42ca15844eaf36bfa8ecad871a3efbc1e5434dc7d617267fa0956d6057a475663d7c44d6da9cce7547ccf2c16966b", - "0b047ce6586bc0a331810719188228f97c3225943d0bd7fa3954fed4a3bb217a95c39cee241efa36c2239268f7f8501a8e10f4c793b0c31a470cbb6e8812ee4e46", - "0a091b6d3d5bc6a7ddbc2f4e76a0442cce1a99d18735095789ebd67d0880d1a5771414290261ccc5f91afd7f707e9efd1f968d4ab42a34eb990b8f50a5aae998f8", - "0a01a0534f14eeb4b60df047e8c81703cb97c3605fc808c782680dbf85768494912c138ab92f4aa07b7d55b56002341f5ed7eb56284f568b0ff0f999a2e977ae14", - "0a064e8f13f535cb20ba5d982925342954e8c48680d78adf5a93e157095c92092d0a981993867cb8584a2a8f185d4ee99c1844a40216db557b738926e819e1471b", - "0a07bb5bbc62614d328d08a6ecbe5156ccd32c9116976b109aa9040d55e6f8117acdd9c9f64954db37dbc147ee6147cd9306a9fee3a6cfd7b657da33ea6fc1f04f", - "0b03ab7dacc319d2b29e98c11dd510c92bbb9be46d810e7e6d98abe65a2c2e8e93591759dc5b1c8de2be9915ac87c389bf56b5b768e030a53dd472049675ca0d44", - "0b0738d669c68b963436cfafbfc0bfce58c57a773dba13eb58e84b8afe13b5cd192fb61e44e4ecea9e27f44135ced76f7305f153c696f0f5118f284b5b4e29f23a", - "0a04d550c592022994ed1894659005a1fcba2ab990f64eebee94304ef3a5045dc0f310c447878fc94e928f85dcbedc0d9e38db8eea03a04c1dffe2de13b328fc05", - "0b003f198513ece6d15132006eedc0dc55ed998335d0ae0ec030855e7fb14052b49797da10fd1acb2e9cb6e64a43b7ae65846d83449b20cf97c6ab2132e7834689", - "0a089f839c10765351265d0e89b6f3425f5f589d7d1762608d9b78bad957be6826038690fab698befe2f9fcb54aa86be3eb07a9096f2d0f7ca46e3d90ae98545b9", - "0b08d9de20d1f7ef76b3e513d1ff183d3854cfe25ac5b803bfc421069577e34eb0ef26d2e193d640915df166680833e12c0a6477c6ba60592b404aded26d38bca9", - "0a0144a0fda43406b0a7a167cd7c0548e284e45191a19b7c6dfe1ce1f47930e338abc90e5cc34ee414885bd0d236fb1c9d827de3bfa18c3d71dab16a6fe9c907f5", - "0a06531a0f96129bd4bd8d71db0d9c3eada2901f8910ed72378302948fbc631929104d48a8e4e68ae52e9b5449c104d6e45e0c80e175342a14bd1ffe0f59a4bf97", - "0a011b1ffc5a76fb412439eaf0d881f20558e058e6fa928ee8a17073cbbbdff33bfeae30152251c9e9252fc6fcc91264aa80a265b0579d0aca1349b96aba193101", - "0a0907a5054a658fe24315ac934acc5b75179d37787ae98fd96ecf64dded43411b6239294eba74d6984a091ae61d9ef6268b6659e0dda773e8d0663bf18d81b789", - "0b056fbb442d3e8115b3abc78ad27cf0cfcb10e1c44b2f0bf72be68c59fc75ac39eae3f7292c0aedf58e3b0d0e613bae838539c58d798538731decd00e35d33dec", - "0b04ade0ab755cc2e042404e7af12b7aada5a60a155c4b76b213e8159e7eca9bc71d3ad71cddbd1e5b214750246589c324ae4ed27ad29943cd564801488a98bf45", - "0b0162024eea05e7ed4b8254a9c4b82d895c4cf3703aad5dec6a7f2d5433655691c6d0ac82bfa2674299e2083c4d669e31a3af249917e50e7c508b123cd05b6864", - "0a0725e77339c93eb05a22a5ec5b2abb82c41cd98e0bed578969303f621fba2070f2cd4dd85da447ed23dc0d2ab62e9a0118e31379b0c6bf97de488cd000fabbed", - "0a01876ef2818c822652c259dc1d8c4353cdf28446652627761143a36fcf3ffa70e93762c52a23ddf50d52235cbdd3ab0de446eb5fdafa4babd4e33662302e1867", - "0b032436aed0eca769af247ae2ed6e532180d6e6d2aca7bbafc272de2bd2fdebc652163058b35d8b7215510400580e134f9e041da49eb786bc3207fd47fa4aa43a", - "0a00e522e5050fba9e7596e4d1a4c215fcaed1244076b42f52770dd3682b148d2ffdef9a0d4da344ae69497a88be0f8275c9d7250bc4b8c7a4a6f9ffb13c3e6c5d", - "0a05ae2268a1847da888571ebf105fa9d14c599719dffe33e05c8b6f88bedbb19183f0c2d94f4da675d8e90699f7bb23d69c91c65575b0713e9ee59c364a2b4b9d", - "0a074956ead94e49003ac7abdb4829301dffcc5f7797c23d274a874997135c6a576b5ad84f9db71b2bce403694debfd9ab30fcfd71473a94ca6ad8c6f1f0e8da22", - "0a01acab1ddad3dfe322e977f75e3f70beb947712ce8c44c90357a88df62a8cba8a31cb85f0f2ad18061d4d8d2922b76b97b7b9ac77f64662d05e99a4fe3a2099b", - "0b06feee3f8729193cb1faaaed8a976dbcf142d9518c6282e8a52adc7323f4a615e86ea5f35653533c5e2431ec560aad3c682955256c435fe2e687ebe2f2891f98", - "0a0120603430737a9e950671d7494a8fe4cc9e7916d977032e5b17327be1719750007089c2d6ff56bb9cfe56d7656e23e7656dbc623db72c6971786640ef7aebf3", - "0b06c3e0a61e02463d665fdd58ee23a1c7fa67cd89b448f2228315048ec032b270bafa62185968e2fc672378c05ce843bed0f8b1496ae7ea6ec70906edc1a20480", - "0b060b4f76a13a180fc2f0aba99c2582eefd5f9f5239ce039327830eb5b59efc88c130fb041c92472af9ff53b1a70b618568ea9dab0444310d8181186cdb4db558", - "0a05f34d04f97d9e26a65f458130e9919ad4714daaa883f735614ad1043ad5b794ce563d102d52d49094e02222bbf9a87be124f4d84f831b3b64ad6a8241cb38cc", - "0a019cbdb5502aa178fa0066143ef1c2d312c550dd4b38e1044ba7e7b0b8cdb5a87edf96dbd8abcaf98dd8ab87e6871904c7a640525293f0debeb72a3e7a7e85de", - "0b08e662b9712d570dec0f2d346375e2cb9545ccad2d5554038683b008f497b0d2e87fa1ce354438e07ad74ee20a678b867903e3c17ca1e6f5a4334aa87742c75f", - "0a043366c1f12c7e3bc7ba7d542ecabf189679125c8be02a1e91339c5d3924181499bdd4744484ad3162b9cc732d32010cc294f1bd7f519ece84682e1af5737195", - "0a027386550e74dc7076e5e902f607b733b79b1a5a338df848b1b552c2d29be2f60c385297845d9b721316a2dbb6a4a57f83afa1a8629fa012fb1f60406590180c", - "0b0284d12fd7c7ec19fe55d0d50121be38145b4f5e3ea878adfb0c0485adb7851a37359fa95f67f0abe1222bdedfabf3e5b81a4ab8008ad93d34b325a9b1d08de7", - "0b0615ae02d567ca3cdb08afbd1de86be1ef3901ae6ab5d6c8ee65a30e405bc0574dadbd3c079744f421f23c59b4ab6edff83804a72c2ac2e2fe1fb4734881318e", - "0b031963e035c225be1dfcf17a80549ff1a5bea3ecd8a08a243af70859e8be41fbb74861a7f23d0a7802c7cf1b3a47fd6aab5379a0e03adcf0bd9abfdb84c2f264", - "0a084b294a46cd2740aa20bec7fd89c20f567d4a73523696bd1f0f0ff3b27926fe1c8d3c648c187860a0ccd6b054e67e41c245c66bb4b06e9f666d418a8d19803d", - "0b06210442913c412dfc57685a985b57af741eee4f82b3f4fee35c1a89285cc0288260cd9d10dc5d95eaafcc269a86b37da6c0145e855fc658a92e522f98020fb5", - "0a0077aff539851de2a7712a3e3e09a1bd0ce99f36b0ca7730c28c705a6df76755b6750a927a9986f333f5a5cffc548bbbab56c97e86a3fb9bb33f7da379bef671", - "0a051e1d24566903c61e862c142411a649b710986a457616b515d1bc6c25ddb8162f284e7ab01a687f1a1f1c1a49e12b3cdc0dfda1fa91c92b53f1f5ed59776c26", - "0b08fc06273b40dc0d02878a8ae55c7a2843df9f1d202efef2fed36694a71b7384654ca83f5ede047e570acbfe93ab78b22558d4db7e7734962da67d3ea3debb86", - "0a072df7eac8588bdac18c3759febcb4d8032e9f4e8867dc9552d65a9ddfd34cb92db0a01faf8cab0498d8429bfd6c220ce1be0a3a04c13a2c37e6b96faae1f4e0", - "0a02118ecd7f3fa89c6208575f1e1421004ad5cd1d7fcacae7f41a81e03ba8c889bbc44c41b613545889477156ff38de7fa955eeddcfbc3955e1e3c424b905fcfc", - "0b0642fb14365abcfc288bab17848a70b8ac94700b6be2f14aedea8451e723962772168e7a16ac8e2165ae5d0dde927eff225b310bc33e92b4f5321d2a9b8a9984", - "0b04d6dac35d9e598bc1a3bb981d0d6b2a0e10824775e182c498cd41a76f0e1a2e8d1352d0a6ba0406251389c3b09748324c13ecc741f42ba674d537bddbdad2e9", - "0b04d6a3f42f487fc4cf25fa584fdafc13c152d1b8a8ffc101300d658cad11e7a1f1b7aab2054142b1ae4cb4ef80893723e8c9fe844e35cfd596a22420c9008db0", - "0b04d03eb9356600dea48dca9f165ab2130d9ce897ad7c3dca43184cfc63aa7c483b57f61f3c25934e08118f7559e56511afaa4ac81c03b3f6c626f41ab96830b4", - "0b01f7e548eaf267f3a67d901bd1126d0d482fe67a9c620697c6ca98efc08527892ed147b728d310dc8785c2c371aa7f3348cc892e40442289a2c8bb24bd2af26a", - "0b0544824d593e366f053cd62c6da6ccbb36b8d4698e58b0895179c53276f89715ba3bab793922e5a867f8fcae39bc7a3828b2b605844a27a134220a05af791702", - "0b0211dc48a75d1b9c6a33118d4b7f48c5924f7a76e638085fb31a8b9b53f86cecf4f0da78a72e286ed7b236804f44680a4443ba7553320355d8aecf63041c0aef", - "0b0196e22744d814d6c5376a0189f61df4a8cdd2dcf08f7f2980d82f614dec51551d4a3c3a3b304c44258b232cbf97059d58f76a38ee7a92d30ed7036a450f2abe", - "0b00c9335f559f95dc21b05125aae9deb039e54825f973eb4f7943b50ced999d6548a64acd46b703addbbc893db3561f9d014e696d33bfa14ebbc5c0de89452d59", - "0a055ce0ebb66726c8cfc194ac036e3ec3315205780bfbc0aa17260a8387e838b4cc2ba203efb15d102905ef66662f49b62d3986d18648965b5fb3c0ae82581bc0", - "0a00705bffa426dacee03951decfaee06bf68a2543165754bd67d9343b7ea3dd13a255b5f3c0be9d83b3e93adff12c516aaf6ad73845381c668d01b21baed0cfdc", - "0a04ed9d2f403068e636ac09637ac79414e9c4016d5ace18861656b7597483c0ee81cd7dd8619a928273010fa7d612b690156421c2a009307276fc90231330892e", - "0b01773fc224fd5209f8900d96566b0f520453c974665744f4023304745b108ba1d93eacac7c5c974f711231e2a80d56fbec3e6e053a311d731ddbbd20706dea62", - "0b06ab7ad9f4a4f6fee7de081449fb1e25beded29c46dacfe410251cc1aa07e382375c8f6ad71cda74c150c0f33f2349b79e2c04c47ee06c73006124096feba949", - "0a01963c6078e3e61657b3f37d1ee7de6e2ca0e0082109b7975165d13343ce78d6d4f2be58ee7c7c33d8588b7bd1bfcbfff23c57e50bc297da13303df67f6917ca", - "0a05949e502922ae8c45e97f861aa9c3fa008589970d8688d8b3094555ed946177138c52082ed0ebeabacec56135db07f6cdbe5b29f612fe0da688fbc7679abfdd", - "0b05b161bb3ab0b0e04830624cc3b4b9d55adcec8efdb3d8f91b7f8b3ca8952c555032d8089c7c9734ba2ad0242ad1b87c190b82be83060d07d0bfdd7987e1a7d7", - "0b05f9cc2a9e975325d6fdbd09a065a3fe4b78d96fd72896c98938264a69714f1eccecb09c786a13f67cb6ef3eb388c86dc22507350e1c8af40bd6381961e28f5d", - "0b02295601e90a230a8ab9e02cdabdfeb1f08b142b0df09358a341389308b5a09d93c2cc0ad8558cbc1052683be188ce5a24ab074fe2e5d8f099eb39a691ca40e1", - "0b06434714cdcd2440ef481dfdafebf82bb956e9478e55a09d633239747253c785b0b5475f6ae5e3c1b7dcbe0a4e89fa7d21384178cd117f6fcb1ebec9929674c4", - "0a00b3a3f4a6735dd498e8022bd5c6e4b52ace2e087cea2e1a6a7841122cc50c63a29a956982d8293e8c6e96179945d95df48466156579c6dcfba7d14b0d26604a", - "0b0145ff657c8baaa35e628d960ef09761e100ecbc624200e6d621a4171099bd90b8dbb341acce54b541f7abb8f7a1d6dc5ac175ea187497ae68a59d717b53dabd", - "0a0411d370d6a357bf0d00b30c025846788192004d9bf85f4864b6994b1cb38837c806340466832d7fbd765763b9c1b56132e28d75a390a5ba80b85747a02e2d69", - "0b06fcbd16051fe7bf49915d6a6e93e31d65d9762f8e9029369b1958230f149b765bd79a6e4d9148e6792c0e9041f9f14fe7fbb75e4c43551bb144a7838752cdd3", - "0b0330bd7602ce9422995ad208beb80c9c039fc539ce4f24d5f0c3a9d5176b31b373b4c00c1c3b26c972387802a67ca35cc4a4cc0e3ada0ab945fd63543dd5616c", - "0a02edb3dc2d7b1951be2c24f4cdb65172d242f2d2e9b5d14551108e2c748fc1f70910de58ca9258f5cbb0d9111d29d4a1a66f5652402c612b250cdcbdb6b5681c", - "0b0160a5b87d8682b5261171475c14590c1b3cda0aec5bb43ca9f98cda282a4d3379a4276d46ba77af49fa280f5e6a7a71b6a2998a5d9031fe302b1e0a7978e866", - "0b043c10876e40f3ddc672848d66543e48783aae44013e63d7ce3d83bdb28414b6250ed03b24bd1f6285c5991ee2fc959d23b45fb6adc4329b68a0191cee62dd2c", - "0a001c8a42559bd7a529843f643f816cb9831f717208f6d68a7cf0beb879beffdb7b910757ae13a6e8260763cfebed428ee238ed99d402a88d942a28e01e36e7e8", - "0a02873a787feb431943a83216b1f1c3972c85a85ef893279fb5d83639366c565d31a6c633ebf805c0c3660b9c42b31cb2b8695a56d5534726283993d36de49e96", - "0b06fdf95a86def3ae906548d8b104803ed635dcd844d9bc2c2958f1a22973bdea4151c96fd83e6bee44bd5971d2b3314e1e65e193712ef4495a479ea05e7f7231", - "0b0286ccb532082095b455b09d7b665683867c41fa459cd665d507cab0f1a55f63294a47fcc218d0d6075094ecd5c62dbc557f430e1adc19c5d127c69e3f75cbc7", - "0a04ab3f8364a1ddc9bd4f1238b6e96321eb623d04970e62e81c9a141f2f373588fd983f0acf3441983d6e3db95cad2b513b2543a61c6d521297be879897388952", - "0a058e0695daed45d6abf7450f59720acbeb2bab0f5dd3cea4ee33ac93704626996d85e95839ca2178189eac8bbdfb2c5cc5a86f3e5ae26d1a5ef7a8dd0ad45e33", - "0b0500851b2a630efe20f43d84a95dc845e733b2a22ea17d1d840e35ecf03485dfa0d275be74877366f3aa6dc1d2e462ab630e0d25f75d310ba61777fe4f009dd3", - "0b07c5c355dbf8d3b34250cca4e774cbdb6fd7dd2f90eda3525e2c670d870af980fcf5c239a71e6b97182cd0ee41eb94af76875ffc99614886dc883a99301662c4", - "0b0332eca61a457eff94780e84cd941b2bda61a85a698badcf1dcc995cf0493d8d6b10b485cc7f61d29dc01cbf5beda0e4e194e925178c7a0744d1cc82511b11f6", - "0b0314a608c6aecac5ceea7fbddd2c0d0b9990adb9218d905a06f1175acf83dc4e61bf99c76b548e6f22b74beffbb97429669f34dd2ab88c57d94b226fe4a68fa2", - "0a01fa4d8f82fc13eafc2cf4308fda5edc171a8e2854f9278db2d75e5c3cd79babfe000b6d552642918892959da2b11612e4692b996ba07b16c579f2e324f50c49", - "0b02ae0b1f668d5645009d7fe6cda2d5eae3a436a26403ea4b82b419f2a5cfe78abdef6d8c840eb9e835f913ceae8fc9be5f631c66bf7d41b8c24a19ac27d6b4c4", - "0a08a5e378bcfc7eb174f76be9e628d9c19976d296cf0b6edff9a7b283caa398007f778312941d5c49d58bea8475a2ed1f4cab58f561acdbcdf35ed6a360aa98e3", - "0b06ae0402d3557d7dacb3d82a58b912843afd936c25b7268b6cff43d7d4f913d5661527d467a7a963d397303fa90af6a8405cca1b8c912d7a628021f759ba20cb", - "0b07e942289f888be9da08f6669e56b3c70ec133307d5238f6a6986294dfe771e694c276b8af20331771a0f35dc01eeadd924b94c760a57ba3bf87ef057f53efb4", - "0a05d6090ed966b5602110b40dadc7b6234dfb96f5031a429fbf81c26ae746bc326b40485bad19034f79d925898c2701e395c5511dc007634e44f574e78f30516c", - "0a06e287ac20d2cc59ae4b0caab9daf6741b8760f1ab1ec4814cd196a8818badc832601823452c43b5febf6f9bab62add04d490eabbef1627ff1824104dcc054ee", - "0a01de0ef354a0c57a2c11d8ff113c28d418b234a42368e86afbb040c94580b06732a70cc9b9a3d7dd1968f9251e1cbbf2552dbf7135430f0ea9163cb5cad55c94", - "0a05156841c8d7bb1a62de02dc8025eb11d7dce894ea481d5ae50847afb633bb354b68d33046d92bd6dc4781527fae49aae18d46218de7d05fffc757e0a4d3bbbc", - "0b0305469c854c6c1a8055dbb0329f3545264273a57e588309cdaa93bc3b63ccfd59d259b32d81d7ac251eb1f0c1e63e09a25c3501ecacb019ffdab11b3045490d", - "0b01d2190360953400fb69a27d2295af6417ffc7c1d47a0677bfb7889e14d305a90571f01649871d2b8d2cd9710b766d916a8ad55cafaed7c27c1cc9a0b5f8c597", - "0b03ebe6809c39f2db6042ea81447eda800272a15961716b8f848b3e4e3b44c5a2e3fbe3c382bf6da6d8ed8e9d4cac9f11fa80123d90222cfe3fbdaedecbb2b6d9", - "0b0574be40bd03f108f476227d7d4668bbb7d120fb282916b5effe5960d56b80b5b3ce9b2f9f5f3484f521b487945c6a0c1d306aa33587cdaa045f78aa67dac005", - "0b053979db98b4db40d9924b2982bd80edcbe7bffe50fa453698f680016c1537205d9d52f97f7886609899de8adc7d123ecfa303c0063ebdd9fd26027935c7081a", - "0a06afe9a70dd54a657cafc9dd382493a9ff77d44cdf215a7af6ccc0e86b04b5284a83fe04b0e3545690045c6cd1f8a5eb9085f501e19d5a72c953811298add203", - "0b017f10a8c21fb963123ec958bca25f3013ac7700b23b25c4c7fe8778af1eefea09a76faa7ddd4c86d8655563eeb18b435b8418418d5697545466f3e29fc25eea", - "0b0455eaea75e34b932a7b9661b9f1be17fe5d83c30d6cc08aebcf1b72a484c028806259cd512f8a0e3c039a971bcc8cb6df64741e0165eaa21b8e8f313557c61c", - "0a041e4055fd28d220f079e9ab103d9ed0d7c7acac9ae3721c34ef11c04fd4f20258a48c4de61762980b8fb8b93d57e9a6a19f881873ae8672c9dcbed567c9abca", - "0a03661d883e286e02fcb06ca0a7ce5f07869da9c87417b94fa8a1c5e3340b1530d6531d90abf7b36c075ef24cdae237eb2b8c51072bb87e4ae27914f81106e5b0", - "0b061d266e9feb80755e1f97ff782225032aa3d9a470c742f51539979d64e2b4bd8d68462d36fb59057ccbc0d4e30d557bc99b5dfec0dd2471db706c7233829a8b", - "0b04e5430f258a747a74308c4550055da8e4cbd77882c1b9c6ce1d5330af014cde912e02692bd75e60adff91d61876685ac8dfa57af702efc52b4034c1cff2125e", - "0a03451e402f3af9e0f18f8286332ddc551ae0ea7fd72a4ff7fc5948bd3a067b0e66f754da9e48e9b9665c6f30ced7cf2e869648b1cacbf9f9e14305b56b9998b0", - "0b04770b230acb0a817bacf381a0189dbf2e45e0774d7a9e88c28fb909f1da2aa9e1ecfe1fc2334503d4ff0d7493602151056052c10429b041c7b3dea57f448428", - "0b017bda28c0bd20cf3813b4277cc42f9d54249bfb1374e536c342b8348560961cdd3f5039299611ec4cb3316cf732145d4fce778ddc2ad50b8a5dea328705f5d0", - "0a0227e6cb4709947b58520927725f4a278b0db2b7a10dd246ce95036e61ffef0e063b7d2a3677b36a9cfb1d98f47bfd1f03a2755a40ad41fe4747284727c2cb1f", - "0b07786a720e4ea808baf416fef9c608a1846c74455257eaac47b781ba44ac1f36dc6da35089d1415a9ba6b9b36799fd8a5ed3824715c9c3722dc9d6e0269520a2", - "0a0746b35c3ea4ba913c4e57f2ce2841542e228d182750d1cc100eed38f318b81f4d5570de9aa3fd3659a375e2b503abf3e8405c8991b045ff134f511fbc4203ea", - "0b0162a9d197e53d45273f766a75d1ed5af9e09dcfcf9e81277bb0e5c53454ebaeb7529e069561b8845d92cf55acfe274011eb57260663fc6dcabcdb8a7bf2a158", - "0b069ed5ba4b9f484dca40c9a80620f271cb44a04f1cb00e8109343d26010bfa4ff685f08870d6f19af3bc671f775ee20ca1da3fa3c783abe43714aa5945326705", - "0a030a10f121daa8499218b5e0cd3fa00179088006f8ccb103d075c2f4dc428f28ba8225121fb6e93d64e6f5d047bd9d747b38bc7798022d7656a201b240c522cc", - "0b03b24ec1409ba6a0a7145a4b030ef8a6248fa757d9764d0cc7add0cf562fa8d0813d2de986482ef9a730b9bf0b21c09aac7d6e6c5e4dc7075f8904d15493d438", - "0a0844ff216ccdb8f42964f7a6b852bd6f38b60f6ec4b236a700374944bc483d41ae12df2d5a83c25f421eb851203ed73828bac0e1e2286e48763c5ebb098ff7fc", - "0a04940cbfb1d64edb1d48a16b1ebea1b1aeccedbe726d69a4361a1a014497b7d2b9aa2ed61f985de87833ac0734cdfef163e925d0c6f9fcce98acf1edd5262b92", - "0b020579ac2c37d999ea6aafa460d9dab5e1c2617c994ef291ab7eeb6b5050932a416ece1f58bdb0b8a470bcf05f24acd38f3b45886c026e36d3b0a90570723543", - "0a09242eb243f18667c8fcae833e4046e6479a89cffb5dc536e02670e9f8bfa76b1ea5ad7482a39a236f60359f4c600d687a1b90dbc828aeab3c1513f598e0861d", - "0b01c3d205b0937e6680a0b4dd28623ab91f51d51a17c733ee43bd76979d40fea2ad05c7caf536cf976aec97556024a38725323f9c2efa024719556e8fd9e9d91b", - "0b07af799d6075ae110c18a66e7195a1f028e1183e8b80fef2287f3615ffc9192fab8be231978d22f36e73adb31ca40459f5d237d42b891822b73b6f382e9bba3e", - "0b0521172f8e7f05bfe403bbac4422565a959f9c0cd49dd9f45b48386683ea12a2f85d1ff5a6a2dce52b8a653111d6ae0395f6093ae540580a5df30287ac37f241", - "0a078bc2656da33751a4e08278b0d48e37621682206fe8a6217e1068b05f74976a78e24aa3ed6b62843a1efe99bc073ccd8503ee6ae7c452f29f35640c27178006", - "0a08f540690b259399f9106dee9ddb3ca0eae1d684cee2a02ea5beb4deb203d5002a8f57f46d7ebfa200c9277e5d494e66dfe48e8b0f9c718e0551b430d0844a05", - "0a03436d657ad221784af04e45e640426dc6f866759831a4530e30c63b2b77d8ba5575f2358e04bc12fbeabac49b09592bb2904a9cd8f2d5d0770e57a5d73722b8", - "0b0744cd0b2c64606fa172041ea199747c01ef19a8e8ef43ffa20da8443e8b8e7ab43d19188cb15138664ca5de7082659fc30e901681f8b9f3b6492da9dc62bbc9", - "0a08a54aa941f76515933a9df3ef9867abee88be9bdc27d7194fb9633f8564892493fb561738da4319438f012e5ca5d856a211b9fc37e3aba89f03c210e2d98021", - "0b017c6ebb6f7679e71c32b3eae9a779a09234637118526fe82ba1fd7871b40322b459c25e0912168e3f749db103aef545197b24a5b1d11642cd91589dc25e4c60", - "0a0508763620250603b7d9f1f77856a7b85c9bab4058a42d41c93ebb2873d2057423febe56efa21d8307e499aeacbc82e98536f509fe14b5fa3c7ffc5757dfd35c", - "0a014dc6e1695a3905615caccc535b32173bdfad4cd00f6803b1e2306ab58dda502d7b57523d8d0050137bc56e86acf4307148d8ba899fcc6e6458df32aa6b5d41", - "0b063a242d421a8aa449358c3878300d538a46b260ea50e88a66bc7b5029ba5c7274f4bf4f038ac4da7e594fa6a3462bb5ef66d456c743fc27586c44cb21b2c2c2", - "0b02412873a89a4e3b83b2427811d24d3c27a7c46fb0e46df786da17af9d05e23042981c486d9fa597fb9f1992f216ec669400404221c302c60cce74f0d75c44c8", - "0b039e9a4829b7dcbe49525d274361e665829b51793a5852a9e0feac2aeaec2e21e09460850a606396a49e34202a7bf8cde920d3093a7fccc6ef54820a18ded40e", - "0a03e86c01f1e13254c0ef587344bdaf4fed11488af3280bad226ffd0ba390288f401a75ee0cb8fb794e61e633d543976bc31a0d89204ce5e73deaea3cb5866bb6", - "0a05792215655c38e339039b4e3bc051b9e2d8c554487cfc9473579732c001271132eee6c7b937017651f64085affc7597f7a96d4182d668129271d10ce3e2b7db", - "0b03c8962f5acd369c8e9871531eb36cd06aaac36287fd96452ea718cbce41b20b0d030124fc2d0022996cd9097f0e5baddb9ae7353c0fc176f1837e3de6b382b7", - "0b044226eca4a481df8c0a58c05b0f19abe184fed78a27626bc2244f612a30d1e274af96b9ca115967fb4bb1f63e0f4133665213f83b31e7b8dbdb9e75b95b3d73", - "0a05c124420ad005a582b864e1eae8f2550723305b25c78c6f46e6e508a1ec216778e91a33c8ca56577cb72136728c0c4d772d872b6ecb6943b87f9e12bd6d1dd4", - "0a064914f031f41a9c10a6deaa5ca28d78926b14e49c9cb38dee2a3bfc10a308214e75c704cc960499d47b5da9c272c22204f456e6cd034a9c1382293bd43ca971", - "0a02b94b728e2e39ad54620b76ad1e9f0d1e79caf7b552344d24609fcc01efe9dc8396f91894907cacfff021bb8cde853820cf8870312d9164e704ce793e014e9a", - "0a08b5bcb9b6b00755d5603648b13aebe23b9dd70591fa872eae0b58ed6c11d3930aaad856154e0d7d57ad141390d19c1727d6a8e7cc76965dd8dca9827b5e11be", - "0b02156c6515ce02d9280acc2509deb7e5c8341f2aed199e3cfef32a94888c80fdeabd599ea2a38d831db4207612b96d63b71e48f7da8f2392bd9eef117b1b705a", - "0b0786a7cf740b25c010899660dd1a67eb05a49a570f367539d3378f071405ef9fda884ab93cccd6595ae07fe2749ccef328f4ac3c3cb27d19f6f9406ed221b28b", - "0b08042d60ae70a7872947f5870aaee0b86188ef5491ce58db44c37a7723a06364c89cafc2c90084378bfc1d252fdaff027418c6a6b76837f67148cc5bdf3c6082", - "0a0062fb099acb51db482274195f549d081ae54461c1ffec9839c9990055253824825acb9bd4d5e84f199c60665ab109fa1e484ead2b9a821a8c87624878c0691b", - "0b01504f6a2a574484526ed73b14a49c047802cf1c2ee26d73effa89ee5eb3db6c1bc2148d01f145bdbf1cead2f15553f17b0186cb36f419ea0a274cdb7d9abfac", - "0b064b5b51e33ca4874b2f07034562640b4f6f042a39de91f4be3384c89eaceecc0b15046bbc86e5317b52e598490aa7dc45ca179a700ddb338e26d01e725fed84", - "0b06ad78e80e139945ebee1a3c0da69bcd020bfe695b9b422815381112d165146bbe251c1c9ccf646f69d2a2d921d8344048f6d0d5aa27f084bedf2ab0042e0508", - "0b08d182593c31899bdba443d40118d7e4096a925f3a22bcd027334505db615a05c4240d256fc7473abf13edb1902f17eae4b47caed3d7b650163933c2ac4d82cf", - "0b01ab3239df39292398be854364dbe2d0719934e7e4cad97ed6964299f81d61c756bf7698132e3224bc56377298850cc09952fa86e633eef8696c7803fb7c27ea", - "0b0498bc18208b2ff5a61dc88bf17bbe645accc90db4bf27ef55290b2207686a0f2f37166c4f0bb5f9a05cdfb26ebb121aa9ff365e8941b13d209b8613b998939a", - "0b023631f7fc12206d01575136ed93038d3bd3b8453c235b7eaef6683230b5fef84a12099aca5fe41f36562ff184ea47c41f76fab7f824c3be251e4f83999ccd8d", - "0a02761aef08a8f40e0847ab8a2accb8cee55b6605561d74372566e092447d8c0d109e90cbb9b25dd3f98eb09a99fec589a1681898cc9e5e0fe995bd55f2efc7de", - "0a04def3612a9158f62471619066fc386a4683c466c6318d34da7d0b474251e965c33be91a564cbe88094ef08a56f53b4b498e0288742bca3fa72cf6b6f3335124", - "0b05572e8b1ed75751666d118ca96af21105ff0af367dfe0de788e7afe446037d58fc8dbf8c347dd8c7a6d8e8b291e2d22a5393c4c83d9b8d549a79822ba8745c6", - "0b052672eb97368a25b29e2ecbe185659e9ae9c941900403fc78d2f8419bf787a9d884e9fdd937dd5587191082cbb7f8b1a89c53605031f5040c1c49f217df5b98", - "0a05defdd7f9e17d16546078751bd5810c27022684a7fa7094c1f40fcf50fbc5227c7d5f651811f470846ccf3f0907732d55461bbfed86fa966e47390fe66e0d93", - "0a01f6d0ca91c82d1c103cc84d4bc4cadd10528ffc6d2fdad59f73e9b4fbe3232780ffecf58b196b0c5700f15357f655ce9243b18a962fd31ef09a937048e6715c", - "0b00accf85d0217f0546742d8763225d5c9eb90d47a6d72201bb299a459034b30ec3c7c929bd67ef2320745845b01965b0ee72501c2b4901fc600c515fbf9fb31e", - "0a047c0bd480c3f5bc42ba7c5a07d01eca381c1d8d8d96108e9cd98356ffb1060603f35c355931e9764676e75f0df4f56ff04b2bf92f9927f1d6d6c35ede233893", - "0b04e969ad143aed4bf70e7879f53e445987694b6a00ea33788cc6f510be64035df772e7a0c0dd2957818da65a9a6fe2cfd9313677fc010b34db4c51c62a599ac5", - "0a080665ba49dad6f84a763e0a48c2235e800de01ad05325134e214ec57e3660875320196f4a2a27b4da0bf474b2319a3174f4cefa6abf598b505724f38f5d7898", - "0a07678dbd222d3edcd5127273149e9845648e2fd5fa36b78555f6c965067c2910d93705ded9454d0ff92671edd3ad1399d4cbef9b1c8afc09f87ddcb1ffeb9b6b", - "0b090855e259abdff0deba8a6bb96b5ed04dda02ef3b36817057600e4787e663472e18b36985bf145c57168bef3b51f77e9e54b57a6103ef6e37807e51e267fc70", - "0b086edb1f4213534d4f28b98e92089ac78fb902df4d541780ca1d6d11e4def57b396d31b51776635f0f234005f115df6279a3efb56404c798f8ddb2c6f20a242b", - "0a026355c4df3873e1716212b5d73a1c9966e857a48c9fa3762fd8ad6779cae3625c70314de2e9f12e3c5023061c8a0a5270599767c4c831685a56737aeab1f0ca", - "0a03f3710b66aa7efdab6a3524657cba973c9e48411d8a6f6c8da58e31a64b851e1d4af9711519cea6acdf5f24d90e1efae5961f5294a04b6fe89ebcb022c9778a", - "0b019aabd1750fe4b95bf3fbf56da48ab8ac55d84fc40b1f1c579f607e3013385bb5d9b1eaef57e9be0108391a2beeb12e8875f657c9b2ed4f4d9915b840d1ae5e", - "0a03172109963a7661a1a07e604dd3b7f880fe426c3905ae07f72e32a8e46d43dd9958378f4ac15e483c10e6ccf7f3ed4aeb6756b913c18a41bca7acc22dfa48f4", - "0b0175498799d42bf2b6bcb69aa77c389aae0b119455511214e2aba2e9ea73e90ed3922beef291fa087bceb6e7c9ebb37a79dcfffd4877fee7ee63ba33184e052d", - "0b08fb8e8cabdad40f108c23463e3562548bd8feb8bd2f4d18178645e0eb24ad501cd02f687401ce2be59736435cfcbe3704842dd0eecc328f758d2c561ce77135", - "0a009f95d9803f9c4498867ad784766e1401759239f010493c861a18e49cc3d43b6254ca7cf65f40a0d322813fe741e02d6ea3af7a04b3842ed2c3801542f27e84", - "0b060856bc977227e8008f3658913dba678a4986f6e8ddffd1c5aa96878b890287422eeb490f12c345525850f940b5f952bf0225220a84ca14cdb27f3cf0c3df3e", - "0b06d8fb730b2e56da6ecd8a6b08035ae0bc21722a0141e013d02ef423aab60d208de454a8090a25409b11a314aebebde27805c7af62ec46b9ab41c23af4108891", - "0b07473e5425bc9e96e23358d6c68ab871dd006b15944e85c618da0bca41095640c9af0f3556e7cd4d21f706c0740ef4dcf538d13757c7797c88745b6abda2f8df", - "0b049d850a01e4cb95427926212ed3f99dfad2bb73e59b86e557601513411748d860cd17c001f7b7fbbb64ae3560f35d57173a12509e28d4b1ead562bdc44338ab", - "0b0099b79baf10f97d4cddcdd186642317f6e36f79040a4bf166984395b135407797e550d02478929ab1861fcde0d46d34e5446965e7fa57cd651fff32739ab962", - "0a07df2ef922bf16e09569145c4452370144e504b6b73543e38a19e1634b263c84bff4ee4e783b85708e6ea592365b96aaf77e1ce4c8ba73cd721ff1bd4a121cac", - "0b00a8919ea26a5fc5e9275b23bbd8d5ac33328bf3352f246fb6fd10f39ee5b8a065967d934cdc522761101f977c1bafdfd92847086dbd3e8d138beb2b7c5c6170", - "0a06c33414bb423496455a11334f7360cd243dee7072723916e618078d85287006f947a9d69ce86571e0e6bf50e58ec7006000feebfd1325cf11f341000a904674", - "0a07187fccfa2341be864505e4aa5a64011a1f6549366081d434a354996166689d8ed0a5d0f96e4e7c49040b88b5bf26aaedff5c732d5a6a56ec9a3c860a7f10aa", - "0b02d056e88c74c261c2e104a778a944c84decd33118f071930b7153e4c837fbab62dd8e996d3d7a99079160c4c26a867a85cc604d0b84d2f35aff32428a146ece", - "0a0084ffe07f168af9ab13336b9b382a3ecbca1d27260b33f71c0102ca46e0b288dec1f992f9ccd7e654028f076f77a4461345d8f00a1bf467f9866c6fcb64f948", - "0a03b45291ca0cc7ef3cdced02305e1aac76ae4d72f3ded0dd87f3c7c7d435d98dec698ee6e08ceb878b99e9a4bb631a1bd3d23cd2da5fadc91f95da9d580ebc97", - "0b06c9847bb9f3333ca554c5ecbfc13b074b01c93d56d1f86867bbbafd6d18307d2c62601fa3274c466db1c29b2b5a16d9f7c8200a787ed029003b3a336fb49a09", - "0b0113cf5cc2ae52c547240e48e422d5aafa9630d981868ecb443df723aa3d700ae78a8c12351dc4b3c2920decee11ec0b273deefee4c98456f296d876131c0166", - "0a046b041bee62b64c98f9266a326e14ffd5db17f0f3a9aff4524fadc1a875db7173666c45e38a60a83a91f7abde7d86e3601dace2aebbbd5911d687f2ffd47677", - "0a047216a54468c7587cd594a624aba354ab1de725b6afeb7c17c9e2bd147a4e49a7a3d542122fe8f4b92f2bdc7166c80dbf508f56397a6c661f085424a7bbc05b", - "0a0729043c5860bfd2962ad30489f16c7281bc84053dfff7298f2799f72c35b9fc7f122be7be148bc365f54b01650379f70d21a8758ed75591c0330975fa335507", - "0b020650d286509f8f79450898c7a1a408166d54b7b63ec1feb4d32db7cd4abaaea939c471e0bbacc9c329504c0d6acc55b9b248f43b92d0600585926b23c02764", - "0b043f71f7cb33c2149438ec9b91b2efcf145d56313bd880b3b606c843715a5030242fb93952fb186e86af8493d277b87dba464a02713959331503cd398537ec3a", - "0a03e31589b6b7bdd64a8051cb17100d54cc4a2cb830381bb19bcf81f74d0544d70ac9b359daf102c22aa8fb79bf5546b23ad0b4d790f84cf205b19b0dc06455a0", - "0a0590134cc496868bf66c7d6d1ed9797464e4c9a02fe8128f84ea6e1778eb37ea70caaee220e661f984cea7a54bddfaef987082c86321e31f0e9104c72b499426", - "0a06c0952111afedcabc36d91fbee2f6dab611e3513eb987ac3aee4c0e764e5ac7b341aec7d3e075020e283fca369da5e55ace50b0f23b7f0a8f55eeed06db9ded", - "0a06a8b2e7be6da6a1f5c07c6956a9335524843d1d92c827b1b0e47c9101d75355d7b1d8e2da74cbbe43aa2c70571d1289f55fad0092f22e70bb4fdb06a5f88ba5", - "0b05752b9db15a50174d1ec694b42eb1ac13db7f860d3e46471595737d866983097cc6c2f63171296f1b703622aa47c1af5c4ffbbd7aa0c6d1d4c372468de8ce41", - "0b05a9ef3e7c6e58350f47c26fd1b0c9420849462349357c63e047e456a4bfe7584f2cbc244296b45a36acce02b799a9e4646c63341424c480cf0bb6178de50cd5", - "0a0877454566e417c14a13fa21d46241760c5b0354700df7d3ce80eba6ea62f02fbe08af39bd89d317165ff095186b7cd7a3ce1c3977c645c8f487e6fa97e6640d", - "0a01de3cead279337211d01478b54b3c588f2ab0034c93a7fcf49e76ad691b715b868092141b87380869f899ac09d40cb7448a1165cafc94413e417357af16044a", - "0b02b3b74b89735b9212f9b6cd1fd8a35afb2896bfbc3265322e37c70e59a26a95482c3d0f9e27fa4f17015f96c682ec17d165ab352af776a4ea8634a078877b6d", - "0a01e846aad1e0306dba6abd80c8248ba742f7f0437615b819b8325d38cb67c449fc8f2dc11337d97959dc42de542de6a1aa9df0ffb620b4a3e941f2990bbac9ec", - "0a0400c56ef7c720523460dd7d813b861e1245414d00eb7e56dfc24aa6487974ec7ffac3d5fd42156ce15640bb96942c853b12e705213bad6a85621fa33a024f6e", - "0a02b980d993ed3f580c3925235f1646379c859fcb1a8586fe24a243143a30bfcfa652ea49bf433fb22278b76e9723da62520340f356f712ca49babce02d6d451f", - "0b08d2573c8fc431b85ae8491b728001740dd843ab9b935369e118f6dd20dd3541f796916299fe29a49be58ba356f7d5e3e9e27f9d5c409bc1bddbd9f72819f569", - "0b06909c2914af8281088622d3613a06561234776bd6ef26a9d33cc8f2c659cb9613373bd26f02e56a6156aca8df5467ce29bd281649d0e3dd6c5009314c50a655", - "0a087397fbffe2e1227a2a19a261d76143d9bad06625bf801fab4299b13ffc718ac4f20581709651d4f2a2aeeb1419929cbd62263f8e5e50bb56ff84aa2fce8e35", - "0b055745ce23205765d525d59e34eb6599105f1fb795d4430ab777141d0beba9cc4c4e083dd77362090aa9513c6f092e6b27dd30378db0f8e9a98eea788bf00af9", - "0a03b6139d4308c209c307d6f8d3233db71bc14f13d8ec4e55c4c3343874078f730ec4d8e3c9bed710ff93f659c51d7a81325de18c34d2c39cc384afe8050cfd7e", - "0a028b4d239553c683be0973516fd03f98129a9f7c14845abde02e056ec1529748b48fd6996463037d98d8f7d60dde708a0e34ddf6997524f2dd84cbeb25eced0a", - "0a03261ebbb6cdf2b59e9f76121470f052259aa9ee6d5f53ad0ea7dcfb11bc570aa60bf0fedd87e63d5670d496d992801f6e69852d610559b70030a369f423f777", - "0b0058f7af1db7099c168217808e58d5f0ec3927275b4d265eec04a6522b69828477715f2f250951b1c46f94f5fc15a6ee5165b0785d4c19fb335658d5ab42e58b", - "0b0582d114d5e1fe749835d803a3d7ba4cffc410291fd188a265acdcd32b110379b86ee6f5aa8a2847121763cf78a03717c0f2567a9ac695f0dadc70735eca9d00", - "0b0915764c64e68ed5a733613d61d0f9ed6446e4dc3e203d090fc4ffffa41012b704619e7e063d36120d399ca54cd0af3171b6b49726fc3a8a93af70ab2a037e65", - "0b018e5821d8b6c0b40f3799106d22177daca01ef8234b828f76658e0fcdbff9808d3ee34cff957650f9914d506cb3ae4ab154f08d401cb0bae02903f5b0778d2a", - "0b045fed79ebf14a0f3d3dd91bf67860f8f461f6bbc7efc99cf0765a20ce760166fb2c319fde88508a68fef1c477f618f74a06da492351f5075a86981647c33731", - "0b05ba1e240ccfa4da2f58133deaca9ba0bd8bd0050f2fc86b84f84ecda6fd2828216e6ec1ceb63b65354944374fbdfab150ab1c8436524d76678c96fc75645544", - "0a01304ddd1138daba271930b29cb0dca06efc84f1ae253b47384b3a21051c83868bc0e3d7914594a6021d7103be9604c405d5d21947e5e7c7d0beb34174134c23", - "0a007800692160ffb99e1511d294e0f7a41e55f76e5b6ee9e09add1de2ccce33b91c3efca44592b2a84910b1d27c78f2db90277872df02b2c0ee8e718e0ff6fd57", - "0b008d821b37e19f5b2fb458a599e0cbbe51e47f5129b1eee9ec2d33458a4283046df2b4c7817a70484caab8839f682101107a9188da741ad4326519fedede5c3f", - "0b045f6740d48a3d5abeb88b7d1ee36e91d468a617eca59757ad7f29a799e6d10fd78c44c0fcbd0acd162ce4b1480f3940a6943cf1c14fd5660573393c1125747f", - "0b08fc788d428d089ef38e53f0aa2e25ac17ba6266db0f52bac46e55933f556734b3a13eee9e6f6ce1ec2849a7300b71d0447596a97b9dccdf5927f3e4f4e2bc1b", - "0a05aeffc6af3bd09481cc4ebef18413f3609dfa5174aa77d528587cdb27f953f3e72a8cd064958fbf3285b690aeac3335c7be85264a9115b4392047ea3654c983", - "0b0834509cb47486e7001b7deec55962123cb868c4293d130ff6f43173ebcf0fa2f4a2d18bc85c7a78749f6750610c33206820ea53edf3361bd16f4e341a6a54a3", - "0b03a1ebcf2d3740ac3e32b1f543c33cb2b49fa9256caed3edd05713e6965fb8bbe774741066aba9cf020e61504f1834f15a14e84f212c05db9f2c1bbd830b3e73", - "0a072c220881cb3ef54543388881a51bbe417c992edb1b06d642c37873511d0e461679b0706c4a91f4a0b0c6cd758aed91ce1af5a48d0aaf2eaf66760c72f494e0", - "0b09245230fd78f5f270668750304fb4055941ed370912618f9566a34b32259d11f579fa9c232e436a757eed68ce67670c40fbdc264d905947e80189d55d8d772f", - "0b050bd6810ab78ed6db9526b5eabaaefa8262bd6ac650b0d494adc3cb4d612d5ff79c7327e7a9c5068c9ff7bd6b3db88b3594388ac9069c2e49a71bedf0e86923", - "0a00ef1653f0c7bb2bb48aed219dbf4d92f49ac694e165ad83b544b05dda0c2425c1c3e0f392fd80d2885333000eadad2e1a52efced0efc7bea168b57246053a0f", - "0a068e5da8c8d97aeef88ce0f743d2423eebe661adc3ee71bb7f624dcd44f6f8b9118a615c83766ad3637a91951509490c7731a0836ae0944f40c0613b91250060", - "0b01556692457aeec828086ddfe884b703cae906610399479d27d9b42a454c20ca3a76c59a31fc72673c5fdd640675745a192908bac7643af79dfefaa8f49a992c", - "0a082aa84cad0ff90413a415947ab799e091d73874fab9010923ece985e5f48aafc447af4ea04062b63a016eceb1923915fb8be44c47326c22435789b67bab10c1", - "0a08b2646b3bf8191b46d9e14048d618eb0a02161761b3a460cd9ef1be1acb8f8304ed000e68da369b369592d6fcb261129727a99c9606675d558befac42449056", - "0b010795b73e57a35b570f5be34a36f04b46c338dc85eefe56f0983bbcef16f3276a945154aed7ab459a6ab87e2b716d5e7a260681f447031374bde197ab7360be", - "0a048004aea1b0b57e904273f92247e777d9f352be182702ffa90868b5b330277cbd7f9b3df2c9e5c93649ffa4837b48313f0b096353a7410500fc9b31b60324da", - "0b07e67d0a705fa01c66a433a3a7051848788f2b3965c688373172874fc230a44f96ac5398475207c4a9fa68c5e7d1757689e33a9ffb23406806e68e08a98a70b8", - "0b00f53ad0f03eaef97bc86252f8f956d8b003fafdbfcf48b92e3549a77db8dc2ac2b9b5e9c01512d287893b150c4fa64d8421afbec62a275319df209c83925e95", - "0a07779886b4b105df24f3e311a961684ed9ee91dec1b1ac847f2d97853ee68367d1830b368571e1f8d0919bb11660b2b57ab02d48b64f380a3c950938536f4404", - "0b03393a727b61576baa0aae4e1585a5b767df003fe38f097f1ac86db023f0b7e33eb05dd6c4facee47fe1fbd76bb4af03935afcbb36a87c3d90235b4657ece4f8", - "0a05997f189f61a0e8f7327c86010a19e82f0ae2cfbb90805f9b6dfa6fdf8eb0ab7208b3fb430acc4eb285412ad6d5aa1831765cea1ea98d1ff0737b8d4a170aba", - "0b057e1c7b43ed99c940bf368422f0951357330114382d887e920a522f750954c3f77c66c6aaeb168fe69f9db5a64329bfb3a32055ee622b3cb1759475be2e0b0a", - "0b08fe7aea727fa07a0d062650e8874d47edbc520e16bdbbe1a70e688f8332a89c7b07b9345fc90d134ccfb25049eaaca527783e765133327991e8132403aca78a", - "0b02089c11d7cd270926efe67bc2b8832c2577fbd885031c53e7169b2a28d736e8e37201860a26eab26c76e96107a29b39597a7d2eadb3c501d7e47872653e0262", - "0b0162754167e62d102a88d58e86f276ec3d95ca02643f999cb0848b7ca906061c22f77703b37c885f63b80a4e6436c4dd40b79f1dbc3e9343179949e218bd3e7b", - "0b0704f14ae18442e6364cde6c3adcc78da9039b6cfc7d8581ade71ae252b001dcfb9595c29fecfd1dba8778062ae08a8f35eccf68ec3531af39be4ec480c41552", - "0b05fa50359e379cf4f5316cc112b6ca09aa8cac835eb7da08c791b29a780367cd6b4585953ea8b35cca8c675f0cecbde24e0b9e9e44ddb3ba6d22488313e8e82a", - "0b04655c8e5622581540ebff7750f2ec636396101e50ffdba7ec3c3835eb09fae2a06831236539a9434c50d8f202260bca7799d2e622bbabfad10eb98f79fe1ca9", - "0a0158979e50b4fdc9392705ce9f1b24dfdc2ec6224397be9a482dbdf52d4cc50a3159ad8d4731d62ee7397570fa27f160a858ec17e71df7c20175fb28adb091b7", - "0a04d309917ce6c281120d0d34f007b729139b7ee7a6e7779b29b3f1c97548d131b840d687f8ca52bb2c438c5264c63c2269ae084dd045f6606fa5aa5f1f8c7881", - "0a08c5b463ee9a71542a487abd8744005b7abddcdaa456b24c3cdfca80b66ce6df827e820e3034ec5787d414cfb3d87964914338e78210898f07b4e44e3bf60fdc", - "0b082c668212267ab20ff2fb275fe21e0b2a14153e7438a031504c00ce6610d04233070a424f80264d9f177291dacc9ab04bcc6feb7a1e1e0b7399e3367b717c07", - "0a05d15b1846cae8097b9dfc9314c0c5f15b86bec0b60da35182d6ecfae7a8426b241244135863fc6ac50421fb1fdac1330f600b9a9ba53743f7fc0fbaef88a401", - "0a013c49499e0ef50ebf89f91d302a5dc35dfc6c363525e502b5905a4138440d09a1708dd3e7e0f5ab3032b56c6f972b472a888a5c84b7282a729edf1dc3ece8bf", - "0b090cd71ce9768bf76bb03b247cfd051f4fb10511b8c7a5fc5de22fbf93e864340649e34ae43eff57ae415bfe38269f170a51afe9a51c81f2eb1878d0f639ddea", - "0b031056e470aabd4a0976fe339660e63273c363949228cb70800adc58d04b17ba5ce20913df096ae13ce9a1cec90ea7672de3b1d33c811ed4a7db21704a7c226b", - "0b009ff003dd454532f65998a2e7efa669df3bb6d0e1b81c4d2ec453eb5d0004737d5c7a21c425b55c524dc9d519096e03cd8fa35de4314d5fc4a8c8156ac9ff43", - "0b010774525d8af1bf1178b0acd284a237fb9ead871847768c7684ed9363c264e61ab8338e304aaaa03ddb45db27f42fb52fe4732427a70fa27f0270d6fd27416a", - "0a01833fd502f8ffb692a8043aa8070a20be7299f52a3adfe2c1abdd4b9a5bee6b7fd30abf0bb52e0278d3eacc83d78181c991b5ccbb9dadea8aff8d5bc32e7367", - "0a043157a7042aa50adeb7a0b2f00bce0370e531d040a8d84b66f1f0aa582e35656f3143e76f754fce84dfaa9784d421db37a67ef7a4ec58c20c7db002e0d786b4", - "0a091a6395aae61bf3d5cff398bebbdf9ca494a5fe74f0e40f81d0921490529c2c2c9e41793619567fafb59bb913ac51b57bc70774354e484f0506746d0768b59f", - "0b00c062e61a710c0cc792092e44571d14e7fff55eab8726fe719bc59867c15099d1290f4bdc3c164d511e278f0fc8f4d5e23778cd2083e4da9fec7715f7ca951b", - "0b027f1c33fa5a5fec74fb662fe9072e3fdaab783c3492a2b6b176ead187d0d19ff1c86834187f66ce8d653aae4fd9f9d1ad8801f21ff7119115d2ea8515619275", - "0a01f66451d876e9568bf7893078209fa38345bf56d82e642d369a9e1122f339adc171bd1f35d5bcf9731227a8f62d9de549e7908b02dc35cd6454ff00fcae0ada", - "0b0404e535f4d4376010d574edb3a83bdcf50746f97e4f1d5215b1f10f71a9a1464d1e328ff20d9e7803014b43ba88d505d6c566a3f93c25df487694d024aa3cd3", - "0b07f9b9513a5cd0fd1b3cc8f1a27d71e130cfeecc898ad4374c0d1c7174b0f1e4d110478db3dc016283b26f6f32473062f83bf21cebdfebbcc69f92c3a9c1bd1c", - "0b09221023661acd6774d1cdd1c421b0d6233043e37da5366f4b290869f2e1d67da258e42a601c0ee394d1837de0e2f4928e1b11c0b06fb2a8f458d40ec5a31168", - "0b0045370ea2001346f27c9dbfaa38ce262bf913cc0ef2ef339157547d62a04d0795225ee9fdadc61b7f826f53c350ed72c6f1d51e5eb8b31467cace8d5fee855b", - "0a0536971de6b0d312b144e9ab07b50b417982e3325e415ab38dbe423ce0fd6a39350671354f26d43cadfe02e6ee296905c00ee098c3f14b82789643d6a8b60acd", - "0b01d8179138cdddcc73691c0ac30596305cb3ac696caa330515d1c0dc12f1987543e2d590713df5be032a5e7e9a656c5588677bdac253646bc43cf4b80e84f249", - "0a078474e9409d450e957b2288f63f72e6e00b8899d457697252bfbed394b477d2cf338e782ddb60948472433f7a9ca82f3b2a12d64fc0feefa55d9f19adfb2858", - "0a009d850043220206c799c4b550c15ad6a85dd51977fc8c234f9f1daf4333ee55a0ee00f6b4309cc3184bbb707b0b3cafe1cbd93b382595c6fc29057899dc03b1", - "0b027851b3ebf63f79c6a0b4885f35c2ecebb82160ff636cfb0ecf9132cb2445a1b0fbf10058b8c6c05d7f5fb46f746384d58216ea62bb9d31da702f7feb7d1342", - "0a04ea4526b1f63935defea1ac6f876e5162f946c109f4cc0b0279af74c3f00a53043dfad5b99a4522101269de0d7d5c157422ce2f8504e143aa66b14424996099", - "0b0620322fc8edfd03a7b1aa4bfeca79dd9a4dc213528c64ad67d0ad7047fff0c1cb8b34b606bd693aa38fd1456da030aec06b2cb7ceb0559f0726efee6d7f2600", - "0b0874c8e7d5be546e76aa52561aa7d71a216cf23bab4373a7269ca009364cefcafcb92ee80124a156a0f3de9bf6d7a36898b76d1ba6f0171fd9031468056cb6d1", - "0a02886c5793bf32445358ffe78c64b370fd72b2d2dd86565f5cfbbb570d4c68d7002527c9f947ce864c2a89ae6ab276c57c4e9bc281353043e1b91a540ce00ebc", - "0b040b7392c799a2a82c6191a21fdf05be7f0951829978e4c2d0cff2f9ec986ad0406f12faed0a82e25d099b9960c9a21443a1443a9046d18d2034ed72a44b3728", - "0a039a16e27ba3b40944cfa6a9e4c6992c8973468fcb1f6232d54853d497caf3a02a4d88948fcc8f19646e16c2ca832e649b6a55a5bacdc5d783883b8d7b49dde6", - "0a05ddd6369c3e0e073a98aa3d9acc576b37927ecfbea5daa7e07cee551789074bf1591b76f58b25e758e5e7c1e978bb7f743b5048b243cef2fba68a5e8f7df485", - "0b04ea28d466acd3b5ba09c47060ef89b131f55bf81b3cc26d8e0b4e126bd4cb85fd0047664e896020c9016c96c898b356f3584f3169638eeb1cf95ab011618ebc", - "0a02562c11117f34541912b5f20ea78dd400a1abccad334eb19a04c57a7b8342a0716f5f8e3a89d6ed609532dd89062b2e18e0d1ad9bb08960e8c8790077c650e3", - "0a0486cf70b2b8d60ccd003fd77503eae6ae350177feb019c348cdf2abba24d2a689c1e4c5be9f011143fa88381af799dbc8b85bee2d283e13858d65d8338fa054", - "0a05516fbeea5e8cc7714678e71746e2a134f3a78dce0446a452d707bd0b609044146686e23cb628ce76332e0e0bd5528bfae5d33021185a336729e480e5992a4d", - "0b00d3db2a2d1b1c7b691a0804b07fb9faa09db26c92d55e620ce309839646c63ccb6b05fdb69707f7da37e4ad18e26ba160921cc1b76e370b30d8f57d937357bb", - "0b0478e802f13d9b375f4b816129e0ef4cb3ab508a5a1b02a899f8c357ee30867b68f634e0882702b1edc42b6c05bdefb4f4c2e8fa4921cc26ae2dfc775e6f7b4e", - "0b04358b36a7283a211395e83599162e478f3e7412f545c13bb1aa93b1df893b628bb83168dd3dd79e55da0a08242d387af50fd3041f6dc420e58ce12ea87be3f6", - "0a04b7d745acd22e15f3d7be8894677ef177a0b9aab3acbe2eaff6623c4fda323c755179577fc12d621a26a32b6563d261b855ee5f021ac0cd553cb5667657126d", - "0a03bdc9e8926727f6791ed40c76e73c1e676e168e38098bfce71e2137ca9c00723cabfa394109b5ef017e64c597b2a196952b222dca743624245b472b04cca2af", - "0a06d42a9e27d091a7c6339fe18fd31d9c20944a9bee2c3464d63a512beb54ced5bf7d82ea0303662cd469c1855a2d7c8501eeb27c3f35894873e4ae9d4f5cc42c", - "0a01d6ebf7d4113956b250f40f44742c822c92b808217164455306d315a7645197d05f263a9ad71403b960fed00f2a0525ef61330f91f44a16c232c607edaf42a4", - "0b058466bb2ff4ca52374b79c6b5ba8810b565d61355a63f13a8897af44239054de7939b8663684ab906d708783d42c4f24f3210c96279ebde46ab981109946388", - "0a08d24fec5f4abf2c80dcd52410f6486aefea32ab512c3e89975b714042ed64d7cc9dd85cdfeb1ca8a5b7333dfb01154d17d1e13d2dc201b367912219223c1b1e", - "0a0162ee54e22c72e643ec2b66fdd152cc5918033d44af8b356bd5f9fcfb64b8e9c6c98f432b6802846df772e6fec80a7a9f01550a85200c917d1adaa6896aeb59", - "0a032194965d2440dfef9db4d63b2a97bf585934a712b3cfba30cc31611f9cf4e43b472151792b0195f5bd3e10b6fcdac0c9ee3e60f46edeef3a2c296f37629cab", - "0a09134a286259be2bd32847b36afcdcf0a56027be96aab793f11092c84c38166f06fa980a344bd56b081d7d515ee2cb7f7851114390db990540717de17fc1d643", - "0a03c61e9a1f3c747c3c9e082e9e1d040e48a8005dcedb54590c22b1fbd5adb7b71a3af3f42fbf50e75f386dc5933b7dd1929ad66e2ef22a13d8fb9697d3c111ce", - "0a038bfcac2bf7e6db3aa387e2f34b19a9c7ce501aba3b7424e7e04be4d5bf71bc604b2f9c5e48bbab0447ad529bcc59175fd5db77a61023904662a5e97d68b4fb", - "0b04b7aa4d46c39616c98a107a805e73fada24246c6e474405d203a6fa247ed107b9d9dbffd591212ce2c45bc4ea8b0489ced7fcddaf66a22353205404ae00232f", - "0a088a049dfcde5bebd2c6dc320d55c3e784688c82f76906fe540c03e1b3d30d8c3732740c08466592148efc25378f86f33281e48108a9c16d000711a80b650f85", - "0b04fad03f219a82aaa107295a7d045983cd8ec8a8819dd229882a10f1744a9239f84e2b6e1824944386339687a5e523a7c7cb8abede66c9a4fef02e0bc242d60f", - "0a0176d02a046d5b2f8cf0bbd9aea44dfecb1db12f82d787fb77c36877b388ef0dbba3c90409a10d915475ca380b0ef80ce3375b52623d4e0214e103d4ccc6ea4c", - "0b08fd75d6b9c4926325d4933971c461a5d15eab841fff07d3e6f5db7a14bf942c5eab4f6b0819ead3c6a8d087b8332c9c43be7b32f675aac95c56ea41943cb031", - "0a044f1173ab9274e56ee9ca8d400940df33950528ab63f63cb9b350491a1184ec26ac48e81a0336c4dadcf1df1fbe6e46e9f79369c1363f79fd45c1cc572bbed2", - "0a00cb64bf8908d0051d0ca4655f85df34efe92a534ae845ff8dcbad5443d3693b6f6ce6aeac15b4d432c6bd08504a8f42216a4aaa2614024214923402e682bcdb", - "0a06ec0eb4ff6efe7ee7104c4e193363c1ad56ff8cfd04d717e8a9c963c3d50d22e919c20fcd014e29bf91e9aea3efcb0161b9f78725b06b037b62baa218bfa3d9", - "0b04ddbccd1474eb44aa55b4a4bfdbb73a864d716e62e322ce2550e264b0ed66055a89069a12c8bfd644970da4aa0fd60a8d6cc71f74791749d73b90d6e59ce82f", - "0b0381358cb20c19803e8b7953c33e3c47989a6414013fa4f4db54de3841ab3a8e807e19600ed320023b43550055e6d1f6d38c66df2f8274c10aa793b8d5560ea5", - "0b0142a17e2df1e7a4d12df874f4475078524d4f28b8f0a7e380b5d818de43c41a2dbd1ddfe0f34853f4e721fc7e9426af31634675ed616d52eacb66386fefcebc", - "0b090f3d51c5620061c62ce4e69aa01a4213d7080ad8fd8d2f63440c623e63747d65ffa8902abd841c412dbb59bee99de81a977d6f6818db41d258ee4f1fc70ed7", - "0a03ad011ddc0b1b45bbaf9f7c7c953e9773185191976e95f6eaf767a719eb559a7ca68c541b7419ca99c61cf74a350dc46e4fe72159b7566a6ed3ca074df72204", - "0b064f81998e9ca8e5de9f037a7ef3707667ccbffb7c651b6729c565d03913d1fbc5b29ee845225e6f2047214abb6544da7652bd9717d1d4e98eb5ae8182aff299", - "0b03745952d957615b116b6d4f962b0791f75ac5c75a1225496c1e2af233a6aefd73f7f5fe8004bec38a1f49ba22b766399003cc82bfe423b0ce6151f32f76076f", - "0a05a9e9858cae962b510c5a61d654c8fd429d07e570e613557f337d2691c70bec62d81a0dfaa7c4c249178d3def9bb303f3e33893ce264841e853d9beec885a7a", - "0a058bc1cf97ece2c4d8efecf85c1967f285e8bc4a5071d733e8b97e68cd17181ba58c3562835e3f2e247f259a1c4c28805e4ec8007c9aab541f1bfac9c6486459", - "0a066d1526141b4d9a3a7b74492d93698c60bec6108638c444a9cd5c5d6c0e740a34695310e3a9c0af6e435919b4d471108982af20a1d3067c6d7a4c0ef982e2a0", - "0b0526eca89c09e4fea0f4c4e6a6b377189f1ab4067a5306d7e4da8d03ac93e44e76646bab33b8d524ff795b5041ecd8faff357a8fc8e7edfe91683fab7ea30bdc", - "0b033c4b5a04e65efe323dd59ccf1612d6183f296381f0951f0f5aeb6e4c4fca7617d388a0322c97e75e03bb4231737f65c4e4d22afece410216e4a9257c4ec6de", - "0a058c835186ef122333354fa06325b2cbba6a94ec48d644d47b921a5728b89eae73226e2b105aa95a120685e45a609e70e8bba05d58eca6e4f067358e435cc775", - "0a013bf484b58d94a056dc62f55af3525d6c08b8d75695009954862ca0f3ea7c86519cd9862db56190d519cfe5ff18aa377c1673818baf53816b1fa3fd37240d5c", - "0a0508ecb4e7c5c53abdf206fbc794514d275acef53b05b5abf84850225efcfa0928bffb933f8bca11cc699e8b9eeb850ea91929ae03f299709ce2209afef517a9", - "0b08fdf81bb1d7d6dc4e13e7ac86b7fdf6f1d4fb491bfaec0e6e6ccb98c290e7fb4416e1628ac281ba5363f08b1100ab977914146e6141566e10ef61b438903c8a", - "0b06e856de21e4eeae1d0b12d2707fc7637371f130c68fdbebecf79f92109d27a260ac490597d95bbb743ddafa8ed873d521d5874e19415b7bc47061bdd07ec619", - "0b02437dc045132382622f976b3e5cf1d14a4d16c0222e7925770177fd9a35f639d5678ef3afd12ffe74d167ff1fcb9c3ae1672c4b32e002a3bb2c322d62e8df49", - "0b04936bb4e956b3f78ca97aa8e73b1bf30ac737d8f2380ae2199395369fa4bd83c5e509806a23d92565d3a2d65dab101b1baf280ca4cf66a043bc6af46fa7caa2", - "0b0265ed3112b61978c8fc58cdc5da4ed4627fbd3bd30602eea041deddd85ded76dfc6873292adfea6d115c0dad8003760aa7dfc7d8e040bee1f1d64aaea107f98", - "0b07aaa4f6c4345860d8698c7da8f84ad04d6c89d4ab54b86c553ef2cc0eb055fb913f75065750c1136de083fd171595129b8c2b8415ddcad5c730995dd74ca5b8", - "0b08158145b643e467f6c22658b8697e8133f9949fa56a3a11db9c2e80008ee3b7114883bf80ba529cb970a520e747b008becd3f15173cc22da79df7689e159a68", - "0b02a054807638d7b673e57087adcb814e850d51671ce01a5719ea60e63af40fade2323b27db8392cc72bfe283c61863ab1d0cf3f98c15813315e8f13c2e23e747", - "0b063840505b1382bf6e368b5de41ffbd8fd40ddb0744f89dd3996833417109562767dd2eff7b3fb9d424502dd27afaeaff9f4458c8633d5aac47d0bcfba444249", - "0b0043e3dccb1f12206a7648b8676ce1b4ad2aa9026ad06ed53b04613c7929f1eae1b8dffe7f61fcfc0d22e6abb8067f562ad1767f852f2a0d9ec2741b07490f72", - "0a020c2751f18431dd5e5e66c27429673aae3ca949caac5f45ed44f3dc51f3d4ea8525c1ae69319cb710d0d9b79a011020dbada7297bb7370372c154ac51a97b11", - "0b021149a680b499c4bff91b0e7a62d042cf62f02ce8cc64a7c8cdba0d40a5d5c6086cc998824a93c64036bd007d7eb663c00c982f89f69d800ca168bbc9326fea", - "0b06e4b6b741b6d6ab2abd2b6a85aad456336988769adda71ebca3eac87c5c691da5af46115ec8d5c172dda3e23f955fff713e00727e6098965f680c7a4f5a8d4c", - "0a065b96990e38894e4f8f7269c45b86f8f47525fef1b47a592b65e1e3fd6a4a75266ed45ebf4fb214882b2106f2af8a2425817a278065e33590473a167444488b", - "0b016cdac7bb26ed19b8d5aa911daf8a8417fc495fd4b34943919544776ba048ccb0642aa36ca514cfd2d5e59c67c91ec41105840b4f523787a9d67604dd4d1860", - "0b06501193612780795372b643f95a48c953a19f964e0d7cbf8460fff1b9b2e0012688d92ec96531618345163c16709e60d358c9667d7bb5e46c8101191a101c87", - "0a017b416efad827820de0744ca9cf6d3e6dae740c56e2c57f5dd259e54d0eee0716624ccf874b4b380de2a9f279d0769bf72b1d4c0f34a681a7af968e4b28b0f2", - "0a05333bd17169f97752b127b8b38df87460ab7bf2dd0e1373bbf685aad2693643b238e1b74d4eee499c88fbf2692eb8df68cc99c768c7d4d127080d8c2c2eb695", - "0a025aabc734b563fbe59f6895ec04a7720764451c2397aca48f219826144b9113c2ca4bc1f85c407e78485a7bd3bfa5b85a10098bf088b14b3358b10351539f2a", - "0a064b3677fe406a480aefebf8933f02e0c236b7d9c2850f6eee3494110574fd9efb3ad83c09533276528739cdf4463389fe2d0347352b861258cbca1c6a66b66b", - "0a02803a0365873ba68a73434b1e4200c41bef6c3453c0638da4b8791b1ebb740cf8e057407247e2be718f2baa14e2b28b609dc980de57f9dced2398dcd752f9b0", - "0a049c76039cfc8de4ce9366801db4ccd17dd4100534b59850db29345f51d4538f0bb3145fbb932d332dadbbac5835b481449f5c7c2add0d8bfaf899f130227a48", - "0b0701b487b10694b00d6cccee153ff1e6fff05372e9f4974951432ed5a44582ace0bb3c07a5280ad6843a05294ef830a8f5c299c508f0c121907cca6416b12004", - "0b02eca6d9d677ea11b952fced751c752bc97e2d15dea2833349e810a25ec6cb8622440bb1bb3965316710efad2b857a02bd1a3f79d24279d869ef87f62a118e5c", - "0a089746860225342468904a9f151914dde35e3fc410bc02f7733b1b9a8df72a52758018fa6460e54f97b0663071840b22ffb73767b69b48b8550253bd50861a5d", - "0b02d1c63db1e98af7859e218b29c370c03c55253df5a04e3bccd2a3d0a9b126d5e38508a8ebc13b8d329eeba9c8fac1d465ad7f1fd4ed85dfc7a016bc76d2724b", - "0b08796eb08fa73718a4354a3649cc0a91fd098748aae4cf80542b3d9c98b984ad0e78f30a8e84118c5d1d7e508371c5516abe71f90a73b5c786b23649d9da3b03", - "0a03d4fdd950b466e87b6478b5486a1d7f5686c82fea7b6bee3d61bdfda7564bb2604c8415f63ef1aaf1c0412ee9c9f99d7ef30df6fe7b78e787b2b2e4fbec30b6", - "0a0887c1a75f921a65d84480dcd90b711857945ec8e5fc7a73f0d353588feb27a5cfd45161d2dc99999669d5b880c0005d2794121b681907ac26db3c31c5c09b62", - "0a0724dceb0cb5bd05e27a74370e80e702e60be511ae7f0433730a1913525dc4cb17e741d7aa10f7d88e35092847fbe9f7f17571867eea6e431ce0193c82068b8b", - "0b003de5a2d9829a94cee21a4ce4a6aba9baf9422f1a10195e50b6a6a27c5d1f97ed7057f133777d17cae9530851713c60c701113419a78509d965e4352c650417", - "0a005a4e3c88291b8f8f6945bb9160eb5a67b4938d3db7c3be8e7c724747c9950476202daea87571dced4066ac615cacc79d7f1546d9ec7736be5d1e940893a251", - "0b0350af49855a299eb521abcc45b1ee265df186ac467017570390e7a2cf96899c0bbfd62d55e67528a32acd5bc3213d3d410a3b2132b5e7eff5990c39b9724868", - "0a0248f4e51a7220df14e70eb6af19efcb489daeb25d66772f3a3dfd93b2fa3c29fd1322bd2119c79bd42c1211d6dd5fb5f9e0001b6dca5378adb8f9b4d18aade0", - "0b0682d71b8a45284d255c61b1c1998996a58ce17c7e205424e32c4a90ab4c873e5d8c4b4b1dcbd158420a8bf9f76b895b7c652f01cc53e44b21b458d1801b089a", - "0b02c9a92fb4f4744f0dc595049bb3337bd6c66650e5736c5537fc740c0baf5fbd4df6127542b3d8e7d52e3e04e4a8994201069fbb0f91e463ae177bde6dad11c1", - "0a0774d7c986774cab58a57c9d64b6c3097c05aad4f8d997e222b93f2a33533226073c8486fe54210633b5fb44c12048617edae67f97250abc446f5304664dbd3e", - "0b09167133a74c242d7e76782862d35cc922b2929ead1a1784f4f360d807b309616752ae6e66e43bfab2b14670835105ad74eb009599101fe25c728d142ba91d9f", - "0b014e1cfd899ffd53520a5753274ae03f0c273bbdc91141521561bfb214858cf64d40b93e80a4fd5501330b43a6d1f231c97602ecfe458e9bf999373a609a7954", - "0b05c03874b48437950a8fafae9e8036f4a2a67b823625ba3d3db0685ef93a85e8043097f5bc288b8c8329181a50e147aceedc5a6d9f7273f1d50fabfd2666e112", - "0a04c29a202ba357e4151b6ac43de3ba0cb9b89eb0262cc26c275d40f7870b7c0593afe87dd86d656e6de6ede27ba284b3a766da7dba4e5ae69b6853c938450a61", - "0b0575e139756d4abe4e7f2e083566d60a0a521db62ccce143e07b6b96a70adce3e5c0b030f8e789da1dc04f6ab6e18639bbeafb874b752e23a309a082efb6c063", - "0a024a0c75976d9221535d91fad0e047821ba7820394053be4079d9b990c2a9a6d67b3be967413104076db5af4988ddc211af8e6b762d1dfc0e75fbd595b2ea692", - "0b00084e23de19ea6a77120f1829e99b195fefd6f6c867e52d041c9bd6926a7fbb44fc51d4ecf65e9b52f6bbd5316cad80c0716e8a21b3ea4e0c1f3c3164b0bd6a", - "0a06995a51426a2776c6213a945d474abab52f38cccf479c7d00611c33a9ebef3177740f99b338e9f3404db960066d51f19a888d25ac80b1355579d96150e9d69b", - "0b01d778f309d38e8e6c699f520d311a3a527f394b286bd2ea36ec91d0ff8f290f2fe629ae2a15e83f2dcfb8100b0cd1168c3c5938485f6ad365e812bf9a1bf4de", - "0b0237d269a1f77230c9c0f3c1dd31449371d0b89d6d94ad28a7e9e7eee30f459b4426051709342db06218daf4708a3a65e01592b64c47677e16aaa4be0c6f88b6", - "0b0216c22baca29a07b5c78c2df60a75113b89b843ea4f6c4c7e54f15380ca94249b0f7265d659c08e1254d3cdbe12bcdd232683a6a994304aaca0518f1fb14860", - "0a04b21922bec2d1a5a9647e06b0b75cecdc3e489c1a4310259d63cbda93fb4d78ea696e80f8cba5c9f11128f6ff4e88ad298027c15449eda1cbd9007651d1a0b6", - "0a01d2ce098ba7071dbe04b3808b7a92e4fafd82a69cf3d2653ce1178ff010690199f46824a72cc331ac3607172dcc992a62b236bb06756d1ac8905b8f94c3ef5c", - "0b02ac5712e31ff36a0dbabcd76fd49a815654b6b704bfe63b6d58884d9397b1b632ac2b37fbf75a33bdc68fbcbbfc34102d38a918fa9e02ffab4238e2cdd097a0", - "0a007cd0d60adb4511cde0f4d1c2cf0833ebdc402c0ef716f6642834e3375b0811daa56c07fd44931cdc8ffb0de636e4087b012855cf7c8182bff130daa90518d1", - "0a051885a19eb2587023e9af184784b2084bde474125b65928230d55ad178c6ce57bff5206f9e7f3c055afe03f6672f06231375a8988c849a35c29baecaf184a42", - "0b0450726fb04742a5c2c3a5ecbd153e03373a7d6ee45774d0eea083fd8415ec9831b46dde4777eb10cb3248339e5e5b107e421ee0ab75fd961ab08d5fa046c5e9", - "0b0007f95f338736f8755fc915d546428cde8b0086317cad65a64bcb60f5f9b1391a88771a75c330aa3152b5a0e9d3b2d26c2be69f3339f7cd00cc7406ac02dfd3", - "0b05a64224f34a38d8b86716f2ea50a9cec2db17ab46f30b1d32357a5e01ccb064f73ee4a9673ec639cdd9ab8054bbbf7ee90934a1981f27469ca7b548fca97a90", - "0a05ce73101e04542dc87848fae714be931e07290552285df89d342bf44400922ba430b2005b01d62153c63962675f18fa0e494b022f993d4690744a78a749e7fa", - "0b051fdf5a6eb09b06762c3c63b7943028b64294bc90cf1b104c2262e76ea218da466d49a3b353f0ce34fbe139c3ca54c5225ba39fc355878b26ab587ad5687bb5", - "0a076924f3ba542eb2bb927d7c4b5855045a17992dc98a5c96907fc84a4e29abcc927dfc263857e5e62bdc9f75c95befffbb83e7b04db65ad8567bbf2bb5488184", - "0b032b64f842c553f50db1a9c3038f47c7be85857d3c05dbdd33b061aca421afe6fa15054a403f31736fa6700ea9000a5b4ad6aac4dc325cf38ba4cd44636866f0", - "0b0704dfa04c4f58dc666ce78cb1205d0f17e549a8344aa2eb0e71f39c3b981f84a4c8cc0b5088a2d5814ff429551cd3652cae542ed5f63186fd2a0dc1df3ca8de", - "0a0634fe9294c7dc5f63818ab1c548610c4aca9833b2af1d714e19bd10de4b8ea5da152fcb81b298dcf26790b7b6a0ebc0d6060868a3724aa50eeab520b4b68fd9", - "0a02e90ec9d152ddefa649fdb967fb232d966b9043a2c43b17f8eb8d207f2ca2ef516e65e203547a3a08155c85555c5e9198b46a65e6c9732ea6142bcf5f310a59", - "0a0410850b03936246434ab00979f05481d2e877817aa23b22acd84af12424aee64d1f707a25e83cd569bd96026619647f04a521912aba4cdc780483369cae8160", - "0b00e4713d662fdb135bab017f82f7c9316756c0ca03b375a03ede4447482f458c4351b7213b508475378474f9ec7ccac0b9de4df4ad5e745b0ce598e3a1b8190e", - "0a068a340ad772edcab6dd4e55664661e19f1eab757b6379a98a869711e221414bd0da1c453f63886650b2b5af4b67ba09378285299d625abea96dc7f87ee0f0f5", - "0b0860102ed43c6222f7c63de35a511c548689dd4cb967edd511578a554b6152a6059dcf35e5aceb477ba6ae63ab6bb088e1d6b98a9235f748c1b27821a76d26a8", - "0b023aa844942847ca2bb8395727dbf0c11a7b79de080d3e3dd6cb924e318628ae2f4636bb747008f176145915b985a19f24ba37236174b8ccfb6f2a4b9de41f4c", - "0a031e7354c49c6a1323ac82fa995e4f1fe8f799814f50435d6b2d8edba00293d3a7f670b49475693a744ecff853c550abad41a682137880e65bd16385f619153e", - "0b06bbd93a776f3da3530705b84502411bbaaf2bff79c7eb8928fc3cb90d34fdc1c66c2ec0e3229d0ed38c9798a7cef6014718af88737252dc6927366f998bf7dc", - "0a014aa1f53326235db30d37b4c1c3ae18d896dfc85c9c9d178c2c6802c4fc4e1e92d24e153b7b326e23ba82157dac1526887fc64f0fe1f841c26665adc0338254", - "0a0193037285a1bf0250f064892d788739353c28eed5f81e51c2bb975d1100660e06e56d61dd8b1511477ba01e39f616cf13b2454ce61f57ceec9acec28481d134", - "0a0639de1c4c4fbcdf0bd9f9c19dec8426edb7bef09dd44eb969b7de89c741bc602bfd2458afb6a1c70c7c9969e7564dcaeb19994e22474001a540e7f1816861ad", - "0a064ac01b9af71415a5f83889fa6f0130260abe78b44d1fa699e7abd054d9c91ebee2f2baae3254bd2405859b4429d8b65c8699f5a305ab53a08cd60ade50de50", - "0b01b599429aed0125a67242e30dc5d38afb7106dcb42c237f0c99bb4e11004a3e9c8a4b287068c6acbc1854ec734e43081acfc960ccbffbb878a7c96a33a6aeee", - "0a03e64b206655254c6655e5f0aef3a8fe2331792c8d6e047aeba13f09da26a3785379e62bd645a638e46aadbb6e3fcb5abfc5e608b1438ec92c1d76ea0ecacd0e", - "0a08bed1a360d9248d9d4b8249bfded926c3aa26319f2a2b97f0bd4055740cb33a6b78d1bc413cb775e4b6725722167fca5b47dad4ac343b0eb600701bb9a48062", - "0b08d536e244a46fd7500658c7eb6d39bcc27c5fbf7075b321cb36f5a40c479bd71d3b1c8359f5f39e22bbb0275e564a251a14973f09dffb2eadebcfc8d00d3647", - "0b076a323a027b29dcd0775202051256202d2cc9568a7824d4fa5f95dd41dc7413b69cec1f5399c34786a36a8cc472cfb6022f0d54a75c964084fd21cd295759b4", - "0a072f93f34e5ae561965c856ff94353972732ed14950466e0e675d1aa5320a8286c201a4ed4430ae645689f242560557303035a1d06f7ee5991cdf766898e8d78", - "0a00e59771d31b85ab620f636595d1c6c79001c2d93318558ca72f7ae5ac10be68dfb12381983977a2a9101d5b48c5aed991e82a3057131a62d4c2c0987c38c281", - "0b05c0290111c172c6c682f89e3920f8a6b07e209d3c0737fd96496a9928d177c34a03593c70d4c6c996aef3253694f88a460b751fa9d24cf65b96004aa8ac5759", - "0a07609c1a2462fd3cdee7ccabee672e8c607c646c50187f6c42e0fce3c4faee000003ce109920b843fcf59f12392fb274abb7dd16f7b6c5ad31058dab4b28feb8", - "0b06fc11ffef9faf2be162b1f7ad44fd62e85b3c10b1b7d91475c77950eba4d32eadcceb0747e92210cb1bed81cd1f137aff8380ac9ee8abcc567c079e89841fe9", - "0b038b7e2012ef4ee583ef37232c54db26a666060ef0131c97c9303d839160829e2eaf1551c6137edbbc54b5beecd116b4272b4e5c6496564a83387a607a952df3", - "0a083ec395e54db31c306bc42ab240cb027a345ea27ccf66c603694e419547f358778bc471d468609e238af28f20482d09bfacdce07f419532bd0c0f30a48df018", - "0a08b87ea4d0fb8f46ba2f52498d0f05edb7398ace2f55e0c1e69fdba50876e5e7089aad32305af80f4d3bb70fe7afc6a3cfe4cea5652fd403f5aa4cd686033c2a", - "0a035bc760f12975c37a8dfa7177b28303c60137e93104ca23a1cc9b8b435c617dbc49ef1237071b4a0bcb12a84ab439aebd1f9d0c71a72167fbfa4a285ac1050a", - "0a037b4b1f9955a6098d0b170d118a16e43c9bc7a71e2431ec2c77a4091f083904e44146fc36d6de642aa1cd20bb234b3a6e2d16f83c57a6c617aa1112e31ef3d0", - "0b03b2046dbb23a326b53c9e41168885d24d9a957b94558dddf77328d510648bdc59af6420324c9d92e769601cb6c350d53063925ea109bd1d33df745d52463845", - "0b04e6f84bfb788d217cc381d14f8bc5f75b45ca32765f5896624d654e6d55425ca6e9db4f8e19915de5cc04eecef1791af71af01e60b8b0ad4f29eea59132c045", - "0b06de90448b5957df9630e881b63e97948b20f5ee3d5f4de348631f002e48242beda9b061db9a53742094747f6860580c9001fd1be04102d52d723838f24fc4f1", - "0b04bb289881a033eb4a4c621969a21f5999f52bd00cb26c40b5b5d4febfb5f4c92021520f92f1b8a5d3ca96382f6f17cec16b6ac342274e47342826017a2be02d", - "0b01e20567c660b4338290754f98a0b38c1cc8599225e7913fe484f62942e0fd27b60c9ce28cb8082f2d93c41cec8781d83a96fe79627b0db9f925797397165f18", - "0b00fc9aba964cec94ecdc09553eda5bef2fcba7d10f7a8080e56d1277bc88b25258340d682845d39bcde8163ec9174c0c966e85ef54e6969a89cc74650ed039da", - "0b08cf2ae0111a5f687cec365ea1413756cd10d172e05d1d5b61f09e76251d9a3a150cfb4fc84a8650c4cd448a99bd64263a71c221b65e637f86793913a9951bed", - "0a068892505203ca86c67987a5724044169152340e6567074055032db3d9845bcf240a55b691333a6355387c1a5659b31ff870c499a3ad3f115d19d1822b2b81ba", - "0a04a8dcd057ef5ed40f11990491edba76b3d35f339d7e9938d967eab6a7efd55d8889d44759518dc46494b098d9041f17ec69f0cf0234eade284d97497720b42d", - "0b02ffc459e000e9ac7e41eaa29bbe9b20a8f7a841f27c65b0896b7dfe6ae828142158309db1e6a510b0b02136302ab1a3310f7d2e3b437303163324db37dfd6bb", - "0a0873dfea9d7eeea403d261a572e9d7058079cee73440e2db0dc31184395598bd5db39a484d4c081dec825a9d9d36620a611bbb0ba5853defbf5b273e4df49b65", - "0a02ea86bd10525720e5b271f542f91d1df31da6661cf3a0cc62e15c0c239259c9bc7e15fb7cad12b3ae98e1b3d9a3f1038d67192e083a46317f2d5b6ceab42a74", - "0b062a3e9613e0199b3d33959bce2e6b38c2a34c55f46027c65d741d846bcc819bbac24d3635b51a8612edf613472b73400b754d759f760f6921e69fd83ef8035d", - "0b005435b94372ac9354d485619df96bd5ef31a3a6283b91d648a40a1bd79b1261c89eb2ce13251598a5db5efa466a26fba396321e19ce2a1a81d7c489dbaefbf9", - "0b08b375ef826888007366eb6414a896cc982ac039c3bd8d3af39b126d8c4ea536878d5a5d35229fe3f13563dc09478afbea5910567d19b83ddc73770148bcb5aa", - "0b077cb84170331c7f28b4c209c57aac4401a82ec6250db2da58b2267a3008ffb0d83392175a3e9b612f0d98b04ec31d283fed511452ae49ead962fcbbf8967a17", - "0b0586a36e79bfc59f408ec9e10947820da8996d445eea44fd647778a492a2f977b72fb7079db872b5fa34b82b164abb20eb214deb8292f3ec627e3b682d75b1ec", - "0a032dacef49aa9967c3243cd9e4abea50d8ef3388b57bcba281e60a52e289cdc2335ed0b2751f6d7a6e035f824ce4d0da51ee07daecfaaf08ba4d0451358d3300", - "0b0602a3d4aba19ba631b0979d823a64c08162a50ac89ad0f590df8d492cf93624eec2bafb9d54b53103306a61097fc3d3722ead3696fb7db1f0bb8d4ccefb7661", - "0a07c1e9dcc25f8be8a1b82f3aa179f2184c21d9e5e50fead6c3d6740086c7ef2fe0b2d8290cdd3cf56f123df8ea75c2017fbfaaf965db8866598ad648c0b05d55", - "0b0415b1ece42d0af3d8445b6873d4437189781e3d35160e6d2711b2546d0e098ae23b71fb62c893a9836ab2a0205d13fbdc5d748187de8ac9627e8c722bd30977", - "0a0173b07c1091bc8a6ae2e39addec732f0f47d72933db39aa7838c11c281e962df8be0225cfbc25d9c4cc7f7c9d098f5d5e19bc2afd3e56892ca2ebfb8b5b2ea4", - "0b01309f85ff00111deafb036c707a84be3f64c95351a4ab3165ee6819c0e2945f8c3aafca04d0fc8e57aa7eeb18fdb28dc700382dcf74cd380e90d291e3f95c8c", - "0b08930f046e43f43690e644be46a390964491867dbd99232879101b0e93aa87b7673a05ca1ec9b1fbc8e02306db1f831fa68582ca5ba023f5a5b8dd8050300b80", - "0a06166919a76df9dd98dda8beb560ec5223de00575445501e873822f6d47cb9f7ed07086069d5ccaceb1ce5cf79da9ce94342f5a777d1fba6f1b7fd641fd18e3e", - "0b0245e0c39c612e0d9cc027b6c445a1374cae3a5bb5ae382cfcd332ee830633187bf4b556fa31d19f42ebd49e6228ae4b11f6387ecc569ffdb57fd3d50d44a8c2", - "0a074e19962fde3437ac1ad75dfd93fe1d8c4dec1036f45d1dd0771edb77c2541e857e2711a76036e82836f8cd22ae755985eac5e7107fc8e33aef9def8e653a30", - "0b08e49f5f35e372267eb966da77e9c1012e6352f5cfbb7ba2063150ca345ebe35a8470c014aecdb5f92f4879b65d247ae244d62ff1fdaec845345d8484a12e7fb", - "0a05bb81c1cdd340ed7c00dfe1eac93fe5526cf72e42e66b674445cf308fabb5b288f47bb4c8f89b6019bee9151f6c1e4d89daf6195900a850aff58e315d183a30", - "0b067c76ea40d1489f0d4d873b38048a8f45d56639ce5ac6ea339563eb7fa23cc07b3af88f7e89e9be5dc036db899d836e1362a68a815a5f2fce97327501554eaf", - "0b06ec0ee28a2d327cefeeab453e37fb5552c7630338eee444d9b2bef25cb5a491920357487c3f3f3da1f8eebc328a043aa5e8d4d144afd8a1191761b19cb5d9f3", - "0b02ceb4e67e9f0a21d94121cdc24f93cacb8246240014b8699968a48273b2902490d0ecc48a7cc9b94984ada7f8c376f18526905880f780b24c772aa04812b48f", - "0a007cdf1f4ca8486e99c29e6c4b5156170019bac7b54617ac2fc83f54954498c55fc2612e1694dcc67883d231cb1f8c5e8c4ffb03bd10324da0f5a0d2b901122a", - "0b009f9f9c087eefe0792e8865589636afdab11e246796ae3b30a9a6a3571669f685e0b877470af0519d2c34a161c169b6ed7221708975e34e4cb9a3f85521d503", - "0b071db7a8ca0b8aa4240bd9bde3c7fb8517c3a5a0b776712ec7234a01a9f715f2f3a1a4bc657d0683473c9e072aa73148f29d3be612b1933258eb2c32d29c21b7", - "0b03e89b66ff7eac1cfe76714719da96c9ed9e0001731fde0e00ebb5766b6b8aadc99cfcd559a3362aa2f4ee193bef0315bc321872401f23c46583c29746e7dad0", - "0a07660eb4acfa92c572185ae581fdf5e5126abe8e4948d6f81215f1b18b69205a835d3f48dc790cc41f6d56d10752b9adc46631f348a0474262bb85a7498c4d5e", - "0b0749719beaf25b31498626713580ec415b8627b4f0656071c2d366aed7697d9a4597ed991bf199a147f8498780dc123179ac7411c026e26255b8e271608674d4", - "0a0645155db25c387008d279a4fed9d4f0431430e84124c21540cc91d227f2c963dcc000f06a757cbda6ed60a7705cbae3538216238ac7423435fc71ad22db2a13", - "0a048ff40bc5f0e2f3fb3620e60ff83991304cc255a07c403b3209d528cb569867dc4de04e2fd3f1c966899fe260c7b8b6271dd683686074f0bc94d1ad4e5bb507", - "0b016a083d27e275d9d3700c4657e7c0324d44a376e2e48dee8ec8a4643c4854070046cfa1bcac6463a5fe7484bed874581444292799f43887387643b4f4f4f754", - "0a08742396dedde6ca49d9087651ca56043c37ab69fb9cf5142b48a8a423b668bae32f05bb8a52260195323233157a8c9e7038dc5f60e0a6e4e354462c1916efae", - "0a08f7733ef5896218e093992d6cc02e6e4469b660b6f765aa69754e042d814af8dc42902219e109af7a30be712b5af6700f06d2326e62ed9205285671f26763ee", - "0a06481920cdb24e009482fec9dfcf1a7a57dd1753b1946f45ecf21641b18690d570e3fd237a3ec79a9b358d50d0ccc78712fd8b04fa478c7f8768f8ca8179144d", - "0b053eba6c37ef71e1f68889603d2dba323e626f5c1feec836d3864c7612250a967f99f651a9029af7e5fef06ed0a8afff7330177fee6817c19c549b6ebf35f2c4", - "0b0327520647c400d156564fa2f30b138ffb2333ecca35791f8775c1e002a0b6728c010dbde4921a1d6dc3675816ec155c92f44444b95b008cec61e81a72d4790b", - "0b01f9fdbb571f31ac0f1089c187933e7dce6a8b7d17aca9d798778126bb71c99e6cfa8b6a2ef12bf7f3947132df1e805495cbc134ec61d3a81c9b1ff94179fbd5", - "0b016f88be3a7a0de6a4bf866c659d935803f439015101524a0ec850b8e84665e25a57f7345f913e9b1a4fff1f67f8ffcdba7d5f8dd891bd1e2629d12d9f9e2dc5", - "0a07f9d580a95746edefd28c44a0d7593844c6e40add857f2a0c09263fa5a67e739d463523c76a47083efd45eb55d087f937cbb441f0da1395b93b84f394b8218f", - "0b0080dd47cf65ba980495c0e9c0914ade4be55a2529346a08c5ad19f6563c7166f0db6872473e7938e40833835ec98a7dc9c0b5772b5ce53d9ea244ca649c7c13", - "0b07b6120ce91256b47d53010a9a04a645c6541b1f62e419eff80dc22384210f309b496c2ca999d3a05386a3d3549e19baa4007dc1c298abebbc8e594abd335bbb", - "0b073a2ec83adec37791fb291cb707be3c0349ecff08cca1d55385f888589e7ba41b740a955b0c466cc64250cde4314db2b715ffcda56f91891f4491f7608e594a", - "0a077a7520becf83a2eacaed93f2420f4007b0954db61c3e56d5729683ba7a131d32a15751585ca5aa151c1ef38d3fdc19b9f96bc998c7732def1e0a81c61cd045", - "0b00734a49375ad0fadd52b68a0ce4f1863743b4d582b05159a807a2a59f4bf2656637b91a86714466f4e4453bfb08eacdc8f46d4456a167b6767f25902489c307", - "0a06c95532f031666a5eafceb60b43251eeb9e7d98ef177de075a1df2ad78da1bb60bac99453391a72f2ae688b7233bbe2572454265e0be9fcd92e5618dd229f33", - "0a009bff2996f589d5fb27c70c08d830930315f6c9c09d0aa69106f569e19f975a6def1ad261ec4c6951d35a1921bae2c06877f79b9159d9bc03fd98b57d0c4180", - "0b050843aafdf0ace801ffd9b19f142c2fc0651a18e1ecd3a38065e9ecaad4d0a5b99e6139567443909d85a506db2eeae29c1fe601c7b41d9a5cb613ef0585d9fb", - "0a031cd6f127e8b3a656046a4ba5add81353885355bb56ac0d761868b6765a75eac13b26546e67539f4dff835012597dd6aba0d603e1f1e11f556fe855789af2a4", - "0a02e3bccb3d162cb08a6389654533b6b7973c09bb94c370cf931a08ef4f9f3faa68465fe433d210479ac3c9329f185276ca0b2c9154eda8eaa073123410f413ff", - "0b035344d98d1a28576bc3af1e4a464fecfad4add4adf92c99d92a2c1abe652a7d04cdd1f0db1ef6b328f8796703059ab15d3e42e398cf95efb9eb56d87ac221d1", - "0b0724a7ec58961b5d846f3e0b6ea36d3c49efb6584d18af29996fe260027424afeefe346207000cd293dd595392eddf9847cedc6338b24a4870147bce4b6b6e75", - "0a024ff7fff227cf407fb4774f7a618a098549668603e7e661de1f44a8a7110ab922c2eeaa9085ce9fc1ea3a5015c13efc4b1bdf23a84d4561142162671c73b54f", - "0a037200322463e720a05604868e29fdecd0d8d021762ff8abbced240a1c4e02f00bf9d3806931070a395656a7f923c3d83131fa341e9955a36ce10dcd55de9eca", - "0b089d4b805e89d04e67c8df8049f29d4d4e694a545093c380e63afd6e0f20000640310cacf0b6053683a83a031d8e807932469c446f6966131a57ed1ceabee684", - "0b045d44408d275e83e50deb9de6f831861e4d55953fde8e620267bc9f15e3fae61e49b0467d9e50fd5a14a0b9a1f51984d2d6d6cf3fd4dc35c8afcd516199c4d1", - "0b0242d24861160584fed12b5d45869fa8ee4dfa07b5e5b0a06f9d3ed9d3113367d5cadcd6f7e0ab4c7c697ff2932f72dd61539e4118740074cd1f3cfd65b0bdb9", - "0a036433e201aa540098ea3d55dc6fbc79174a8895afda414b9e264f51499dfa71c83d9942c0fbd252f8049ba71cf2a7b2d468d3632e785520f82501f9a2ea26d4", - "0a01ed89f9b97e1461e1d70d2fa5ceb3d60cb8e818531a9c50091a99f02f42fb5ca1b453a5c27364de62ed4cb06929c43c699fe5af514372b8948876640b090060", - "0a0581f154638277ae305aa6d139714b7f5713e0293901c4d07a69118a435a9835f68b8e5525e4c1649a9a131e964662f6ca9ccf895c646e24c695cb9526ffd305", - "0a0427a81a43740103f1f1524edd86f870bf3083e30fbc6170d3e77f4c39f320ac5d5665dc6d4e4d5c6e3415fb4c57a589981b539611639fc8211a978b8822a680", - "0b066579b69d3f99db526002250e901aca50cbb58ef0e51b570f94d230bf234322e1ac949693eac79126a30dc6c89f11f9801e44ae09ae5a830628fbad1337a782", - "0b0290837acc086fb482cb209eb40c22a6936d37416801359b9edc5315da56a592c30761b8ee21ca1c5bb0cae20581c4a16800467ce2f9c35e3bbaf49ef3186a12", - "0a04883d7a310c5088c1be7d4be9ae738b36105f47df2bf1d1eaf9912138a8066af3bd520471ef86eefcf5161dc37bf9b169af13a35f3bbe7d55d242425691cb53", - "0a05bd785fbe7bb2c7abfa7a4f9bd5cbcf817aeca69c4777c945df1d92e32300b1498c5ee61b9b543b3c190160015f94d6b5860c274d57853c08541ff1a14cddd8", - "0b08b54a7163300911d8bdc8f8f4f36114eb60e31187746152ed660d1c500b08a55747bb88bb6efff992b53e8cce6660684696a2412d2ee7a1f91dbab7a92a8a5c", - "0a0146727b48fec30277fa913df8b6126d9bbff4c8873f8e2d25dc1348ffec169df6be49743ca3bb2f677e774e187f941b196b9c1b2494c6b66c8010c2058e567e", - "0b031cac1b1c8a5e395222f3f2d81b35728bea6362359e54970724d13d05f95bb86e9a1f1e273a392720d979efa09f72ac8e06aa106989ab360daf8da4616bf643", - "0a02d3a49e48721be9c152bf937ce97a13542cf6b3d1e4c1a4507c3ec8c56ce5927a7a334563a1d2ba3702a0c762bd802f417d616eb3594dfd2f7e27326f7524f0", - "0b03774d9ab9cc436db5a6620ff0abe47db6b84c76309f92d970c28e5f389765c9650b35a4bc817f89d2b7da63a8230931d7538fcd2f9dc54b467ecb5ae196cfcd", - "0a081572cd576a9af4522139eaf5172eadd8f3056de92e8fc4bcb28f7ed7ee61761dcc29be4dbf388effeafbe18d37fbf606fc81272bd8cc8ca7d87ee6ff09b52c", - "0b087e95a8b6af87620e8c41018f84598bc1f2e749653c34f71e4d7d4657329a03ec17d6a1ab1256a8bf0fdebb3e745f5e45bf444838d5dc6d645134b71e6ad13c", - "0a03df1e3bbaaf411c7b65ba85d3fa20ad0160ff1efd94fcd4c457d9ec7d900f777e2cdc3de68a6016588cbecddc35bcc55fcd25d510cfe60a8693b129cb55480d", - "0b01a5e89126f7957635573b21d96badcbc3ef67bc045557b41e8d64e1a8b453b37ba0d3db14bdf37965a46ab22c734e54d460fa9ef6d579e24ce80009bd1daff5", - "0a027c3ed6713414d9e753aae755529a3d946d5ff420597135a895bb9e747fcf5ab78cfb6b7ff4474ec79e530b18d624509faf959cb1f1cb67b616229e7a2d5254", - "0a01451ceb308f9b3a94cf025e296cc24e382c7578891074d646923fa94b022a3bf9100d93f5c825ea196b8bd0b3ff165b86d267aa9dfd4ccb3ac8e4f419380ea2", - "0b0564c442a92c1c9c15941c093fefc9bc1bc2a5da53fcc3a10784e50dba85dada12bd4038391422e63458eb02b6b5014f4bbcf8880fac76fe01aa973b761a0f47", - "0b044ae91bfc86414de2103eaadbe5e35e139aa82f4d66493a3e5cc314cc8d942ceeeb5368a7ead4ec787f332e1d3d307ae0037794da5cbb72d410d50e821d2fcf", - "0a0895bda884ad7790a221fc7074ac97994c0560abcb61b98c28fd226a0a97eae3bb5b1f8795df7437a9ed784b432389c36a4b462983c9c3b874033646ccb1414c", - "0b0200a910e6a06a3719b9f180e5c1380c20257fd7bd868554e820412ae9351a6fce873c0366075593a88266705d8efd424d969c7707148df2323e42a093723ea5", - "0a060897b68a6c31a3d4f9e0edf730b6b4e64b174fad1ec672fde3d3bdf4fbdacae5f170a02ff03d214eb742dc82e2f2e1a2cee0d15bf9331c9d68cc09f1fc6d1d", - "0b048105fd3f9cedfa18c3e27c9a7689a6ecc71ee99e3faa0f8cb1f3b5cc70f4917457dcba8226409e0d9d1af82413b91ebe922626da73258a801bbeda446b9fe6", - "0b02a7f1aa3ad32c3cc732f995ad25d001c5d32e7f77bb486eaed8d94139e0e0e8d01b5b7a1acc83b5adc1a26cb121828cd715e86f961501d7a83712e0698ec401", - "0b03c4fe8c2bd631b5a195d90ff894b199337b524e7719d1956687656521e6dd04ac5bab1d47eca01f10ebfac7dabff82e59a81a82a5ccaf5174077709f486f22b", - "0a06fc81dfe96f9fed2d2daf7d6e8067c38f804aa8b540b44b9e2a56e20625fb33c5e53ba2959214d7deb96c1b183851a6bf62b70fb6069efe2507c62fa54066e6", - "0a066ea2f990497275ad3866d352a17626de2119a88ec9c1cec51555e21da7292fc3516351853978cceb70d8e423e8cce9b629fc823680b4a7948cd9595238514b", - "0a04c64c5ad07c72cc748d85208053defe9683f133bf0a51e444578a7f965355a8f890fa42820fe3f3cbc3f070d5a93d5dd9d164b18658414ba69cffefb0e50779", - "0a059f9889c1f9181460d80476ca68d01c896c18565855be80b89970d2a6d6441bef4a1ab2eedb17119225ccc61d3820b2ffdccf830cec014ef521494e1c7a2ef0", - "0b077fdc14564a933b1a668e7331aa28b7ae8d1f0537e8dfa91e9a49f2cb8e8298ef95b565ee9024687d821751bef8d26b0349d04130ce40f0438135174b93c9ab", - "0a080bbbbf27bc12d42528e9ffa4983e5f7f82f49f7d53a9d4e88442b97c81a0e6e3cf5d9c835396d12df9d5ad49e5be7704de6059e674892f7b7959e84ea475f6", - "0b07a68595221f755a44cb09cc70d2c3be2b480c59fd474df4061be2f8761faf20a487d31145cb62376f7c43c0ac08de239eae643f615380eb456623495792f0d2", - "0a02d70169d8552d010af5299ba2e14e0b876d2c5cfdad1aa71bd4928311d75d43cdc85876305f829745de8e7c8711fff6b2ff889046478c77a5921ca4fd3f415d", - "0a04a360d9a75e632647a086755c7c2bda1b6e83df3b5831dc797935d9fac614eae9baf35fb8dadc72f4c5f44ee39104e00168ebe3c5a32264534d56d77b8489eb", - "0b028435226a5a66eb1f866843e65d4f549d34bedfc7b57cb86eb95d78d6985f1859e1e99477680de5f3661d6496fa22b7350a7681b715254a938b2c49bbb0ca9e", - "0a03300f9c85d2347bca3abd05c0b361c9872f36e9f5be1549395afe573a84f7a4c0a7e6c3ca536bcb98d1cbfb8c8aed668515781467a27b85043b9fb0b71dd498", - "0b007dec8acd46073ef30c17f16c349dc48ccfe9f6c3dfd1c3629873e342820f9cf32079f70121d8ee20f261b4659c51459ef364e127043b0e8a721ab0d744ad6a", - "0a04b759d922e447211995cfef21f7f47342f5ceb21f63fca39e8077f0ce9dc00901813d0983c6501f8a506322c2fed67144f8cfe3712ca6cef32234a3a89cdc51", - "0b07e4e88ce42ea02f26e6662b1d44661094e116d12cb197a7239a65e132290ef7ef64230648e195b6d640faf1826f725cbd73a5c348bb762aad4606c3cf575abf", - "0a03f02a39ab7fa8324632a13081572afb76c49f81d8328881ab60ae863724b3f5121f4cd2245604cac51087fba6083c7cf4a15e01b77d42635c0b3321f6be1814", - "0b0711e75a5c4814896a233cf1231ae925dcb6e4b0ef5ec77fda576b8572041365474b68b410dc1dc271a4603bd0e715f0df817c33a0a097f222af026f4d115946", - "0b053bdb7f2bbc1147a2ea23acb833193fcc7346d0c43fdd59a9547c4a00a34277cd031d6a4838a7e484d12da1399f92b23d6ba3585515b7a07933aaee91082fae", - "0a002c8700e8cdb17dc52f88e2bf3fbf72ad6eb3708fa663f20f938d699a542db7a586c5c00fee04820d6d1fa504cda65bdb5897f02cdaeeb00034480bd8be6889", - "0a04669dbaed5233f5fc47e393a730b29eebcc115529163f7c4cb7c116a2ec4dfad4203282e2a0a9ffc5e973d2e137a152889c80f526c0f1b1e9328dac544a142c", - "0b0006c41082fd49e3d06e0444e2478086900791481286bb334aaae96e0025ec7d186718d3ed1e90da4128e88756957faff021fc25118f9529d08c9c16ed6eb44b", - "0a00f9e4505e68f8632e795c6e0c5a5c3a57d687e75c4db5de348e7923325ec67b970e99d61001bf71c097e4159f02828c62b4e4bc3d23f49e404152b325af7a0b", - "0a01b9197b492313dc1d3ea7a24f1765faf99c851f01d4ecdda38072dbdc960cbea844ae656a8ff853bd51c1be3d3dfc7f437bdca13f8532e7f0a858535feedc67", - "0a07448f2c06a047b4a4f54586b48c58ca12976f79c89b3f81077e7daf36a8149d355bc408565c63e045232d53f4b11dad6d0f1f6796585273d2b689f44512c205", - "0a07682323905d95082159ef8856e801b6cd169925cefa8f9bde779684aa4e825da880f25e56c7671f6f7f547ec954c7d5104269f647dffb55530e22e63aa16360", - "0b0487702b539ba4f7c0985e0d02b8c1cf7c9a957d0f5af5e64e974e813945c3fda69fd4302355e13ad5349bcc8a5719f96bd3bc58a983572cb8b1657108fc1950", - "0a0333140ea84e8fc9ced9a5e8a83d10bc01de624c737dd36ea90e0cab4cadf0811c751d714e02d3b0434348ec42d81fd733e7dc7d1654a65e02772cbaaa83873c", - "0a0082437184ed84b0f229d628899c2de05bcaf2e3b7409cd45ff5cbc72fb5809428b0bdc191b0ef89a73d19630f7582f38a788379519f83bc7c676fa47b05308e", - "0b06b21bddc34546948dd323a3b7a5f869a18849037aa8eaffa55f8b8e6a65da2f8b61b46869ddd9675f96a2a1c5793a0f7b5f7d901f66665e2f5e05cbdcb21c40", - "0a026c90a23b5bbdf18962b39cd09ab5a64a264b2851bd77b55a48b82dbe4b33dc39f9e6ed4a7ae8a02802cbcd1696db261d434dae36bd4276f3cf871ac124e869", - "0b066b481a120fa6fa76cf1115b6cc69e816c7cdeee717d8b0e36fcdb379f351341564e0918898958ac05c41b90411fa6cfbeecb71196d5ba5dbaf2182324c47af", - "0a07e81eb024e120357dc072ad33e4c91cfe741391d5ca27c0a6ab55ae038b20e59df9754f9eb32e54ab36346e0e2327269b67ae63d8b0c2fe766a03d01416e909", - "0b043954cb6261a74d1dddd9abfb3e9e386d28ec31d01dbad41c2010b6a580f593bf9ff9114d4988dae6df7f276cccb529d5b4152bf82569cf4184f41ebf15caa4", - "0a03f825eb51f6db2e6b275689e303f8352a5a4b92019b9db72e23518f6ba0614036b7edd8aa50c6a9081edfd7d09dddc17f2be930609c138bfb0e7eed1ecd3fe3", - "0a0377f18fd638618c45727c7a2f0f707b46444dee67418e8abd0c8ca65cf49837da4c3d1a4ef358e166ad4985562c0ab7131c6e2a281169eb58c16ed26b62ed55", - "0b006521bb6ae0f801ef090ae93a6879f32335a52b7d89334d4938ba4094302a8c6bcbd3e96481cc30bfc9d44ae72637f2bebf2eb01703db1e16b734957e31f276", - "0b051cd489cc969980838aa6ab142d2b1af115356d3b62e15a6039bb573165e0bf3fefc6454378cd8f03492cd8d8bdcdbd80efd6a6e2b481861c1035dd8325110d", - "0b01440d15c4750ccbfa18175ae8c3bd28f355b080cea9156c02f0a80282511ebc7469583d412a4801d7816fe744ee4a700b5d02367cada51e720e9998a77cbfba", - "0b055f3738fa8268f7e7a65500a8dc126bf48ade83af8199f189008be25d3d34204d61e5fa39de77e33e15dca29e13223347d02ad1ccdc40e5131cb1fe267b928c", - "0a0329aec7ceaa14f3451292c34dd2fb431f0237f88894459544d6f115fa715e285cb2d94cd8043882062cd935cf39b49fd66296060534fb8bd9d1dd95fed792bd", - "0b06203a7c251200438cfcc84c7c83f06b59a2bde5f4a462880119dd2333a50abde31d8dd3f8be3da0ed25f1210ce36ce269ef2134cf28e949739a0a2670b8839b", - "0a00523d075256b0e0a6bf50138b4d69f705fbd97a94b08c1052bad2a17507667f3fa2cbe614f9f8dc47b8c09c1e67ef4237fe7f8ef9bac35b8a35ae390f62e4a9", - "0b0087f68787accba82bac58f6ba0909437cac73ae2da8fdbf52582b56647f0249032f38bf88cd644d799ace5d28bd234f330ba47790d93d0b802ca4ed9fd68711", - "0a088c9dbd1d167f2ffb5c7faf105c5ac5f7a5256d326331fb1d8c4fa48d82929d2a12bb130b439582a373600f1f8e9ab3dde0da0a96b4088308bfd2ed2ba7d105", - "0a02685e835895a76f0ff12e739c6aae37177c9af171b03ada941a548bcb3f346b935785825c53e65c0c48d94b94bf66d502dc7370a062b201e5f758977d184353", - "0a023feb4b53543ddbeb534579d7ebe50ee3263b3d114b7a322bac7fe480da442c63cc853dbeb1758fa343beb29803eaa3c7b3b9921e81f33d3d8dda0a679e563f", - "0b010a65f5919f7d9c49e9b87d011b2c0084bafd05d65246d1505b1a08458d96b7384b5963b374481674f884ac55d6cdf0047859521fed6d0dc06b8f7241e0070c", - "0b02fb9b8b796e4501e726ae8bc652fd20d3139186b0539f616bf7ce2fbff5a41f0b732a33c4ee495ac4cf32f5f7c2c5bff9ad88fbcdee87f782a59b43a9cdb707", - "0a00c35fa06a34410bb17a086c262409ee53ed32aac8b1a11862d109684d137047515d31254e613eec76d76e35ed4510138cd8771af58dd8eb17b8f0ee1bbfda46", - "0b021b54110d609c46cb45a609a0f1ab6b6d18d9bf66bd502e6217e7c6b134f2f05eb4c23fc506f1ae9a0af371c059f715f7ada57807559bb6e397b3ef53a87523", - "0a06a604f729d28410a9af2099f703b7547afa5bf32eb5e83c0ebaa51b38fd98ab78bd945db9dd8e6682fc533788a78a92a692e03d0cdc8bd0c1f04ca9383a8296", - "0b04e9f2d6a2bea0e98e4a3cdab00b99a7b8e1ed153b549ecb4813e1ec1b0f7ed826449c5310b64481a3bf92b8cb4c6352c73a048e0833045e1816505d63cf7b28", - "0a017d56cf9434f4dc5472e9ca16f554b095dba38e6063e50aa7665907be613f81b6945e7334497a978f6f8991cc4c81f03e7231fecb63d5040dfd9172b458571a", - "0a03c267a67b7457dbb8ab26752973edea57110b20c67e578f4c75fa0086b29a57f8cfa5630c81aa1f9dd552c5f46d7977a6a2aa177a80c8e0bdfb6ea3e1653443", - "0a0639acc5ad64313597d2e8d55f81e2a47624368b1303caf25cd1b1a1b418e9d8f1608dda5c230a2bf8797cf0906aefedf6b4bfd449cd2a500c2b02746bfa7cb0", - "0b001da86fcce864085b2ec81d0e8179f49b3e6ce9dfcafe7bec13ab4cbd1be71556d0ae1605d1f77e5679cfede7a6353818be1031a9d49d03aded8ec834c37b4d", - "0a01829a44f638401e786643ec8d31cb338646803223936dc788d151571a0ec3d0590c7f73b1df52aed5b4c92c53e1610b03bbb1b719862470b79974f3aed6b9cb", - "0a01c718e376851ca9618878ff5cac1ff70a8462c7925dd22e6d0cd085682dc832092145999f0b3ef394ae5b0181c69734774bdede0d70149bce28be0a4975baba", - "0b0730c4e5c4eb4543fa44478c5741740ab6ea556d049fc20e98d4b160dbf096f5a5f781efc8155742b7a145a5d35d190e88ef0dcaa8d338323e9277bb7df0d800", - "0b05c96efca71e6f2ed2d34788a85c939672d7cfe52e121f8b8336d7f32ba23b5a5a1983f15a26fb6e046fbb729954b69abab1487f1c9b76475909c422f871787f", - "0a01abc2f974a649b8c9ac7aa765449b67a28e70c15daa73c23ab6baa99660757705906e8a98a1dee4b73431e950c65d8a3126604908499a73015f22ad233ce7db", - "0a03b2ddc0ce4adf94e9e83ee07f139e156e2edcaaa4a7b405328aa7070ea86cadba65295eb7bdc7c0b4d956fa4cd41af8f568e5faa508519767631a4e550363fa", - "0b07e728bbee9549a720399f5071081b78d41085d362c7a071081e9d1544b05bbc2dc1df1711c2b40591d883f047a3c7e59175276dfdfa75a1f8fa92e8ffa9996e", - "0a08d1f9c9b6a610bc4947c0155511d4e87855456feb4928dc4648c16b8cf939a312a2b07fb5dcf8f6548581e9eaa65f8882767aeac50ab9851a8f1a7ab20cd056", - "0a007eb0a412f9885f27b52c86a26bfa25a94b5ca035249c63d43174c0c741de57c0f11b88f9c931e9ea40fea661bdfcb9240b82ec2db9a7f9b2976ad588dd34ed", - "0b08ff6b8e08306913ab93c377035f9adef34197168deeb5e029928720bec79e32f55ea2f7f804f560c401ab9faaeb684defca6f61ce65afdf6a1565daff5bb43f", - "0b030a4d78f1029d8b933db5afabed358b5a8b0637fabf33f39a736e82b00d48ca11f003b1b6ea1e056809627c7b0df43984d3dedee9b805fd551ea63fbf3f14f8", - "0a084fd670c42259b38ab380d152c1a5020ce3b2fcb3f6f8c474ed8ffdc3d81eaf29f86f302b838780b6b3544478720dd2f1106be4edf5b0f5d19e6bbda8973ca8", - "0b053359edaac6a57bdb15bd82e1cd645156c2416960df187c9f67535d0d76ed61ceb0f5b4eae7abad738f643fcda86aa52a38f623590bfc50235efe9068cc4160", - "0b020eef2e6baf09a8db78333d815e3d4f622e27e248a14f01177ce4f7eb65f4905e19b97449e87d5c8eb4b3bb48cd3559a627291595f7bc0504110ae1dcfa52a4", - "0a023aba1dcfda3213a35e4e4c26192f3ab522c0fe08c6fa937a95b39ca26164d853c9fc0238f53c9f31098e934bc5bce11a1177e12fe5bbec2477afa0afb6ea9b", - "0b00f5aea41e3097f07a9c42909e25fc8721d653dd1321f921f0db67dfbfdfbbc6ea8b21669c43663705aa18703dca0a7850a4e3cdf3cbec5a09dd5e1de05bc273", - "0a055d7d62b5d7d10ad620a45ede9afa927a8a09730a7098b4ae3637abd582f2673f878cdaf27ada06b39542ce2b06c3ef964009ed050e5d0057db2fc51895dc31", - "0b0654373a9996fe46d5f50598fe327247434e029e9fd1ae144caffadb7721dfbf6824ea3134a05cf2e57aa83ec2531ebc309a1e3aa123da9ef0b0084398ccab22", - "0b01eaefd2905f62a97cb1d15aefe041e8e938fa6390f7e6dc86d73f70e9c9ea066a00712ea37cba0c055193a08f04542386cb29723f9c619607b7bac51e0dbf28", - "0b006a67559f7e50ca51e2b04666800425bef92bb364db4d0ddb58053fb6168f24022c9b30558ca233a51cb641485c89c58efc7989d334036ca20ddf9806eb84aa", - "0b01c3f8e1bd60f05234de0e79c9eed7b30c356b7516c1b254829135c7532bb6790d35b11e8495458b91b4bc1d88d754ea9beaa01908804853044dadf3d12effa2", - "0a08692163654ec035bf57a5fc50dc5a579db191ce5d1d7513d4ab629ddecf6f99bc31e828d6f8f499ad95b4c9498f452f3bb3ee536a0ac33e38e2fba15b11e6d2", - "0a0707fc1cfb3ea9a8882244b77e5f524d00351eff4a39101b78d0f896dc450e6f72833517dae0f69df8767509fe11f38691e9c0abef153e905c70602c36e017eb", - "0a04b7be1f037bc70b7bc782c429af0c89dfe47b27ba32650f7b198e26f60fd6b69d1db571931d96f92c258978f6b0dbdf63b46a93d15a6346fa0d7ebf10c9b855", - "0b0061bf5d41f33d96357bec85c5a76b1b527085b3415ffe1fd83b1226f7b05bf1ad1bc5eb44dcdeb3cb06d73af2b513cd1c4161ab1a9a14e3803d6208cf2b42c4", - "0b0891614056993489c2efc3691be1a5561d85ad3243bd5b50df23190d839871d700dd3f8244600e6b37823ddcca02b96487167f6d28a5584fb30d153308c89e91", - "0b09020ad2e99e3517353b183ff677691ca848718880ae2b09d493d66636f50ee19a7222b11cbd21e41d7b61d5f7f06b52ba56c6d354ce819ea816b2cc0aaed8b1", - "0b024058b98e5895cf67980336f932b93ee534631b2951e41efdcd9313d2eeb2c5bc557ebab8369286036c53beec2ee2d71298805839a3f743e96598b2bb998582", - "0a05cf85085e5a2a6e882095e9036d0c95ca1f9d27db73fbee531771b426d43b545588e16fc4220243ed90b5349e94889135445760dd79b4a96d0f0d89aaba905e", - "0b02eb5f1b623b89d1c5c0b50f31ea09537e0030523c03326aa7e093376f902df8851f0dfa1694daea7faebfac45ec3189eeb8d957d583566b8f06592c29aed5b9", - "0b07a63d8b9102af508b0c3929d70c8c0a5c4ca011bc560721fde405a51189a9324d935f306f91a18b948d41851786e84f618ffc96dacef1735f1e6811fadfee77", - "0a02026df7e3ec02033f408cdee8afb08135d6d9db9e5c86f23ce11ca937811919645031394f53023cd36d0b993e7b4d85c35b9245138ca4532f58d4a8cb516b11", - "0b04bd87a773efb4012acee49ac9ab568b5a61e894979099ec3d4f670c17f1acf511fa6d0e946bf37bfbe5a051d99498f814337f02be465a4c4442f7745518a032", - "0a074492337e745530c703618f8bd484d1256dab6ab0ed660f4d25df5fe775c586518e8dd519577bab5e65247f2408a1fa406c107ab3ba7e3285eb0908bc10e203", - "0a04c03872b16772f6be2a4901a9dce448b502bdb3515a5990012553fe44f8d12c703723243261fff8174f6a59d0cb218252b724bfd6c93617d51d4a4f1e5af9e6", - "0a047f5d80d15b913cd8bff54e9c2bafacb4839567d53b0dfb1b33f0014f99f73fee43fa2988a3ebf82a7571432a085cd17040e4ae89b727094535759bf69a6951", - "0b06e57e11ae5de427f0d97b44db45bf7bbc702b3db084c1527efd0e9a869c02b1ed1dbfa4b9f5addb59e5ce898a0b3feaa9b6f5998ee39b744e4f61e4678633bc", - "0a020a5c462847227666a51ddded98ef93ed59b9c8f11ed48a81e31f6d0ae1218ba6dd95248fde4e6f7c1cb823715dce5509d9c5722bbf0a98d4e4d079696a301d", - "0a004b838b2ea13a8741c455137e465914dd51814bafffd9b84e13f84bdf38fdc64c0c1ba1cb297c7ea4597dffdcf135f8948f57befe7693d7132da335bf38c752", - "0b00bbd4bb551013e192bc2380d19c23147c51f863e61bfb3459b49fd6221b2295e9c963363163f2ae99631eb1ea2d0037d066a4810813ce98696bf9423f26530c", - "0b068f1ee8657b4019eadcc6c8ce7ee05c7a7f30eb298d65612899b1921520e54cf04484787d35bc44af0f683965b10c4c9e2c58b448207aa1b30a8ef0c702fb3d", - "0b00c428515001182cd465da973122fb9b5a488dceff6879ff0fb08e9d7faa49a286a789a2e2aa62f8cb029fb8643aa2a7d4ddd58afe8cb7df4e999a65a9096b7f", - "0b05d3fa67c6a76c66b1388738861e7618af3ae9ce219b3b811eecb09a4d7907d39ae40aab1cd36f4d311ef9f4be5c736e4904a3d5b41ac83c06daf69d8584d567", - "0a02d07e918307dcc1f5a1717d68f6ddc14211c404768258fc9027a9741bfeaf3939b3ea8a89904e20830dcf42d3d2f903ff0ae7d1a3303943a4780806e54cf96d", - "0b01f2267580952713aa905935af906c57d89046d4b2f268f1fd6ce5394f4fee06dd2b594d2e7fd07c3ecce48b5379111d4bf413d4b0e705da451c6165b22351d5", - "0a006712212b32154f31a7ba37b64f32cb1e628f84604ff61983ef1a23d207bf1891aba62cb872932bbcc6c83d524dda230a59dfa564c28d2a320523ccdf03e485", - "0b084cc4f9a8e02c816371e25615a55c13701b8eb3f35b83b7cf8b62d2d05251a32cce7e26b7461aae524db6905330169a2b563ebcd52c5f46bdb9faf330da2417", - "0b00b3e22dc67bacb3a1cfc674638982dbf5c34afd4d681dc13826f02bc0b62afa58699cb63e5af65c1bfc11947cdff133d5901cd2e42134f13e7a52174494b5bd", - "0a061a082388af7a93130a184c4d2889c10bde6861859fb392c386d784ec9d5691a49fea8979affccd8fa9d95b72fddddfc9f26b886fc004c736b0ebdfc7684e34", - "0b09111c7c730a42c4d71eed4ecfdeb29ea6511a37d2a2a989243aa99a00144f81f39cca94446c781130a3e3fecde93aef11e03dfac772e68ca2129efeacb5329a", - "0b08781071abb9ed1e78cb563857744612f43d0b613d22db85b518eb37380d3b50764877d0efb0a1081e11cc4b3859950baa39e721d9216c7a96b9ff24a110322c", - "0a017446bfbe5318d823a6eafa733525c5ce1e886f9403cefaee565e15789e13b944ac3a6b8605f6b0b0b4814ac78ab325cf7a5f78c1c884bdc387a5910bbf6e71", - "0b081b219786fadc8423cd5b427d933f7da5a6500e2095f86686ef148e872eb42c9fe90aad486859b395b587959d5b6b80e927286541930629fe3a707f11f4a1dc", - "0a087f9af01f80eb72eaebdfc295558fa35ca16a77b30e11262ceaead4bb3e8e14dc398a9712a80823211e95cbed5c9159d524203b182781eabbc8c454504d126e", - "0a06dd27459274bdd99a723bc78eceabba61703cd43f1d3b391f6a9409267e30efd9fe1f585d17737cd46f733172e07fa9438ce9b81e5c5bcb3178de3bd1a06f05", - "0b0013ad7fe0a437ccd896f7a368742aeb8e9610c2d328f5f0c9dc06297536129779610e108402fab4d3624614772757105d9625b99a32276a4b23f6d2389b193c", - "0a03c3206d4f86cdcc2b0bafde6c5ff82c11faaf814aa90a56ab94028e0b02893be71b778227e527173bd0bcdd7c6257b67e3dee73137a625ebe9f7064a70d15c8", - "0a01b3efe31267e3e748a8178178dc45c4c2b841200743ccfa79a4d1305ad95c4f9d4565944f57bc5018736426b637d039bfaf6d7ad6285753f257a16276a42174", - "0a06f7fb8425d12e0ba8250c67abe8806702a058120e1a80f08656de612199a590203be05916c80ab7911360209efa306f3e7bcaf1131258cb89ba32bb9ef6c765", - "0b082caec723212d4d9a3172a9d91f962a1813f06402b5461c70c19cbc62e56107be9f8d0ba0cfa1f752890b4061823fa7723e4a5c94bdba7dd4c48964e2a684bc", - "0b01516703a7ebc7432906dfdf31affc2fe6eed1ee77f4eaf85286acbe017d287fe0fda2ee2a183e571fbd2c90e9c8a9fa319b35f8cf1625664efaa1db9a074e9e", - "0b08c52ba472455534660d3f7457f8febf379fa4493962c268639aeeb63e94e696ee3e6c752dab8eee2315f1abb8d6be4c81fe9ae2b99362ab5f22819baff98131", - "0b00714bbf138a291748f49be7ea0a3bfefeace60b3fb0ececa2611375e6af81a149ac170d691ec2f9b5c6ec6b9431962c17bc1d75512def862a98b074994a6f28", - "0a067d27c85905c30d9237705bc5cccbb52e722c17a9cdc64c4cd009f342dd51f7b2e52fdae4784e5f5df87bf29b004b32a4426d259164332ad28a5012254486fc", - "0b0886610cf376c6046bbc6255d06fa424db94d38c8934f3c7c98ee2e3acf2c7a55857ed312bf239ad065835ec00b37bbed74998610f4e1bedb20d59de0d00d8a6", - "0a08249349f9c156a52fb0c10d887595e2758d631fe406f17fcc4647174631bb26da63c5bee08d534abbd4b77a617fe675ac19aa952f5b7240ab9f079932274842", - "0a080b3056f945252a5005f0ddd9ec052a7b20cda6989a52b5d6333bd3cfaaf786ca74a937c9dc899b6066c095f1962251392fc63428af0c04a6b0c13b73b3860c", - "0a02982c0fd1d79ddb5ce825fbaaffab5aef6073531bbe6929ca22ada222eea1a71a218ec53192af5edb3c6f7368d09fcf94eb681e959f54801063ec0761da109b", - "0a07dcaf01f2e2fe5dac1008b8d8f75d0c8d210e029548fdeb39b8e0452ea2988019e254f3404efc98f1db95347cfddd4e06522d5cd6ea5b6682d0d5ec365cfe8a", - "0a07a3612bd946af15abbc18b0652962b6a6c8a645740743896450dc6847bbf0191874bec7795ef7b4458bc2b759d42cb44d327f45c99e49e046551cbc1244d3f6", - "0a07cecf70a0f78c770cedad9591dbd9fff55545954847d21489fe2e21731f7a2778385b6e96af323c987d9ca7a23e922b450d69be974990f7ffd399e7062de307", - "0a089f1d95ba349425321e7d59db0a5bfd854b3906e2854f09b0082b36c74c48885f614d7f68adac7554e1d92f85f633f036e93dcae64e67fcd11e89a14db200dc", - "0b08af0afebe62eb75c2ccdca33448f270a5ef8c8a062ec53e2e9ad24808bfb4eab92c1fb3d013d2d9c18b1aa9889299394768490ff8035cdae189fbbb90ad1b9e", - "0a00105929bb27d3b0862fa5ecdee2b720b77bd0e3e3d244ca1111d90f38b7d119c8f4bd696031643216a7017810a030c6bb1df57f650b03fd50774a74e7e316e5", - "0a02ae9ddd4ac7b922bb8e372f0701d3edf5902bc1549ae147ddd9f8a917a7db91c101185de63bf0b81402688474403a5547c0c63b58b6176b36730ecc1559fe7a", - "0b01b4b066a0d00de4dee14c1d9fb62095a67042eb7e305c578f788310a601bc1e87bb06780550f14b4af9073a7b1d519a81b3d353177d6e55ea865746a232e9fc", - "0a0137015cb0e487cf3bc5861d332f9b69ce2941eb07b5defe2a4338bffec7ac21e3d78bbe95b3cbb54ca2de559fcaed9d64f3e16409580dc2ae2df35390d63b43", - "0a02d5ba4fdef65be14e86e5967c90e716842fd17237f9a6bf1e01549145cedf60700352348ceb74343709247980b9c68169aac4cb2c5dcd1f3634ca3f14be8a0a", - "0b00c3464aa43ea583dbd45c0bd6040a09391fa17bf4cb2c5a8b42a2cc561cc159d28cf6e0d8c78568743765516611e358a50af5aaaac658bee5b23d94dbbae594", - "0a06a9d03f9a55ef10acc0088427f4101a9c34c46173c6785e55bd9fb15782aef3ff5da7d53810e375923e770952f091ae1a7b526b71784092ec9559f6887c48df", - "0b03d12cd9eafdeaa86ff612f05c4c4d82243317939008fc02e2f4e88a2dc2e40b5cef04b53da7d78c42cae38d5883b3edda64f4a16557d9531c5eaa7b3020301d", - "0b013bd5beeb415f4222ce9b4bdfd0e118d1abbfa82531d2a27b0cc39987d211440f29d4f1414fe0b73bc4dab817d4f577daba7e396de80de3c6de7faa7a1929b8", - "0b02109943af59141994705d5f600540dee4eea45b630c15be595c4e91941670969982c76b47bfc2dccc6abbcb671c8a3b80603e63f2b614c06d306baca6b7c15c", - "0a02a6ec11138fed9d81132da2c400e1a78bf4b7e1689364758221de075b4aeb4aca72a34c88fdbbad54162ced6833c073ff860843c0b3b52358cee38c9703fd1d", - "0a017137f9ae7a03dcb7a4dd21dbdf67978a47e10aec036f407fcb34dacd9a5ecbaf15eef28498caf0ef9542dae6b92ed91d390036b7a875b846a700297e2c9424", - "0b057b69261814e3b5df4d4cb189ac909af092962e6168bf2c144f47ed64e44ad744659e73e84f390ebd2371be8c2bbc9646f20f9aebcac8008c692c7371ff8919", - "0a02b0737ff645b78743601802bd6777d34c0636ecd38531af3f8496a40438e2da710cca09c895032dfe07c6ed9958f986c4f98da33d9b7e17fe60f5d2e16dd512", - "0a01a5fdfc8fad13d6524cfcaaf65e2893ac91c4b9293fa51edff0dbfce8da871b7d5e1ebc53f05c6564299b207126b65a50405d905b57103a76d98da8368db1d5", - "0b00a4aacb7d8ab988f0abbb9ce4d520d7eba3b65010778fcef87378d4231d683b5afdeb74ae1253e0398182b9de0ff869f39f48a4401937cb5942c57994803cd0", - "0b0611fe18672052a312655ac72cb8a91ab18dbfa955fbf7f9e9377035fb1b69c46d7e07fad9a68c8cfef4622a170635aea92b4859107db286bb152b40f355f94d", - "0a059f8e2a8eb4b6276a47ad87c189d06c6d7161d9f853bd302e41411f8d2db2fd05431e53c948c7a029a588a68dd1ac7cf264da2f677798f567cdb27c7fbe9134", - "0a06a1ee5a4c0e3ef7c603115311aee22de238b47ee5ba17b0a6ed8325da0883432bb6275c1c33647150bd9b866dc4d1233d5bddcd4f792a833bf20cc5bb11852e", - "0b03de952e97880b686dd508464d6138f4b2f9d05cc6178e3031c4194ac66e4adc135d2024ea66b8ff5c39af2a8e6306a97a60cf2f8a3742d57311b6bf6907870a", - "0a029297186107c653767bbf3320be12665f075013899b242bcb8e37e9a306d3d56f1df4243644b5ae1a3535199deaf45915728f3bfe712e76cb9bd39837b5fce7", - "0a0745b58e6df598cd61bebbb0eada0dacf6ebbb4b9a47780d19dcc9052a7b9d1dc827a0a3a87018378cd30f20f3c2463f9b0efb584588671df4ed2216cb7c64e3", - "0b090fe36f3ba900b086e07f36cd39d4be3bd00369067779e134d6d9a26ee3c0feb930a251d10b662eb18e7c78275f49487af2854ce00519c0bd56c653a9427245", - "0a090d9d8615c5eb567a4d17aae0f2ecc4d55dc298ec05a9c6f2764a9408c7a0aaf04883593cd673b14038907fccdb668f0cdaf9936323e6382ab7378a71dc3b28", - "0a01b21aa58c77ed0751ad76cc64ca7d1fc7de0b6e7043592c4d63e43efb1a6a79033490904fd3fd41edb9a23eae5cbd5affeaa8c41c2902b26ff652da0b9d1eec", - "0a0096233e11605c37ab78e5d91fae2ed703534d0c594f425a3a57120621937c856c9b99ddfed16bf3a33e4de28144bd5485e8fbe6efe28675831007de0d3cd738", - "0b07e924c512fff3a48276c0176d719ae1343e5e8f0c68e96dababa428f1f57da44b08549a0c9010fef38be133a453fea1c7e5a416c1f9f0344358b0307c564ec9", - "0a07d5b38df8b480f80aa9d3b1cfb72232072169f6bda400baf26cb892639a04e7ded378a2cb19295a9a32b0a6098e54efeeccb39a9fa6b93610c50e12162e11f5", - "0b03e98092a6a6eef5d8b255a8933bf49f118ab3275b4db89ed7163d2ab98ef44debf418160ffde4b835bf508c66901bbef3307cc38565ae28afd961e709d84848", - "0a01d8b39333908c38b15672ee22b54bdd573e94362a7476870efc224092ba582ba705c763a93b42530a48b6dccefc0f083571a66dade3ba9c556a456b0fcde294", - "0a06806401197b9a7edf4ad821ebb1f7c5fc69b3c9a37d4c384249f4888b82f12424be197d97daad71baf44c6fb94479bcf2a8010a5c337001a49f47820b48b635", - "0a04bad46c7817eb19127d4658adb6acdb8a995896481745f9293ba1d9def5ddb41e1c7221d68e094b11bafcd0cbc159d6ab25c373df82580624250460b1ba5f3e", - "0b06c254c1c66476e41740ef573529ee3c78ffa908bf10f8063f4baef06bc4dda587ac979399a10b793c5f92c21ea393439a588b6c4960c76ee69fe7c7827edbc0", - "0b01d0728ac99a082992be104661698a589590bbc46cb1be0cbbe72f84a0a7b62ce7b373e11293f728cb5885e795b092f53d134da5677193e14a6023a7fdbb47c4", - "0b061ab4e4ad5b4f0301646aa494e42e7551772334f102c5db26029aae10276d89a5c6cf44c3bb612a7922f15d153897e3b5a58e1be403c95f3b779c2ab104a6ad", - "0a055bdd5ce5f8ebe983763f3aace6ac2fd7c4b063727598f35758dd6af5e19d0cffc8ceaf299cf06564305a00e2e990f9bd52719c433ba0c22c86147f215e8f05", - "0b02482f3e19c1aeec9179c831aa2ad2eb1a7a7e504db218078dc1647cce4f77c1cf486c2749aae59dcc299b619bc351715b127814bb0466e918ebdbbe37df7aa1", - "0a0874a819065eaa8a1b768564351ed5e33481158c7bb5826423b57b82d6d77c4ce23e6d5857564b9644c0bc9cf0700778adfad2b191a72bc439f22493090540d8", - "0a056652bf8f02f1938660d60ed05dd7b5af326bb91deed1193d2df2a4556da885b6ded8a3c3abf87100b607f0d6003bdd03c3b06571a6af8696ecc3078a63ec67", - "0a04c2622a32f6629be0178991a18a4d55dda278a8a9b2c5f8129ede5363f4a59c6db8c8f6d83a44f7e60324846d677e218ed4c091c6ba0cb41c611814309b3c1c", - "0b07c886961899c778bcaac1963e3d5d7ec214e33fc6d52d7cf32e36e2affc7af3fcfc704a422eb19092aef1c3c42ce57127cfb704ecf7dc79f7fb7b33a396b5d7", - "0a023d31397b501722d058c9a7655004f87051edd8fd3ae861020de8e2225fcd1826ea9b8411498e93295c03ea20e6f0a791699a0187355ec998502ea844bad269", - "0b023d9fa2fc8b21b0c639b524c069c908211f20303dd6271649ebd59925117fdefa35526ebc727da58ce31990440004c845d5162db1d1549609de233dfa239dce", - "0b05cb78e446ce47fe7f7c39dca9892b4b78c7ec62017f08e2f4c5e327083a39859cc97ff2f6d5467410f2f78c57158ab8776310929b2e148a3b5aeac43fa4b9c5", - "0b079bcc655446d438290bfc07a1956312664c88dde3ce8dc7066073a671dfc53a2e0025408ffbb21ae27a3c63cb41411a388c20e5d34cae5cbdc67b524a09e1ed", - "0b022736063ae030a2dd8cfdfadfab1b675ce52ceec1704984f23fd8bfa733ab59f20c88b61f2faa1d02d093a22f9f790c6ee2bba3150ca1ff7ab23f209ccaa85f", - "0a08acd0e0d5278b9f776027207c9d2fde14681d29e5c2fea55eac108910378147640d9c8708f8c7c3ecd27df7fa8256287ef0dfbe9c65e588116b57708bbb7780", - "0a01be3f2c7e7666559e3c11ea821e2c8d69a7553100e590974d164e950c5d8e3d59d8f5ae2c0d90de776fb544fb616a60c4ec6e2f33b858f0b0a40301a1007d3b", - "0b054ac7817ca8b4528ea696c943747b461175cb7ec106e44aa858d5fccf4592114ddba7aedf84c65f1075604c38bf59d265857a0d90c2aacf79b9d990611c86f9", - "0a05275464299fdadfe2704d3b0dbe10903cc4fc5c1b08294dbd3107e0a59501720fcb4c0a50468f85a79b95c330cf3bd384323c8c74ad9840440b5dd276bfeaee", - "0a05217d6c6cffe122705a955877fe0588f0162c482c2b502647b00a997f467bcfab5a5c5edbb807610a72446da129023eefea29ee644c04f61f30985223d69e6c", - "0a00f554b3298ce191698d94b80147d777f065574a4f3bf9e7db854765a68446d9a17b9916ec9c0a810ac82f6b54aaa2699fa2d66d999aa4be5d16a02c9f8ca701", - "0b01ccf0bb85376affd9a6d0c75a93ded5c1f3f8081c8ead2cda40f8835eae9edc4222fe35d48fbd49647c39f255f139850e2aef7dba8e69be829a0057c2173ca2", - "0a084ac128f61c5bcd6ca3054a01cdee77d7f895ec914bd5c8d76de38be17dd14a1a2f7f11deea3333771896e16434798d0c75025f4c2b11c154902cbbbff0608f", - "0b034073733725cf03c0450fa64e021d8f3f777aa7687a30d52bc8a441114dd953329fb30bded8d70b68fd9d623abf5603dc0dd9609fde91b4ea29b0c3024633dd", - "0a0539802d2becf86f390e46cbb0c2e985362995a49838c573baacbbbbedcbcbfd360f5663ebd2871734f97293e5024927d3e104554f87f06319a68e0e87da82d1", - "0b04efb3d297afa3fee933d0e978c7809bd9f4a4be2c5c12abbb94d086774a2a68c3512e1b09421b1951e244794650493344a79988484340eed40b09550ae73cd4", - "0b00ed4d84943098e45850d6492fc6262724b737f24eae1cf6ba0b9b216e02616703e70fa871750e781f3236b23e863a6a36af2f8601f5e2ab315be53b93291c3c", - "0b02b9e86cc5f7061cae1781d011e3a29cead682e79eac54da9c8052c3c3733b0978eb84a561025bc8f20edd4c67ddad2a16a2b2fd5e490d79472376b1fbd6b4c5", - "0b029ea56120640f70c0cb0397d1598e6752ddb160a8458bcdb4a8ab49cd4973a30dd51ffc2b34098f2c8e786e8af51e3857dd4c801c89acca52c290d2d9c60557", - "0a047d14e042a45dae14d982b0a0ab2861570047236d0d534e2104d1c50bf3dfc3c221c28620269634945c3751adddc41dcc7aeaf115a5f5cce55e2a76d0ce1916", - "0b008006355459e8f0614d034e6d285acaa6bd167a58cc8a5e9510cb70d0f5c2722d679609cf05b845b9669b4122828a64cca6830cba48a6756bfa6562666bed9b", - "0b0594d48a2a0b5538a0d20892ab7372574e52d485a990cc19097c876d2e5dfef87e0d93cf8f032bc2e1a04ccd527468d62728887c5215a58ed9b9f7a2bc9f8169", - "0b055c81005980be926777ab5a2af5e85419b9a915336eb4d41cdad26260355370c1201cdbe8ebfa8d5b0c2fbca9598b280d5775286d8ddb2bd9ac3936fb73a30f", - "0b03bedf590669f0be241a5b77479cf5bc045f35af18e43a50bd19ed9a03be12e85b4d32d0662e42aa959cb878ee65b65b8a8786500c260ea9cd97e2c5ddd06753", - "0b0771fc90f0e662bf3ef87bfd7725faefbc8941d989e40823fd427038d55055b2bd676349f6f9e22dcfd4b401d4f2df8a0a72cda9dfac9539f7605f544e76ad09", - "0b02637de8c90c50dbd6809b7881399f6edda826aa70075cf22ff6e136e866936cd3d013af48f54db30876f460bdc2fbebf8418fa73cd95bc11824a20c65cbe02b", - "0a02ea21f9614490c1ae5bbcf6811f3e9b9b664321f826f2faa5f8a10dacf1d61c63e8bfd0c3c87e8c5624c8968459cecc74260f473bcbe8aa3fefa5a6a85957b8", - "0a014ebb96d190d97aebfdcfe3fa536b47d46d85ffec1f04d696260cfdacd558b9094d02c4106066077d062594cfa87e8b7f34c32af0945df6bd88d0defc0aa37a", - "0a049b9f0f08ec7ec8054cd046f9a4aceba2cc22b9f9c79ed04d9c246fcbb4e354a1bdab97f7bf81e9e9c13875737e6e07b0347a7976250a697ab4b3f7e81e2b85", - "0a05ea48d880096896a116ede2150ef2c73c9e1ec135f030f5f7050040a5aef71982132531071f6b44d94a25e348ac0b579eaf020793e36df7884923897b7f9d38", - "0b079a11c8301514e82ae4fdad30d2f10f568d22554242eed2452c06660ada467cab6f847cda67df724a32637d30a40c50789dd7de75bd9d2fc435d3ca1ddbcc62", - "0b026390f29664de63b8d02a7fc408b7c07b4c1867d46a013ba0450c4f228de81a8c0e6ce01221125761016c5231f0544e2435aa50103457ca035bf7c9cfe9eac8", - "0b0108032352bba313a9052c5161943a19a74ac1c69a18d4284c84ae66ca990a195573505a961c19e43a992dd615a7a5d8834b59ff7fcb15050456c80490f89765", - "0b07f7bbf8fe3516697678ec96b75cab82418a300aa47ec1363e98e18d94d8eb3c19e615d54f50cd72c98df35579764c8c44b2d836d5c7e2f9bbe27fada01fa8ab", - "0b08ce304002a408f507ad1a007168173abf90d5c570d4282f89df46501d985924f12cf92baa19c89508f676c1d94a72426d0a1c37bdf40727df0bba78eb03cf57", - "0a008ba3774d987b54c60fdbd0d2cf103d1345d3062bb591234c86f901daae724683d2ae8b963087f15802f811347fa8aa4e9d067a637c7ec53a6dafa3d61f4baf", - "0b027e9d67be015fb0f9ae567ed42d3c5e1c0845a2abd98056f06b40e21818bbddf8b958a23d3c19aa40cc9c809256bbf3fa9cc61500bb5b4f5359d8a0afe7d5d3", - "0a0215c2812c1b588e34cdfe155308a500d6683bb7a6436179a10b8b6b495ef90ac0a08381ba1c8538364ab69c3b9c4b9a0c8c7c090d80d1769a09b922176d0866", - "0b078539846874208bfbf0418b190d379dcf7ff335e3f3f3cf45d12a727ebf06efcc8593017f1cc4ac56efb3fd12791650ef817b2e12fe2192f5271b93fc6f5d4e", - "0a019354830843b3c7d7f2f6312e753cc42b831a779caab3ce010129e66d485cc5e1fa1565b1b4d6a9622922c7ded4be2712226d59656d9dc354cfbe215a4a7c95", - "0a055424983bb860b0bd86f1b50135474238d15c3fb5c5e3f6c6e2bf5bce41b243917d258672b32b9c4ed8b1d81a099958755ff65633dd898bb1ed8adb32e0205e", - "0a069dd0e1588edf0c6119131cf6d29a2976a4fd03367d6951cec79ed700733abe367603c21a6efcdab457ca39b4a68962e3729ed20676a64260064518444e9462", - "0b066377a7b9995dbade7cfd0af7ec1113c4c9fefa6e1f8cb945a51f9bae50afc78ce930fad508f376849170737c1bffa46aaa2fc70bf15c8249bc63a5136a8741", - "0b006e3e4b5549be663e67ab0894592f1bdd54c0d6ba046ad4e983daa694be7cc57145b10b6ac431437bb442bb93aa61b3b89e3953ac25b8c9732ded880b514112", - "0b022685e0182fef27751622f3353718837ff125f45a433198e62e075492478b397ac1c9cb93d92e000a087c0079c1f7a0d6c8f705b31c4937906ad75fe9b908b1", - "0a05b476bc912f7c03c781f3e887c20b653cc2b8377fd67d7c74a1e45013eea4fc889522f2aa5ffda4b75e7a3935b3cddc6cbc5eac2b21cc0ef24857a9f8701e19", - "0a07f29f921e7a76d642706bcb1e11dd6b7cb142e72ff03f964744b3eaa87cb22c7d6462988378a49731646bad25ee1a3d9718f1e30d3d022176ac1d10936c2c2f", - "0b08cec86582d8dedb3c710220b8babaf06af738a03bbe264d41970250ef8197c5f2fb9345a36bbee3eeb42c5af5f19c7c34c3a16782bd29fb2c5946bc2b851ab5", - "0a0277936e5a71050ee1df7f6e5db92fd0d9a4fcf13cc6e3f9ef5d469519203ef5d29b86b2855fb7e7aae78a788565ba149ee430eadc0dced361941b1d61ae3182", - "0b038b784a9b184041c034c7ab8128cc78f3a229ddff09f0f86e42211d657fd8705a6969d13075da2676aa7db7eef42dd8ba9b1d20f3af7da0b891bac326f490e3", - "0b0887b8e2c8cde7c0d8cec9feb3d85373b26bfb9aaa9ee0c2ca0a6534a728ee5caf2143abd6b2bf167cdb0b90395415da2c8a485f20adc175009f66581c6ebd06", - "0b05882f679e8323134aec2e3f5ee2f95aadb0d2615f3a9330bcc66a54a560b88fc58933bd41ee279d57ecd05f988cbc6475cf63937df17bcf5d1e9f789525b4f4", - "0a00056a7bc1859ca00994ad1cc5e5551bf1e613b8e73e53711b0a4d8cc1a0ab1d0cb593657736790951e6e789f69763aef24bedd1a0ecd29fbf7b2e72ad27c234", - "0b015513f507be29bd096baba871d33ebb8505057dcc8815e0204352dcaef8cf37043aa9a55fca61c2377683c7b9beb2e0af57f134918e4a606659dad659d2a4dc", - "0a0442113df6fa264b76ae64318c8dc181bfe260cc8942e09ba136863a42c53aa9bcd6319cc15aa11285470e2ff3eb69a9d70a09047069099b2a1a5983d66061d3", - "0a08907d8ad821d7f51c147c7f7a39bf98ed75179cda2f4eec62f1703b0d911a32e2a0f7534a16069c99a562bcda6fdd8eb4aa2639c6d760768bd155ad4df21862", - "0a0596a0e58dbbb68a4122e8d1ca59b510af988c2199d92138d030dbcc3a2288bd930e2dfb4e2740866e7a04b713775754bc454ccdd65350ac016b14c41dabaad2", - "0a029830569ffcda67617e8002005b1a52e3e97aeb8684d17695b4bed82a87078e1ef998c551f378e9b1cea768290223636b78a01a464e2d68e45433c6fef55794", - "0b02ae47d2eb6942020f2da078f565445ca3122b343f46fe4f97b3d36a3c70a94c295fda87e5beddfb7bb5acf5924e355b8b2691b5bc5c71f39703a947c991fb4e", - "0b056856a7bb58557d5743e7c30d218e7862eb8bb57ca0c7481400405d21ee61f246a6baa19b5120deda182f7a700ff2d03e365fb42330b490dfd83b4fe136fb2b", - "0a000cd58b42dc77e277cbe9ba41d840fd3915ad9c3cb84d14830c36525e8cf74ac61bb5c2e1c9824794a18512707a2342a59a2ade762e61dbda72e9f9ab4114ad", - "0a02ae906f1d2cb241de0e36587c5e9927d34404b4338d121b6aecd3411e4646373bf4294dd14801eb84109dba2c35c9d5cd9d49dc744ae2d570b2017add1c21d1", - "0b0880300365cd8a5e30ba477a7f919461e3be88cba78ad994acb69de47e1eadaeb2936831108c939c5fec0028cea75620936007d947d81965afd8deb1bc4bfb33", - "0b068b8c8f665122741d0e97cb88cb23edcbfa9e954dfa4daf999d7f0fdeb90adfe50aeb24c9a22604eb93ba49391cef9d5e871860c4fa18d511ffe8f6aa1791d3", - "0b029863dc2abcfcf483a40826ca19d95224795d4cc29033a3e741c0116496abe6ae9a609d9799bc8afb0be7ee370663283e4b5984d78874521b1ec4f637c96162", - "0a01c153718fda490b9b2e09ddc19b031adf49524a0bdb9faf375bf694b3e20c28c439a2a35472d381ffc482811e8223920131d2a37dad9b83cb4a1992b4e08853", - "0a03f88d27bef26ce0e5f6cee40f416c792a0ec370cc3e21ce08146d35a4cab208ff3ec64495b7ca2ce2c5df7b9be0926e4c91d0e7abc7e2821e7ec0ad48427e6c", - "0a08074289b6379cbadce27977c3f8e476f892d0d8a54f4d5b22117bdd06bd36791567fe91b1cfbe3c2c2ad5239975836ef52c2fc0e4314aa7ec35c4f4f09f086a", - "0a06753513cac42215b4cddc26f6507b3ad53dbc12f25d4cfe0549b85010abf20c2b31062d82bd1d0538fa18d458b30f9d2cd065b8ca98ff2816b65d7a1f07923a", - "0a033779ef864f14efb643806ce02f910bf152fdf7185ba78da66d02d5629fc9ac7b0ef05c638751d635c083817a1ce9103bb404881d597fab5dda71ed93272833", - "0a0097292ee168647b088cc6c036bf6174fce22a6b242a9979a3f94ab883ddcbf6f543547f3577c361aae5ee92bac0a20f0724270a6bd104f54b6667371938ebf5", - "0a06ba1af6f82f49b63bbc5df94152263e8fcfa9f025f58a8f70040976869acd01436137d28c1a6031250c5f22abd7c8dacac8b9b9c48d1ce85a3951c068365436", - "0a02dfee40d194a9e3263ee515d442d0dce473401a6ab2ad355c85697e09118709a444337eb73a10f306a0eff569c922f5a22eaf13f40f1c1956660d573cf75961", - "0b008b078552a15328f0b0beba37d17210c85a55fca4ef997630cb76ca9da07298c420d364d3f50b2184d4bdad4d9582a5c2bd5860309b186485cd256e517cfaac", - "0a062d4eba882c02a1329aa65fe410dc6438a0e8df388b2672f1e7f3f114f0123975bac571ee35c348e7b2bbfc5e8da0913f91d2a6886ac720204ac3bb3c94e999", - "0b043363579165044052e9be8e2a8067b1237e6775598b8a3753164f49cf9a63dfaf2e8eed48c220213c7b1a7bbe48d5899354d3d9cac4bb29912eee813d200ccf", - "0b00abfd20d50f370a78297803b2ba115a44fb70ad9f9d83cdf518b3b0d2d1ff3ba5ff5affff301581dff41c69e3222af1e9539a85e0e55c408b5b3ff3b388b170", - "0a05dbc9dce4920932e8e1be9fe184f053e32972dcc5d43b7f456029ad5ef2cb39f98ff5cea7d5849cbe281c510ee4c60f10de01124789a12de70f69a34fea368c", - "0a083b44d21b471dfb44b53c3bdb549406ef63730a6a53863b03b4f2d4fa66a3c531e07241df7610835a6c90e8c22f0b8bb840e11c72a2e916251a5f066bdaa962", - "0b08bc2487d0f7029eb3b0862af640475102bcc65395810f48de046e1c04dbaa115b2168c0fe7dc0cdae0b003178f6d8b71622f9276b43a302088c895d95ab3553", - "0b00529254cdacd3a2a03c1e189d8ba166fd2fe5858b546fa8f0a867b469f773312004f46aaca8578469ba6d49b631b8bc7ae0a4f4ca2ed37d0ff72da620e565e2", - "0b054b4c4c78f40598c1152b625010d1723e3f03cb38ad2faaee2faa4b0b62eeb9cec10fc56990874008cb76dcaee9bb3c43c31f599483f1d5f4c000618697f17d", - "0a04e2c9beacf39c974b122d16d1606025a546dd5d6d9a546b1aa44f017f3e1ea1cdcdd335dd28c280f69beb8783d865d60104747bbc1eb93c6c5b943505aefc6e", - "0b011ee0f62aa69adc12758f1cfc05410330b14a043f1e671c85e997d48bf4269ddd4ba8133fb1fa6c1aae949537f23b9ab4cbb03f496e3fb81956b99fb3a47e0b", - "0b01478c64e91af96415925bc719e6105f86915f6529686a8c28aa92eb47191ff92b244dc82819d4fc215d3c46c70b9c5477c9af9d77c996af2f2f25ccccd75dbb", - "0a08e9d3a10b7bfa26a63a2aa79c1e1c2f8dd5c3b205c49157e1da38bec383626effd9ac140e8b47e7139bceb7f0bed2d35cd09a5c4d2f937767c3f75e43273b63", - "0a082423d1b083fa48bde0506a355fd0a8f2aa7b0c3079f1fa564b248fce308f8b0522038e118b0c21251d94b283b2b97d3d08bf490dad60759031955f8572c10e", - "0a08a2e130918b1b079e645d67f29efc64a12eb39574c8f7a90cb60c39f9782592dd26567cee7b9ab95994b8d2972bb5ddd5356c77489cebf24b7723a2af145cb5", - "0b063d740e4b84885c3a75bcf174736fd95f9d4772fb212d6454970b819ef6f1052db5c888b763739812afadd3b33e32536130aa1da85436b38f35b403f72ae921", - "0b08a30e1ff32cf54f3ed4571bb35bfb5949305d49b451f9be82634ab455f810a7a188918fecd002718df05957c189212673ee2dc7a3c1d73798feb3b2b4ccdbab", - "0b06e552eaf13eca5ec620847a167174925d56925a9cd069da022c60e4a15d2008f8a2538fb9d181d933ec1f2c40c3df11e1b2cb2363514ffe2b54f2c822c4f208", - "0b0799447ad76a06bd8883f91bb4785a6f9d703b8a217149867943db9ff57c7eaade099220c5109a059e8ddc8df8232930dc54e3ce0fad55d7b46c688588355cc0", - "0a05edca882bcb29f7251e9ac337519572ce32bea5c0e86c19b31ee96086d5820d5d8b1b7d888e5a2f8dab598a90fc77acd5e27fc7e4f7189cc7c038df2977ab72", - "0b05f3c7d11a742f6581fe76dedc922690d52fa26417596718695d96d2568c2c425e921e254424400c3732eebd314bd30e7eac697652fe952da55f0346e90c279d", - "0a02f190c5f8dc04b3088ab3d08633ee0e6f970b627bf4e6e58a76f754feeaf305c859e2d78221556c22e0646cc2ae495563c481bb55ad42285003116e960deeb5", - "0b0007aa7b4ac806b7fa15ce4e5393ecb968510fe370b86bc1ffd50762220702837c8f1f833f675fd445f33d67e395444d1abff8e2d6202165e2867147c7c4fb9a", - "0a022ba1ece39c88c9cf3052db010db5e506d7ed42bfda0fb209aa81617db58b1c3efc849ad1dd18ba6184b2240c6c3630f3e46d5477a10028a7688bca13c56341", - "0b00fbd6d7c220ff1b6abaddef37e3e31f6bb99733214e0b748f27e8ee77aacbcfdc0caf55f803a52bde1a4d01cd7e97accda67aa9455849c8c2f1f938f60070db", - "0a0179e612198af4e628ca94a4bd3ebfc941b5e0a1a5a951460635a98e59beb8287a6194db6ba5603ce44c7aa87af3837c436c7fab4f8da1b1f8d1f367dc248ebb", - "0b0865a7eb2cbc8529a1b97ce7b0ca23a212d4390ae4ea67d2cfe2f4e3b169ae5eca37746c1aaabcd0417f3a7492f30b2005253703cb4e8cdf218ae548fff4f843", - "0a08d2920854961aab55be072785d5ea31d6932051c89da2fdfa25bbaafd0c333eeb84ff3c0a4c76cab07dca3712467d1227ff4b8ac2b684dde626588e49487bd5", - "0b0914c4961ea6e849bafa590bfe5900dd0c76905eb7111839961e1d8836ce90440e995e0cc17b08618794798839a753d9cc70bf6718de48d86dcada483fbce38b", - "0a08d49178d0fff6fc024c7bc3d1523024739118f7754f303a7be54487ff1bde91e0c46ee358fea4369b6a28bacbffe65c3562be20dad6bc5e90c10f30adbde456", - "0b03bd00aae5dcaa975e3703077a3528ac2153ea3d9bc69d10dbe9e7e495fac8d3a066143f436e97eb0f9687c104cd5e5d0ed4f7c2c6c0d07bb12fa612cc9c0daa", - "0b0860276ad820f675822e1cfed769dcc2e2797e2cc2b67f4d1368c0ea75d112dc5f6f186dbdbf853858ede3f80ec25b5d540938c47a3b6bcfd28d7dc081fae9ed", - "0a046a965c08f930980347ed12536b73a66edf7276752a2053ab088b5a4a4035d31d46a247b36718966cf4f2b30c09567a39c9a2d9ab1f30fb9c2bfadb6fcf4f1b", - "0a06bfaac4fef7e7c52932ecccb9c64ab3233fe2083f1328f8e4ad59a8d1d15245186d6fe9ced09ea9fce592c766c8c1b4c367cb50defe4092296b87efbff246ba", - "0b0229afa92a0c13517bad4d25c862130effee181ce510666a8982fd1f7ed03414dd51e79f0314bef1e4d6208976e0ec2b59a91f0e2d13456192c4314942a227fc", - "0b06c8fee796b9b7ae9055573e43b74844ad28f138c450241463b50f7e1c206b890185709da9385b86d28e0be72dfc9fcd3ce4b6bc2d7ef86402b15d6d0374af93", - "0b084c4a4338cdff4dbd1e50b9efb17b0080b872f4c8c2260b95dde926e5cfed279c7364bc0c2221ef657b66270e13942e5fa9f2e20ab1cbe5c60938dadee49abb", - "0b015b3a98f675afc4ae0270723264feb2770273b18bd52057550991adb96ab71c47059cf3a7e91c7e2dae4850e5b8e9239600b90dc2e654d64b38394ae5f7163d", - "0a02dfbb3debf353b62541a6f0347311aa7d1327812d5ab9adc8afc54a9cf4d3d24cef7d44f99cd0442b99789bf0001b9a3cd2b2fefbaf85598979df5c70fb552e", - "0b0770b5fee28258ffc8ad89bd16f4ec0e9dcd10554136c25f7f48b97eecbabbbbac0765b6c0634fdf8bbc6d3dd349edb2cf933327cfbc56328d95b8f8a129434d", - "0a022dc15808c2eaaca0c647794efb5a9521a6a25612e9d98fef17031f5257c62c8575261858c8ec3dc80b94e2b93bbe33cf270618111523758ab44ac504960aad", - "0b068ce444f97a0236b75c5a628d5f95631f9c2affb60808d88df46488d92ebbfbcf594f69bb4563d83d33b99a76f349c7dc1dab22c7819cb6501acce97f463bc2", - "0b06008260ee0102f574ef6daa8832f73b9bab37a3710aad61a32d473556c4570636bac269a0b82faaac1fcbc20245465287f1467a4c7f793d745dada52f7422b4", - "0a0786583088ac287021212dcd77ab80d13dc38b5c36f7030a58aa76cf03a74cb4955f34d4920b312714339ac325f8a92e86cfc9ffa349d705f8123820803f6e48", - "0a04fbd23ff986c0e0759d1073a65b6cbdf30370e2dc3d4ee1ba193e92af202a73aacf1ceff4f3b3e78d56887ce15aeae5683115d2dff4a5bafa99648f825d29a9", - "0b089749338e84d16f83c12665f2e64f3e79e41ebeb1d94f36a1f1e6a2ff0d8bb72c3cb85070285086c3d2fbbdfee5e5de6714f2afd3bfdd6d9503a05ed0a77ae1", - "0a027ba96afb05411a6f5ee738c09850b5908eca1b3e22b22a1e6038f802970bffc2164ad71e7040f5a92f8668953961662fbd2262dff2c9cc394107deed214b78", - "0b0022e0dfeb7f0e44c6355b5c54457f7fb2f0e70fa6ed5c80ae2402073b1108528d008e5f7a4c33d3bfe7bfd1e87e432e605afa1166fca4a403b6bdd81d81e2e1", - "0a005ffa76367966abbe106807f194323598dab72d7c238f6f177249008b84dfdc58e3b0f681a9413d313311d760fdf6f0da3daff42887d426d21dc4dfb56e55ea", - "0a02b5c98b473d9a150ca2611a62fc25264c403ed9d116405e0b1367040a8a9fb582f40fec0d52f1f199295119ad533443fb274e977b6b62bd08c1799ec413e42a", - "0b0376019bfeabd10d238bd6565369a84b068058ab11d33c0140c94261c22d1dd06dd6707363ff909a58b4b292dd91b650580ff04042dd54759f7f15b3e46fad3c", - "0a00e25ea3f1faafb79617b70a3ded2ed07122fc5a451baa9ecab26ead4722ed1f66942c54b3e74c0610dcccad79dd19940e56152fa304aa0e6801d1a23fb90276", - "0b0615d9d560a9daffa5e472a7c503a44cc47d5188c26c90816c8c2ae835887c0c1a3f17c00ab45346317ef0179207743117493a4243220336fd50093105f0159e", - "0b07265fe306fd627100152d87099ba68203f727abcf78ad1b4a67e960d23c0cb1bf5b9a1f19e6dba0e5d897f35940c691e290ff0f4528637e75dfe2315f2a94a2", - "0a06b454dbbff640f0ef16f77fc5dcf0c866b5e1d8bb6740c019772ce8412921ffb2cb20a28666dfddbaf3e05cbd6efd2b012a2e0e81b757a84891d7017e151e02", - "0b03f5c8a13e9b6579aa2fda9f6badc97a5af720cbfab180407ebca54eb05874d434daf476524aeed7ea4d7978da9960c688c4c21fc081baf4054117d31d13b885", - "0b0605065532e8b337e04240a21c4f938592440d1a47c86f06da78ad1ae373f6a22d8b81e40c56eb54dd16828acaa334a2ec0ea9f3b87894a5619f28b500d7af52", - "0a041858582ea3df3bc53146dcfb6fb93f2f480bb8526139b558a5ed4bfae326395d1e891e91a5d6919587daa2e7d27b511228e6668aa222a36f9eb200ce85d249", - "0a0718201480fdec3085ba9d09baa595d11670db6370b6e864f78e0124fe5374aa12d210f5915030fb0cbb1ff1de15d5168f6c4010b03ea2a188e35e5ef9a654b2", - "0a06f1e6eda34d059997cf606623f5a4cdc35656e6921e47fe34e86dab77729dfb52e38255614a12d30be806bcb585fb858ba630923f6c57b66b81f0fc3c816086", - "0a03d5e7bc2cfad4b3ba47c3eb9a0d08d7c536893dcb9756ff9f0400635a92bad28c412f8a1d7f249714129745610d130c7d0325807062a2db7e425af720362e38", - "0a02a6030c71fb2a73c71f13b1e01e46109feac720f2ecae9586e59d84da08b40c839d574bcebd2285c1c2e16166a291b1b511d75fef1c09377e6300cddb0c9278", - "0b018be6ed051dbd3d290dc776e43c1c52f58ce6c869c43f8caa2a191765c1139be5a53d3425d02fa7a753b12acc58e61e99078838f7657f0b234414ce61924724", - "0b043b07ec83aeb1a92ed6d611338a47d57bba85ee3d1877f518fc32e0d5009c2da80bd41e6c9b445897bad078867130e581a36342f6963653f2b318710de4a738", - "0b04c2623433c16027e9014a4f6eb874d99d91eb298eb90a56848e9197ef6835c3d6279ac7e0edf48307dc2db076ad81abd8e07d9f8f96bb50e0f164f1b4861d6a", - "0b060a52afc6aa7a9d4534c212667a1b48fc0393fb709da6d536278c20f08b0b5996eae51869cb2e3c55587f90f63a8cb18852285f8de03316c64014ab046e3a8e", - "0a0631314e467b606ae6baa798b0591ee41df0da417e20f11ac75868fb6f3a5e413db210b9a428152df4e2858b1381392a2bc24312ce19dc92e97e8e7fe01837dd", - "0a057d055bdbc045fdadc54a72af985e9e8e444460c2a454d56fc0a5790d6af69609ea1272b0d41840f40dcb701c13542400b7ea0e399a43750444de583ef0df82", - "0a04f6c4d23bef1c917a5624dcb60aad0489231fcbcda06689102fb864d6b4ffc303662f00ab523b94fb6dd8ad4c985745ad89a7f8bc99700c0818279d8c66e467", - "0b08312a2b9b8ddbaa6fc7f4910850ac75b511f23851df49d176d9a26f2923116034a49cd6ebd1f050614282adf8265907ff9653011a35fa7163c4cd671f58d3bb", - "0b03114b1b4d32e34509a530b1c74722375e81809f84663dd4005f613452a2f3242f37c2f2446e53d49077cd42db984214a38d30808df7dc7c56a45a3da441382f", - "0a08777d72cff9004a22e97854ef3f01f460895b79b3f164cf25c3fe876c0bbb72a6425e01dd9926e6fb6a9ba8e5739f7305ef54696cac66f81771e8d6bcd7bf61", - "0a0858ebbb9141691e22e78cd345b13ef26c891469f561a1581b0ef0746f4120f96333b40fa753af71ee533227a53f3f9c733ae01c82356fda3bbb3560269e4416", - "0a046f0ac6e5d59a9f2a55979a3c05520bfcbaa433a1bf1250c632010ac0b29ded8b6fcd8f77835cf92495360ddb73f2300613e7a90cc8949b09fbb183c35e6881", - "0b065f4f08e14e73a5a3be68586ac0bc0f11366f24c07bd5c95d00950ed0cfd07cd84da562ac56998c7da12673d337a853f139da788f109b7f25b4f412a7f96b8b", - "0b08c8611dcd4a4709d259075a17f6643adeb16cf2ad49ca7d594045ded1edd06858e520fcbb8163c0bfe9d6a9d5ad2a68b6f2a39b1fc329a1c8f37b2ddb5be27e", - "0a05a292afba7a51d82092ce008c09859431febf160e8b76fba5d8161739e7295068a61b09c095ccfa5d691970f2fdca88146496cff41fa258c4980e0d4d2d4382", - "0b003325b8cf99882493451fcc45348153f09bc7da404b5d714c768e2854921cd74fa2cdefe13558bad7a8f2b2b20ff81f767341b97020e3e79c6072b33742d1c3", - "0b016041c8d6344eee0004e08b905721a21002b323b027e8f0dd4686fa5e8b9dce6cc1acb12aff4172e9d3953b57a2763b529b348499204c45bdefe7e5584a0c6f", - "0b0765b37228c47f5b5268c52f2dc2c99a692a0928b2f13f896c9f788fe3f530fd1952a4a6e91f83a6a272553228d92d01927a8195841643580097b519e5befa2e", - "0a000997dd46c7c7b15620997db8efcf3e7d4701a73b61a5fe39b3a9d4af7e5275aba9b2d7e974fbd5d2f14303749e5da1d087a92e6c52ab6974c761c76a0757f1", - "0b0861456cf520b6979f330faa87da9d8b95c87fcc9cd45e4cfd67758b636613626c93240e5a4cd79487d8c770a1c397d0833bcf2bb7e19ebe476568e9e289ab3f", - "0b019a60626769338a801619278845b8d83c9e58b416e6a7f669cde86a17fe6f474c91cb2b28867e10b6a93f5f9660d31c70a283b2ef3ad115692755267faca130", - "0a03cddfa40f3b23607477a2a237e0e31614292366a1f6e3ede871dbad8a319aae4f9d2bfc20928b9c739c8a66fd6444162f2a2865b21652336cb11a5ecfdacc9a", - "0a074db4a17063604d77036c14841aff54327284ca5aecaa2eaefe3709782f38e7eb8bf7d45448a714b43cae3750e5407a8d30cbc7e327677b786c529049965648", - "0b002b8a9c4dbccb3a88af825eb7383fc05cb2129082af4ed6bfe6ad907465df11fe6a2f83ab65d0dc5e619685d17923cd62823dfb379bf741fd00a60f256a1b90", - "0b04cce8685e424a14422e91f6d9da584db6567392a87f43cbb0d2e3e286fd923a56e3020722d8b34e75dac0538e69eaa3b63a3530da634dfe68e5def6a318a1c8", - "0b03a4ac9f44380b3e1bf6c205100ed92b5478a4db1b2aeea35f3d774e5dcccff0cf3bb59564135f2faf3e7c6e824b69f823b592a8be5781dc3903219fc866d478", - "0b04da4201caa3677817a5806500cc210a999b2f8a42164557e80dc17203564d90261be75b534a6e8b3a93eed70f99dd766e6ce1c99c82ff9fd4c1335ad53d00b8", - "0a01daac67db5998c513c0ccf9ec5b49941609e56e8eb8aecda0109cecc2980756bc37b41272298f0beca6ee093c8adfe5ef53a8524792504fffad26a4e9317a5b", - "0b0205af264a0379a0af63118e33dfd3ace1394397c6fff778bfc8bf3281357904366c107f8238774c7dc6252f0ee729c5f325b06ea320717b36f74e3aa3425d63", - "0a010335accc79d572ec13d22c808bd57441e6c21d064f41513a222aff29fbd70a89544abc9a30677d2da00389271a91a3126c15867742baf14a7f668fa5970331", - "0b0744b23b71870f6699ca22fcb174905df7346b8acced8f5837166a6f4fadbd4dde52812cf452752b6dd68a863c3eef9f00ef2ba42733b1b9a409045291fffc8e", - "0b003376329fd9a2b7362f2fa21854bcddfaf174247adfdb04b1fe75c6486aebc4f8cf72dd669ea41318cdc1cffd5acc49b37919932d6ac8329c89f862744f9a9d", - "0a04acf72e16c12d19950d8f352d4e7d8ce887325371b37229e0781510ff228b55ab4d10c41f57a1d861492f89a9c0c10cf87ff40e8da6ab2ed2a81faac0ae1c6d", - "0b00ac213ce44f509be933446e1dd66e4d818d4f5a77b89ed6d0f060b05d2d01475c4704d8daa1d1f4ae8dd9c26beaebab6f740342d2b619cbb4d30a91bd0434f2", - "0a01a057ed8171fc862de5da2395671a4cf718d9c11c51692c40e2c0e542c22c3968ba0e888a4a7b0b46309d9514bc9da409d7b5e2748739f179ed578b16eb7ef6", - "0a04b8964e360aa3839030e371affe088c4a3e1ecc285147aed37f2ac617a4e9db5e434403e9ee4c1febb4191934375e10c4d1e000af3d1960b4941ef7177abb3c", - "0a0073174b55c70b478d6f7d3abb29b819530108a4fbd17da44fde4a0f446a89ae5b4845470413560915d9054298c8a114166efbc1299082cbd3bc81528079cad5", - "0b04c13563b6546a3991dc92a268810e81fbf67f93906f8bb5e3eec1c40a2e249475bb6d344facdbebb6a7c6768d106dc0be3f28f661f1bf84f3121ddb44acfce0", - "0a02248d12a2193584d1b1bcbbd4cccb16958a35375b50b3d64b9fa451aded2a3a7afefa4d7dec20b68d7355481f9cb8630d4539fb2d687fb973aaef1cc6ef5220", - "0b037ae491871a5532a3434205cb427cfc2d81c2547b19914437e6797a19f83e6a51666f39be1681d8701790421d6d880d39f60bb3773709c9dffdabd67ae26833", - "0b07f98b71e1e58c7c411d418cf7598512a57b3db11bd0272b00897f8974f68a2dc79b7c59ecf327abfce0cd30019006dd0e0959d1b4cb10d1e086658cd90c9bc1", - "0a01a03e1cdc26923d6e0456a8fac4d484bf79ecc15b5adfba65baaccbeadc3b4bf72004e14704c7be453cb099aba8bf227ed0b7277aa264d4bf55ddbe1210a2fb", - "0a0726f64e20535540086a66b1fa766ec3ba44888d4aa39c52c4621d8456635c7c415c9c679d6083ce41d9c009b9f28ebfa0d3b07963cdecf3abbaa2388d719636", - "0a012c435826db21c5479877cdc002eee0b9e8fcb68ce2a0b498f8719f9da07bf39fe9bcdee71b2e9e825fd580ef188e1072b94304024af4c185021e47109afb2e", - "0a05ba59014f507f91218f0a37a2390643062a1a6090ee0cf1b62fbe81b568e8b8d60b46475e7546fd9c8cb68193d6cf05c33a9b817547b2bcfc7b9a2ea0fec610", - "0a0548b3ac49748b893dce2083da58ba46ad6ada76f708ed515e5520db2ab11f31db06bb0545f7acb487da747d478b065a3fd10d4b4aac1b1618eeb987d69e56a0", - "0a07368a3cbaf68e475640fd5e95a47f45901c3d8212d4c9f61e56c4ca7b7f92d772614962b3806d692b66d22f01a7e2f7a2faabcae61e2fb051502e3069dc8be9", - "0b08468eb8bfd6273a5b6798885f9ece6474f15e0a8cb46b8135be4d4fac8f380ca8f6fead41e8c9c2c6ff4e0aa71f72979880ad7572a2328a3166eed7e7028fd3", - "0a025f05ea486ed1cef0819963b2069394809a4a568a54998411ae964ae940ee8b9cd211fabd29d4f82142ccca7abe7a4ae99dd9e9ad3dcb326f4c1ff20abd199f", - "0a02f8c953988390c89451c39b5d40f24ff1b70f9446a0d9302e3f2863ec6210d42b1d0db848a8ff3da6a78ec633a59e2fae0c8fa2ca19e7201c629a3d822ef9fc", - "0a014b2f02565bc487b36b3c3a1195565fc2461dc59a4ea1130f77032552cd00eed249b0d2fa470b8fc1254907dee1d362b3b21d9c487db9f0a5cc7f6aca7fe3e7", - "0b069c05d6bd4bb9813c02e64fd5c5c8cfd88c6bb78a6fc837ef56952ca4fee1a12a32d5be67361d3ad2ea92c37d1f1a97d416486988ee04ef9a790712cdbae64c", - "0b003a919361d3a29f1943b47c092dc8188755ee1d47465a599bc2191c56d27586c19ea6288111287de2e55b942f9ea99f4566eb1c6baef597a1ff96906cdf4925", - "0b04c2ac769e369ee7d9cd6512b9e71c31cbf39eb8bbf7f66e9e0c29db1e08f50efa68f41d8257096f4c4e7493f5f44b6c054391b4289952b16ee288c47c48b4eb", - "0a05e32e21e617e655e96a795586c056544db1fee0041d9d9d38f27171b0177402a9d19f991d87ff3e205f157b86a7ce1ec19dace1e9166dfbe52048d6d171c0b0", - "0a02ee9165b467eb004a6a34cccb1a06a92861e52a83eccc0807a8206cf75211d456474c272d4942a8fb6aae91cf150d6fa899a4f238d4f7d75abe1bc1dbbdba98", - "0a02ef5b7a2b2c236339ff710212d31ac7e70da21385063ddab44429dbc194cbef17677d4139594f322522be24eba0ffe86c6ac82f796cd1b0ab42dfd01818b75d", - "0b0815e4faf3f2de2bbf4157542d16c8eb772a1ae17cbe856a17c4f4a8490a06112e8a7738a2636b4151f95772dc8d73d2a4eacba2901c8ce74e71f2317d27bad0", - "0b027fb7bb41ec453a3e187544b9ad6653ffe65307a9a82ed57d89c2ffa57171f7a6ab424403e066690d619603107c6995d66d23fdfb57af110cbd997b9274b445", - "0b0759a8456fdd485ee7a5d599ffea8188ccbbcc1fdbd6152c7749ed481920fb549bdeab075153d12177a7f99d9673148dad6187cec23525bbe07af0b343d25921", - "0a012124acb4f145f4ddb724886882738824e4cff26b06baa78165fbc8db3e669a971971a98ce8e61e93c68859d5d3bfe335251f456f4339001913464f1f61e30d", - "0a079d02d5d51a814a984f12fc5693181ca92a70d4dea3ae9c0813f5c6fbe75eb45078277be4a08e9d96355d25991ad8288a16d359a4f5041acc58b35b1610de4f", - "0a00eaffe55c98ef5c9bb05489e5616357e29b30fc60e6ab3cfcfff969402edb0f9fbb026ce85ba3d054a00e09eed5bd97053977327b491d560b367f906fe815a6", - "0a04e379bd730b725cf8158617380d95f6b0f31c0f8b7ff3935219ba7c03f1aed265ad7551cec82e0fc70daccafb0db2ea957a3b951c81b4f2c65c05ebd0b0df04", - "0b06d85f294dd2f1296e58af9f89f7637dd6958360e5a527f3713f6c40d65fa186033941d863ec6e55a5f935f3e76ee3e878541a236d08a822d652595c0c1e6f4b", - "0a02a116787e4ee335ad87132285232b2e860d45913305dcbb5fbef78f82fb7b16e347a62c2751368d6737a11e621014a8c2d69d93ae829e6c66cd12bfdc3cf0e1", - "0a00170091d602a740dae84613c003e8e0a1541c303c90644504b1f7b2e0e70b6a72420ffcc9ef48a2c136116b51cd8aaa2ac589b5f289ba5e40a012a29d868901", - "0b06ee659b45dd16dbbb4150266ee50a4be4f253c6eb166214a16f90fa978b9d24f19e20258d2049b576473babb001494f4e93dab91f476b1dfe965506d9fc5564", - "0a055759dbfee37479eaf9908336ab18e696ef1e80203d345a2778aa74d1891f76982a83e1bc1f82c306b03c4f124c67486d381474edf5d041e4169edff6f78a20", - "0b0594b78b283f7e96a75753c00d9e8f43404120347bca7a51cbd4978ba628ff1dc9be86939e50eaa2b63df8034f2770c5711556c9bd332e9cb49632bddb8d9e2c", - "0b00035e5504145cc7c6cec7e6599a6b0b876c0855f178f833ea683b689c7444c997c73b2d4e5e6d95319e6a02c9caedf58485a278638c7425520afb234c3af143", - "0a07028eb1be626c5b8fff6158ee9aa8dc1a5455fbf84ed4fb48a71c9d888e79861d9e686462a3c93bf97b2cd36df1fdeb63afa8bd0b9e7a4f5dbe6a07df072017", - "0a00ea19af4b0773760312697583cb7f35d22f31083f57d361a55f85dd083fa012eb3ca2bfb3b3b6a374dbcbd55dba761cd2af09e4286509723a86666cf3affd00", - "0b06f0964dfdc0dbf877fb8a7766df5a13206544f2929972749dac2d8678d1840b485329014062fc870b6f4b557fb517e97fb1254d046e5cc4bd73dbcf8ba18d5f", - "0b0019c17f09b9c6aa0aeb1abafbf13f11674e853fbc4fcbbc6d0cac1eef60b5e0abf2afe92579417b76c570f40999d92cecd735b77ecf097db6461b4dc75cf5f6", - "0a04da95a62c33e1359c4d99ba2d4ea1eb972864aef667bffff3a1ea4cd2027786b9d22e815df1f14b17af5d4320dafc607343a0a43ff48c1cebb56a550c9d99b6", - "0b080c9a3edb5bd6a08cde7ac970d47b116d258c818926d482ba2c0f7d8b4d17f5949b9f4b7b8c090e1f58d55b3bf06d4c996c0cfb7cd9a560ebc985326bef72b7", - "0b01d63c5ef78c44f709214a1c52cfdd6cb2c485b9f71ff53250d582f9788abeb2192bfd51f97be1fb61b7c2b64e41d038c3b821fe47f8451ff7209231b1e348b0", - "0b06ca670ad520747a55d4320d32a6f9fa6336225d092a342aad1c01b691cd0a88d58e418f492da03ab45735ebaf8233187c2ddfd1af401be8080b0e814afb38af", - "0a00abe0531e0a79f3ec026ce6724eef2c894f440cb625314e7f9ca374a2a7e52af4a79df2c1048592921a832a35e46f3a23341f9cc335e0d49397d79300100f04", - "0b02cb8f1e5c70222be20c8d882ffe9866714e52f11ab85a2fc2bb9375573be41f2e487fae85506ed1cea4042f000502f36b13fac0c818b9759a0a2c2308ec4f61", - "0b04daa58d5e4fef10fc61d82aa22fe4c09e1aff27d19a6746ba9c67381ef0aa5b60c97895e2aebe7104f38b3a4a035edc88b5f5b9364f80751781a199478d7d05", - "0b076143c7854620be7ce01e0e13078fb9af3db52142b5390838f0fb5fb4c099f6768e2417505ab399f84a3b0541a3deae4ba2c1f0106855237f228b4e7fd25c7b", - "0a062e0fd02c9989823fbadcb7457295d1c58a6f24f048447c8f61964665be3d7025a54264b67b97b658af4f6223c171dda029f97bf995685271846ad057ac47e6", - "0b06209a017e339068c44ff753fd4b5735bf7d493e9d27b4b261a8992e3ce8e044c08341b65a4f9f26d6605d9d359af6ffdfd88a2f3fc7cd9d42668adb763fbc06", - "0b014e9ce5acc318102a0c2de00d2d21507ecfa6d93bdb2cdb22a8cd3c58f49f9012d482cab906737930e8e24b7ea07af1d7376d86a85875779ff16504923c2a7e", - "0b04fe94e6f51ba49e4b87150b35bfce261833c3bfd57f1a6c14af59fae78b7c8d84880c4821384d1eec9857b284a078c5753d5ee35115d6ec748a0d6200ec45b2", - "0a052c8dacb1a949a6719cc59bc9d8698d97d98cd820dc369cae9c4fa222de067822ed6b8ce6cb7586062889c5f101bdd89ebc235e0a4d6598598707437a0b1cff", - "0b003b216a0b7c17e6e4ae069f3382907cae83985f6599967b1841ab62aa09e9379cb83a79f76a05573cf03f91a78a2d02cd2705923b31a8f3a585acfaf824eb25", - "0a04221189fc37fab5fd39b9c1e5d0b9a8124ce4dee23bc1eaf4c7f175641415c43bf634bc1b758f9eaf6251db07ba87db11068358b07300484f6de28f3c388084", - "0a0066afd2b825c9a3dcec88a44897c4d9e2749f0e8e3b7a539a1cf82731feeac227728b0abed7e82bd9fb060a07ddae3e0ae80bd1a8b34de4155dc877126ba880", - "0a076bbfa0d94a62ecda85d90b37e0fec99698f5426568249aadf7358ea7a2d0ae8eb31069f847e1f867a7b0baf0ad4ee048b65c73fd9dfce1ffff3811b8b89cc4", - "0a07bfac4d8c405a7188f44440fc4517f32c8607641d2137fd045519bf210d5a90c2e5ad43a4cfc079ed792efb560e1c9b93523a00310512a229b75ca58ae5ed75", - "0b014153c392507dd1bd314337a41fe67785e21745c11c5e0b1a6ae25eb945e6c33fc2f3370a795a3d72d17af09e44c9cfcedf791bb5744ee02e18eac85849965c", - "0a090c826e75ce00f04059581b16bca42c778816c3e7c151f525cdb4d52263eae036a5114eff66378a50598ae1b3aed6720ef4e66acc8118bbe3391fb24476c71e", - "0b029351e67f09e5f0ed5d67e432bba1f50925e3984f69d9859b103822bdfab82868310cd70db71a8f66c7247ed81bdc9da72ac7bd09561012d80e9a5e5e3952e8", - "0a07d7b7533f5f63978cba8b21ff7d335e2fac7845b659098ec3c004cb5aea3baa9498df8c59d54608ad40c1edca4c0275635ff7c18d52f4ae4e58dec1b0f7fe62", - "0b01fb74b67d38725247ea30b0f5d374ec3f60a9720dd17c42dd5b1a394d36c179b94ab25793a99d778adca4df955659d5d99eae709d6bd0eafc630d4e21aa4b18", - "0b06fa9c5b3369d843d50b37a1c2f81ec7b6b5801f4f795b38e9691b06b7784d9a57cd0f7d44448423b5819d6db18743d8f5c3b8dfa581643d38359d9e29748cc4", - "0a0668ebb4ef58bad5ec3397edb32f6bf6f6c4a18f3420018549ca854001c818d943bceb44c21b4c3b00f087f321b5f1b9c9af510ab79d0616928821c6aa95fcc6", - "0a00541747de5c2919da325a34121562d3f2f615ae5bc6951710f4ff0e635ee496d69e8768a1a7ed8f310d4dd0792e47136fe0eff7bac8dac5dd22bf447161f4f7", - "0a00ae07109dbeedd979bd8f2be028225c7d2ce050865e6b83acca609016c77fb94841531db0d4658e6095641efff58eabb1d49f9582fd0b643605ba81372cd7d5", - "0b02cb803ea4c5b008852f0549b423e9fcaf92bbf42829e9a335b798f9e11c913920b694070514e4c9574472a5bdf4e40014ac6e09c442004916356215e1325dfa", - "0a04f9127d542985a272d3afd16ebf5abd22b728168600e7d4fcb64fc59580043b131600944c1536a04ab835beb241d680e612054f70eee31ac1c5fce823cdd9cb", - "0b05ef752f7d4d4914c72084f43c922442fe43d965cf7ca4b199d4a6ded08c03fb6e577f2223d808f167c7f6aa60ec697b11d7d21096f8c8245acfdbec0a8d5599", - "0b07abe6d101a8033ae726c054c5aa1da3dab1c4ef9a36cc8052c1764029b32627fce42c09e25cf1a4db307fb44bd7d7c70636574ec477130deac3e9a811aa73c1", - "0a082de5f129904718f85e887abf131a833a20445f0f07b699676b4c66b3164cf22ad158b81c811b119da6b294af968e48ffe715c8a1e893d588d8fa2cdfcdd1e5", - "0b063c438664c1f4115a73f517be715aeb55547689d49527dd4e1a578e7a7442f2125e4b66b2d67171f64986d94472e93fbe449f3fe9a9dda7d53eca05686b2f1d", - "0a0149e33ebb0c78b1328ce3d7d52aef9c808bae800f68ede6a8b3140cd20c2308c2caa27bcf821dd80cd39c7b70deb6c7a1b50d1079edfb100fe30b5fd7ad6764", - "0a00055dc8d66c8341613dda82dc48f7f39bd43bdd2102ba9e7dd922f82446223de0b203a24cb9fd5db1e9e27a23eaf95ee4d2cb4881e204c26d568f4aed4a9b40", - "0a026316de1ab64fbe596fa4287e382f70317da088e70b5fc60abe5f4ab2bc2ae609ae797a34b41a7f69d8987ff8ace6d61ad58a50847aa9d006646a839fb5e7f0", - "0a056a95a6b61ac02ed79d16f044d28d788c677867f440072c3754f85c2b7956f5fa933cd33cf2ab5441235e1fc45680f67795c02d8fa13e3b4f013ac876974199", - "0b0123e76b73b9d0cb0fd30f8212d19f5d2ba9abed55fe5fdd0ebd4253bb69273d993de4b5f7d8a42bc13fe94cae4f2bf788f5daf748ced073f841668b39d18dc6", - "0a06d79ca0d4f790a5faafcc5fbd39c9c54ee61d64f2646685ff4d18b558e41cdaa1693d59cad8756e51d1478d4b11469ca0fe985347a0fb04e314aa4f901cbbe9", - "0b015c575833ee6aaa73f2bea9421ba698b78250e73a83ade06951756e3c105f930df1f78f34bd9024e2e4951d1aff7b25686e1e0cfb1141c5b6eab6ba3ff4ebb0", - "0a071a59a18d447930482f3a28ceb440e9f10026b7f387c65f8598331e95d4096c47b3dfbd9d759716e3377f334ac1049b1097cd94f2cec48b423c3cb3c26cf0ee", - "0a01739d83965c1ad53851c3e6a0d6ceac09c10b459a76e7b6725537597121efd1c6a328c2bba2e5bb6de9832c4588d393748f0911c7484a6f6045034837d36583", - "0a00879e5c243f798c90941c19e9b1bc369e15a095ee1a984f70776045ad5d3c6ed40ec1f50f8da57f0978c0a2d713009a02aaab58c35723638004feec29f7fa5f", - "0a070423bbd52dad57ad6737fab0e2342ae03ee19c3ebd0b7dd3e6a1604a1db433d28ffce2f09289e02fb2988da2be66320ec9588c58cfe3d865aa184103a0eba4", - "0b06fa41af7ace1fc6f483442e2359fe581264fe2ba89a102b92a9d628d5f5f98e6aa460f8ea47a80d037d1366f1b82dba5039aa8ee2e7515a1aa69e7d8eda1be8", - "0a03813ae30a01d8cecfab19263afeec6435fe85a495bd9b26ae9ef5c950c08f0a9c2e3e91dc751f77ac6babf80e74e2d12c8b32c6173def13377cad0823f67a44", - "0b04cc5bff48cbd6c129f71360694c0b4a8b5b50ed595468843f98a60956f03ebde6c26bc84ec55ed6983906cdef44910664fe5e6ec20944e44b236f42a1dfa3a2", - "0a04d8dde2f241f51a42ce36cb81977ea05bd08806990cc82e3c7726bf2e10a3d6cf5d9cade0af6797c3b66464bae9c1722863e92280a8a53f9c42be7be1e480b2", - "0a08a5727347ebdbb8887d1e2d59c2121a6cd0244e8f20b5ecdd9b807e5241a8e60f3c19f400e5be6436183ca948c5d1aa0ba910e8c1ba81c12ea8c19cac4d69c0", - "0a03916d9c19c115f5c48b0ad338cf99883091f19ee34c4e253d30e9b218c44e84a65c97d6bb8ba34a3a90dd9fa7c7e95868082c8e625fec82a5990f94fac8f1c2", - "0b024348a32b2da17e8bab611a14c5282677fda1929aa9e339a7e5f286e665eabb9e3119dda30f1c7e6d4d1f8d290696117ec777e6e9f9ff5d0ceaab21b56d4ac2", - "0a05efd0d02ff618465319801ed587733e0ec0503bd057dd7af2bf244cc2bf109e66614eec8d09b85712db1baca0cb613f7a45dda58d3bfe07f6224aec1d0762d1", - "0b027bcea421632761db69a530ef1cb390650b02f2a70c8a03a61861f82aef021b2e9266523eac8603c24c1fe1a45978b778d0f638e360b3e83c0100c4a5b43b08", - "0b0136796303dd7163cff4febd1f29cde4c0d826a63f6fd434d47a2d46e1b1eaa7609d9d0b7dd1e73abc1d660d1a86978b8472854cb8e0fa58dade88ebf501737b", - "0b0823492bc56a7bfe773d4ebbf60c38536c15ff0f2b556e672b804f12d77478337d86c6bbefe05e59504b8efc6f7aeba1717b25c08481fd8d9866cc2f6f103556", - "0a036445a3ddc8cac31c6b9d85b845d2b388ef16200a519cefdb76713d3407fd6b5a2f11aae96785719ef4d33e00b3dec2d95ab4ff4a92b95c854fc6bb7f4ebd79", - "0a0067b48b8ffdfe0039f547a81f2f0b850e3714a1d5403d08b09a6cdfd066428a709b4d121d25a9815b5bc146ed729e2b11e80ef2c61cc73e78673c863442516c", - "0a08ddd7dae83c85ac0ad2c9a99ebe7494607da0ff5ab70ebb882b6bbe0abd0099040d429d635c5dd0de3a62d93b9551594c6f258594a847b68a5487a94708f61f", - "0b007d15c5c7783bd0a8e14167af73a23bbe88835125ef96a57e2fd508e53af8fac59b5e225e3aa878c23d0d9ba086bfbe7a8383dde935311e7ed77a9c2f4a741c", - "0b03c3971ff7f0bc2a035fab17536123c8e73279cbe56c4175a48b2c3e2dce72b7102afee1e577e1d35c12d83c5ca4eef01e7864411833d3f94e49ec68d3d80ea0", - "0b01330c3f51fe47a07c975c0a3fa171a1bf95c6b4389769c67e1037bd5bfe2e53bf570ff4638a20b30d65a174827f6f1abe46db94c64e68750b9f33241e661e9e", - "0b032353c73f743659d3b1979b18db7e9ccf77cb72173bbd4d9b464005c6f00e675c511925a08577a5fa4e4c66859ee5c318b41ec871ade2ae3af8e9e53b9abfc4", - "0a06a81eb01a189b31dfec17f39f6e48a4d500084a2227240d46d1554aa3748bc8417dafa169f36bf895f53d7bb2950ac3443a3838195af57f89ef3a706d129fbb", - "0a068c37d7c6931d340c706ea2ab1031a7ac8dd569e46f7c78347073f03ca5110afb5714227ebde4ee6d06b13777bb1606e440a9f291868eb1982e0da06c37d85a", - "0a06db344f7b40a8d24e2a9ccb0ea4b733e990a56cb0ae2ecaf1723e87c90403c1bcb9cdfb47d576cc4407c2cb7f95065f14dfec9fd76d6522988b27b07774a1ab", - "0a00f2030fcde07e57c772bf8613c9b7a1d2358e712420f1ec6812e9c5144f5038852f8b06e98b576b1330bb1f541c51a2350ead89b45ef3420890d4fe061b806e", - "0a04e9b5ba225c0f7986b8b8f2668f8d57985c506289ed898d1a9bf752b214fb45f0ca896f87ca2c88747a7615bae9b9763ee5a2f8aaf76eb94ecb483994b06098", - "0a01a181f52b8515e7be5b8c688499092bb0a96e0ea454b0b64ac073ec30c3bf92655bc2a8a93c852273a5b810f3ab7f8b1117512a6eea30dbc03685da85b15ada", - "0a04cf71cb2425865e6ff7b10ff4ce58b17185895a47943fd9b592a3e859319644689d0be0d49ba4f8e9737b8ed223a58e2b9d0c6cca209d6243ad4ebe77df0943", - "0a0887b9334d9b1a450d88e5dda98e6d51cd73f438059d186c65442acc788c3bdca61d94fc4a42a44ed9a45f83109c262c9cf76db681de62b9bb28111a1a7b6b77", - "0a05489a436211d9354f94451cc12ec54d79aac935d7fea037f0f8090af65069a46d2ac3294e4d0568edbb6047d903c1f2cb05adba2c326d12d53d692f9a768d9b", - "0b0825febf0b198033984decc6ce69ff6547ef0d0966d3cc0d02c4e9d88067fb32b80ae7f414814ae8d4b62adf9c1f5e9f632c124c358a592ea8abd6e02f24dd69", - "0b00e752cae43bd592ab96913d28a3a598157561deab8cf592269060836bfa62123bdc3939548b9a4d8bcae91662147c358fd2de95aa5b6c7852b5811e35267504", - "0a03b511ef250eaa4befd1bf8458ad841a8e91b4e2c3cb01c8135ebbbf88dae206b88811d48f3845fba5db8867b7f6890cad72ca65ec6f0a43b4c0f3c8266fd478", - "0b01a3a689aad13a2b76adc4454560df7b393840295b0a868c1939c80c88964173c2b49d10f7517c150827e74486cfba640687645ca4ff13cd5d02caee1b61c373", - "0b063b3a3fa686a05539d2207e02b6ab51169fd9de94fa10853a31ed6f6c5c484c67c9ee9644c4535b3226ae8ea4cf37da539686d63f27eff386e383bdddfda75a", - "0b06d6b864c6994039c4a985c3664189e339708dce7689dd2445ed251e696e480ad31764c1223d696a69bd015f2ecf1fe310006139f1ff8e482c3c33b843ae79f6", - "0a00f263eac73f988806b7a54cbc012bdd5e60c50139c1fe70267d70dd253066146e93afe21ee09eac215fb94b089baeed46bdf2509fd885d5fea192ca976d810a", - "0a03b664ee49068b77be904459d8f73b74962cfea6e3b3d86fad0b054d7e8281120696539c0db29d904a9320996bc6f55c6c19d32d080637199ac5d2e62e209054", - "0b05982cf93694df7abcf0c06fe881d9a85378934de933144cfc67892919807ad4f522f0637090600ae5543aa1748a37e318a8974f58ed4116028998fcc325df4e", - "0a02270625e1e45a9a76b5095b60d8fa502e5d0e7462f223aa3dce727573d03b3a02a95e85086ffd930d8e183c18ad8344f664ba221ae7b1afe905f33a7afbaf3c", - "0b03a0919d2c93f6cd26f8c09e49c8b04412dd8ef5105d9b747026c9705839411074d6a5a04e9114120a0c5b23c258783188b2778f8540dbf6ce166b5030bf4ddb", - "0a00575ffef34863018f7a450ddf21a9482db07458e12b78fc2868bb630b14315b8c3f09688c9773d8206023796cc8750f2368830dd26a6ce7ddfaff3bed851438", - "0b028db32a9a901dc6c4a9e9b8563da2973d1f5c0d926564c2b354cb73c1c8585032a732ae846f2a2f602d114798d09dd5c9e800dd8d64e51d4f08769874d6e0ac", - "0b01168f0976de38fb27687dcf272cc44af74be7ab37f6b6bf96d54d6e5c66c129f95f72aad9e639ce3c8c5e002d454ee228dc32f39655711152ee1c39bba41f4c", - "0a02a4ab60590a30216503cd5f6fbf899b27a135f7c34d750ba5b28e2010516d01c693102af32137e44fe4296c01f8596ee261973d91514460ebd55c615b242bc8", - "0b047bf0fc3eb254c055351840be48ebcd87a7c04c16ef24c11237d69e7056d73e7186aa7f30cf390aef544dfc94301003da67a8dfcd705068f9697e6f293742f2", - "0a08b41dd2dc0f1672733cbb3b8b3c6b907c9af1374094911dd17f41d84b3383751e9d230af1ab50bc499cb2cdbff98f854e7b880886bf917af4a03d87b7ae930b", - "0b02f77663df5a772f45b2689572044f4756d0c7cfea5dc18789c2038ca25dd771c0ef842e71bdf1084431acadf2c0b9958d11be5db30dd16c6f0d4e0d1c4380f2", - "0a01ebc7c6ec38eeeaf3d3cf0f04e9ee757b0685852a62daa8aeda99f139b9e124d09ad2b0d469cbe3cb6dd044e5ede57547fa0d3dc5b6ecc75ae5986c94c91628", - "0b05a3e19eccc619ef5c5bf7d6a6822686db5d3af64695118ce0fa7bb1d8e262d52ee869653db67d711e5cd09e99374185abff0a2af7d53e19a43bc8c39a48017e", - "0a027104b5be110adb74bf7b39e70b12e4a4a227047263f15c2ff6920664b892383a20ec03fe16b534cf16ac439261e00f0824ba119b7ec12ba202c80b1cdc8700", - "0b056a6f8cf8d9ace82c5b9596c308e915eb9f5a7127cee97011a0681a5942505e1a19dea89369373e46711548b113420522a4f1c672dc22520032fb21575b1713", - "0a05b256c088f8321a8347bbbd626fbec47c618302858f2043fffb564af2719e94813b20a9d30476b50cfd1a76329a71575eaf8b8f776ed60ba9e23c7a6e5a1a05", - "0a0915616147b2f5539953be6ab9bb9bd246fca5930f73fdc2fc9b2383cf329db913081bf1195b73399ac51034915d4624310a61394c156d63c02144b01ea7d046", - "0b08cf8c38ba62aff849c73276835f1af2eb272d24c874f91efe7a6617c8a0b3c62cb01a14d5372f3280f071db8c0ade0b55b6cc8f3ebc772bf06df5afa24ba54b", - "0a08c52091d59086ad8fa6299645200d2b3dcf0191d398b12d61bdd00407cfeda69617e856e70b85077b2888489abbde12a704e98ebc5d158d538d4a94aa5dcbda", - "0b070e3b3b48d792cdc294e1931ef75a27d8fda25fa1b0dcc2a35a5898656893f8cafb3a8c441db08da5f93464efe2978eccdd93830e5ba859adb8f13b32f62436", - "0b03e00a353ef895cb04184795009667f532c2e484e83514631587cf69bb11203a6d67a3eedaca1dc5a3cb7838511c6486abf0ef1786f3bffee4272058de6b9973", - "0a05169bc63f45ef9ed23523686631792f4fd983503cfd8e030529053f5af5b1be9a8571e3b021169587dcca3a5024c6841c8c794d024afe7c8169b7808119680e", - "0a013fa7a185d9717c4314910e92701ebe1d662ad5e5079314ca2e01b5ab37c3f871652d088025f9d722307105d31fc47eae94dfc954cba2a55afe237088b2d3eb", - "0a04ef1547eb6761551194db7e2fba93d2fed9afb56f38fbe5b1901fcf609a16847a7ecea478ce8ed488c4aecd71a9ae64c0e05d82ef26d196cc772d4ff3410e8c", - "0b07a81be3a9680ae9eae8b225aad3765e5d6253306f9c6c952d468d3f452032265f0dc8a804f6bfe589a4c83fb6308320a6c9e418721c517d0750db6472d22b63", - "0b0046420101462b36fce958fa1f4df380273890e2494c4ac9549999f73adcd80ab4291b609e1ac3da7bb82fac6b9a0fac02e9d6e4daba941f9e297250d62e1c2e", - "0a001364873a9e4a81052cde3179a42f545513e703aae6896589b507b8420a3f391639470680a8f065efa27e375b0b3ac7352829994b9085fd426fab9a1beffe0a", - "0b016cef8d67830d2a550695f349c3dc2941630268b90d2272ac68fdccfdeabe38cb4b3ee8311862b24203e15c5e116dad57540a36d1c574d1c5f0dcdaa06d471f", - "0a08f9eb9a7d1b58db61a8c1f003809e0ecc923aeb5a27e9bf87b61bdc211a52538da1c0c9a5a258d2fd37ee3c0f5164f62e73b0764e61d6b08007d6d4a32e8b7b", - "0b05d3a4e8749c8bc5f606197452beb4441f23e914069d4965f53ec0c1d6fefe6a498e662eac91b725e737d1ef4de1918ae0414ccba317bdef35d3a900757d9cff", - "0b08b08e75701607bde57894e8a01bc6b8e329df7e3560fc20eedd863a9164281cf1afc615d53db739964107698cd3e841f8108df6b00761785f6a7d49bc4237b3", - "0b01e1ba0a888b36c063842d7e037ca90314f389eea1eb7758bf742ce4bdb89561b60fa911ac5f337e50a607865a79351ba44c0edb24e4d43dc7ff75325bbf277f", - "0b0390479e641ed767443c663aaf7d74287f03b0bfa9ad565f4c69a3f94257b7a9624ea5153cecfd51b2544400f6228fccfc8ee2aff1c553349aa7746e18a7ca0b", - "0a0184ea7f45ea8966c6f024e193b23eab7ab94a8e02be90e32f1ce4f5026d049f21323659667db5d0895808af6685c5186088bb05605903617091afc42656b4a4", - "0b038852fc91fc8eb9c10ab0e14b24130086c8e9b3698af9817e88cc434977550535671848200940c20fdee3f3aa6257a15430522d5447f1c51d9fae8fe24a5f37", - "0b07e842f50b6e4feb88ada42192ab817eb8e849144b0e3ba8347f4f9c2ac86549a73e7dde741279e0af22bb28dfcc50772bb851cf4ef22136895ecfa54a03cf90", - "0b04d272960aaffe931399c924bcac90e357b4fef8e524d72106c012649d0f3d09ff9db1ca8cd3fe39d5265c727c50061c5b0e9f616ae1e771dba0ddeac56b8c80", - "0a030be7d20ab3cc12a544019c699d168e018202829f9aec44e01a8ce25c5e7da2efe514f0787baefa0c127482b90aa9b161a2e389e6a5a205abb3eb43bbcc7fe4", - "0a049ddac8aa2d15d4f2dfc414df1c7431d8e159a6c6d06cddb15faedac54ece4311866e031c18970bc76fbb164e8dcf6c539c42ed24dde453b2b969344d26516e", - "0a01aa0c007361f48a0b77940de39b4488a721b453f3ef4171b19cb4b3b8a2b0f4a3c3aaf8acad6af43151f724f5ac057a45e944e60d639ab6f5a99d9d8c778e73", - "0a014542fee1dcbe269bfd77f2f75b5371f6578893a4bc9bdb65f5c92168be00a5f6aae81aaa42b019c7437f84ac9f8796f76ac7b4600ae63c390d49a343c715b3", - "0b0267ef7baf6af51137c4ea0102ee64a4f78ed53c8d6270b7430334ef42140f85608ca66142cbe9c2c669b64f84d16e11668ce7ce7d91c3a33a56f2383e92fd44", - "0a002785929fb9edfefe2b8af7fa8fc89296296de2d29ee54dcbdb4ec5f83bfdea5893e21eec28af0fb698861203b8e7bda295c950c93bb94e6ca42df7b8f445a2", - "0b082032497d113e12a734a97c5fb363186307a48d9e6541c6860f2c58d5836908a735bd19f71092fa226ad09fcb59192306d6522e1be74a7f65967c718d1a07cd", - "0a03bb3e55f8249d6395a12169a7be1e8b8059495f3c19e1056ba2f4bbc67924ce3eb412cd12e434a52b2ee5219afdb9f7af3e7a092986fe555ced53fad5ad35f0", - "0b0834e2daf5ed945deda2ddf57dced25765dae39d94315ea3cd7d826c48d8f73d160a813b2fb73f0d36a83334098966461dd355ef8a7b09d613b2c0608579c5ee", - "0a02fd10abeb2a41f283d84113c34223c0377d6e7aeb23a174c0d3be17d20e465bc560643f6ab690a53a21274f479bc4cb7832e3734289a04d203a1930cc521fef", - "0b012445254aead01069bea994bebbd37c0ed91da17131a08bea9a178b130a166d199866a78a12610b4dc3d02cb4579ba195d4494b8a47055256ea360945cdc3b4", - "0a02b3d373e1077c02fd0118c0adfacdf1e940363cb6da92e71a7ecefad169b68a2c0c71a3614cd42283dfc6e9b6fab5d59ad4e28de04687aab3993eb583d93467", - "0b07493079b245b8374d18482af0fd03523940d301351d11fcfebbd855c763fea962b937d5e1548c350ad92c8fd4ea8ee7c4917b709ab065f82eefa8aea4ed210b", - "0b08d48b668c1f60209984885eba04f0abfcf1bbec47840eb9324c11d0f70f65abc5083e805d22fd6066556bf3f618a5d74f9dad835d15d4474b477a16f48883bd", - "0b076b4121564ed0c666db38848f3eda5674054fa5112b2f9b3e71b5fc53d5dfcdc5053020229e97d160c112c2df7b2c5c79b9d5dd3a78625fe615d37961e5edfb", - "0a0120dc195495ff426c4b3c43ba37ae6456e67c1248167cdce78ff035e44824c54b1a621b038c7bc4b720f87f469151211e04d7bf4ad4d6476677be6a4e6496ec", - "0a06e8dbe9527f92cb3e92429a4463c3d3266e2917257e306147b0c4ab059f351f1df2a65a193ed87558ec478f36909ec3ccb45896ca4e45e3b1825dcd446380e6", - "0a08fe71161c545e7d003771506b10546c77c1f23890e5b6e0e0e5efdb9c8aa2dd5643d856606860baf886ff3e3bcb2d5365766a30679e13f0d19062583928e418", - "0b008028ef1d78b36f925e7419f14ba678ffb9ce2800221ffdab4e8a634cee57c6d8afe273feb0d9373f0580607ef35973768b7de7ae39c7f755202cf8b0fcb091", - "0b05e6ad8d84a35105194181d83aa0b24ebf2032ed55a0eb8901ea1b57ae6ed1ec3922299717582c4897964990c040eebf9a18f0dfdce0767f785ce5e295373ace", - "0a04cea8a197c43a8fd9b85159f948f9b388122be39b7fb747a2067c3fe35981bb0d2256d191e82be1ee7096f41d098ac1fde160eff036e6be4f3efb785fed55fc", - "0a0275db1cde9d46dea7a30ad5dcb5fb8317caa142f9df1b529c8b2bb6d1a75eb6a8831d28949f81ecfe250735e76a98a58771eab64044b42e417a44e936cc18be", - "0a0157b5f9f50ac45154653967a77565c9f675d46385d3f727a3c874393c00eb36ad5f1ed474a6cbaef36c3040eacf0ddf62dc85d81012c139376d5ddf2a97b4b6", - "0b02acff7eb0d8bacecc71a564bdaaf16f522a6a4e06c5048e1892234f3d86feaf07dde74c82825e507f0608485cc025f9af1a2edc430add0687fc3828275c217c", - "0b0865282f7d6337cd333b3aabd5271a33f35df67f475d2e1820d6b6e00533a5c41e607cac26c1349de90d327cbe6d5c31646c0caa40db460e4a2f0f15442a4938", - "0b037c3fc318a7f87f2e32870863d669b233c48be7784b49c6eb8a436b85c69ff4dac0d81d998c41934470ea82aefd314d08993a1b10ef6d2360462255d2635f89", - "0a038bda96feb9ffa29122a0996480456c8318a05365d76e260f4d4c234ac0f75c456cfb13bf167e01cc591bc9df999f2dd31bc4ab01589409e8b32f2919048043", - "0a0335890709176282c69769aa0fee57729c6712c1d49bfddec6bfe67921a57b2dfa0ba07531c29565b3d87040e787bb18531767c3ad338a1834b017f30489a9cb", - "0a08fa7b6f2fff4ed10341d449139d02bc34d3efa81fae68d071fe10f53431e62ad7c7e21ae28d2362c82e9d45a02ee625e23e48068159e4d86f871557cebd1f66", - "0b0600a96941054f1722cf803027f483de3cb22642775c038552ad8465e3bb9168c4fcbbc339ae2451b45b4ff7af96dda6bf1297557b2fd6c2d22b6a9076a138b7", - "0b069bf056778612abb811a9b07d81b8412491ad98ef27e42fd2746378cfd77e51328a3a71cb899da2eb18d1593ca815460ae3a8858ed3745e252edee38888d6a0", - "0a03b8d08c7db443ea100eac6e0f4a7120a45ff7b7aef5b5e021000ee8015f94711c04c526b55dae088ab3e37b601cee6542cf70961220a00ab5e889e0f53d3b64", - "0b00ff85d0fbf103b4e8a65e73d8eeb602ff41e2b064cd6f0b01d64625567260babd1fcabcad12338271d4836729da67e645ebc8a8d048cd606212faa0cebcbaba", - "0b05226bd42d71339c766fa40c70657575b5cee48f3b9c387f563bbdf9fc887a6a7308c5fdfd1f8b06b3f459dcb0d08cfd2ca34f6d543a0a0313d9050f52fc5313", - "0a05e7a7158117a865f20b9332467c3b6a2b9de6ada4d5c62753d853d4cc98961e88569df7e809e37ee8cd5bda219d129684327d60bb4d85c01a50fcfd35a90390", - "0a072d0329ba6faeff9f8822a331a2172a3be728455f052e255837fd0621d5b83e9b90c0bc247d51200c2c3fddd7fd7ed2671afd7c72f49831df7692800bede310", - "0a07156736264de9ab08276e6f7dba034ebd724d730e65a87020d40713f6f04a7388d234fec991fd795274fce07a5f946b298106250bc7397812661d4b5f39496b", - "0b0521004a29b4938ecc56223c72ec1a96be341d12c80dea9de17dc9141601057a68a613a16a5e0f69566c764c91b6234ca043a0ccdf25c1dfbe20c7d6ecb586d8", - "0b082d288242276ded20f1ac9f34c18e8e3a9e35f8a1b79af91d8b1f32430da5ee439345a66675451aaa903e15a5d530bffc8f4ccb4c011d41cd1b4bd15ca4bfcc", - "0b0584c9fc1c81af63db4777bf2f0760f72217b9bb86be3629a2879bbd6ae1c83e79af890f205bf7eee08aa46de29f4319ba1597a1476891a233e243d81903ef1d", - "0b01cd3a67e83e5d7354b24bffff286fc5a9d88ef851385af0cba791f7f523229ad44a2e538cc1fefc83050ec2328f97390b5279d5cf1cc7f93cb01ff7c1c28430", - "0b04820f58371586ce6d4db80d38c032e3383ff29915bb2be0c2646792822a94b6272aad54ebe0a62063724469557985b67d16083c876f5e085e3e49acd53e4fe7", - "0a03921b966538443247d520c8e8a79194f17936550d1adb4e0882a610e79b13d572d1b7bd3c34877bd7cf264b72a191e6d46a9d77ce2b6746a70dd90546f53802", - "0b03727ca6ce1806208b94a3ed72516081c02548a84337e4b8d27763645dcf4c4dd9a98a78a3b8a33e86fb7e5c7acb4ef66a0816808017998b6b0e1a27a944e53f", - "0a0889732d89a5a9655879e35cccb7b6d7cd6d5cacc393c49ea85bc1aba534e38e318ef283498257602806a491b89c974f6821e4012f9f1f387cf833f7a8b3ac98", - "0a04b7a233a6afaaaea4d1d7393608546b2eadea42bdbc3b17ce0bd4c19adcc8f784694cf0b8c97862deb86632f57dfa44043261f0528616369d320bd9f7c3d6f9", - "0b04b2f039970039e8f7b32d3f408a5f6f04656425f31d547d213a2111703f51377112af8e94058bcd0de468bbf4a267ebedbe754e7053846a17696ce1642f7643", - "0a0716bbd079e6529afb16c8e7efe8b3affb04aa00246a75e130f43a33c49c74dc0e524d2f4c282f324c697d66fc7a6b7468496b4b39939fc5168545c9b5db8451", - "0a010f687a5a0f9fcfacb4a4e4e35ed077ecc51e03f1e09a239f6d7565e90c72d92149813ed0d69138dcfbbefe80336452be195081ac0be389be58f801b38298cd", - "0b0505bf5b8fa4986df68552debe7e9d576811e4c0456e073f157d9c7e3848500fc0a66afa5301e23c4f160b21c3dd180b25e342df07186947e3875310ccb34bc1", - "0a0068b70b4b9aebcd4b3c908b3aca363566e33ce75628e08bfbb8036a466e000f9cc70cfed68b0081a36b1c3898f5be7da78b2bdf4240d63d817381050660a058", - "0b0566b4648edafdb05c085ef2319cd71cd73514193a688cb28a1e300eb47f84e80c39115dd51ab3f7f95d9a043b1a3916a4c824495f95873d3a2e701de663d3ab", - "0b0914cc174b7085fdda2c1a11323b089e99161232411e2a8bd16c571f6b94ca5a17777fa6454ffa28f742a78672e7a9358c5f17d2a70ea4675bc4b0df9f63794d", - "0a090f3640d953e169187339e5856e683c1454bdf2c2576f86c2c97375fe28324b1f0d07d8f6fac5be3055d85b06f82651cd9d1a92b4639d17c2eb37675ae76704", - "0b01e8d6ca61399f39364174f347e41ab2dceb02fd4d1360df2380a0f1a45fa6cfaf7af1ebb330ecac0a52d16a89da2aad81d54c5083612e0b27b7c4bac1689ade", - "0a08b68434926fee28bb082026053938ef6e1a4b61ac29b9c323d002ab2ed7585322c0e196ab4efe3a5a990c54da81ee1816f4618cd2272cf12478685cb68c8b89", - "0b04109782a517d97c993e0947b05e9234ecb1d78374eaf45395bf428a639b5e80fff7518b241b8724c2a875902a65b58e73b94ae8f6096c829488f6f5202332c7", - "0a05cba3419f96af0d97d6a50eac7b30184386dafae03a2579f4affcd5785d3af44c8d85d94dc6cc923a5afd12729ae6331f94a77d376f833cefc1542804895fd4", - "0b04b76bd8f629e7a31df2ea838fb8fffa9e15aac1f4838329b13bdc8cf7a4fb20b4eb14d9bcda754ce904b62d63a405988fbb2739b2f0b0ae634528c66e555daa", - "0b0189c2c72686f06dbfd8f27628bc2d52a95a4f6e0baed06d802c68abb9f3f90b4ce3aaacbd1d1df6c88b573bf4277844e02bb49efa559c878e35926781b49ec6", - "0b08870af78839d70cb8b154b512784f7cf8a8bc7a2912144c4440907beddb5be4eb5ea7f739a8970740db73652f47d8c53a092f9493af8b2cf74cda065104a553", - "0b0781322ae4b3b661a7ce1bc6887d3e9d47949e3e683c176c2b605ee9c6da0563e9963bb0c022fe3a42788ec337729e603f3afce80c053f8281360646daec5b7b", - "0b0922a99d84d56ab64e804ad8a06d5df266f7c4b4cbdef3b7130b7d796caa594b785ac7ef977a25ab6a504572b9484d26f8181b67e9e231b652f776340fe494e0", - "0a0056b9f425a5cc64ed272a0d46215b153ac21b1740d251bb646859fcd5115a6a5c6c51e63bfcce53a7d00ee5ba67fff42492b76712fc9ed5e43190bfa62d1a8a", - "0b074858eeeb8b9973948e1c073140c7eb7e44db9828fff9ee2df25e32cfc724c80f3e1f8e8db9df3aca4233bd1d6be01ebeeec391a5b87f72dfdadf816d0a5df9", - "0b0630cf5f155b85db974dbfaf7211040b4b743e5f46ec99cfeb12eda17a1c217314d32bec37d9bc1cc03c998ed5e512f32e30867d0567eb1653b8e2eccf3cd685", - "0b0111aa206c5e12fc0d6a7440b1f1cde14f1d87dcfe252585bc799244e7d4fd1269f6ab44489705aaff2bba0df246258c391cb6df2d5e414df7ac727924f1b8f8", - "0a06dcc820186a8b4fc1632a15cbcb6f7a861075e43cefed79b3eaabd20d2eea2aa3a267ac416666074d6cd67ed2c7a0a89d9e13513ee86b9ce35120ca6c5b35af", - "0a0437743f1abe4c16af258b4d9ed07d8dcf2f9c42d865f26e47f5a76fab147948dd83e86153cdf314210bed4d7dbfa461856c69e2661464ba1fd7a32a3020f4be", - "0b043061d5d71f64bc3ab31be66875b449d5d70cf2361a70cb069a3620dcf6a4fc8f94759198ab134db190c45710fd0182255eed7173576786c665d319056ce2c0", - "0b048533f8c0df6f44372dc6a2b9eee891b6187521328911e6d5907331b30cd5f56b1e0b223d5591ef308525160c1cdb802237f93365c5b871c612b33d7c8b9b1a", - "0b02c59fa4e967721a4997cc9300e7a4f60906ffa6d7cd0d8d52207c6c75894d31f1f0c5eab95832bf10888c85c955e2501d4f22817eeac84fc0b9d832c1d79d34", - "0a08000e1dac021d5433f09d4179aa635f0497c565722d8829ebc1cb11ed731ef5f1f2d1a8d453406ba78db16bae7953b423e7d5b29a52dde97b5ad6cac8d89611", - "0a01835a28535800f273eec3626968a60333b817af5a9863010cc2d12371d3b217c78ee2abcdb77c3853e8daf8c9a22eb9aaf493a46861d3fdf032c8a5cddff698", - "0b07a118de3ac13f5bbc3f8170c0b088e480f178ec62e39caf4506c9409122b02b04e781443c8017bff3023c09c3312108a62456e76274c6946949188c1c5ccf09", - "0a06f240f9975c79384b881df7042ef77038a2c43a34a050b31b5a0c084a2bfeae040112555eeb7d9c119806942ea40fa0357c103d1f3c561c80eed7b61f475bb8", - "0b058e570399c947c275a61f7f9705a15254e1d01d741103f05e809ef5431eb0f34ca35b0701321ca6f3d217cae43e913dcc8fab74e118c786021832bcdbd50fc4", - "0a07a92c1d6e39fb602f5f5ea08db243b6217452c1b55093001749de9d40d6bc2c35ce5685f9113aa196a85d113dac2b2643e6889941c13fbf72818650927c54fc", - "0b06fa13f9de9906cd9919285a8b6bbfb343f8a61ed07365065f7365de415520619564c8e800531fcee29bf2287d0b646c7f4d85374cd98f006fcab3674462803e", - "0a06f8c4b86a85ac3f130f4f73814da439355104623edde88029a7b9af2314addc9a6bee8ac8254b91614bf70034c7b0322684924d8b66eda0c51fc704b73e0143", - "0a042cb2b444944b33a81b7611c278d3f926b6b2102515e52afed1aeb9bc391fe782929a9c57b40b6058fbda8e9b39942d8d2b1ab97b04424bf83e76b2d6b388b3", - "0a04b5154b4a1e32881cc86ecfe2618d538c8dd50ea64cd5604731ff330d87c992558a39f171d8120a8a3caaa9b1b239bb364d854fb9758daf2265c1f6690d0fcd", - "0a0462b23bdd4ec5beaf6040397872054e30defbb3946cc465afc8e56921911363ebd1451c664f9589791b8f8ca6a4d6c3aa628b7834a1e572336e0748299437d0", - "0a0183228b3c03296d9032b6dc3accf307f5ee3a13879a9eacd54554eecb5cd9696d1b62f826c9ca12ffcf66e862925f3ce47a18072b824b9cd161a892ce76b698", - "0b08878c0399458461d17795fd802d5f6e00487a327cd3695aa0b9820fd6ecca5607129d919739e7834551698451750a4d27ea193e44f28e082a3862499c3fa8d0", - "0b051a22afdd293967393ba4dd3faa2d70f86be4bda1d5a3c82da0555e1e35bc3b06fe7f46119409b3498d47d2b072e5394ac328002afcdeccd1d520783e981ddb", - "0a02ffb68aeb421a547d8b35362bca2a5c04ab4ec70c045c105b145805e9107573e5a7922c16942ffcbd754add40558b7696d9f51e124b07d35cc58a4b32ffc67b", - "0a010c98108e2abfc97e4099ba1c294cd9747845833552a11a09556a95f208d93f2e539d8e03232a97c473c20d65c309d2a17ea71513391ab36308859642f0debd", - "0a08098d6cf82f4e810ef7f24f92af2741d6aad911b12be51f3816df114d39bd22469ca18d020c3b7c1b81e3282ed571517a967f42561a2787c853fce6b0b85b9f", - "0a036063cd7189e8815278cdea6429adaef567f02ea4875a655578075b69dd12f6f93203d74dad3b7eaad4a0e84c002f922b2d344369398dbaba7a7eda0409ca20", - "0a034fdd0bd92a737d7597b9f762b84718c9280e7acaf4a463d8644cf053919110f92c73bf33c5a0ba326c3ecabf430997cdecdaea588e87c9931233256688ef71", - "0b089e46e4f290c9f24bd36ee63861a43f5cbbf5e11a3580e7d409f76da7e2e403c66e963526363e4e2fd326a37d211588af71199fcb6ef1b9cbb9a4eaaf8a7c70", - "0b0756ae7ff0edc8d73d2bcf382dd5b1f9164a9263bb5aa0f96e27a8e33644c650e7e756bab62c41803905790dc586433e90f02038cabc2828663ad7dbe5cf8887", - "0b03ecf2761224becac45e96972396e9f7a7f1d57bca149332ab739644b8e2aed325be0706b168f80de5b54a99cdaadea26d76f32058f5aad1d2232225f7176871", - "0b035ab2a13739f1bcede1ebed4528fec5e08c0c982c333f5d030992f9c296f224955927ebaf307f6a71d26842a7396fa0848c8600494b054ff5b2aedfedee5a4d", - "0a075ffed9478ffd3b65a38f3ce4697ad7e71f5527b805225b1ef042bbc192ef7e5eab53a9ce170464e95d6bd0198651d2514cdf838e5bb1dc01949b5d8d6f9bc4", - "0a08611a29237e408562524032a84825c64989b92b014a8370bd9768e3929be9e832dcda8e65a2488522be270fce2bbef16c0c27b63c316289f892024b372a52d8", - "0b051a11413995fb15270d19ac4a64b329e31e10a25251283ef39d327f6062de4638de60c34cf5a5d31f3bb2765b7a738595c3da611e378b840968c717c965e28e", - "0a04b00c884311d70c31887f1d3a0665e1db8ea33f1019fc44c323802a211e37d4e9405f2ac975888570a35125737c742b0d00a29813aa5f78c016ce2b8edbd5d1", - "0b07e1d0675aa445fffc5777bfb9dd3170be3e280676c247c19f76608dc07e76d4f87d24409a1035fd53665a3bd9c6fa8cc21a5202a400ad5832d0fac3e838705d", - "0a01d4ad0497b5f49de70d3eb350a41b2a9a381a2ec58c3a502103bb630d89c28edf47fe960987cf6d7074521f4cae0d22791699dc8637c66b2fb69757f031736b", - "0a02569cd33ab66f57568a1e9ae9cf677630281b5e504698c9f60d5f2c9d6336374cebc261cec6926ac00da03c01ae2cf2be25eab44b2a6e441a7962a385c756d0", - "0a085389e32e9b6f0220180e8ba4e323a8a81c95c1be825d391512d5eddf40304f5a31b3c0e0ce7350f3162cfad84a2fb78bc0fc7c02101833337d8ef7e7425ddc", - "0b045d2b871e4532581ec2ba3737bda3ac059fbcd5ecaf9c40db6ea364e2b101ad6774b0fb681388315597ef3f335fbb9949c77ea61484a2af8bfd75041af33631", - "0b07aee9e006931a7de60250518f8af27c6d7992c03e82133d6cb623db73e0d85d07b7ccb658f99b2e299d137844db7233ebfdc77df5ac5b57ea63d274253f7b16", - "0a00d96a259e66c35551d316b67e2520ca59848095a922110c094e85b413e719b1fe78887e7745bdb7184eb1ed184965a6b5a7a12fb53012fa3872e3d8090940ca", - "0a043411875349b0e940e4cf7d9458f48f0a947d941e3931f1846e59179a07045832e0d29bbadf285c19462cb55989a541b81b1aa41e2d182889a66c1ac6881791", - "0a05f970a43a0372d384fd65e2b552ef73614940a1acbd071ee4d0c75212348122e377ccf2908405e2ff14bf3059f89079932dcd2fa78564571b106754871274c1", - "0a01f45a64f63fa919058109eb5b0efd66c7f1faed526cfbfc16c1d89e9e791c63df7a615e3f90b7924956c2ce71ce3fc4e703425ce0e0e73fd78dbed8f6b795a7", - "0a04d8476c461276247cccbdc420dde829313767dbda644deb69c3385fa6922852d7c151cfd6cc9d620c73ad4473dcc0edd74c9d8a0be821a1d985cf16044a4658", - "0a01af3c900e9a1af26a1bae4896fc7f464893385e01c2d232f58e355d5e2400ab8d6bc5373bf66f3dbc4ec923b5334048add053e3905d9b763604447558c9b006", - "0a011484b98941718004cddce89d30746d9ac08a299aef5f88e0f97b14119e6d47557bf279cd9f10679706a3b5b7f75065fe4fe81021c76ecfc5d5560a1db5565e", - "0a01ec062407e8cf5ae46639c5db64c43d2ac83a8967cc9a6cfe1d66d3960fcc5e62c393f8fc24bdd94ecc9d7890013b7c98a0e1e57b25b42e178f54cbd495dfdc", - "0b070e4fd6cbb22b845505184442ffbf2289a2bdba09cfadb405a7625ed792597f5d72b56351b636f1f336b498f3bebadf4584c1ff502bc125864ae8be0acd92df", - "0a02af6f1c8632399346ee2c3d7e5c374c4160f4e9b107cd3fced5d43d0a4282408119fe5d780edad6bc0632af4faca741718529caf703e79daa360b2a4999119f", - "0a04282e6326a1bf5ebd0aa5ac952e85cce0c7cbbfec02a41391b052b562703c11df41c0cfaee3eaaccf7f5d9c02afa5c28d09f439e65438bb33831dfff679bb57", - "0a020694c7f876d066a3a0e3b058eea378d5d1a5195b93822536684f7c5796b682966e6c82460d7e29ca8ba5c05536088703c02e8803e926041924474061b73609", - "0a016854db75fc893cecef43dfc8adfbd95585ac8bfee9a576e165b0489bad7304afd0d3151921f9d346f0aa652b0e454e4ca36dbec3739829280d7dd4ce14fcdf", - "0a04d3cacbaaf8d2641ba7bc4e5431dbf40e958eefe1b6086c80860aa8cf8819258903173d293f676b589766a3ee35d509658f04846473e03db5cad2f0a8d5f61a", - "0b008b006900a045e62cf43d8b92a2a7ee6865c11a66aa864faeb7e807fefb7ccfd21fed2de305b1055b8bfe57a5c7e71620c2c5f89616077abb373112dce6db0b", - "0a00c061c7b809e967e495bf49ee82d05d1a8c454909ba9c4e7121f7821e0a0b76de129364b6b5a1b1bdeb9b59d6e0c16847fa17442e1448439d0edeeb39cca854", - "0a052f612a91669df425973761301b9f2ddf959ca496525e45f1b09c605b49b1cfcb5c587f62459bc0625eea02a1272a9a83ee130ad7865d93a7d0be7a310d5375", - "0b076546965944beb0d182c1454cd3511bc9ac019df2fab97ce39d104c331d00ffc3e83ee97363fe1b302d1a50a84f15efaac93a4bd1f962e7ca78ed67d7e42f86", - "0b033f68f0c91d1195fcd3a6d90808c71fcc0de8fc3166d113d0d45a8aa7de928c151b5629595b44d4b359f204960cc66cd59ef87a49ab406aa943464287aabd7c", - "0a036ec548fe3c4642023d2c36e1770f0c15440244a3abd36ad90bb114cb5322ee635e888a11e1386b496208614398a592f65fc09361f5575eca5daf24a375d19f", - "0b0415f414b5138a026fc7553e399638867d7a60d4bc9fb81f03235c19219aa341ff6d9be3e64af6017141df7d5fb24a304bb7393250a0bd0fafe75b0b92a03907", - "0a03bd40cbf6e3d7671fb5f3232205640f2f1fe2595e59bae360a4e9686355f88f43c3d85728e65a7239f8842d2d796a694df9ee46ac6097053dfbb24c8a366b98", - "0a0573155903808dc1a273e01a8bb3bb4dcab11e5f26a6c69563ac2e4e6d6fd3bfccd332a1f5d2b7896c02cced320068843689e80be1e8c341d837e529c139c5e9", - "0b059905dca9676091338cab38f861367659ff4c4984f816413a45ad921a53c20e547829660935781d75011c75382cce79f155e31ba2c092d0a078f3f176afce96", - "0b02782602140c5a266cf5f17c231f64c58aa9108baacb55b136ba68c3a4f37622d2a81988a63ff7b56d697b6795e17398380a7e185059980676239135ba4a1619", - "0a08da23f2fd43110c6c529c92bf63bdf0300753a6deb244ba812212e6d84559d5df302129ea2c256ea01f539e19803b526d8324bbdcd9a92d8eef8bdde9977aae", - "0a02a76ea50bcb9d1a23eb3cc11075654c7317ae6cfa5267b2e6aabfb5e09576984b423aa0737290489ed828b293aa8691758af8494149621aa0b5059119eb787c", - "0a008216f55c004f45ecacdbe8e0acbc3e9de8a21739bd50e88f8057bab622e53c88aa578f1c5b5b33dc976e0a8cf455efb414fed5bee1f072ff4f9910a98200ba", - "0b02da9dbe1894046b7c8ebe5125fead58af09e566118897166b5e9fe2e3a878cf96aaa477f0e76464b02824c5e87ef87bf0a750a5e3ecf21d861677089ec2c9a7", - "0b065cec122b2f57e0ed7ac7b506800b9e8cd55c9b86b50e32c746facbed820759408a9a8604bf86179b837fe8be03107eb5b8a78b21933df36c2ea8f88980a52e", - "0b014b6bcf19e7118553c2a167542b4c777379c1101221de734f838e727481d0f1b47a788573d019097a44c8bd1fc9160f1ad4e54aac8b859b26ba748a285b4bd1", - "0a06015100266a287dfd0f3cc2f02033f2e461b689f2ad089e7562a27bb8fe79bd62e78fe6259d5ff84ef8265c2dea62e7fb5aec096650acbde77d1b11bcd90de1", - "0a0298bb4843e66fb8169c31eb67bae6973a30c345b40c35d0df1f46f63210145c4d53b58a594b2dffa866361e13b1d5c9910bd8bed65a2f1afb7d3aaf268b5231", - "0b0759134f5052257897bb9db17445ae60295868928292528b1c9472e3a4013f015a9d8605deb9c89304f05f9cd73516680fecf34f5c4049719a011d81e19cd3da", - "0a07a09fd0c9ae09445e0fa5535b2fea3a5c86a08d9bcb8603855d46b10ec2593ff69ba1f3abb7d14a85b7d435f0fc25b6939a40e4b98af6ed325476d566d1d055", - "0a01aa635c8eb11b5f06115c52a046fdb97804382e81aa84d50a7db2e3fe4a2e2f656b353f9ee4f8b042ded6dbbd30fc278a8dd5b2cf98204cc5ecab4518f82bd5", - "0a08a6dea0fb72c0568978925519f7d040a3e2f1608698d9ad4ca48037c8bca5cb6a6b3c9890d5d61569130c76dde1035747cc8956b96ba10f286af54e4d2f7792", - "0a059e8a30482cb638a7c2984777207ff9cd75b2504f9d49b426e9188ea2be7b82821d35532c33562f4be0a4e3825bef9470bfbc050edb808439b16054a2c467ee", - "0b02a316ccb0fb3f8f1cf08685cc28215cda2a4ac3d13ceb8f470d293bb4b0b68da9405aec17c8a741a5ca2ce236e2ed9381503e449fb03f6f9b1870c5f80f0ec8", - "0b052a46581aca1f7643b849f07b71fbe43fb9d424b6b2b06fda1a20a6f58fdf7f52fb1736bc6abfb47fd2d6f0b7d34f4dbc9a5a16d9c464bfa36fecb9aa86203c", - "0b0427cac69b05ab280848be2b0bec3f7bca8360ff810d7958a3076140d4d3866695b4a963921b6fc2677f165962c4fda8f62df49921d2b5c98d4f5b4e4b4f3835", - "0b03c3a48fa614a85bb1c77ceddae9bb6629a5ba4625a5b9a2546e06cb14fe9acb71eb033ed8d6098ae32df762d532c2464103d2158452b054f5738ed789fd987d", - "0a05f4b8f2f87fe5a13fca5203487292c38f5ea02d3b16b92aadbf282bcfa3abe958e551863879ec6cd85bb86b2ba46e1f5f501cfb7644721cf769ffed6c74aa3e", - "0a033c3e9e5d911b40d212629991000aa47265b46ded305dc7aefd49a3d766e1056651a0b3847283dbf0d407f2faafe8a46034179a3ca8df091a09eac8b86b3889", - "0b0227c0eaca070410dae1cd76c7e8adf3fcb8160acdea64df607e74a8b872023aafb80421e4446cd8d58ff7e89ac8fff661382e50836953cf3a563119308acf8d", - "0a0752182e5a5c18eda8cba0a73fefdafb9ff34e3bbdd46263434dea26e6220b596c893e9af14bdd05acccbb313f481832429cf9360ddc1cea3ee91912c7fe813e", - "0b032ac9f6185141dc9447efc8df70fca430de32f6c3d895ce47e5b78890f1913b5f9011c7709022bf700c3d17832429286f04e84abe9597a7bfc260851dfdc141", - "0b06212f21d961726e81d8fd7113d7835410069242e7ebff12981e55fc4302761fda3e03554d8ecbc35408357c6edae20bfd894735029f721478d71ccfa540669e", - "0b067f1c4358a3262a2a5107a49afb0a4f864b9f9f9a11109cac605c70153564fae86d577668a57add36bf17bcfa0948ad3d81594f478c853dbd853678fb24dd42", - "0a0307ac2a9edf002cd1a4d3d17cb80d2017c8932f116d7f9352e97c796e7db989c844c38a6e2f6d38b7084cfd73f68ef00b5040f714177b7af046a2adc5ab1be7", - "0a06751d4435fd1973df9f08ed3d4b55d306243a3f83e8e28e766afae3687e8ce25b89d0769bef001e3c18f2cba7b2cd7ebc39e638d385726f28fa2f43fa01b761", - "0b02bec8ec7e41cd8f9a35fe563e4a81be33e0392cc0e0ae3e4801cf42ede642be659e89fdaceef0559c89d341ff52c51187cf64ac89ef1fb0f31337a0f4a5d09f", - "0b07cbd8cf6dfbcbd8b25ed803c17708ba6411df8f867ad95dd521fd14bdf39c16f06f3ea80f10b314c2c5891ecd482a775cde2fa74161a19d0fd15e529269a19f", - "0b06041358a4358bc242b2b6580caf91e0c9682fac6150ce7f380aaebc93ba21ef41bd46813ed22003bb906e998f19943238928a7d7d2220b639f619fd8d8e1307", - "0b06d8ba9df5a76cbbe34a92bb9c8116fa4c23c78f06896d547317b418ba60c74c2c7115509f2f33b1133a6be1e86f6097c83e0c7029ba310b1f1feba7a8ea2a57", - "0b01f8470d609ecbd41b5f84675bec3191bc5e3c22be36fc9655109b6587ba864cb88c5f4178c52049950af45cb9368a6f1406bb7d681cb3a3ef584fe545bf2ce1", - "0b02164f1c5ce7c20bcd90b3c6eb4c236ff7779d30cc0a1cf109ed910b6bc670638a45ca5c5290b3211c56a014988ce6433406e89dcb60dfdd5941ab00331fd630", - "0b05adc69e75ea6e304ac0d7f0fa1849c7e7cd797b3c2ff405fbedeed0c16d232dd684dce0292b1d1e0a059f43234823560caa9937f2d81b19c3d1effb0712a90b", - "0b07e59846c96da44009c87f14a33ae3a158d1842a51d392466653507fab1a5e8258304b5b722ec340f86f943299d61ca4ed81c734c2beea6b9cbbe7c4c00c2759", - "0b01c4a1b0e7d561455f0e68481b3ce77f721c88eef6c282c4b1a1ca395d36bbb005551b60412d0fee732b025e47bcfdce473007c45ac27fefb3f8b7ff0a8f1bc6", - "0a043995d2ea8ee5c5c16f909c4fa2630dccc56833ce97f441014c5cf8dd621f95ec8cfecf4f4ed774474bb8d3a26fa5f8d350e8933d858f9107cd61b8a951189b", - "0b074943e827c9346957f074e1e1ea4c28711582b51262a9e467fe76fdfd171a6af6e0c483beccfb124e95eda5b28c0e538f2da747336b8a6e51dabe117a0efa01", - "0b07d0bf1e2d472a1c342e3e60c2a66ab491969f142fa1cc630fdac28584a30ff50d639ae9431357383c9cff7e1ddf119afbc0fbd379d9b678b75f9a8a3b43592f", - "0b00b6fdd847283d3deedc452ebc3b27221c53dc33f527575f5dac5177e6d46a62416b73b41671bfa090ace2f9b64ee55caf2c2300441eb6a4570b9be8ab7e5830", - "0b0364e7f47ded14fa6c5f347490f84728688d9858b49e290b8c6df5b80d39d598b7fc8893da545d26b7f8f9ca22d238928ae0d22f08a7d6d68025bba38a181738", - "0a00c509b16920425abc45471f988310b915dbd12c6365e8d72aedea4bbab0006f3317073fb58e7731cc5eafdb1f522a7bab2e883480f39b7b8d675c46ef7e698d", - "0b00380fddb6b3cda482a4ad38954f0f7556df0364ab15f415547363f2e794e131ccacbb9e9738509e06543e292ddda87161dd4d9a3ba0bd0386ba6ee49e1fd019", - "0a0158f71b1185af76f7be0a40a9d69d0b4894d01bcac90b1fd203d81bf0769582cc204c0e68adaf5ba3a58c2b89e7bbf50aeff7084e9636e8ef94fff5c711e3b8", - "0a05501fe345e0b20dd72fc5c81315d40a760bbff0c32cb3850bf2cc4670e815b0d6fc300a0cf005ee2da0fd3c3d64c55f1e5abe56ab9fdaf4149d06811e67468d", - "0b03c8fc9e1e2986ca1d5a40717b55c2c2ebae2716a8b182a0afb41ca1bd06c61257a80a42abc62e1ac9a28fa48b41412987c865fc85b106b1490adfe3a18ad219", - "0a07f5e4d89855da8e965d26a4276a3bc879a353aab98f3edff0c94967daecef364146052679fc0f33ce4fa34aad348a03fcde36c57ce9c58154ae4d407947b2e1", - "0a04f456bb273c95b54c40421c6a26e1f5e8b6686b0c30551a198369d38fe20946eeed063444f2d8dceccb8b4af16485f29ac3984fe3a5bdf1fb50032bd211a383", - "0b052e4ac823a35974520cef039c942f73151e735753e53a059d184ac2cab5d6b17a0febc01499cfa72e616cfff4462fc3a9b6b2ff0fb7452dad18c616bec4c8ba", - "0a046fb6a4bfa9307a7926e6c1fe803d1803765e3796677c51057e9e43134169568a694f484c707cf1d9fce48988b59fe0c52c6294fa71307b0345a915370042e5", - "0b0032733765e0509adf225bf1268373ce5f46036c2fac51e93d50072d83482d0b48706a9aac8afd272f3762eea96bd6f7191bddfcc15bd23505b1c29a6943aff6", - "0a05d9c915957e060f0133a6ae2e7a78b47b7679886ef50ee2e2a2893c1b613362ddd2139c7e2efbf4d8f2d433267bebae41c4518e66a17ce87b1cb55975eb4851", - "0b0715d9cfec1ba155d3d8890b0872f4a59e0d40b06140f4740669aa6dc93ab0b3e08e5d735193654d9dbd303425d29cf4772db15693bf66ae485ea9503df60b46", - "0b00583cb25b09ae2638434b63057b81e1c2c46b9d541e19ff9e4948c9a7d4a87ae9bea45c2ff0bf8879d26f8da02c334e4f0a85935d4000337908539aa2e7d566", - "0b020530dfc28fa6aeecf943065af7987190ff3fa5961717ef0ddf3bd305d63b1aa43196ffd7a1428fd6e4fc76139fbaadcf704336a8fb9edfd76fcfcdd42b8795", - "0b01969779fdddbefc8b54fa79d454576f4037885390919e389cf70725847c123b381d2a8158e508c1f653a617559d7ba12d3824609efb66d9816a79c5c9146bbc", - "0b0627afa6e1f2820156ec3e573dda641f9271d920515218ee5fdacda1fc2a59b3c3c17755fdcebf34564655898f56c7fdbc80415d4d814c410c0e20bb8e8c5dc0", - "0b08ce446cce9c35c623527034b592f46944e35fe0a5d0b06dcf687efcea33b77a6063c30496ac25a0fd4f50b897a31ce189401b2ffe5ed1c26d9902ed81a508ce", - "0b08205138f91d40535299be36b0031a454e4c9c1080de91d2dc8f398fa0d052e68dec18402ebfa63f09cc3fd3ada0c16f1799a9a3af16f8fdaecb449a69304224", - "0b08b23542879cc217d2e976159846bbb5bfa2479e330945a68298313b17924df3e12ad095c1cea15dc106b744b9878fbddf0d29061683a787444cb9cda69f1de6", - "0b00501c9410b4577b44f999570b536c3817c3d136615b3905753ae92b2fab81975052bc771ab7b1ab0f028545df912c2237e46aca39cbd6201b812a665d2ef7a7", - "0b08b49e6b56c8faff21eed691743ffcc0fa0128e19c69d8dbb1eb9ae1b2fda03af4116e49addbb979aa5a50d9506f9e8f16ce2bc1905908f6a8999552a9fad408", - "0b008bda024db1277b7597ab6c667ed3c947d647d52ca78f050399b899cbc145684790cd443d0c0dfa99320ee4adda782a30888e7b40af4c71c97e96b2f1c94acf", - "0b05bf4bbe15705d1c8842b3c7df37cf1e0f2b37710c39e8d414ebb02e6d53b0bc03554888c87b9d17a41210805316aadadbf3edc0158f37daa8e4abe2c8afe1d0", - "0a01f49742b86c7991122b3f142ccec5f1be22a99eb15fab15ce09f6052ca2701010518110664c6c23c8c8cc796ec6651e39a7462ad942a736cec6e5c3201ab64e", - "0a05c5aae6bc96cf162e6d1744c262c7f8ed589472014ccf76a0ae219eb399e1064fa803e619a4657865543909a63286f4e45b9fc27d48073893e170dd7ddd72c2", - "0b058e1c33e03682dab6732e7b5bd48dad26cc040f75307583acf25f58a5ae9fa454aea49e0f9b05e524fbc1fb8f033b703437240b4a33e8adb5859b634d215d57", - "0b011ecf2984b9c650af0756b6cb90e0971dd58df306d0d8d3d240c908b904ee84bcfdae145edff01ba6210ec7e80190c9b604f1d0be164501929ebcfccadba9e8", - "0a05c9d7ab510726ae186931eb997b08170e1636397e799d17cb5223a4862ec162f089bcbadaf2af21b92d1c56834a42167daf9e54c70cfdc9a30157910bb0f5e4", - "0b03ebd01bc9884c45df709ffb8a73b50681102f2d2c4beb3060377d65c95db15d670fa5b25bd7c094065a164d0d28e37c83d293662e368afd2a4d23e7293f4e90", - "0a0537e29b42539c5d961c66920b0f4e72135814aff124a6f3b423e018e633a36aa2cb83d865a77300ac8bf90225b7d1f68f19ed9ed13e785d9e724d0462cc4cae", - "0b03d6845c8e34160281331ce94f04a872ae62bdf708d4ce0015f8414723ccb7548b6b51a9428153ea6d9d154159a0ebf4a31047bce3b3c28116eafb2d2a6c18a0", - "0a000ba12c53ee15d25d592e6908321bf788ca34504732d5a218469e39d1e47d7d22ac62d611fecc8f18c19ca7fdf9c490dc2ed145555ea241c77c621a76bb3ddf", - "0a074eb320dd006d6769a85772f047b5f175c7ee846505f45c6631ca655edd40a71f1d53253ddc3180fdff8a301caea8560280e27ec551e401540fa7531a0a75ac", - "0b02faf4d79412b5446fc1d4ef9ee6296f1b95e6d31543ce690f6ace93919637b752c51154813cc95064d6421d181b816817d3e414a2d6690f299bfd826a13d88d", - "0b0321d81702e944ce8f90b9174da9a2f79821ff454a0f318e6f8eeac03032a8dd9a4365a82ab18b5c2588c79c0cfbb15141af5e7ce2cb933e7b956b62c68316ea", - "0b05c5a137904ac89e7742efde72e9e871d15eed1f671738346e0953d0044e4eaee62dac55b05d41a145b8ff861dddcb4f0952929736a35b0ccd7db0ddc02d62f5", - "0a07210bc50be64107e2d814581fc1b68377c6941eadfe288b230c68d779bf964e015c754a996248ea6ef31b77230a8e95f999a288dc60240c78a19e7cedebfd31", - "0b04fae44e5e78903447d51883221d2a04dc99395362bc5eb25879fc3cd8ac006497807ffcbfea236511922d139f455db902deeb5e87195433dc49bd944004e947", - "0b03226bcbdee7213bbf3d2cd1afb2d464067587a67853a3766b03a40ac3ec58e357bf7511ed5da1808af631c00b7fffca8a17121d970054abdbe502c407b2207c", - "0a011e3ce0abb1fee1c874a7c20360a17b694857c64820f1a900bec2580313581efcfe69ddd273d330a0e228800c51b54334d6587243bbc86057f3252042346d0e", - "0a03f1ecae4564091023627312212804b5fcafb32dda6544a156a26ef2a5b77afe11c435c02826b45d31355d055a80e3e5bc6b868e29917beb28f1555ced039ecd", - "0a0517cb8bfb0d9cb0f6e4601e3b23e57457e0f4003f1f571f0e92a584c68712ca40b7a02b2fc9168c9e7f059b15e04eb022916897a8cb4c04743cb397bd968d19", - "0a07fdfe240e7536cd828e07ceb83f791b4fe0a054e2420fcc15adef47e62d2acd19d40843af0510a5ae27b84f536fe130e23c6759fe0b27b751fa9c4d67908a1e", - "0a040c4c2c7edbbfcfa5edc66ec23f4b75d6e36728be40f2c819f9069ca0c0522be3915ec6b11f8b269bc5a168d4ab60510bdc14afb916b49229f951b46803b713", - "0b06d21718a744eddd53d0bd819098d275b659f70b8ad12e60b99696763a0ba16888eefedade6cc93e26a882e210ecdc0c81a3991de3f89090e3d078dd0d229fb6", - "0a02ec13fa52062378f17ec64fe75f3669eb88eb45c14ee9664bd7cd290d39f38103775cb4310c341736d09ee98c4224f27691018f849333990559d77c64618a2d", - "0b05b60db947c273c236ce645e7d5267410c26f9fb692eb6555de145911093cc895675ef7b55dc65c9981eb78895a9679266ac9c80f32c886880f1d899521706b2", - "0b07d6d4f6446f523702d8c139cb3a4b26d3f9e4874768b2484afc550246edabc842cff8692c2ecbf8fd8653f106939ff275e0f29b0aab98710e4c09ef76202b4a", - "0a042f90c48a8e230d1eedacf05a6b7130e107ac482170297d347d7c673044aa174151c02405173d0f95773a053c24b4c0c7f3b84d1796ab4e676cc65599ce5a91", - "0b05145a298727d416dab743b9183dcdf9291fd120a4fee31b4399fa8a71d9d61f58aa3708bd241e7fa2f6726932973ad6e5c99b347ca8bc50996c8e44b067b002", - "0a062c1a13bef798961bbf920b1c7b3a8c19b88fdf78882a3ce4cb7bb61986f1a7b8cf0b43ccfb9183bb904dc4fbb23cba8666474a2f24bbfd66daab00749f5ba7", - "0a02c6e4c8470e86d9bf5e4021d666eaad8c8bd78ba53e83cdfd3ce7c1376908dd0e123beb5c35063bde067ed353d992f106be1588d45f7f6a3d89c17d38c5bf3c", - "0b088c361198f6a1bfb68a6578fdfd20b6e6195c1ab3070555e86c11a404287bb30c6e6a83529fcde6a2cda331ea57a321e0eec65110bd60fcc318ae4d464ae0a4", - "0b01732d681c18b6cb2131754fc3ee616213da6764b8c12a7e039dd7151d4055448d93fddb805550b1d3290c2afd5320cbf606d873f3947670662180b0dbfc406b", - "0b022646d6150946a8a55b79d7d36cd48a6fd3a3f6177624fa59fdfb13ea0303b152fbd4ce7dc562a630df4e073b98ec74772c5c8bfd3d2097857092542d28fe87", - "0a00fa01b9d1d90807b2f87dccd0a31598e405aedb8b5c3fb7bbafe2d54f72305bac9c5eb35bfe33f90e5459b6838d91ade0513d1f69352de36154a689892016e4", - "0b02c067b577e41dd3d3a4346d48cb87ccd671bcc3a52ec761de626cb7968456902c2bfa1c784c0d96c6355146535b4068bb1f2ad067583f2ff6b5a81f56bf55a7", - "0a002bdae89a95c62720f128c25a62be0b9754d5dff16aa5cda9f06195e90ed954d17577fee0cf5038214e51c3c85b928a021aff9ba04ff3ffc529fb480573cde8", - "0a03023f838e260532387df9cd7b5a57d9f7d15d0dea0f55e9d1c771654125562c42c63c2d1e9bb9ff43707e86e515df7c2283aab2dc07b2281a47b9d054cb57f5", - "0a073c38549770b3abcce0ffa67dab79cf1d6b76a975d607969def0e08e58e49ad076291aee1df3e3da28aab3c9e917b960f9910e0a16a155917ffeb635795dc6b", - "0b01f3b6b98dbd1a060df9c6e5c43890e15bb4d6cfdd9c8c9bef9aef86cfbeba269913dd84effe677ef85a1470c6464e60e8f2985db152cb1abd8a29a03124eaf4", - "0a06dcead35946ce33afde411528c57cf00de82abfbccfc7066622940e56de1fa1de6be3bfe12a8f5997c05890fa3d1cd28f67714e9a2e0ccfc624ff7694808fac", - "0a01b47cac449419d5398145499860f9ef29a16b7de1252336f606bcb76b177d1ae70a9300a0eecf2a1dfaa83ba007b014fff0c258fccf569b7a9e493ce87637c1", - "0b02a3b940eca26a083679811eb52d8d9dfa9be7368740949d0ae4c735b46c55fe2b8987fe888c93de7b90999114fa360648e289c00a57c060961cce0eea777fb1", - "0a03fe40b7e3b646e110d41eb0c441b28e29758e4828a408bef657c19cbf62063bab5a8f2986884094db5c8185d2f782153c26645361137e1447fcc439c984d101", - "0b04dcf2b78385d0fb87f476130b920bc36bc986b27ac4df53ecf5e31acb5b060b7250e7b7f7771132bb378cb7424f290bbab0c1ebf19bda13cca563bb2639cefe", - "0b001bd127847224834072b457926df66a867a80de85dab5bdfc0dd2e114654cecd318e4ad236a5672a6b57e3fa5ec9dd57e7003b43357636636be091df9e1e27d", - "0a03512b84e28b7dbb498673bd6e89644e33b0fa41dfc16e57079643f5200860140226cace0a990179d7872d4c5fed5b63dd51b41600f9445a580b99e3c30d10db", - "0a011a0295774e3430289cdd26273d9257098c76d8ae434ae061dae8fc929bef1407f498ed6238053b9ffee4ec058f9a1849dfaaaefa9af402924a769425e60497", - "0b0196dced18d208a87b063d5ea2096527ff3e678e0235db99e0d6470de20922c1e82df658fdd8d763c64cffe3992385169ee819b3b67100e5e870300640613e12", - "0a00e158d5e83019c154ea8b8c7ac7e9af05faed9b5e269453a64b3bb918dbbeca2a980100a0b643cf22608a191cbb021a5cd9a65b4973774b49deed6c66a7057e", - "0b03277c8ed7f7a2317ae3bbd50a6344a21f0317ff7599b1966239c67e29eeda7c4e0ccd3fb3aa9603ab3e6f2b46393fb6abdb3dbd14865bff914ea54443747909", - "0a00ac3a5fef0a88d066b66966a94f162a7181a0edc2240aacd832065d4d0207ebed6c6e950b6f3dea9fdee571acc391171fe62d7657ba86de6bc8f727e86d9ffc", - "0a08cfd198647161a612a5d79fcb2b672089db5e71c96545bbe4c10c1f69a5b419111c0d99df75d03f24f7d11cf7bc2de374abf7acce90c6514693e70a689303c6", - "0a0337abf013b8c3266b4aeb676fb1f052cd9d1a83364f2822daf0ecf5e8763a00ea786164469774f08034e7e8b3d687ed261e8bb66ecb1c0046cab574f3444d39", - "0b00347e199d194355ff04327a1a6f02894cd54f0dfc57511b992ff196963f2f3ef1c9df4e33c0d3724e7775196a5ea36f7cc278bc8ee70f63c0d6e984f941afed", - "0a08ee286b2bb84811c6b9f3e0ada05f1484c0e30a2ca805fdaf090e82076f98e543c3f3c4f66b388fd551e1cfb684f401b025f00fe317eefbb69f12c74eceb073", - "0b08cd200b73bc53058f1641924eff2777e94bbfe0620ac6245e733bb3060fd0549de0198294c16d4232e5335badd699143b3e5df162a176327d27a52b85bf0569", - "0b090c0feb18b8b30fa2665f3caa9d6b56579d9190cafda617924323ef29c294bb6d81afef8279a7cdb58683aa7cd89e396a5275fac26c55f7a4b6e1e20e4354a2", - "0a03e896a64fd7a9d7eec0da5ac82c1c538ddd7a1d2cf913da247ee6ea797f71eb6e638bdca4a015f042a2d24d5c56a72c4d16e0253c0bf6aec816a48024c8e805", - "0a0116d7d738526538319dd4dbbdc02b692a6fa904d5e38feda9eed5ef3fb596a0d6b32c4fa162810f8d1feda490859d184dd922c0a3932c317c23fa93d9c3af7d", - "0b04ea63b21ebc50c8aebc69bd4559b2c56263b558667d1b0be2034e150286fcd9e75d2c7cdd4bc9adb67d678d0cfe3b2f83afde09836a05a3a41067064b79c613", - "0b0200618ca803fc4384c6a0199ba478373e6035b71c773410b109148fcdedd96ba85a9b9d58ea67417f6b85cb18364e4b9b83143b96e64515e1e9697cf26ec150", - "0b06b6c1b5b1f39ae4439fdc08f5276a7e21f8d89455d011b1d517c2ca9ad51b169ea5dea4073e62ad664562b518904f2a7c0e491907beae2b7912a240df814137", - "0b01b1cc39f0a1a6908e06d1ee4fbd984acfd4a9d63d48729ad25fd283119922036b90160a7f56fdb1274c1b5eb1170d90129dcd7f47749e35dc8105ef855709af", - "0b004a95f30466567fc2248ebe32c0ffbcc65d430a74ec83635ee1b2539376a2a0361c9d00fb4bc688ac2fe128423755053e60ad4d15a2f23ac6917ba2c85870be", - "0a00ee61562746ae4dc1e95f63fba6e35cb0009e555219a439e43177315c7a65b321620bd6acd5ae0e01fce7945bfd216c16697158a9ac20537c7af67c62336e8c", - "0a04c31fe452717a37bd682f20f5fd4956140b31fa9d94a466774b6ecc66f19b9dae6a6a725a203311c3fb6c1a135765bdf3629b2801b26df5ff2363cc9eb7c2a7", - "0b09158b925968d79e03b7fcb0058e872bb04aa9542a5ffc733eb69319c1797555ba42e0a787cc4feccdafbdedd3e133465f6617710e497a178258eaf5b3125aaa", - "0a08a25b2e5a392a58ccf2a5ad62454b8e8e14b7daac5ee240b71dec22e81689e0bbf6d9a869ee65a75e867246de3e6ed511bd721f40df1a17a9b2df96c4565094", - "0a07c41e0af7d53fc45f12a01aaa70044e2bbd0e45f370911161919be5c0eb380a9dd325de7e12b7bdecd699bed9182ce5fb8103b3dc98ad2dba22534fa4acd478", - "0a01f05073a60c0e2e1ff515b40049c1219d8c82bc11d1e3250139fb7288a677bad6d90b0181fb4257a9518fbcc2e6e683fee184020ccdbfe856d02815a2d00aa6", - "0a03f032d42579028396981ef5d32da905fcf191378377b54b74f0022dbe986dfaf19156296920cee4271106d660c9eea7a589ca59f17586234db80e1b20685406", - "0b03c7834f4e1ff5a0567b915c80b124bea6f8d5ba540cf30a8f7106793c548570553ec77937ab6231f84aaca776cb8b23a850845b0496ca67bb816802e51aab8c", - "0b0855b215062e23e15d58d63f12f870253a5aded6e0a5ae93b389a6cef2e750aab80fb7549b0b8eee8f74607f6478146d1b1dd1151dad52936699cf13ccef707c", - "0a068a766c45d74ae568edac9e5ee4481419b326b2d60aaad9ab3292a1a2a0a1909e29f0fda1e54508e4a516647cca3dd1c9e3b80dfeeba0aca6ce8d75363eba87", - "0a005dbf33deab8b5aef669f5515ea9709946b0de7a319c5dc6e9e8762277fb017e7fed7bdce57c64cacaf08f865aca90c9e65b3d716fe40b36964975401211788", - "0a06777d7c8cd93243b192e97952ad1c7cfda3faf106452e84548b03d5f0206dda998d4fca451fff72bfaf923410a596d2c34c1d31e576e6502a9b8389baff5652", - "0b0698091f866f0f9b92849272f5c5cc8611434a007c868e4035579c18687525610edc161e134b794b8869e85d808a85d8ee00e23062006f509e5803e2bb73e882", - "0a087870cabec11a63f0d1888473cc607da49d70045b53fd2ed6d95dfe80a493ba25410a6021d52c674f6824a1192c8b930875aa10d05a6a443cbf6045d9a29bbf", - "0a029908ee3fbfd2acb9b96d01ccf6f60c721c0082873f11f78294b4ae1fa008314a315d9af4c6add7738b1be827801277ccf815416af3d2e1f88fdd2290b8dc67", - "0a01d5a168878d887711150a899ef7bf1f059a9e634ba1a0470e4b844f5030afd433b7e9de297666ac4e1d65a8fed52b5dbc3f86537f6a4b6b3ef169587529b5c4", - "0b0202a59bce18a27697e6608183682591fb56908115edf082d1ca9fd35c45bb9af3a5aacb6c6036db121ff69f14f7bbff48a4e728eaaec6add3ad0d23c855daf1", - "0b0613e2be8053b89bbc656f5136d340bbdb07dde6ba26cc34eb9efa611a5581220749932ac3110675a8fdca5c4845db8e11efb46a6f5c92ff5978034714b4df57", - "0b064127dd6cf2a939b35d09d63ebb773b78bd62ad86594b2f9ba8a00b3a1e8daa54712315a57417773299acce50dbe6ea48bc2d911e1b4b78e3d275ec2ebb61b1", - "0a002cc649ccb8448584f297752509277a870bd92737c7fd6c1869281d4313f88f44ac24f85376e402a1a68f185ea65a157bdc376884390e8bdd9fa591ea7321f7", - "0b024071fb1df29e82a2d6632d69b4bc61a0dba979a0162ff3beee5a0bd54e68cbe3e313c586aa2ff93e26394113a898096059fc4755c121be86dc6c7136e2fd7d", - "0b07c2506903290ef7f50a065fd7fe150e9ada6434d9e9d65caf0be9d464035a521cfb0cfc8a70c4bcc89fbd4991d2940debf5e2b6e3cb3d2999c7d8ffe366323b", - "0a00af47a7253dee9e4043d15d52b1cfde58432dbce12054c0d6cd718230210904af8ee45bad795ec2030b252f79362a0fc2bea5f7ef5fe65459e87a4478ad98ad", - "0b002855f3760323a33eb7bb12f51b1404f80221c32456584ca93a839799d2bc0b7ed32622fb84c742697ae14095005904fb6ac92fb7d4a8fd405f81a0b3b50392", - "0a040b0d94af11ae6dc67073a0f4b691b6eecf974ed305bf1bdf52c051048fe34a4e4b9140a90a5bd503d4b78f7c0353f82462b584053b738123e6502fd6fcb519", - "0a01efe531dfa28b93fc47cb6c296d0478eac6c7eb8735e51345f2e9757dbac563140589e588a0958225ec7fad353313968a5d7af875c2242b49299ad0038262b9", - "0b088028ceda4d8b371ed13abbb065cd20d3c7c50fe768d81cb56038a769bad4a5f48659af76fbe607bc478fca5e2fd0c29eb892fede6cffdf188e6764868975f4", - "0b00337cf096099315f41eae9f5334d7adf8eabad9c8aa70b77cccd33df919d52df13d22cf269587ead3cd77a6f7700c635229f4049901d25bb1c83df96c74f7e9", - "0a07797e04e522c8223e70afb87d4e6bf59744b9f38d272407e0c83e2fe942cfa17c55c3f6103a618f6283e1984c03c056dcc313e737d48a437e338dda9e0bca04", - "0a07d6addc50fc439ab2ac3ac0c0c83a1d9cee26b821d3f9b530733bca45f4866e800e6facc467aed6b10cc799815a3b69bccb98569f3b55fa4a6c24c5b558018d", - "0a0346ce07421aeed82dc427ec6e494e06122b11366b9d472386c401ec15621cc5064a01d372ab4299f228071147921a3c6397ed1a10b94cd3e5843b50b4ccc1e1", - "0b000d9bac9e35deea3c0d34168aca8ace393b62c8fc7c0f2f7ae289f758fb7fe2e7a40928fd8cfe911dd21db80a38e42d6a7d9883fdf4dd10197bbd6ed488f3ef", - "0a0870488eed7ce7a8bdf092a042c2cfa2828188a95c294121758af2bebe7ef08da5af608304ec3e52613eb0734d566496682e02cb98c8e1ce8d5bff426fc81531", - "0a0627191bea5b1e8dcb0f70533e559601811f517dd50d6ef2be1bd74c614d7cb53a91559613d46e4c924aacd11ab55b40bd2669fea0522f23a91c44cadcd1bba1", - "0a07a44c3ff00bd4e174db3eee000666df0a3a1191550b0ba38b04b115d0e284375cd8acb37b3bb563d3f6991167c428abd3f32aa03e36e79b3832441c5c365fb4", - "0a05d40ae90678122f3f45165cef15cab5b710298c63b027c278e6f287ca50334fa69265677984c4bce4fcb5bf9ce26993c041cf3469e41c724b55ae8643977106", - "0b08909d731a8f4554cfe807dd14c25bbad6d5b65ac8e36e80b366de156eede2f640d14aa9f43c15317c7722fbe6b4faf946e0cf5cc29fd0dd4917323e5b1896e7", - "0b01736a994d45dc2ba93bfca839f698c4dad28d32e19e5e4845d2f1851f7a8e84e55ea1209561d9396dc912a6c84f54c3d1318f7ce50b64a122949501b9ad8ee8", - "0a05031ea2dd383f69b3d567c91053ddd24d8c55b8b083a92173c52a303cf093250eb4896181951c491397f55b4d77d2f2b388ae21d5b1a06cb252c1a0949361ae", - "0a061bafbec6543ae3815e4206116269cf67b5f7bf802f9941036ed9b397bfffb9e1387928a962d3ac37b5770744d9ce8931ebf45b3a5eaf7552a488829566ef11", - "0a084bb29da55ac1749ff0a436a61e22fcf753f2d5078ac791276f59f8527471a46f30be0637f5d5cf87e22c89200b6d83c8b3d35b65e14411eb72d3eb3260e852", - "0b003f3725b9f177785b0a4418fab1651849247deaeb923d04a81d0766ee226c0ac5c10ead12d9391446d285d1f47496b41c8603446e503d52752b82ccc3634ba8", - "0a073ecbfd31cb5328c68f5c87cf2ae80375d394f98ef63491b7d77f63527da5e7708b6db7e536ec9dda4c57d2c4cec990f581d61c4870d1af4cbc38354b090bad", - "0b042073a70b1db08d9f28e0ff0a4595d41fec126fa518001ba40be0acc6a43d05fe1bcaf816975073d0e008029c55e7c9db05400a8b4c9db817785c5897aa351f", - "0a06eff36bd59bfff0e1e5fa8127a9f4f893de091a25daa7d560cb83a48d54c1e94400927c7560912246ece08f40faf7c2151aa18c26aaaaf34b32215be4150bc8", - "0a084f3e792b4031b8b7726162a01bd6faedf73c5cbdb33d1869482a4ec89f25697406bd075fa65b93172e520d770874437714e73a28291d426c0bb3fa46c9bb16", - "0b0891ad95913ff74ca72c7fa8df5ba30ca7597cb29970c82b6c40518d610c4e377263ac274733ede4c747cb35c9b01bb6e2bc6ea265728034dd622faba9f31446", - "0b05e811b22d31edda8244d624e03412451e8584b08547ae76bb46ab16874f97186675ad019266c53e68f7a6ab13e7de281698058d591bfd972875709ad39ba4a0", - "0b089f8b2a77bd45b7b38bb9cb6db641558221692832beb0905b001b9422da4291155bf4c986cef7a42f27b1ffabe01db2abc82e53c416bbed4bbd8cad34436a3b", - "0a01d313c84cac9de95bdad21bc06cb73a12845d3556af4ae3032888658223d7000a778df6be74df537e1c3d528440a50a5e93e4f31bef0263de67279cb7279226", - "0b00bf78bfdb250695a4ca553c8222484acebb5a922ab44b0f4c81243778dc8046655617f0ed15640260bb532cfccd8714e5358092f2e6b2acdf57b2238502b305", - "0a075b5b7ec4df03c4cd06933b81bde8834d9fc7367ba395a2819b13f7cf512695ca53ef6b1516f3a4117900ec997120683b6a19c0b43ed854f5a806057b955346", - "0a05218bcab57578609a56fe651be9625a806785ca6b9a77b5e606002010216dcc8068442bda287d1aed50bb29915c3855afda3149246c4211f02cfdc479ef8510", - "0b004ff9276e7fe7ea5cb5b24aa2ef2c714f23ead653cf264b67d59fbf3744d1cf66cb1ebe598b781e22408b9ccf7f7ea076897887b83b8da1d2588a2b05e55fb1", - "0a068df8f2710689ec79a1758cff20446ac76220b49a94ba35958ed8854247cfddaa668e8fb2fde8bb7bc3c7dfce38dad712ad12d31a3ca2a0c58ae56e5d04766f", - "0b06427661eb7cf34af980a8b946c90003413a1d059803e36826180ef87f9c87b4e1850373d2b4c2e8eacc5b3301a71173981564b25556af0fb6ecf47472559d8a", - "0a060b8efb188c11b224e10730a2fdbd96c87456382964a909b3573c720d85aa22a1cf1927611db309898fde737aa54d5f069d426621e3099a8c87d5c1a4b571f6", - "0b091dcc549053dbafc72a8ea89c79cbea9bfb3830dbf671293a32e3aa673d3e0d05a15810c7dacfd33db00e07c3073754944c024604a8ebf893fd9b1aea709b1a", - "0a061d6d7ef58165a661ec8146a962a626519ad152955c14d549eaf5233ac732c4f5a8f553afd27c83bbd13c420ff5c040dbc942351a879316b1a6a39770986ffa", - "0b02079b7b61486a7ae37dc649abedcb8194d80467eb1fe2f737dccbe062034418cb9289fff8be3e508660806f02308af40b2bd8a29b33b968cd1b7c94979418aa", - "0a00629b37a424e230f3f99d56be314267594c6ceb3c338848b0af3a9a5b08e7af6426e721bc52343826c8d22d64254fe753a262dfcf54ebadbf31bed74622ee7e", - "0b0232f948f6aa8aed0af6e28cf5623873186046c9ce00212df289db3c04bb8192915fb3ed70ac27cfcb0e39d88ef22aa7eff7feff1c9af3f7908cd7c9e561a26e", - "0a078097a7cd88eceaba4c116d4b4d5404661a64cf440ea0962a638a27988d895d1d20621c737b22ec0219115644b2dd5491e61dd8b857c02d90495323a99cc111", - "0a00d44ae231a24499348fd01964ba9045122a2d5562bd1a511ec1eca2e8f732b70bf28a84c987b881a2ed16343fda47a605920a709ac5525a5cca5a14c7c6cbdd", - "0b0411f689064ca88dc447add14a593b159a976a5d5208197092dc0432c6fcdbea4ca7ed1053180f7c8ae43d6ac243aa4ab11932eb75333ca757145b0725bf0e10", - "0b06975e7ac9379cf1309c7b96f6af6681743c99798e42b706a0740d750b8c836e29e002a0bc6f566f47b4fb3b3385cc1d1d97b5e31ccd522d4ae38d97ca68ba68", - "0b087050ab24d1cdaf143f4ee398af84147e11dbb08ee9d63a78189820301fe818ac71208ba101f36324c94728a6620d652d3a794842c12b32865e74b50143ab1a", - "0a07f2c9e6d15c5f0fdff9912a391d8152c9661bde874e2aae78c77acd226483ef5d1e82fb24ef8930efdc8bfe335c55ec6d15bc1aae72ad56e1a275461afd4cff", - "0a03313d3630d982a8bf83884b68b997a00049527d83995a2c52411057d2c9badbe04561746ba80fcb3d99218980c7790a3660f136bbdfedba842f08f21a9d78bb", - "0a05980a8c4ecd540f3e6c2bc9bd33e1c10e5d36b80406d1af9b82e5abb787889209607da71b15f0dff07ab48e9ab1c5fdbd0174e1e5f79fc627ee2ea3ceb8b0f1", - "0b00e63bf17dfcd4c7516dcfad0bbf95db6b0abf78958ff40b4f164814b0470a5e1619dac42039628ad7e60784c03904086128a7ebc98b3b4fa28d028cc905f495", - "0b060ae42ead6637d273ea1226c3bd27cdeee49f225f614e0b0d4a60f69588c957a35bdae52bb0255e92c68367b1ee2d265b83c2ffd08d33671dbcd96869c848e1", - "0a0016bb6a3d17066a8731bd78b587d7424556168a0fb78a59ba2d1ebbeb9872631ab6cb15b4065d878d3d9fd96aa3b8e4ff1d503610b65e64bfdb53856b5eb229", - "0a03e0c7dab5ae505d4d71366482127e6fe3bdf12e55ae4b8d28f4cb8e5049b7f51f88567b8503f222cb244e2cc6649bc3d6d3bf9eba2f002c244ee735d01f7495", - "0b04823fb843353917fea0b37cc21af55d1a56e51b486f9ca61facab3c756b023d46f96145e0c58307e1b8a5ce2f3b458256205d98424f64796d6a3dc627634843", - "0a00766e31bb64daebe86186bdfe27250f048b9e6d1838000205a5ef5a81e254b00d6530b9be061a275a73621433ee0831b89961cf4761305180b8ffdbfe1a27f0", - "0b07594ae2f378edfc05e045d7d86becd06082ef286379b5e5877bf0bd3855a103652c0e96802cfef8620391d19838d17a92cea363068d7c6700243c198011477c", - "0a033961e978170466a73b21d5883c2161e2d42ca5aa6935b959c108b04fa7f0bb8186fed9db35fb11d3ef463b0e7fd36f44094774886f63baae8c7eb4e00d2c5c", - "0a01b6b58e5e1e4e5975a7bf0ec57f886dcf854dd5c46e5c86eb9f9f9eb84c4ee1cbac776348fbe27d2e84c6d699ae0e933e051cad12f7cee5eb8406a3ecd6e5c9", - "0a03cfdfa79e0c7bba8ef3efc44ce7626c12ae2b09f2da425eb03c0b2ac43a8ae180571717d2bd39701be3532b1e1fd98867a47a60aa6cc08e3fbcbd34571f6250", - "0a07f49c8b9d63e2630317869f341722bbb928975a5d14c458251c37d809eb74555fbb43f60d11bd56ebbbe4df4471f67a540e10c4a38cd76275a5c1a7057a205f", - "0a0320772ef2c8315a640885093ee65dbc934b9dbd15f46a11fb10db790cddd4427f1b78aed80cb0812812b62384bb6a1557280fb6c095303146c1b335f7385045", - "0a05250e98fe65eaf824c55e596e3d52992f59c3cef6ea5c7526768b9915c96465b74b02f3bd615553fa6d096ecb21a580093b20961662f32935119c112b3cd771", - "0b00d270c023d90f304634a382001b5134376c57689467b2bef3c7ba9c4a37aea8a0a0aedfc8ffda46efe09fab70774da5eea7af346aa8451eaef9c8fc9232bc50", - "0b070b7dd4c94c2e7b19d795253217a7d120831d4b275633a60f485152eaaaf8c6fba726f91f6cf7b6ffb38e26fc36b28d6d990383ddb5faa26572cc61b3b62876", - "0a029ea4f1cf4bd1cddc0ce225a7ca4d12e4ad095bea12595bb85f3b6bc63de91e37752a8ada68880378c1a6da8ae43f1ca923a6ca2075491c0de0ea7d67638307", - "0a0671170e42947610d92d78508045978afad90193539ff4e8c0f89182519f8db471a1ab2c450534ed00fc2c4700d26ac0ed3cdd49d3d36fe90e0f374bdf7d321b", - "0a0110da6ce6bc66f439be3c437c2e8d9dbf6f63444b39702eb58cb0b1eaaa389a897d8fa214ff2fcd5eeaaf8d912022c761871be293b66a0ef61bfc9f3742f53a", - "0a07e1b25babcc962e60fff24e4eb6d9022308f21e7da23183e3a1b88187ab30831b086bc8acf560b680a76723544ec3b2e7018d49b4011d028caab8cd3fa42d2b", - "0a080f3d589dc3156df224a5c8fae4cc65d25b458def475503a569497e13cb7fe650cdb536cc602536008da930645cb4d8026a3576882d9c5263bbddb8427dbf95", - "0b091bad1bed6bac3ace62acf55c7492c759e8bfba114fe1d09e2ef651ac8bfc6763d06df9264b36dc97019131bf8a3e555af9d59725dd8e39e94f50393846a455", - "0b01418af08eec02fbecd50a8acaf3c9e06c713fe37b2748c5f74aae62fac9188295edffbfa3ecf32ef3feae7f30077375ea271c8a566a2bdbc3e84e5d360d63c1", - "0a03d137f81c51811e7483aac6aa088a89b3aec5e6a41b85c2950cc4c53785417e9d060d4bf0033256ae2b017334f5fe4d40850157dc15504c3a8226f2337ae7f6", - "0a03d1b4623ca237b9dc4836f05327228ab703547dc73ff4de65c57bfd265b6a8cc44926fb4f227d5907ab65b5030c9cbbb236997b5406a74091a914b418ed1847", - "0b057be5d40f88c7118f0c2c79fc5d380486e0c0b662a3ac59cb14bdb5ec703d99ded4864d6b88f5078efab600aaaf971b4353a7b6eefcf15e978a297064bf35be", - "0b087b7a976a7433e86ceb7c65ee925f1448ba255b18b3cf57ad18735983550ec465e03ec7c9a625ad69127de7c85822312146aa7b9f1ea7fb7bc719a1da443081", - "0a045596fd6e1a990063b2323e5a070d15dbed120ea764d1aff894303bdc841a771d57a1fb677880a38c281bd7290e37842bcdb020e5a8bce98c361957854f350f", - "0a04af7c70aba4e8cbf4f59ac09cfdae09904b19dd0ea5f70d103cbab7890b41fa4312033189094e15602d11a3d5ce6f5cf7ae29beed049054e7e9cfacb0b652bd", - "0a018fa0c1ae50fd7cb42a3e76bc00d8f1009ccf771843c71ca7592742412b5055f9ffa65e200aec178a0bfda5818a4868d8b60fb36c6e4af9e2684e44410b1afc", - "0b037e03e015bf26df8c85692ae774ac1d426fb0e4ac75313b18ab2436a4740ceb20ba8bb2b24567f4bd5958956be04eaa8f8a52508f65a8083b0b097746e42313", - "0b05f518df5bf08c7224f756f8634132833643020adeb9e737951eaedaf90082b4428bb666da3b5a69c2260e199b9c8880773cde94e22a46f067bde4f3ac4fc0ec", - "0b0483f8174d8ea7007466cee9c3bad62df3849e25072d32be3d05dea8da0dc572bd1b4fda0c916eb0dc2df48eb58292f2801c20f911ba9c5d86fde9cb6eecf4f4", - "0b05ceadee3b3e15b9cb8e7283a64eb4ab0ea91c3ef9f2e17ea922578e94e1a0fcc8181ecfd95696bc855cb5ed46be437e9224ce02f9ea4b5e36dd4322f3629f2f", - "0a06eb1bdc711a2073bd80124057eb4725de7d8892762a9e38e0bac0476f0e6b8f4423481af427956d865341e88111652c5a34cb6b9b3a6e9124d851faec913f55", - "0b012dd61d17a73bc21dfd3658f922646d9699841925291e7e46a7310ab6b84ad73ea281f76a68e73689375fc5d98f4e595a38018d511cba682470b68067550d3f", - "0b04c48c7e622d2e2385efd8f6099b08e45786040a07d5d9939f8a1b2fc610e8e53e529547ffaec4e1eecfbf231b20643bd68285563abae353c937e993e620c9ff", - "0a012bf3f68fc9b3067a8fd3afbedad139367234eb8d07866a60b423addfbb22c33ead42ddae0dc3786dd0d49afe30a35f968c64b3decaf245af1107a9c0fd269c", - "0b040b41d11109ad4da730bb4daa94af723e4b68821217ce1fb4e5d090cf63a4b7d424cf192e7c143ac46c201b11e5890c4bcfbc846e1830617549b7861035f537", - "0a068569655d8b7a75dd3ba6c33e347011580d94af66a7abb14378719b56e038527646070887503a3a7f2d81f1a6e529f85360ef98020042fa37cbd95fb2771eee", - "0b07bb8440614aa98c51e1f8f2d38fcb1556fe3e8b0c7c46e5def82d0346dddb561efd2942a901a45e82daba2d2578d34c1479a97f2ca0690573df7636725e1106", - "0b08e5431a1c883ac2a271eb180fb0b4fe70dac5fd93e7dc6a1d6a08806aeb798a7a1ad5dd4848eeabbc8686d41f9977b8116403897f019c20253a9b639be9cfbd", - "0b06552cc40ed4d4878c5cc8d2ea9f0f0e3ccc8b34a88cadf5a1b18c2c645803e1941b8d8d36fb125e24404972110f7554b4a8b71ed2412de8f5f9b73e21d57d53", - "0b02036b090747b30a7ea8d7489f71d7546a702d1c555a6deda87bd1dff955fe88a4b715ca146aa03a954a3d45d9fd5dacb8635415b77f214e232e24aa9ecb0129", - "0a07fc4692d407e2e236d216c99d35a5d1d41902280dcff67c70b71d95689ec18ba2ac9b971cc7a894c2e761aff84aaf9d6f1a4cacd221fca1964a392213366e2b", - "0a0723f1849c33cd2193549fc390b05bf0a3a3626f7be718a2d375f6d29df488fc330c5a8f926de7a106d52ef43c399d43d9a0700a6c323e5feb64b90ec136c586", - "0b074fb8b63400f087bdda78a33e016b0843cfe46550f5a8b7c27d910e125714af8c93cdad6e096a6e39a435004bcd49fb29f4888cf6f598115386fb3f2fd9ae28", - "0a0235608ac0f20a901cc9e90685c8ca1ce0698a80e2a2da52131a874576f6a3e4a0caae8a3f72667e8b5886b46e170b11ee23597684038ba1c908dc6ee06bb06b", - "0b0196b0e868d040f6201325229347658c6b4e86ca7d49ec3ed90186d739b98ad22e8dfa4583e1d150c597d28b2e6870773fd337a1ae2b00ff305741a128849500", - "0a027aa73377f6d30eba89421c63e4b3c723f67cecd79336b684de9c8aef0918163ce21683879287efab7ad6a83ce29edf06ef19007d10928a38331cc01e56758c", - "0a0821cbbd1aae33cfddd5b9d828a0f005dc731a3b7b4fd8f69ffacf6e8f791d9bbf676cdcf6d790a8a4bbfa20c2fd586c9ff5912b79caa5634f692c9478ba985c", - "0a042e543380a80241c844b0e81231a6576c8700e4d0b27b11b7753f39c4ab3c6ba956687734698817c96262d9010e133948b155d9de4f0317c9cd62b399036d2c", - "0b055e0b35b2eba8580684bc7301f346551c128ba828e9ee90a2563a64ec7091a9676438225f76649929cfd0c1a97ce1b4d7681ddec0a22919f1ce6ef6d40abd1c", - "0a0060a16fa9c446310d29314e38aa1b6e979b54188f87624284737c2f935d858717007896a123bc528454d0fd450ab600a6a522da7a11f165aed33a6b6e849ebe", - "0a02b8f8272b8ec067dacbaeb94bb524a1b3a397ff7b6a8fdd1d119fd4343a06f34903201274624eca18b5f44ce709b7c7ec1f8e7d874eba864a9fef734308df38", - "0a060562e96eab6a0d089352e559c3edc53b0a0a8bdc68d80debc33be2c9c7e768ca9d9f5698c50adec87340d88329268c10e7e71522803ae88814643d0afaf655", - "0a08602435364e9e4972e0c101e7636963fcf396b650c67b3851e3b3753acad6dddcdba7a4ea9c12870a9521e6be111a0f0f7812a2a8222f517be25ca64acdb631", - "0a008431c1a3f0094557aa28c69a6d68bc7277094b803650c6e905812029e736581b64e3c9d1e261af69865e61a2590549c9e7d49c7237d4060d43e949181313bb", - "0a0332f61ccd2cc35ca4c52573a3f2c65f1ee13c09260c5d5a5ab3e9cc5882533539ff68b43b697b47c1e0783912524c49d0449a5461d16b8f83a35d3a988a606d", - "0a041511796c8f37efb12ace8df84b64a24b3c9b7947e7ec7dbebfe0365d5337bb06e302cc3c3a1aa30beb3e548d6c57c10082293f2c4014f06ad6a2f148641a03", - "0a0449e507c31e694583993d52db5da0f1044f2aa55d9a3b61c59ea49a97d38863cbe915886210ec6da943dba812c59b73a0eb6d41c0fb0b4687ccd3046bf6903c", - "0b0186cd09624ef8a756d12473786dc63aa8acbd68513503ab23271b5f9a57d2da370a06530b05cefcc856bf8d2c7d9c521f2e9bdbd9b29f9a71c1ef7143476874", - "0b018341a6abcfec39afbfd29a24ca071a8e98e513347d9a1184bf011f29037a3af890bd8519bec4c3d5f04d51dc81e997e69c9ed295bf783f2fe50aa7c2e175e6", - "0a06657a79f1ae68bb66c2cc54cab766da52de1a5badd389d542f8306bdb33ecabbe4639f4a84f6f528c9a264e9f1c5156cb57bcf51aa6509d1f4380c7379fc336", - "0a067c6cfe28ba5f775eca44bd6714113d3bd95cf11c67e99cb30294108e0f8dac9d3ac60bdd4ea5c62d949dae20507ceb0c46986d72468b83dd412bb1484b68f0", - "0b03cb36546303ac1d1cb95cb88d9044dde93c179ee58292a973ad77b81557899552689869edb1cde77fd57a36bd6e9b3b3ab15462247fdbfab1923e78ff7c53e6", - "0a03c5e8fdaae529c49c324c7b7245c3d48800426f7bd2c91d492891ba0f649541112840279c6c4fff1bbf0d59603b49d18ecd8f91456b71f470fe22260725d97c", - "0a005661690058a8215875d7ff079e68fd4bcd5a020d36da80b00bc784a8c7fda8895f0cf91f553619656cc6a49fbe803059fcc023efdd514d07fe331e35f6ad7c", - "0b06dff9d33d3c209ce7e07ba2f717b1f5ad5cf5e09c1107251c705283a1b10a4064536bf46cc84e29d9ac94861946fda60533eb84fc292ec5d419aa6de05af851", - "0a063904569ef6c7438a6a9f1333c673a1f05dd5db03c4e449086d5dc116f219726136ec9b1bff4cec62a1bcd55cf52b0fd101fa59257f63b4dfcad23f0017756f", - "0a0232c02a05c77575976118e3ccde52709323efcef1a19d3c11e6873eb25eb411d9d64fb4310efd831d98312ef9f299e7ecf627119a9c487def6f016c72f4d947", - "0a040eeb26bf5c3638ce423af5f9d1a96f0dfd2dfdb67b79a1e45100b84b56664db21d4650482d4adcc3a1c21fc67d654bcd13a7b10ae415c304ca06cb6b764e3d", - "0b0860fcf0ebed43529c312eb73163d821e4a3d6708ec7b1991e9c84df7a2e9a0c1f856bd88d598ae293c44e9025a4848395febd83fd918d8da4289705417750f4", - "0b06ba5196e93d313b5f5fa8494933d310e6c719e9303c2beb6146bb55c4ccb3032e17cfb5b421d84bae0e96aa9bb15635b7e11b8ddcf4ff107a82595e5afa0e80", - "0b00c1241690ff26d47a943ff17e438e758c24d05c9f5a6b9145e362179aa226068b716bb944c8287060418651849fcffa600bb0aed569ccb594a28e1d97b223ce", - "0b013b491ebe0b33d232f8fd744592820649684239baac90dc03ad3a80120a36e24fa68ed67c416920a5575826b12535566072df8808e534e69f206f5b7e9acb17", - "0a08387f32a18e9d9630793fd1a6d36ec70d910c237e7d18ef5de75d3ec3bf0eb60c44284beed447fe49242c34a876b5742371346061419f2579647db239e88d92", - "0b034795778bc9e5b6d9cdb0d1dea5e3b7484f3f307ad6cac2a6612d8b0aba3d9c89990f2cf8eb6d3dd8deb3d32b3a0b24291ea9e454ddd91110f6376a9e7ff7d2", - "0a04f0bba715fdc0fff5187501aaf8e6ce9596dfb1ab2deeb2b27c3d6020fac91ce43febc4f1b053a3945523eb6fd5b2b80f1e366936aab3cf8fc848c255387f38", - "0b008942b86124966bf6a0d2dbd5542225728ce87903a9e8ef41d42e065abc7e66650a2d85df0b36ec2423ac16526c69ddcfb99d04f220e643058a2cec42cca61f", - "0b0124e674b5daa4b717d00bcde86092783b08465c1d9fb25ef473637df1c2072f17efb41f493b02d855a252322c3a736eda4d9e45cf7d3e1bed0c71c705c9c79a", - "0a075d23d93d3fe9fe435f504c944b9d6892e336d78422454f049423a24031e1eebdd6fcad32c4d663d2c8e22bfa99451620d4d92fda1361b13607838322d11595", - "0b02f08bb55209b003d73f7659c022882d8e6948f7f3663b23e307eb2e91efee7f55983181ad49ce7629bc32eb4cd67b89345c1f19cb7e361d250448c943ef8a00", - "0a01d5dbf12fbeab02fc252b98a1f4f7ba90acaaec6374278c745d9283c589363e67219c2ac5f45287adc982d7673086c8e21db2004e83620776a468d1ea942220", - "0b0792c903fed7f18f6b6599c97b15dfd4dad8607b502fe83f84c202955c4b33005d084b7a570eb961e4a1dc09369937541cb43297055d9c61111d41839cdb8271", - "0b06c7f2a67b387b057a3de70db0acc50efc9226a30ee041b1f5c1e3ef2a74ff4957f40eeb45c6794a131c8ab47eafaf6ae636c5490553160d95121fec7b322f9c", - "0a020089f50e7ffa1ec420fa85fc48cad60adb4adbf415a3307fc0fabd24ff9fd8eb645328fc25f43c5d95ce7de62054c791efc918c29d933a85ee9a42ef203b7d", - "0b03ab573f3adcf10e601b304fa1c5f7689f44cf4e8f889817c55ef0a13969ce60bbe12aa6452d43e3d304d40ce9106795917d8de34dd5f02771b0bd68912e15c0", - "0b05df6e48e4e822795ce2a2d62aabdc1ae648c174a6fb1166655cd5f4f9cb701118852b9f9c4508a923c3d8f960fbfd244fb94a163c0494c273c089af7e27cc36", - "0b06f70983eae075057e580c05c3cea6202ad8c44804c462786389eba6fc87faca2754714b01b208cb19b624533c8695e93f4f32142feccd8fb6c290a17f289136", - "0a01009d9571a231a061f0b89aff109b5b8d9eb5dbc2211bf5bb38c569989234d923bcce5d5581368cf6c68c32e6c316c23015fb9dfeea8bad3c9fb411bb847fe7", - "0b04274b492bf8c8712e0956464818ae1d058f696199641bdd8d5d2f9aa96ead4226647b6c8024d3f9ec76bcaacc03ca63afde3534ee47cd0fafd1283a87b0db56", - "0b0790a40b60817f329e8f2ce115acd7aa2d7d51cc22efd874f156484c87cf5b7dfd0d1e2ef9467bdbbe643568858fc8b440129b7d0976ef27d2084fe37cc92c1a", - "0b0008045f41044d73508ebb660bad575b2765ed0e03ee4db04ae49f641599a5ca9cf7abbda4ff87a536529c128b0245e199d973583ed9d16d9d2315477b0d5f12", - "0b055f24c5644a798f4a5c7a3e779d7f3e069ecc23d4c700f56c2dfd2d303f37ec6187d454f2ea4ba8879371165cdebdb2040732b90d928bfa0451f9a63bf98635", - "0b04b6e251333af15559c4eda6a9f2ce4fddcc68dcd6e6f0a86c19739ca20e2a4d4a2a665b2de8b9d3ebf43b8feda80e5ec26ac64f96c1dc8388302054316dda4c", - "0a057e5f9e2017741bb2bcec261a2308df3e8ae5d71c2c73f5166b5a1fb8e169a014d83ec04cbbcccecbb8399379a9516a123321e1795ffa42085a84ed340cb40c", - "0b03848bb27cc5a7adf3c0489c0e0f737f446dff8a8400a15ddd050cec2f045b156791638a70ef42486f6b7851d1f3ea13da7787f0f73ec837061fb3f8cc7a9fc2", - "0a05b883a335806b420744b9e24380a6da02360c738addec1d782cb900cdb0f6f4eed9af1a79ea9fa4587a07870e022a353d453005b91f36d6e6310598dffcd4ac", - "0b09201ca60fa8d70bf8555cb0d75375699d4f395266b168ad51d9605518762634a3bc93c95f157a588aa230d79210e57c20cd99127cc65f41821458a5b92f8329", - "0b0359c8a2a9e63c761eb42b38f12535e4778b74017c9e36e16cb4a009dfa1b873fd324ff35ec7446f1d0c7f11b206cf749ee09ad9419ec50e7c1c93d37dafaf2b", - "0b0528f6e76d6e8a757d29a58e289ffc4703c2dd2b08431de2629e3e6aa6448fbdbd3f916c554fc7a3ab529407fd867f2829501d315c2724ada9ddca9b935fce99", - "0a03f40e16239b45fcee3216014154bc214f748a8b8e14edda2d7b81fc932f3afc163fa309a4af5ed7667093a47bc626ddaf2530b0e3e8a8e49bdf7f457cb1d4d7", - "0b0378c2d38aefb839d94a95a3ff41db62b881680725c5c2f14e561cfa5a98923695faf0ffd22391c93f01953b177e8dc0ca1e9ed41806dac6fcf93e263c0bc65e", - "0b0678288101018ae0ff23f5ed6586fd56bbcf1933d11069849d8dd96ca3c754cac7db74b83e2202b2ae30cc485f82d5f50d379e0d218e0b198431a3790edba030", - "0b082f2bcc77a2d72806229c4de1e63fd81ed8af0d50de8104d1e76056350b0f9e1917c0d8c96170b95a90891dc238f42bec4e0ca7f7440c87772e2b3b2f683328", - "0b0017afdab4b0e6e291e68a83a36f635c1dbea9675e40ff1fbe1799739bca8c89e5948be6369acf9c86f3a73be41eb317e7def16d280d546d77a7818680e06e65", - "0b039a63a8bef6130f8d177838a9cf2ca8eaec8ddfb9afedf3ee409111000c36bcfdf5418629abf64b31bca9e52847c22be32da3c84cef0fa478043c603dc21463", - "0b01005b6af2110809bda214f80c427709c45db01f1278d7667ebe2c809c6ca3e3def9a3a16a05857c44a8664206776836dcc8ca297b6f446bb1b4d30f5bf2eb33", - "0a0224abfe2d0a433ac1ebcf3bdbef82d2f00282e1e6cc76c12b73add7bae694a5d2a9dc8f76fac14505d7dade628ba1303625efa57a5f15a15e463bfa83127f68", - "0a04d3b61859c1d9c9c3acbd4ac5b07e7e2e6dd540cc8e32b904bc8d7c6baae0cc7db7db671ac856ad55b310d6ff33b18fb552a3d91bb258fa733181355702684a", - "0b013c0153ef6967c246fcc17da960121a7d355cb60f90f5be53a2077f8b69e14d5a26d3d75537c74c11f885d2206578395ae81e7d7f6c262ca66a22959f7554aa", - "0b06e04e0d1a1286eed99b370ec3104f853581f7d4dc05f5e4995daf17c64a5fe4bd3d01922412ff767e8f79425e9041d231d5076bc91dd68b31a28dc5ddc6d910", - "0b04589f8cc2cdf57053a0b1870362ff44aae24b0284a4e1206630c0af564c79e667b11016be8b81e82f603ab89599c411f89a1e0f496a8ae52d798393f641d7c1", - "0a009395ca185b5b729e2c61a4adfdb17c5b7eec82d3a2e2b121214f9a4b6c1548bf7c2cba731c8a2e9f5aff0501242a448d21e271a8aae334c814220560bb94a5", - "0a075acc173986631ec450beef5ea1280b640ba539239f806c583a6645c6f7138266c8c2cdc5fc0fae0302b2fa5a451a02a5f1e778f43ff47bf35e47b99addc144", - "0a03da57ddb7c9743222ffd11bd2c980638b46904d89edb601e5a8417fc93a1f27bce43718e691f1ba94f409e80015dd2a6ac238778c3bc05a091265b94f417f42", - "0b0522eb5f0e318ae3b481404babc0908c5ef0968e026be0b387fe44b0ed30d6f257170c4edab77d4fc02a78c8407f30dbc68f515b9a5903fcd87d82ff0b26a406", - "0a08c498751077433cf0aeaf0a57f31fd3a1ce73e449193144fc6dc206f52a9872f595ec9336bf8b3f98cdc73be696b5dd817e7964fe6fd3dc4a2b899b7bd18456", - "0b01596e5948f1a183f08165ad711f8874ebef9f156829d4b1ff00341064749b9d4a141a82cd143f3c56a639a8a0697a2f99aa3d0fbe9194a25d1e737dc4d6599d", - "0b0257fc38566c24f8a167720f5dc69c66ac71ea922fba496d928fa14aec0a3299185c6771009db8b1bf7c3631c91ecb92a45e02c14ae1c98cea1b4fb3a24626e4", - "0a05437ec322d716ea6e020124d9856b05018cecadce9cde7dac5885a8173c7a0d07c3ecdf395c49368c85d52e147687585b1749e80fc54c5a36271086ac14e82a", - "0a023702ba46f5044cf4e1d0b215de43bcfc18362e4c94a68db1a0a5a3684c04c4d79bdc3b6e8f32af562a6cdcb89c236cd2e715fd2867f3975c768b863c2fffbe", - "0a056e0226a04d193e5f12dd8214d827df382f28fcc0f2c0784bd410cccb0f81064a9a1d25ed6633a5f92bf379ec8f54315c14f8ca98a2e448d2951ac891ca9bd9", - "0b0560bde4f63486444d73de6e07dc580ae4a00e7a7e30c77150749bdb35b1886e79dd6caedc602ecb002be0089105bc4bb0e1c39f8cf9ea68fd3f77f981d3cfd6", - "0b018121a490be6ee1a9d9d2fae52b881fefd97efccc900c93d4d9a7fdc0f2d7f957cad2a62efdb7433204ceb084189a3e8577058b5d4f553640929577f674fc99", - "0a00414facbd0f4c4cf45735e46644ed52f0df3fc8c6499795bcf8c5b2c11adab20f481169600339bcd73c3660c0404de4966118dfe810f6145a73795bffa761c2", - "0a0106710c490d405e2c0f69752fdeca8ba85362f6ae3f046c231370b0b7750103145b3d37060fe1dfd504cd2f32c38cfb9abe6049683e9f3a7e0d563f5940afd0", - "0a01bba2df29b427f4e57133a70dc7bf720e3e10a76a7bd3294fefa885055cd4c49c2b50da179ef566a77d4258153c7310e16b3dd85be16f33d038b6cf51439042", - "0b070385794b643f12839ff60648f877c78022fa3e0925ceeacb0af903220bd7f8751670813f8c6c02d89b8e08ce590c67c06eab543741501d3f2143cda7931a05", - "0a052eca3d172050d421bbc0bef0ccc24141fc6013a0a578cca4b623a556ae2a21f863a5933c394ff0cc67451d2c3013026eaccdc5bfdbdda3d8493685db2430dc", - "0a06be5524ee39d3e547c966febf8947f6b68e2df6c7d5f1b49780ad3d4e6f8012403fb4707560d352e1c6f4954e849d2e4f788dfb85c8f2efd6d6e65ddca1b6e5", - "0a08a009497504cc35ff57a73723ff634cbfe6a4375d657af3f181d34bb3429c3f4813223fc70a7e208a8d9e97f3a58b9dd96d93a58faa14aa4cae523686750e13", - "0b068e444b125ef07de34591160633a0376a8d08a49e32ca4aa95b55e0f275fad4fbbddd56fdf725239401d49ac86f159dbad707742669c45e47ab99875dc60e07", - "0b03fd137232943b9ccf3cb90011bed677554890cae6b5e9c51cd3a8809f0b45ee3b343efd252e54a994c31b4dfe83fbc2189d857105e3927a585130018b385477", - "0b00d0e9f06eb5824e6b1a20ffe6b5a9c0811bf8373ce40f8892a8f4cc21fdda195754d01d8100bbce2f9f53e585cc59bbca8ad1206a3f046b2bd1737665342fc1", - "0a0905558498f3e6d9e795b65dcdb1c4bb9594e46640c4ce08eb52cb5014a730cffb8e15df8ff735cd84c2f6327b1cde50a66774eaf30ac08e94fe4f98b55e6b74", - "0b0398f40bc04a268234f39cd60b3b1af858bc1790a17eb33d1864136970c22fe01ae3769f13a99d0b0294ddb4dd4d189c26a3644017d4c42b575f4fd333a567bb", - "0b077ab876a64e726d1203c107aaebeb72f4d9c5fc687950e99023757ba5daea49f3f14e237329ddfa06fcc44ba41120fdb5a0430ace5f13988ea3d7d72888b314", - "0a01cb99edbe47831441fcb085835476bf2d6f1394ef9e737652844103333d642e84eb236945a77a77e3f6ab5b7237d1458f5b5fe648accba956d97875ace41822", - "0b065b908b40ec1105c6eac6c059a30a85e9877b3415142662cdf19641060b0bfd7b428197c6fb5d41f6773a1f405cb43e988f4eaa2f62dca34d846aab8a819015", - "0b05cde6a140c9e3685da634fba1532c854c3f966f5989418715e930bce3d2e5788efa1222155b379ff025ffb3ff91339a3bafb03eb20821be0ccf24571fcac967", - "0a03cb216f459908ff10ee8984e578603ec93ef764c439f3e67be4a8894e65ae921a982f7792769e995f74d6791c4cf3fab6ce709dd2183043adc395fd53a27417", - "0a019e51fe0e08735721b0bf0aa499e116d14d9174f973d2e19be03ec8c9d613cd2d0045d87379a32ca8e918b3ccacc8402a3861b83af1f8fe253cfbb28bdf3850", - "0a07a33c99bc375c1c0b64ad87f1a510611c3904a4ccac06e97267a3551f4981fdb53447d4b7a020db278aca0f264942f706964762e573a789515496456d821df4", - "0a091c352b5dc7694f433b8cd69690644172d5a574f6ee43bb308bb0d9f639bef9025ffe5b8b5f6ac1311ed2627b5b7a04f20d79a1f8e781aac6e7b8d4253b0506", - "0b081403e67e2add3583ef5bd8d5d1737d4104057ac81bcc2401d8538aa666375713a00701973b6cafa648f8c0488304650ca65d723d64e35d389adc9acd002985", - "0b02e31d1bb6a756ee8e1a1a8879ce9abc2239c27cda3d249d429e979c3728d554731c936876a32765ffda33b5280064cb8a546f090afc68428bdb80fabca8b4ff", - "0b05ab7d617577570a645ea3b56af5e1807bcb449f8dc102b9bc539c347f14bd343fe64d2a4462ef3ceab08189a3c4b5e9f9cbf0ac8a3cd29099186b91f7cccf03", - "0a0128fbd113985582d817338f503278d779cd4696627fbf5ec7ea5618ee43700eaa217715fe75926580aabdfa47ce94a029578ead7ebf1f4d8e5f78f88969a8b9", - "0a00e7e5fe24f98251d3fe8fba32a2863e725d272c9112da812a8089ac6c2850f67799abb033dadc711800c3c54e554350e4659afefd2df0d492fb5194c2754564", - "0a0101e306eeccbcf06f7327084883a3a8d9fb4edc7a5602f93d12916988271556a3220d2092d701e3d3263dfdd335b828ee59e150c821c944b26922a53a665bea", - "0a08294b3b0898bedf2faad5da4e011bd5f4c4d77764fe025f02d05b42b7c9efbcfb6db6571254d65a0d87f5ac2aeb79b89ec51bdf40ddde4b7e126632dd6bdf99", - "0b07d90730ac3e95127ed38f719f7bc3f6f9f969ec25b2962489dd0282abcb7656487d1257260ed996b45f01ef493e4d54c299b657f32b7bbdd679a6fd0ea51442", - "0b01e666a86785f5384f0faa1d611ee547c0685986ad8ce352d72af797efed6dff6af5d412083ccf1431a78197e2673fda613eb81b09fb6bd339e44b4d188a1e9b", - "0b0821278e6532285ceb50855fa6e746601b7c7877698d13ae3730efe634a42f5ad6e039470585e8c0f9024af101e867d34b6c243dae8c2f6a809962ba96d66b3d", - "0b0043b09fb4ecb5d6e829390564aa27f79c1134b3abbe09312d791c3a5115b9dba1a0a9bdae2f420e65087f34c2d85711e63068afbc3db40a4c9dbe63f327f70d", - "0a006b1d8d03a6db2b68613578c9795c5590dd6d57275ec8d1b45846d054939b22d2351e016c88faed374ad96134b07f8655d17371f819fbb1fe4d0661b66eb56b", - "0b040adfa4477a32b6cc955e5ac77187308dced15617545be97ab3a59b86486867766ff41a5f57a566cf8819de0bdcf7a32b0aa2a843f0e6865bab581546c7e146", - "0a048d6a15059acb3c4b929efe21af975ec903b3c55bccb43d3b6c9bf13b6118bcca209d366d7f20de8b7a33dd9db96e4b1a72a4834cea04e5762ff3633b939393", - "0b04fbf19499a12acab48662ae08abaf177ff8ecbf3a1962afc96ce75207cb4d9776b15390acc816acd1c9a6e8937cb2b1c0fe69ea9fa0e6013d3d76a36fc03117", - "0b058fdbf6ea0ebf2541c5402211c92198148bea470fe49443b34062280795803d5df97673ae3ffa488a8ebc20475cb16822abeaf63c8b351f04ef1ae57b37ac50", - "0a089a7e156d527aba0a28f912ade8ccc57fffb5c1286959d73649adc88811f935b3aba51d138584826fcc8bb8ad55f783331e90c7c10fd03db4d2002ad40572a6", - "0a0012c00bb9cf62ebb6c0b7d28808ec1058692150fe9004f5fbd2a9bed06d647ccdc6d8da30307ad9e9e22fd47f94c133ce178fd732c155c12f4c28090c730d4e", - "0a06361792ffb1f51d8dd15f306a1747d02290873b7f694729a2381e8cdc043e987266e19fba6f3f704efafbdb35cbba24bd70eaab723f252ffe0d5410e8a50ca4", - "0b06a87db5e5af39df8fed777282bde9a1d7c1073c2bfb2ad1e599b23aa5e36c45e4eec5557b8b368e634a77ba894feaef8ea7f70935bc4cb8b5eb9d8547e1c9df", - "0b0894b00cbc31fa14848ea2a074ff68265541318ca824c51907d6252b0df4ccc233316aea09221e4b7c2f331648c83d08d686b465bba2cbb0c67845ec3dc1da11", - "0a0301867ead34f39d2c6449214e706c07ab006249362b922521ac7c419072c391131c68a23048a90cd0f786cdb57b4656cfd1c2fd887a1f6d91e525dabb7290aa", - "0b08bd8e5e14bf330d94d1e42e4dfb6e1adba06ef2dd2522f8a5141c1a66a54b0e090830a1edb796a79d6b269660af580fdd39f25cf218be7653378db85af0666b", - "0a089cab0cb7dad8ce7edf7bc2fa70f09da82d2fd631eeb01e4d32c758fdb337b499c7fae84d73208cf784e70e69fa8a840d0ab87c2f2035786c960aa105886121", - "0b06ea66748630c2761663da786ad555c3b30bac3e66b954f892d8fb1179530afb6574c5a98acaa7e75e072a165e3dc8644c54720c54caf72d23e8beaeaeb1ea2a", - "0a0116f456eb907f371b2eb92fb89bc88ad31d9dadab81248fa7d304b13e8ae806312f62570b27626d8c19f96a989327c8b4b79399b6dca30306af8e086c6ef701", - "0b00ba66ac6a0799ccef4b9b6767116a640d3987c4d283c74d656c23be23108be2b5e75e39af3b2b8d72e560ae573af30c4d7d3c7072a3eb0b69d8518cb8fc55d0", - "0a04958b44902b7aeda28a352ec80a64b44aee87adf18da9cefa56e9bc8ce56352418ccdf5318fdbd2ebb16c2696288785a55ed83f19381d632ade9f8c34ca6f8a", - "0a04d548db039a89a17310533621d5f5e7d447cd0b5c06db709f68891a7a9caae0892090c5a05efd5db08cb056db6e1ed335d079a3c0504415f27b4d7e5ec0b6fb", - "0b01556d316eae3da5e14162b6cea4368bd4201c9524e14f940460ccf7be5f7fdff0a1f8e6380f19947ee8bc148aaea5daff947a9fd8d009e9fc3c087d959d91b8", - "0a037689c62f6dc56332e17047063aa1541ce120cf97db8a4d937768be88b7768799adb381d39e17e736bb6e72146213d515eb3f1ab38d099372ce9f658146d981", - "0b06d75e3df44d8659d335ec785c0f4b53a079f2d601e5d5fa12fce65d4c9f628085f35d5d75b4d81697d3f2c0df148357376def351d5724f3795f39f6dae38297", - "0a07fd706b82535656f5b61dc0c3b99544be1750c7fbe25357d312d42f8075f664ebcb1092a7ab94d0ecd226d2e4fb19155d54f33f206bb4d2081ef38226c927d6", - "0a090274a07a40f2e7bfb5a5569b535b2a249a350d1ce2c758e27655526cfcf3e0b8d90e2c53ef8a1d275fda850267be810da26f282b6d5797271c202ad27ad97f", - "0a014c70d08504ab3c5a1f60290d422ea59735a238ffd6d12df0957362a68522d409b0ca53f27c613813ead541148491e042b4ca9e497ce76832ae1a41027d5dff", - "0b06b0181ae10004655df9686b0e613cd1a76d818fdf7b1412dd6a24f80aaefee474ff4dbf570b55bcb843ef030ec18c2f726186286585563216ef241b24721ead", - "0a036d23279d88d095ea0231119cc6cb3d840b469b4d038961f6ca28b4ae541ea1e97beb72217bb3e0f49887c6a47bd3ddaae5731f219010dc785b0d58858226bd", - "0b0502457ba1299a4fa2b0f88696952870d2c03bd08abb3ce3e38754c04d9a76b38b1b2cde8f647093ad9b7ed8526f18c8cbbb170d37b9441935c92500abe60488", - "0b073bfbf119e52a73e002997abad7e548738fcdcf48303bfdfe55aa5fe4a649ead10a5d354020f188aed728d76d81c136969186f7d4d4c4ff3c6aaedeb0b038e9", - "0b02c619aa27d12c97f36bda86ac2c64be96ff8f88e198f61d0b131d74768befdb878ddf86fdd66848f06679bdde042b08f3a94f4d5d5b3202fd6dafee531c149a", - "0a04e2d3dad5e35853449811208babb0a33d5c3bb65934b0bc399ece55aef1d607834c43976f18d49be578c16de8c37ebce3da6a289cc8ab151e2d34f3e0cfca60", - "0b00490a5f9735af9a7bcb916991c3b547c17f5e40ec0748108a41875082b9852fd169d6c6666d20935ee0656e8ea6000e01dff9c6c7d848df0b92d80d32994e72", - "0b00116e7041e1b58d5ff0d575c287b86c78998503920d81f874c13103f05f8f2d0fbb314f0b7635e2a4973350c38970f197e2ce05f4c05d8b27f354ce1e2fe9d3", - "0a01f9fea5ffe7420ac909bbb9dfd13a999b877b57f78aa07f4187765712e169be5bbf9cab6cb50dde4d89ef459d38dfd30fe08d6b0289059f1a22278ff70fd09b", - "0b068742a33f000dda94727de3053cd90f83a9d65dfd3f8dbfdfb7d1476f9640a32b6acdccaf2407ff2d7f83c99c4826851fff71aa78852403f2d91565880c50df", - "0b03e25a5bb53b31729ed5441ce3c38158b9c6e63f7ee391860387b3ac7abc992ff0f6791f657ab36d7e91449e02ceb6cb9823dc1f397a32c8703ed442ae143684", - "0a040fb6bd47202d6fc4240af40c975ce29d3ae618409b249d0495aba244eda1d792186b90e23fb104be9bcdde59639fd833a2ce368e08338472758a4d2d847a57", - "0b09185172f3ba00b143055d8f44fcef519d68f0e7b26cdd0e2b4a07adc017714996f637f20cbf4fd2bb32248ae3b316936db57cbd8211c8ea6b7063ec656c8525", - "0b07c925a40754bc9c8ed84354f38d246b48dd5f848c805f529766ef522234c1ef7bfaab626adf23cd30a9fd1a92f2dd2c3384af76f6166663fdce535e00a6157e", - "0b02248efcfda03107e0a5d3933d3ba9dff512c5976b48059eedd18e4cec4b53f0b8c523d1c93e492db6def3188df79fcb931a6aa17dee67622bb8ccb4b6690572", - "0a0591c04b2d54c111ed166ac4e9b3c6181f5039c7d2474bb8b26c1122e8aae8b27d2a0da85ac4e205cb53d3d07953dc5939e4b235342be60ed77ab83362d3f22c", - "0a03c97a32203008b8bee937f95f4ca53e2b54c9f6ce543561a0e6a5a4cabf2c54a00d9e88ef867809405def051f6198572369d2579b1c7253153fa819bc6aebb6", - "0a05e87d6a8a3a290606bd1ee2b5713f132c959519e8fa43cf44f3c1b1a0ef16a078b3603fdedfbd1cd69de38e810442c47d7cd4028b74737c0415ed906bfe1131", - "0b03eb7ee85eec6b8a9f7129f633e8077a89cbde1883b9543292182e55a71bb3defc3bdbaa27936582b76dc2311d1be1b3b618bbdeb2629e2c147baa091a708e59", - "0b049d8b13a9d5990b428504fada7d837945b4da0c42e4cdfc259b9743d5b7b39f79389610137a26429347c35a7780de7bd2e5729146b1582bb6b58b3c51185061", - "0a08f6ea8957fb7d5795cc92d8bc54422305c719beb67679efc8775616f00c1f9866c7f10b396515eef5283366aebc13525d16a4db7c3091bbc3876bc437058909", - "0a04bcf471a54f13200b2a1d67b2cbfa5eb3cc20303fcebbda2189e0a1376193e869471bcdeb6c536896d4b9165da60905ff4a2f59c5b6dcb3cca107f46055420f", - "0b0037c454d0e93473ba4d087ade2db5e4754bd2fcab027ea38e00b30736645646c0481aec1778cd84ae7e306be3d647164ff79d5113ef06219467d5d7fb425ae4", - "0a01598e66af56d0e19df4ebd5c764505e6f5acaf7919059ad3659aa12221f5cea9e654a78d5426c3aee608bccd00bd3c3af7c605df8b68e6cf86b4352c53ce305", - "0a050580fe448d2463aba2febfc91aba6619f6eab8ec6eb1cade1be61cf0f72eab36ce6bad35329a5af9b6da923fe62e24625a35a09fdff6dfe7e031e309163ac7", - "0b020202061017acead09e927807be43cfeee95bf2f177a6801b8fd7c4f5c61f90f8fe5237b6e4aba6d0b860e2897ffd9fd882caed7369066bc87b6de2f3e61f7d", - "0a00e67a3e37e078d000bad6f65bf550676453b5c944054f58dde6879bc6762f9f13ac6d29472ca8175c05996bdb3bd33e482abdb7665e4e1c6300c3dde1fde3e6", - "0a00d00d9cf3d8577b80909afa376cfc9bec56113f4e96761da9fd8302e54ef27e5949322d3bff6a78fd5247e0843544f45660a7063faa1596338ee91be3c0d099", - "0b026457db4eb990920b29bf142b90e70c6b89e73b67a530bd07a8b55f4711f5c53443a213ea1ad05d456255844b2bccd64404524ad9d9e69e00480940b742a585", - "0b0245d7e5f8c83e3458eaab9dbda346f96bf3d7fc84232242a1170ce7814cc58b9a9329144b9633e33493ac12e2f60ca5010ade6188e840dd81c6e4bcad08a9c8", - "0b08765e174d0f6d59d16d43a6168d18f98aba655f50b0d7304f932714b41f2b459018dcf147f70d84b3d3f5d6dde58d079ac5393d177ab9d5c28899afadca1a8d", - "0b07c1ac3a998492c2d7d033b29a74426fe7d6fa123262114cbc2762c9c611b0885c673a01101e5b308ded307f4b0d943aca01042ddd612c4d87fe777d050350a1", - "0b01f7ce25e921b1d9b278db416ee12d4b47377cb8876e13aed173a79cb1c9f7214b7923612e58ad0c9bf58a63edf6bfb0fd39465625f9541bef1acd06f05a1ce4", - "0b069ab154492a95a839480ef023981504889e0ff8efc8e57984ece6b889a89ce73eaad87206d98bdb5e10c3749ddefbe7e3af05b6e0a7ccc067eb2cbde09e7748", - "0a0575006ae4cdaf8ff05670addfd8b93d868f5654e53bd0e8149b0ed43ce694204d48ca5620df43d9daa6228310b9141cefbe0b0ee5560b34e9bdb02b027e982e", - "0b02a98b4bda932a643cae202cd8d0956158b8f390f85cfe33f8403d588b5cf77cbaebedaf9df077ae859b0859420934b6b27b60ab628fcfb2413d2508ba62e8dd", - "0a063d78cfcc98bdbe458b73d8ca7316044aea10b0f15116a53d33bb3911441b7d5e6871dca81a3aab673f4ab696817773ca6944b5911444483589acf066065436", - "0a077241acaf51793fbfb0efdca21ffbb747495cf60e3fc88ef781d38274d076a6d70003bb136d90fdc7318af6f1ec0ab33956873eb636ea20f137ac7da1c88722", - "0a07348f3ef584851b44964b8b5fdb89ba632d29c8b7fc5f16ea36492e7ebe4c74da7e508febd356068afad16f849362b5f885b1c3c04092fc280d454a16991484", - "0b051f7db0d224fcb4879a2e2a5c94f9ef2a7ca298360fd3224ed34aab03a9098be6899af26a24dc03db2adcff90a0b8ec08d0e90937816de5d2f8538815c093d8", - "0a088d7839ff3fefd98609e02f304d7cc6d1b74d37b04d23a35d726b2d75acb1cc1282441cdaa5466dd59f1db8242be006681d2b290aafe38d48a8ae3196107fae", - "0b0884d9ce2dff087b96fd579452ef92833bbb187a7ccda3736b99492120baf06ac828cf6e058c0762f6ad0a9467f1c9317ad706045d8766c8d3f4381556f55827", - "0a07800b1396e5ede2b14b2b5ec81675c1cef03365d6ddfe2b81b087173c7b8fe42985046352d2afe8aec4d8e77a267f8addb751926b62478161b054969eaca327", - "0a075437a7e6551e96e04cbae28b1759d0b9c8498365f92a123599a6f133174e7def3b84a9689301d8fcf20fbe65da7a365ff8fd33fb34788cc7e324abf4fc3320", - "0a07eb1c045c279d509cef59bd56a98a49c09a07305238cd994c2dfd4606e32bf18f0b2ad2a3aa579c8f188135f93cc9fa812b07e0adfeb4e48559eacf0935f9f1", - "0b0696e7bf474b55a6ac1079c355d0d5d8bfc865ca9e9d07071b0dc64816cd4bab225bc28ffe0607a7728aee9addbd9cbc1eae466cf722b2c705f84870b0ae94eb", - "0b0328bbdf03151a8b780ecf425eed53e5c2bd58c0d70fe232ce48030605e59bf5e5ee6d478fe5c55addb9e57174be70fcc9c444c3b0839c6455c03174b592b16a", - "0b055669f6c8131015517f372dbee356304e44ab0b33f1b5939286811fdca48cf9746dbb018926fadef934ee596f284530402f8b224337d56381814a0e7e5157a6", - "0b091ad1bc92638f622c50bfabe64e477525c32dd9fb0f15f26f4e9f9eeb824f63cac68c9292d00f1d0c94dc2f78d02402fafedbf24ab832af7b54cdf9833bfbd0", - "0a05f6ee0689812f7342bc234fba8734978d21d055a7206ad863ab66ec7d0b79817a0fc510f7debb4e7afdc97363d42491eca8f3802e7dd98416393e43f0c4c1df", - "0a07585809925df4d1d61410843f758653243590f252103c51c7ca81e9124e7824855f07cd23f77e18a1ef2aa2bfb5ea701be30ccc3ebc6889c9397e9156880d04", - "0a0703fb126236d005da94403bd396354fabbef3dc5f4270c59fbdbb3199c4129907fbe032ce28b6373f4640814370f917ebf787d357e378a65a1b4b68fa0f980c", - "0a04435da6a613f6a0bcaa418148b94f7b5de429430d59aa45c0286f12ab2f43505414d69b22b98ef27b2608749bb38d8f27a3d8ccf8aa6074eeaf7176cfc09700", - "0b03860b047a491836d3e2baeea2cbf52b94a151418635020b66aa08bed9682131a2eccc35750cf7e8d8413648cbd6929b121d198933c95e818bb75b1207959247", - "0b062299e08d38d6979b931a83a6f8f92d02afc3efbe306a81710276a5068264ec6673e669e66b3476a91a6524fd0b84a780d7e6dd1585cacf276fb92fd0d8bcdc", - "0b04281b7cbd57b6d228af874e134cd1b53f0f5ff479307ef772aa4386448b066917a385248c9af885027a02e13df5ec3b4b3a53f17c41008943a623035a0b8ff5", - "0b08c427b00ce2816933b51b63d68d0ddbb01328db24f5b8851fffd3c4c2eb3c8a4c1aa7f3cb3d394ee8d5f450234803699ec7d6b069e7fc2527889a4558754fcb", - "0b085524cb1d44dd7faaf1d96575a20d50774e197a3b700a9c4566a000d6c28499f52fa1e2f89b33d190d55865ec7b396d7934db4376f0f3c71376af9c0dd3fa2f", - "0b07f10da8ffbaad2b70ee035e4506885085f0bbb296e4f54b18bb5cc50094a7b5a12889ef5108c5386d88784f092f07f8dc10676f39023fb19792add36f23a5f9", - "0a056f07a5744b3758255c3093e03e5039550ea2612d75bafb5884a73f100493281d6ff959680a20b9d1a0e9a8a4f2c0f139acda103b334b61aab8d2d7a6b3cc0e", - "0a080ba1af144957838e776399866aa235dc4f43e3693ecd9b27f0b1e3bdc0f737e0a92df9994204a5c64f46a4968c1f1206ecaca7f794f34db525422bd968c31c", - "0b0581dfca07e5ccbcbbd9dd752885cb0d8c6e05cd6e05a38c34f47e0c44593b7d1bc7737387c82e531a3f5b785aa783c3476fcafac4bb01e6ecf3ab54c601ade1", - "0b052d35155f14309538d035d119f2990b49fa6043ba6edbf9be0fd3a3ccbcabe53ff8763411818b374da77c9343b01ef1fb6d5243fbf70dda219733465d4a8535", - "0b04384689fc7e31736e4a82a69503bb04f55a1c58ab984654169fbf3fe976aeb26961da774b2a208e6071e6a63f0d5628897bba463fe1aa915c8ee2d69318c8ae", - "0b000f98139abdf02e2d578ebec469015a515f63f1f8d5506c3a047772b7da45af38cbfeca09dae6c2106b716a79ac4124c6b273afc244101a1a9f911f1e55347d", - "0b022e72de9c06f65616cb7a11838024151093452db5f794e547ed532c17eebee8a137207718c4678dd123301b5d8b66fe809319d4c957bf9387c55d4e86eb2858", - "0a071683acab98f50c913c0e9fa433af9f76b7ade9e02e6a56c80331e74130fde3e4b6d7b232ee1343e373415a73af0740858b55ab156eee477b16990e654e2db3", - "0a0397ae78660618b4b2384f4b7b2321443d8e6f666e67031b5ad96dc492639ce78ed6a91a581b60885d58c7de91244d52c869d200c2da384c174e8bf85d776b25", - "0b0797097d4de06f24d953f15349c833bdd3afc0e59ee70027d3afcb9c1deef4e03467f386149ea829b06b01087e05c020c09ca4d4f37d5b6ebce6583718bd6949", - "0a054fe43155d7f4d06d318ab22c9be0336f7fb5cbd9063cbd4559911fedcde03f310924e91de071a4394778f322dbc507981969290208770b7a154114da78f1d4", - "0b0895662d115a8b24f43843bab13a57d72cc5a652256f5da19d71fc352a2bdb2af6c826734a20d8fa845afd951e1a111b834b3eca8054c66fcb0afb297c53c926", - "0a03466f21ae87bf19fc8d466915dc5a71c01d58e31acab5424000d8c4d3bfe57776224adf285e08bdea6873374ac63bbefd2f9f50f4a1772304ccdcf04b7d51ee", - "0a091a7a5d19180bb00d09289b3302330e799402cbb29c5e2988fdf03a3996f9280909d8a5c48f1f41f0449239ae18fd42d3e655dee1068a430f968e4eef2165fc", - "0a05ee8574ffde31234bd21ed331bc8b5ee8697cc3fff11acbb6efdcd9b8b79ef08af7ed7ef758ee44ed7d45466fc9bf0f13f47a7aec343dd0c0ddd7ff5798bfff", - "0a019d0209a140388970afe0ebee57a198b8ce206917dcd2835f750de68046bc64320530235cfbc06aead1d8000d9c9c47c2b653cbecd06b5b23de80988f9186cf", - "0a0250c5c5f65eb8848ab1d89569e8955ce7e3b420d263293fdd72c5c3843a207e17362c9cf72a5680d1907af3e3d659b0044cff041eb42deef378b9dea6053238", - "0a07333a0a6ff44e189dc86492a5f49e3fa515a605cf38d1e8e44ccdbc21eb05b1729e9555b8633620aeabfa37a7df275f2480af406985f51f1cf5d93e0dffc13a", - "0a0820b9e7c01976d80ff049e83548f0a36648bcb8b239fb491c20b2c05fc14ca27975342810e29d1980ed375018bf36fd8896143e963ab5c6886cd2765b40cb4d", - "0a01781a3b04959e75b91e43bd33bdd97c0d52b60124e376a4855f51792cf98d7e71d2f329511360cd881f3374cfc378bad8213cf05dce21ce8e7951efaf47532b", - "0b06037b3ed32e51dce35c85b75ce0372c36cd9d59f68fa7f23ffb77c4be70c88fada8eb13031383ea7a841e7109d5e20de4e04036010938117ce20f70250bbe02", - "0b0486a49cb87ecf37e189e2a19c7999b16c0791fa1d4ba83f7bfc622a9f170adf80943175f56f7d60ffd703aa842df26b2b390f6746999c218c43c6f0a43736d5", - "0b091c6c12080c0f748a3366e18488ad694a22d4c571ae87e85ca02520ac19f3164f5b289cffc3c2639ef1a41bcc66febde4903e0936fc7cdcf3a9631c92ff6e24", - "0b091c0de0f927f64e3bd8c3bf6ae8a2d80291b4fe7f71b6cfa4e3e4b365a618c8d9da6e307e8535e0bfb1018a1fd5c97a080001591fe9fb4bdf4b6d80b16dfd81", - "0b039c5384004fbd3d6d07a6a96e153ed82f4d236c3ded4d0dca7c47c96181570ec1e85b8184e5948de07c27f54de187db8ba879c280bbc7ab7c4c830828a4b2d5", - "0a07f874551e21cced01cc731c30024fce02e2cb3aebfe038edb71a9d65f1f1db69ca9c00d8ea0e053156cdc49adfecc14f6657dd3333244ffa1e149d678615f63", - "0b089399dff6488be085dcd5de184a92c7d8d19fc6441ac3febf458bd98e172a96257ef0c10181db73fca91761995fd44183dda4ba712a29b9b47c45e71c363914", - "0b05f16ca6b706daa193f103d5ef0c37c048f854eb52092d70fd70d282a2aa150052cd5cfd852d286ea8533bdc31bcb2d09097d220c3c96c1212ead9f701646603", - "0a0147564dde7bc4602458962da46c7bb061a30a78cf4b872f14c14a28824149c68a829a53a9c02f0446f82a7072043cb1b72b2f2649d27021793c8b1e239d4f70", - "0a01a37e59f938c72dca54dc8ae621e309bafb51bd3eeb25626199329e922dc2f6062148bd537247deb54884322e5cf223330126237d9870d5e3de00818f03484d", - "0a0221992854e8fca8b94e492ca9199afd2ae094670923c2a196ccabd03af6abb6b925db9de548de8f307a6e94093f7af0774d10ec8fd44cca0bcd106a49406614", - "0b01ca39f2914f22e4d2e3675e745e481de604fa1ec5a4bf46ee81f532120c0dbaba5d8e2c9a36578d4ec1d0875457853247610e1791b55699a5ff319593341150", - "0b02246bf83d55ed05eda654de95c811c24b814daaadca0b1ae01a0c32bb6437620a75b23354ec9de17c8ef03c0be3a2b751d4cc1d7ad4cbba6e8934d7e4017d7d", - "0b057fb0a63f5b01f5fcfbf3af3d373554cfc0c50b1e2f4ea6bee6620fb45d88c46a0e7c5e6225e0f613044c245cc96b62256ecc7031f4783d51cd3861fe32a380", - "0b0735990978b3e4f5ce2804e3996faeaf9e8449ac94d7168c79ddc557ee7d2cff0d9bfc114e0d8d18de4d9183f7031e0c5420adcbfeeccea2b30ec92cf9a74961", - "0b020db4e915afd922811d523e28a443dfaf666b5c08999bff1965c587f282f40e81b4e1b382f4a2ade9f0320d5b18ad13e927c3f1def6d161b30e2ccb8f0e4765", - "0a063486c26ac2ad476a3f6ac4fda4e5d65d151f58b3085efeda025d00a8112d1daa1d0d721f137b0c6b39b59eff1d0ecd837be55deb8b6dac1d3fe82f9afd23de", - "0a02174297394c87cb5e1f2aebe27aeb60f12c2b7a49fa0b8b565ddcf25b70c7d1e1173d0733b0fb0c3513348f7c9ae12b6b80e281d201b60e9fa51fd1f010316d", - "0b00bddbb86b0b5831145b8b54f546d30d8cf0fb4448e5f5bc73b39c27e324639963f30d43fde903af3c1e64b19fec0f879a0a1082c8c4be07cc38af79d5c356ca", - "0b0374fe43e0991ebbb9d5645c6e5f7b417d443f76ba36107559e0c4e7d63cacc7951e1115cbfbb1110feab48649dad2b6f41904151b7596141cf961a62ea9c6ab", - "0b06bb70aead0c1ba8f7ad043c3c241ff740d945cec81ef7fa421755bafa63ec17667cc2f3209d5f17caa27b198970765bb949fff632ed8a2fae7066a318bfd5ac", - "0a08f8f276de629fb2a1e25adae5bc850c9e286078cf65b36654b9946fc5f067e923ba0fafe0cbb540b7bc61630aa079d8e3d0772108d2d26c5daa63bf8c6512b3", - "0b059f6dd5d1ac013ea74b9f36a8cbe8007bffd547b02fe51945e06a6f166756ecf3815235d096cd59da119c3c01f2230922a2d0a386edccd598793f1c14c1af20", - "0b022ca5cb6f2c827139641969ef856788293ca9078080ff785d53f732f42e41176cbd9f5848a67864d4cd0fc257c12d144eb9daae9ff7f37580ce3e2c2d7ad966", - "0b01dba55f4da49813cd43a7bce638e7f0d6815a32310d5dc2d4be43edd48313f8ea149413d55e58d0d6588ae7019002f9839c7e1ba016f5a6f461843398f52cc4", - "0a025ddb7bd7dd1e3c2b4a28a9e86bb3b565dd87aaef956a455df849de19e65e41f22216bdb9dee2213467bc5e8702bda21fc0f16e50ad9b0ef7a962febb846f53", - "0b02fe85787294991ceb21c9e9019a67a895d3a0dc0ecad405807db01e53ef5b9fa80a34f1e64699fb9865afb711983ae5b46cbd396c2dd1853eb123bf44c06429", - "0a065afe83caedb540a793dd09ff0203d476a2fc3e5697a40a4740be9c28e57808bc1783022c20a230ba4c049a34bacffd07f08f37c71b73c27558a4c701d86644", - "0a0820246c032a686362194e11ea8fa9603c8d90508f8a67fa1f86099bfc8d8be3d25867b18adb2176e8eb27ddfe5885a840235f1ec093aa741b35818dd22d9ed1", - "0a07c83f2e8d92f8376af24e71809af4d520d6c123b23846082f89bec57c08789f5954dee57bc804fbda6bfd18811006cd9411440e63311efeef4bcdfbcb48fe76", - "0a0589ffbc9ad4dce20d62d5955d209330c42918df2b55f445af3d31bd99fc6ebfe4db3654731ff02f594e746f8e46df7e3949b594679785e04bcf3abbd60dbc0f", - "0a08052739d11ecebdd78a7282a1fec9354037f73f46a46715d3966f20d3dfbe4ec5b3e2234c7c43ceba5ed870809f25b8f4e0b67f0daa2ee4e5ff5200446f6dd3", - "0b00c4a1b8240222bc830afe5891a36305cbe3914a9364e3432999b16a3bd0d1b54a319c21800f99b80dcf72795ef783a4da8a264bc0f6e1398b2c1edfb2d68745", - "0a047c26ff257e22240809cb63fac8bbc0673e8b14cfa378325601c1480048a3dda504110d14f00916e7af8dd2b518a6c1d3e1a0955f188dc0f88008ae2e95cb2e", - "0a07ca47c6f9e1a34f08c5446755473e8b5f3ba9d3d2e8f105aecb99c352163aca3ed1cc48d649abf6f4db5eda6afab230f3120f55292e772ca783adc623989b96", - "0b0457ddb8d915fce48dde5b3344e77d752b7fac5003d5dc79934e493ac3565b6148b4a30bc744b7e51b208c7fe5dbc940fb3e7c301cd43232a99ca720a1f3cd45", - "0a08e309c5b374fb99de0edc9a4e7cde0f59f04369b4e8af6ce3eee8601d1a07d180e09d29fcdd837b1fe095760857976b7e57cdce0d9b75fd154cee87efe03f4c", - "0b03fadea89138494a948a402655cc692e9f23f1f327109cd67123dc53bf36ff13443d29fc4695ea86cf6bbb87db1031efbe2d59f0b487d783de6d633b84a8c9d4", - "0b07130743cd3d23305db88a219b517d395cc756ae4d3c94ec1de4bc7a656dd5df5230804416da4f01715ef55753768489abfe8bda83506f186e8acbd96134b8c3", - "0b008ec7ac27e937829cc28f81abaf93c2bf22a16a899ea46ffe8ddb933b3f1b3da8478de6fb418a03d36eca678b7bb5da077e6daffeb9f20dfe25a5a3c601faaa", - "0b085107ccb09f552b9f1f62ef3b066dc33af68c7fb52521c68b5adfe323c93e9c2b671fdf396a564e3886442993b559f1a97a1125a42644a31cfeac63d94d75da", - "0b05eecbaa1eb1fba6c80d7a9fae81600d52b2f3e2c46a34c63a97072d35e832d52942f45ebcafd1a0c6e0911c7a02cd68102b091c93ccf00302912156275c6e97", - "0a00b89482fbb596059d8b5d1224205892433b5e2f1a9391401f8563b2dd60b474f546528a9b1453464d30825ecec2d5b0cbb72c2a76286a68d2d424752625ad6b", - "0b052354f878f4567e8cfa37b12c62197f73fd34cb09252b19da8aa51f7b149ee909430f2bbf6404b637cb95f93ae780dff28c7c37d85fa78f786efd177c8b1ff7", - "0b0298ad4028b3b719456fd90eef70394c06200fc185e63b68a8f8633c900945ac67d2f5bc3daaf3b2258ba2bbae8bca8c0c35e79436eacdf2891ce2259d15ae99", - "0b0003eca560f85a11abc087f02ab913c9493ab425429889852fc047d2f22b3602cf60a93fe3c89690fec7fa92b7bef05d42fd9b33f233af1377c1e7b25d7c1ec4", - "0a0795827db29e3d2503fd40e91a187fe2706d734562dc58f99261b09dfc241858b31d9a9a029d36e3ad7592d900059a85c18c55ad7bdea38811063275c54e30ad", - "0b03fb21f007eeb43cafd0f8c747825851cccd65734c986f208ff2d8030d8ee8e1d0f5962dde0605c5725a80c9c507347be010701252f0232a8e76b2eadcc78288", - "0a08943c247e1a35aa8c9579af4ebbbc0e83c95c330c1bfe10c22feeaa7768076120ed0852d8fad9949555e09bbc07c971abfe400ba22d4ee00f21ce5faf797aff", - "0a02cf2e8087825ea3fccd01faa52984efc6fcb6cebc9ec0b2757caf821f87459c8b9d469c28d81f1cd478e142162e3c9b9dad44b30af18980412f92a16d7af243", - "0b08f1ad42be20839eacfc7e5ebea0b1ed78f212a953b66077b61e12bb970275dabdd0e411fd2b54f8c13302604c832a90bc1cb58c6efccb3bc094f5f9fbd3525b", - "0a04af4cd882c747e76e6e753df8cddfee874fca8fa147d2cb8b9d0e45ccccc531af864c62e34e555ff2dc01b21454544d29b066827d804b254c579391ea0ce303", - "0b0654fccb685beba09b0cca346daf1e460be52d55093346d3b4e05589f582406e9848616397e8e3f3168dbba04d4e1fe26b27d87c986954f6fc7086830b2db3b6", - "0a073a9f550f38a8b75d700ed33a646dab2d86478492a52b5d75854f98bf868036140c21ef8d455f1be87c6302b2e156582d2ce41824722d876fde3211a3133fbe", - "0a05eed521cd8f759748916e6cd3536db18136aaf534d0dd84d021dc632db9bc68661395742cb4e4a5fbd5dc1a0332b47c074879d0f4d6bfb59ef34e659794859f", - "0a07a6d9da9ab94fd2a87d4deb4c46b4895f207e927709d558323bc72e8c1f933e8d8ec11e28d23cc9b17c9a996c0369e1defa0d002afe5c2fbe2e17729a479b66", - "0b0609ef15ee441fffcff0623ed3fd7691151216312161d5a453b58ad691cde0ed5e4346ca6d3097f548e10e086396cc8288fb619616d36f603b5679d017673397", - "0b026d809a905cc04200c67c68409af5d998e6829580b438a97e964bf5d214a5f10b82b8c204c8c34051f756aa2360083319c06f49487e9ed722e25d1b25805f7d", - "0b0429bd568ff6295d77e97dae8c511c201d448232bca4a410b749e771bb82d766068813a06368122c99a0e1e15f72f479e91ebf1b6cc7ee6c0459104b3497d1ff", - "0a02ff015efa35eb8f574ed798192d0738a3962ecb7e683cfa78c70250319ed4fb42938e358795bc755ddcb4f3d185c5902851305da411d936926dea2635323813", - "0b015c192fb9318c2e1874e10465ef4ea405013c5b73fd5215a7ad1507a6bcdd3672750b188455973e6bbadddb1aa1e1432338a8ab92a61e797d48f0aa40ac8430", - "0b02d6f1db878e00493b6dccf2894d063b70f5c7ad994078b405dcd560c17b13d0ec92a5ed17fab008ea4ea6acf71c16302f062745c61408ae1e6682a077f6399e", - "0b016af1c8e2e66b1a3fc71eb25e8730a35b3c368e94ff32148cb00066b36408864c820fa7ad5790e2b5dc7979bec62325a71f8a8982d08e3adb93e374f259794e", - "0a056374461b873733d58f8d9438492cd3c5fd4be2e680cfc45287ac132243227de60128ab110ed4fc73123e2c76de8f2a6a17e38eca00dc9a02f1632c6d7ba354", - "0b01c86ea0e8425f96a613a936ff97736cfb2deed1edc8da031b7744bb14e90b343cc0ddbdad3a50aaeda368ccdbcbc8a345a8408cf35c7cc6633605c489d72331", - "0a0569d23c88c3f59ef39d0f18226a42a6e173de789b10a560df334e3ddcb98752122186031d97168d804320e6449849c75f785841c08e312a140901e7ee19be63", - "0b01e0607a056e705401a9976f5661dc876d1c1189a8a3ea0c09c8fee9428195ff78a0d17a2e2d0d9cb344a23bd63e80c2834b49ad1668534e72e1f352887ba35c", - "0a02b555e8b5c528bef721a8f11da4f14405dda8946c047d6d31057c08af077b1446035b930fe8b34998e8ac2bec88a19390ac4a7445a02a3506e31e6b9ec3d6b5", - "0b03c0405364f41300eaefc3f75d66b9b4e505f80800c5b0f35d8479c11c2577309421fedfaf28e1d472874ccd09b6464ee53ef8ceff9768c9c780cbbbc6932d33", - "0b03909be894a71b42541b257a1644d342e865a3237ddb8535d4d19aa88669ee9c6b6ba1187651e37ecdb83be8ba4a9d672a71ff644ea9fd5b4b80d025780dd5da", - "0a060ac0bdfcd51ed18821b2ca70af3b9eda55df704923cbafd68e871ac3b483a630236acbbfe8ed9ee592862c29ffb6b986361ffd9030d077ea3c1a1007da8eef", - "0b0393b01c6cae2040e638cbe026c427c044bbe81065ee023643a544e4ce64b67b20e7b7292453199ab9cf6e831b08cd706f9a1d06de9d79cfac90b4a99fb2d692", - "0a024acab9c78c3c5204c67d4fd68ceb961e4e9af6bd3a7048f2d3933872274caffb39a29da1e1de2d574c1938256443f53d8f0a5dc13f867ddc3ab2ff2bcb31bf", - "0b0129f3872373805d84d20754cfa96c71bf39f4381555aa066edbb60dfafff5d6e49c1f59e379c91ae2dd694f644226587c1b327dbe028826b7051f37b6cb10da", - "0a00eda1c9ab222bd2b70c861315f72d721f9854a2ccd78f8ab2d8151aa5e46227df0621d3498a612c01d79bd139123d99b37ed523eb9dd29607c3d1fd0d65b782", - "0b0603fe0a507b0077468cb71dd6c5980ab9f04f6da5a91cb9ce5aebd17f13a886752703946303bbc0179e354fb8695a7134624fd0e15fd8afc1c6851eda99e4df", - "0b05f5cbaa9796764692d8de95fe884b0ec303717d2099a107e5c8603acea661e28f7f8068c32a043ae1857e25c5253b875a41d1072e6e1040d2ac4e659b6486b5", - "0b0396cd80823e7d50e7d0c07152b4c5e1241f2fe009347f7750243187c7977bdc72c8d867b0e8be0a85c878758ac0b5b8f224a90fe517d770be3711d504c2473f", - "0b00b95014f5db32f79b1f1c522ee09bb700c97084d2367818cbdc7bf6914db7188bcb2d22cf31589724f7c1021ca1daa6bfa52e9a7d8a67c2131c0df549160a78", - "0a01b6f7fbad1e6280e212c37c0392093ea169f8ea2a2706ec8c7f3dd6f0aab977c04d68ecc4b49c20960ce7346922f9c7b3c5b95b07c0f23354da81d13fe59fcb", - "0b013e48a2c8586d117aa5b842988ba40c2b79bb8bb6c3a132aed02814ebe5d63bc6107fa0de4794413262cc725d586b9c9047285171118398cb34a3570bfe6a3d", - "0a02147efa4e52e7888aaff851951066ddc4206b7339d09ac54f64ba2db2b8ff7e0fdbfa1cf80b958a097645150d2ac5397fff2475db38dc2d91fa4c857918b796", - "0a07f958d404ff8e3d0e6043c2102892096648404e300748d1c51f53bda96d69b9696b43f2cfc45c428856e68ea7b564d0bc1d318550ba492bbde79e2a87576b95", - "0b0595f80bbb62364f0620e7a2ba7819c6a2dd7f6a56662e81aed24b4df3eda0a5ebce6397072eb5e8fd69fda1ad654655f7755a71ec67a0aab7d644734d98d856", - "0a0076577ed4adac3cf3de5aea7604541fb067d13ac7612a5ae05ae6b7cf1c16d00862ccc10efdac1e3fa33b483f0de0b8d49da8ee4839a86462801a030bbba441", - "0a022a31f242b7c585d8fb4686afd45b2f046125e668d37bf1fc343de293205ba33c6a3de3ef9801b464dd89e6b8055387e5a5b57640370d101bd10700ab562e4e", - "0a01cad16dea558b2685a739cf97cbc197724a444de81378d8678ea598d94284865c7e6f8376e3e4c7ca5d1421d7ff0af23409710d7a8834232ed004444a34cb29", - "0a00bb1f7879dc33692a0a8613a56e8e23ecce8c1eb4867b0ef06835ff2e9008722e3a61d6147c75267d97d11cab45978a6bcb5dfc39b79c12ea86bd045e083155", - "0b0780a761c5b3ac93d5835432ad90d91568e29c5887032efc58d84ecd97cfd58c0886858cc376d69a34a2ab3f406c8d8326de2f87785984251e66e2af7447638d", - "0a05a1882d03d7aba053106650db53da0608d3054d538d9e011d0cd033bb01c2b484c5d89ffec98e84dee0daa7f8847e849fc46e3abd862a8d951ded36e24fd04e", - "0b06cc72cff5901d8fccb8973a55d62246498067ede0e1a60740bab00978c564da38acbba1943366a204a7df812f13b86487b5213995969200107206aaf1102446", - "0b07078d078c0b09208767f3a52ae6b238a8164ae48122f92ac927ca4552dfbe4962374f25f6e018705aa575e3a13b808cc1d0e1a15d8db717b1a351fed71d1dd6", - "0b06efa60fbb6dacf8a3970a085d1c7a6f1fceed4557177e91df35bcc3ac7f819d4b9b1dfd9fc2a3383888c7a90bc06010ea1cdac974a8ef948a2386cb31cf0e4a", - "0a035ed85c93c10e1bdd4a0982d383c620b276a3ee056431e266f23522742fdacacdf0b789984320eded9f03212428257dd19840910fee117904d4918abd27ac95", - "0a026a108102ddf53a5aaef6192ed83a1dbcb3f046b1cd4aea875946d5e84be9c8a146a7321e525ce727f25b87c7a5917abd1603d9ccaf0176f63178ed0b3b4252", - "0b01fba6d7dd018d71e2e44aa9c5e29dadbb0b16bd60e934f47b22d4d4ec398d07ed3267e17a081ec119d50616d41131c043ff242ee964699fec2808b721579a5d", - "0b056638a3b9ebb71ee143436a34c0b732efcd15a31953fbd0b2a8ed65bad8936036831668ace795d9c577c0557e258dd87261142a98ceebaa31fb5b3b8a73e884", - "0b052ea83472219f2ad0a33d332d274810156c6338fef89f4c85e231bf97b4aa387f7e5f65da3ffbdb49c3b0fbf9ffe76792008536da877525973d6fca9a91527b", - "0a017f6af7e9c2bdb79ce94a065228b48faeb3443cea76a60e7c0b22b3abfe81dcd526fa4c1956f2ec36490a543e515a812bbfda1c174ab567c5160cba4d461811", - "0b081be6713435ef6723db3e09d2c2dc78f33117ba83864f8fbb187ce1fc80d881e57b76fb51ab611c32ab41f0b7ad78fe9d3cac145031376851fe6f8a75f1e193", - "0b073b8e1347ad60b8300697cfb469787f6126d56ce7f09d10e35f9435bcd35adb99c6834c7743847de66850f449f6013d8cfb5883f64cd328c2c151e0a5d4217c", - "0a038c6340c54990354f5466efe132f855fc4ddeab41a81929109241f7ebab9f7ff7dd9dda05ee09ef79ae0b1afc1aa8f2e16dc26e86d55f0709a9f78e754c4bc2", - "0b080afed8e934c5d5dac61c1d582226d5c687125492fef56c3b21727eae2a4c33e75589ae740eba49458dad8ac3b92f0dcfc2d1bea27395656ed9e90b7a3d6f7a", - "0a05efa214346a03178168fcf0469eb09215836ed8ad72fdc152761e90b0e415579472a58131535b54a9b7181a5c2b217e923e52d500a30ff8baf383f23430bbf6", - "0a061ddf4bd883210f2462e71a5a864cd3ec8d14a72ac2e67e4ebc34ba8c3773e50a32b35ac71e9a047f340a9410c849e7ab293a01dd28b1d1ee7b0106527fabcd", - "0b0857ec03bc8cc68f3b1c355c34c8cb23e2429b2a9d8b645b1c8be38f1b2c1c68876b8b8f6b5895c564aacd3310588362be87fe587866289aff025ec321f7d388", - "0b07b5c84aa6d9fe40b554568349d6e91070750b30f9c36343f96eb43eee7afe95b513843b797269c8d59d8c8481890fa3ceec02099b7d92fe9e94b71d42e1740c", - "0a05183510d79817450d73a04cb4caeee888ac4ea693ef59387ccf820fcf28df0649c601a71596e916740cc0515bc84a39ea321858a2fb0ede7edaec0eaddbbdfd", - "0a085e81d3b57a22fa090d6613ee7529aeac565c13d1983d41234d6bc9f508213281d8b276d9b59bce81afa12b546bfe44057aaf2d6977d914c85ba74a7e1e6bf7", - "0a085076c7107850537fc9441c96a8ac1543b0afff8a6141962cab4e982b6ce6c2ccc37a49a6608662d10e66be47664cd7ce3b6b1b633d86576d7099c8c10c5fbe", - "0b0557337e4dbf4f930024d49369e9b53c7ffd755c302c19cd44716286977c466d5e202ec4e95962132b770f500159b84a4f21e9bf9290a4bc0a2e5f2ab4973875", - "0b08252a82cc787bb1e93f9a0fccca3bcfc303d9facb7ae90feda618f76ab599598415ff13272bead408daeab07531508cba0dc524c7e103287c2066cfaf768911", - "0b087f52a13efb0bcf6de4dab97915fda3c8502f6a3155279b5a48543ba1c0af9162126382d6e038854c2bbd4e895f08a443db1399c283d9e19653e363b3afe077", - "0a0000f22f7c725741646e12999bece88b23f2338f59c46050503bbba0c8fb84a13d3523747281c56d1a5a6214e48b5b054f79d1d9c7e0e1307fb93299ad5615a8", - "0b04acafbd6c089e6a24a1ca5ac14031303cd8d0b00c760b02bd35c3706e9fcd667d12de2efe3794f50f58dd35d4e12674490c0e5455b099b0414bc09293db49b6", - "0a06789d276ee49724a746912030627650b7c6843cc1ce5ccaf3a91cce6b53929eba7ffb884f0c18bbfde581098c3462ad45f2dc2cb094146196f42b26378fe9a4", - "0b0520e08e79ae71e17484cef4f813f1b5618e10a4bae0423805e8ef301c1c2eb86f887ed7363b4557d9b573de6344690e72c87710f81e9cc04353f28d40ffcd22", - "0b0460f4d81b718e85a19200610da3ff2107969b465ee1710e941174e9e75b8fe36b227960135cc2bddc804ce5d67e8b5a7bdb315d719501e7ad6a6bc9152c490b", - "0a03ae749060d9c6bcb813ca9f875c65eba98aa10c6158e663f76d1295a49013f017ab3983450ef88a728b442cbefff5922fb8f14722f5f4060cee0a0b75e8a1ea", - "0a05fa5ad35451b7669ef46fe1d904bd475443de15f66988ae78ae851506cf07eb8791628b972060c5535471b74d79ae671f617f2c877e886588251f8e9afd7839", - "0a02ad4194a5d652c1bdac2856434fae9e367433e3933eb763b0c13b70fc13be9aba53376ae9a84e94ab5571cd6a54ffe6ead21b27be9ad5a7b95b34ddf897aa69", - "0b0667f362d31c4f1ba332f42786775572bc5b95dca80f59f54719f77fcdb012816f306ad7368abefe9413d7981d4649a813554609ee8ab40254f5157f3f73edab", - "0a01a5adfed98ea5af334ee515b949408f3972db361426ebbc50b42372cbdc5b80b4bd600514d814fee89b36013db9a6a230d015ddf387613383dcb4d998f0cb8a", - "0a0391fd464cb0f22a173576119d6f5c1cd556bdda4ac51df67ee6f1cf6de98b2c23f6033952033c0ddc031745e53b46d98ef52b789fd5157b37b972d631cb880f", - "0a017ea351c1aef837923dc47711b1eaeac138fa579f79c7a512e0c99b938451518b2f718131d35f90c5eb3be68e107a5d02a5d5ed18b1ccef452474f9bbad9bbc", - "0a08c71b4169a0f33e19a29f922d8a520571b83f5cd808b70f74bcd0dcb0fb45f6ac6e8a965fd22b68a73c3e645c455b8207ac46173223f6b94f2b4ce9cdfc3149", - "0a014c85b560755bbb1e2fb3ca03fe3022012e7586dddf21697a5a12dfb3f4b05c94bc2fd21085653df4a76f3d58b45b2735f7b1b9bc5132adcc032ec498c77910", - "0a06c9000e5cff78d29761f81d99aa6a5d9736215021e0e9702b4c23d4bc69b5069fcfcd376ae5c7f10fc64b4e538cb22b183aa12b7a2290b093164df58c0fe2bc", - "0a06c858f16ddc3b2cb840841783a15af0a582a04441e899a5ec37b0fe670a8199a571df5a2c534ddfdd35a52483128ec728b33f12274829028f94c8f6968d23bf", - "0a0412ebd99f4e3adee8d048ac083136cd834b72e557765ea6a380474dbad998dd2deaf1978ebdbf8acd7d954c9711aecec300956f987d560a962de03259c9e407", - "0b02e5fbe4efa2d95bb62c7ba2dea26493435811d16bafaaad8abaf25eb340b4dc6857ddb9924908116fe44c7c7c653e0e69aa11916765cc726c47aaae1c5596bb", - "0a00d85153eb04952be5d909c639cb190ec1012109c2fa065779c0f1464e2b562ab892305017046a71869f7a9891d8ec1fc0349ee1056a0eca773a90950577315f", - "0b037f13a3ec6b3c39dc87fed1dc5f9084a598c99643f89c5b58d6102a7d38233bd8b548f0ac5789d2f0941635327a5d49ee974759eba4fefaf21570bedf533a4d", - "0b0382645801a74df80e22541612c1fb00a3d36b3c3fb9be37a9c694b4f7e61270ec18886e9b9551ff79b796bec59c16e73bc84bbe25d0803cabe608281a96d4e2", - "0a044f3b220ac1bba5ac9295fdf943109675e8653f3cd0dea7688a28eb60a2ec41f1aaa055550186df8ac2d41b66d267c0de9fa8a532f7ede7deb650ddaf51a2fb", - "0a072787045455a8003b6f5a80a365189ad4eb0a933d79033afb6c5f3b08e79d48ec9fab2b7b8b8cf8066368fff9b5a314a3cf2e24ffefa45b044c89167d3ca6e6", - "0a041814aac6552dc6fa77a435c2ee8ede2499d7538923b315d5482171628cf24e6184cd79500f97ea47fffb585a7b2e556d059fe1f08f7a3452920e8aa6470599", - "0a001f286f8955b6904b6314565f878c20d94417289bf9687c97a0481a6db5582dc04ca58d4e95425925364f52c4f1389839468cb8b7bb769fb60bdc733b81d448", - "0a00891745e010303c59332f8d0ab143d05549375b9d30cf94c4f5b361e588f31f54e022e79228ce78900d4be81a1babf1b8d0deace4761f4d21379a5315ad019a", - "0b01f435de7a8db15bf276926787a07a4734e1e8273a2aed84159aba46e53a48861e5fd881ff1021051c29555b79e393a2ad8fb8f593ada024f5acf3594ee4cf29", - "0b059caf28b347d6723a0bbedbdafc48653877f415a87310ee7889026ef4c218f10304f746123079e4e1ef69394b291e6049661f1cc997e4aab0be103b6c8dc635", - "0b015f024cb8bdcb8cf687c3d66597715d790f7a6d4831b4908a12248291f50f1a4f7baf53a4bd49ce7a2781680e7b88e34a6594290e2f2fb2904dcac4c33adba7", - "0a05cfccd0e6a629ede7cb7522492d1e99bd196903ebcaf4a3d61bd0f0fecd2f295360bf3d3c6b1e855a9d03c4b958b581f19904f8320c0266f1d91fcd4d7c7621", - "0b07585b9ff19b87d8221143b4a0f8880522ab361374c3bb2c59c933563d4a515168e00f3994062a36db333aa6f621c6e4a3f0257939544949084146ce9e33649e", - "0a07e411d82175318965980cc8a582651208c33128850e1758c01cacf26ec4456e0e8125b69707d5a75cdcd40183bdec3639779dc0d88b199a797f30e3c0e6d52a", - "0a065a99c069941bec879b71aedc0874c5e812801859daeb8dbb771c682daafea731e3ccf33c3646ff27f8c788c1652f96d81840f669435db6a295ed991a618c7a", - "0a0082ad05ada2271ee41eb2d3e992fd77d7c20813d98c3781757564cf7af8da22490e0eb22584e290ae73518b148fdcfb28fae1f5b474740e19ac647a3fdbad46", - "0b06bb841eb0f359662f572e222301cf28b01a3ae10a96543c567c94f30370d628a4e4bb4f22959d96b26a8beb5bc2aad8804d63ab5a89e61e1c76c90320193f6d", - "0a04a52f73cffcc4f368f22876648fa73aebeaea919c35a7496b0a3cead5f8febf7e9c978dd19d205f295159ab8e6ecf3bfbae716ed22f5d837c8bf84f8cd91882", - "0a049c4c3d341c4d552394cc9421d66fec14fb2f89b4bcb432ffc39f1849b87f1136f10e393b059e7a6d621d8e9e7668652d3164dbb77970fff005d840874e2a4f", - "0b08e99088780d67a036bee545c7f012966e8fb0c14b7137c1716f22878a5dbb5af2ca2beffaa5f677c21980a7a129bb45bac28a15137d3e1467415937bd44a4a5", - "0b00114ab35e6b441f1c7ad1ed168eb2346507fd44e427fb6d854cd092de01176e6433e5308905108ab58702b4575ac233fc2fd5e87cd382945cadb7d396701930", - "0a0366d3c18a97b263d171d224159c02e50fe13b1e7376923080bc918eceba00de9f44d342292fa60b783ce33911a4f708b7ec9ca1dd19147cc482ac977acc5d66", - "0b078abc2267961eb656d5167397dd593c100316133d4232b1e3c4e47e966cbdf33cf2b073ef5625ef0012cb5bb4b1b8e77dfe137c180fd2cf949c433da4cfc025", - "0b069f285911d62ab43b3587f9923addf52130232d33755420226eda0eb396dff2c1b3273bc06eeb49a196df9ba03c3cd18b454868b17ef28526178b465934f8d0", - "0b024b20bc78318f850b91c0a6a9f3f15caa40e1a5e158ab65258d33b33af5186c685b4c20227716bf93960114fe43532db3ae38679f1abf99973fe29467d7e1a7", - "0b07b6676ab295fd3b54f4c84a7fba24ad9f6a689f9772b1aead244a7a159f0ecc3432987dfb93f8545bfb4b11c34de0e65817aa070094d2bfc427e20162828c22", - "0b048adf1beac2d5984f5e71b42fadf26f814a7198d8731c33027b0240a82f20144745cf7e6fea30ec1a6cb0178413654789abee2eaaac5d99118cd72c0d0132a4", - "0b0625cd401f0b0c353ad49b85baaa4febd9c10d9eccc703135226ce4c92bce431121b1f0bb08bb6b8584d33247f0787b8c2145e422f8daede8f1d0114e54495a6", - "0b07cff978843d616ab230ff630a7ab2b01dad896f390da55d11d0f37170136b1b9926a560e2fff76b3289e6eb8957d7a985c2bd0d14b864466e334b58924e2ca1", - "0a01bb752f6727c966da064402002ab1b8a3f655d1fe28c18fe744369307525c153cd9f029060a8805d9ae7048677f04318619b6bc59acd39c07ef2d17ac9dd195", - "0b076b8da2587b144fa28ab76c9a9c042cc29fa10fbbd5fbdcb599863c8dbaba0d1a8e79bd5a891d88c296ca7a8e44107dd660f3152be529eac200ae0c68cba18e", - "0b0695ab51f143d32e7be006dcbc282a1a205c1223fe29e618fbbbcb28b2649f61067e37717bf4cedd7d0a34096ad3d59d73f2cfec113ad9c7bb399c2de22ab16c", - "0a07388818f82ca3233aa9066ff3eae05ea656674b1c51c1db62c6fb6471901f6bc3d3b9b6413a3d0eb12330d1bac5fe2c190f9977017e5e020519e0e4b9e56d55", - "0b002d9aab6b61b0cdfacd725524443e1048ad29b2719beb76782766327ddb129495237bff17d978f03bff13280b9d6b8cde7af6f2162e956c43d5380355d6b121", - "0a00286fd366fefff9f385d7ce77f5971990636119e008315188b4192c46aa22f122ed82e3012f65c26fd61f8e49f9ff1eda5d3bc0af24c99f27b3b4f32ef978e7", - "0b047f585eb310346d06a36f609144431f8daa54b90d2c5306e089d0ffd80de70a83ec8f4fce94cb418e8794b5dfa2ce96e967c4d16b51fb91bb318ae4b555ec06", - "0a041a4586dcfb0a2940315f4803dce47a60fb9c4f80e6584de2b549ff10112be5ed00f9b0a9466b1a5c6621421036bf7e554651bc2ead13b173b61a547368f30d", - "0a030c7cbb3e7336a30f3ed6485e1767d932510e177beca1de76aedb8ebde7d30647369cfb5706baec57e63104c82e04a2b5ebf4aad1a9778e39669e0c37ceb1ea", - "0b0344a2b723d960762e7b9992fea99ae3b7d46de3b0737b7e19cb647115f3a7efa17e7df8a2eaa8db80debc6ea713cf3fe479b5e2dc97d6ace142846c66ab75a8", - "0a044d3ae6497e2c3662af17c02677d7a86091072bf227d1ab359345dbcde44d4956ac15d4c32f4e762d75a63568a7ad35ea7e826cc0a8c0d89ec1f0f814396f81", - "0a033cad12d0f9f5bc472e286dabd3d60134de57571bfaded905e6cf14d81558902f0d543090d319b3e37980c196e3332de39c48672f066625bd09439e66ecf9e1", - "0a0836f4e30fe63933763f262d5b4c4c8b399c0ed447576415e1c7dd33d09cb5d0174604c3e66c0428b05db3213f0290ec2f08fbee2125c5ab9d917342f6f211c4", - "0a018a5af6b1ffc5a5f0d93bd6b7b30080df7169cfdab9c4318dc5271f9ccb76793c1991fd8117ec16a0d0762d2b7f36037e18589899328f142b5663907383b4b1", - "0a044dd2c42401bacd4e3de7c26e41c3eb4613494b424e8f0bc9972c8d2b2e59154d0340ab272144d1130d43f68b598e793e72ad491077829c09f68983abc3ec57", - "0a05d4c18a74a684f914e2014f7a72d47d8f0a5226080105cff33e7bd909a7dfbef074e4ba0c28da2b1a85be5010151294fadb78cae93caa40dcaccdbc0685dbb7", - "0a0228f6fcf9b54924ea5b96840c7704d433f834ae3b5f52344c0381d35043f7c80f7c30925b2ea051696a49284b1d6ae1cc4fd38e1054f22ab8792abdab84c72d", - "0a010b00a27f9de6b04f0914cc27478b1641665ce6e942fa490be485745143d1e1c6f770354c24f6f717009c860dc19418a1254e45e94832aac8da05bccb66de63", - "0a00a4a8a130196189e52afaf437daa6fe2aeefe6aed28faeceec41f09352cef1385a7a74fb1e5fcaa561fc224a14c1249f82c2e1c65a2bbb3cf002b42e079b54b", - "0b01e08b73f9128b694bb6b8c02fbe4ef83ccc15b876adc21a3eb7695032fd45917ddf0f0f6d6b1f59ce547114941b3b6fb4885995be7dcadc131a06b53d09019b", - "0a0252ccfba62872531eddd8d9e5492f42c623799fc21d58e56d61bcf49a5687c7a2c17da7e9d3250effc419cc71314e7d5dd7c6f88c17ea5071cd0a25a673986d", - "0a0033d04a063a86523f957c59fd8e989b001f2053bc5ead7b1c1776437515cbb3818fad6044866e124140912000925ff7ee2b6869daebb4f6b4a7747ea94419a5", - "0a049816bec7a9988a8759c0d58b6ef82e589240500b5d7eab15d66d865e0cdc0527068c8352e16a2e9399d49cda5a603d5c4941015e82987b56f03fb9f2d20cca", - "0a07fe56eaae36dac87393d821fe329f06ee7a96efeaa94292ec975373cf0c06dd189bc40fa230a9b14875eba36136e53229b7532def0f86976cd8b411fc9df9bc", - "0a02394b0cf99fd6d11186399ccaafc2504df579199fdcedb3a0274c0fe1aa2d05121e2d60ae21d783ab44d6db9ee202584af979d7de53bae1382a3a02f198ccc4", - "0b076a759b30dd887e7688046059ca4f8dbef0bdd05c70d11b2990aa3dd99ae4e8c627f5b6630d6550e153029c5392bea00055a52e8f4f51592e385f98c1f050b4", - "0a076778fbefb67590c42f268d7f7b220d9f7b657bfe63c90b7db78130d7344e0c4658278905d6f0c6df14f1ed9ae48359216b333fcae7e281a6327b7168d38c61", - "0a06a17b75c3b62aabd72d2bf3016e1a14f9d24e1c10eead0a640f65da4a41ea77d1c3182c85a855d68d1622853cddc92d5d1718c1eb05d24116bf9efcb389dd58", - "0a0444cd9c09eb5a4c3c7aa41e6d705bf54aad9481cde7ff6537f84619979bddc71acab88909a5b6587ee0d73379d8519745dc625fb2462fba5a42386b39ab8d34", - "0a068b7957b594403f5552b683956fb0c9e1fcd7535923fc989aee8bd3d41c682fea54870e97d803f814b8c79b5b0466a9f1f4ff055b1ab24b75ce710749afb342", - "0b0008f9f2abd44633aa06a11ec2ff822ed36deaaa2f6ce948b2bf9bf0c35c8ec94c6ce65d1f372f7e149f859a36b9dc5734a5e4b6e461178ed92ddb393e9183e7", - "0a04e436d41ab8ce9d6685f0ab7915f4035000bc742a042aa538ee2761e224856f2b845e2221e6df4772d5dce39cdd4cc659c8ece7106a6ca43d91e3175f7bc352", - "0b007fb531e351a30027f443f8a16aaf3d815cb87c2e3aa20327b7706b4c02236602567dece092aab668a911ddd8566a4db9561796a78778dad8c6e211a0399263", - "0a05af09260a8e12f5dbd0a7ee30439b7c86ebead4eeea60ed0b2fc7b5cd463c16499e3cd0e1975d8d4e463ae01879ade902fb127baaa87cd4b7441d620517c387", - "0a0416c8e9e12df526d3c8de0f8fccf60b90ee437155532d04ef455a7a1bbe25fa7f03f02c838d6272355f8d728fafaf0ad264d42cc6178e8857f42fade8a3ab7b", - "0b05807116b628466fa03cab07860a125a4ef6ccced287ae9b8efcb717a2a73d4f504d9a1056f5d5b88902908742a7d2404745d5b9b0e5389828c7c88f01fbb4c9", - "0a039b6505fb30c068c9d8f06e76419b8847b6ad1e922dbaf54f640b7d71d0725d5824c0c9802ec59077aebc3b1e705c396ee5816fe3864a5ec27c5341dea5e121", - "0a07331c036ce4bbf6b27bca3143f09ff827da2b38f5ad2fe8142e6a1381c8c56e21474c0164a31243d58fea6317313301cf6cb47ff543b68d200a8abc4447eaf2", - "0a0734da76fbbf229b1085dc513c246fd9af4cf4a3e9aa7d63b7bd476aa856b166ceab4643d3c94fa9046a4c929a3d8edea3745e2ca8524545f49cc7863e37023f", - "0a06981f2485e29c12f612d978090acaba80f937fe85bcf76e1427cd70041c7d810d73ac6e64196b077915d1ae432fb435ccc0adfd024d67b7372cfe686b7ea9b7", - "0a05143dc239df3507db4bedcfcec02ecd14a7af905a0d5eb7829fefa2ea05e3c1ec1a4e05c3a788280adb78f2eed8e0b0ace70ee91e477e1646f8605d870944d8", - "0a07457441cf4026ca2dadfd7b04f3246b69b75556a14ec37c16f9b76ec179563c8056b5b1761e89d1bef9f36a6fdba568f4f082b14e3cf5f30d4b58bd48e6ed28", - "0a00444bc0f944e23d98c8028f9f4282e51f554a372dae4407d8c70a717ad443e849e7aa6079ed5a8d2808f2bcd43a65a775af661bcf56a0cd87f558bba7ce41d7", - "0a05737fdb10ca29266bf89dcbf2ac595f85baa7beb425343d1956f4da7fc8400364522f48614ffc088b72839efc311f2f98ba33852b9c3ca16aeed603e9284cb6", - "0a08561e499251b31857d3c1a15305ccf207d62b25b266af2094e0dd6ea92fafdfb570597b3209e7256652debc0be6e0cbbe2c707571b55290666cb053b332b490", - "0a087ff29d457573bdb4683d54172b20e537c059458ed90c92409811c868dd41f0ff489fa7e0b0b058595fa6c9067ab6137b108c4a99f91ba61de6d0808271b375", - "0a00f607f4c951436fe50c272be7fdb8ea98205f50b765a06d3f92002f18c76b4b94f63272d6f6e829ca21a4ac52cc01f1c5649da19204fec7a2beea8cc8569aa5", - "0b0705fb73a4ee6c97266dbab0e0cfe850f7cab1ed26f89f4da83aec551466d4233eda3d3efcbe1dd0e1591074a14ee2c1730560aef85282df610d137d50af630c", - "0b075d2f4ae1f7c46d165a3ea95200212f6dae59100c175c2cd34acddb0fcf166b8ef9372cf69c738c21c111bc8ade8b6369c7a2ded7af3afc3dc36ca6c149dcce", - "0a034ff1f2fe93801f5c707e96fbcc3df860ff25b9340562f1cff5f55715238695180592253272c5e708347994f9c738e2454f3abf0755f1e0329b60d3fa79b803", - "0a0079afa962dbcc6746b489e9a13d4d16968e947ec5ec6c369539b94e8081af2c8149168597093524271d4d7858360fdf6f64dcf7d052f13536f6991281bb98dc", - "0b0568335ebeebbbe1e30694f775c80e59e462c16125ba22f1cd61cc9dca916c36feb28260f25eb4da124c36ce5c284c15763a27da99d14fa76437d36387701def", - "0b038c52506c420644fb4d8f8216ba920bb029ba0db640539eaa12c1524c227601c4a0e1590239e999de9b1ddea451488005d37a88c144ab98fddb04d7eb1cbf8a", - "0b07f07cadf3ac603b98758b90cf21e46868bd35b71b681274d020ed349021091cc7cb10ac0ad52c43abb95e4d3d2c62804d011486678c720da63cf790ae54b83b", - "0b06789a11ea16ad0fe7c93eb6511c42886d415d1fa612a1818c02e134c9c78326ba91633d8800d5e8753524326120a12100d5e871181036b3a7dbde80bce58a56", - "0b001305e7a52d8bbd1389790a7f1a8a2e80526c03070ffd082227072ab6737fec5dd36093d91725f8f0b8df75c381c6c070aefee31b16f6534e07c94242cff164", - "0a037389fea220f3e275e5beffbcbf02ae246d0a0349a0b8ea27e1d438ceee41dcc680dadce247d6c4b1670c3bccdefe9475cbe8214dcdbb25b32bf1419027f078", - "0b03e7c667f4312105fa1ae7c775c43ec726b36f0be59b6ce393a40f7d0780e6a94cb8c3f5b7cd29cb06179c0cd31d01b251a2c1d1dca1eacbc709a8af670c62c9", - "0b0635ec761e40460231bb4f852900e17a9c0368af226c76ffb01482a157391db8610612b2db5c18fdde20e203505b55b1f6a83ed7ee69b8771e5dbd2ef353842e", - "0a05d8d6a738fad3281a360f4f7036c223667e069c439e0e89f6545bc6f44d457aec8cc0642d6fb29eed02f4f671a2538cf3beb8c8390f7ef17dcba8238f6a5b2d", - "0b066b6170b621be2592d49861c0eea3f190f128d59836b6a2194fc5eca3957cd8b63957017fdd6f11db345fcda9709bb24dc3710becbeaa0ba0c7610d95000a2e", - "0a07170e58b553cb09d0cdb4bbae8d631e927b7b2dc0f839cdb20a7dabe7d5f315fcc17364f0daafefd9823f929cc76d3c736bf0a1dc7ac1cc05790c1cbde49e3a", - "0a0319e1320f7a4e3c27626a3e402bbd8c70d8c48c7c0f333a9df71aa25fafb53ccd8ee8052dbf73d56ac3873e5097e8abf0d440f514825c9cf65c586c9ed13121", - "0a06c16a1df32d7e359aa62e24fb173f592ce9770b5cfc3aa19b13e42beaf12b023dc734377dd2dbfcbc0c076ad4d3c84408e15ed7f4c1b770c06e88f176e16fd1", - "0b0024b79931433e159ff90c39c88fff8b0a51988b5045151692879f0716d53b45d8edfad1198e649a46b1cbca89d5f53962806fee34e10a7ccda6cc313fad1127", - "0b035dd4087ad0a5696ba176642fc8e64944bb88f338cba7cc91e4edad743ad4ca1c45dffcaee91c6563d204dac6af8b1fbab6fbfcfd48c6b379a50bafbe33ae51", - "0b01542760b31f4be9eca70df9cc5fdf71f998ae66adba4d14b1771736e9788c583dedf02e722767627505b2a5e11b9ed7781d7a17fee18390bbe02f91a622641d", - "0b01601fc955a1f8bd3849026f2996efa07f79d9d9b0527a11ca21024a774648ddc63f048082cc946dc63958fd992ff789ae48541aff400b06130883f243eb8b74", - "0a080c4fc2a86d0ead238edd04c13cf2f0ce6afbca3418c0d44c20c82473756d635784bfe73ff606c1cd08ab8cf520b9a25a79160aceffb9da052e7e1baa8d1c0b", - "0b04fdd4808d763d5c26f5f06a744ffba365a254952f85a3861da0ef1e27454e01ad3cefba973c8de0bc981877c9dd4901799af004a45199d97e21e9a54e464226", - "0a03a1525282acd82bda6ffaf9e32237ddb89cdf7e3eda76f2f839c659bd0561c23c8cced0bb712f961eddfe8f1c66a58251450b057b0601e4135cd98a73196eff", - "0a05e18458fb5d8b4e75770f08151d6e6babf63b840ef1e8d17e4d88e04a727f4c14e74350589118413bb0af9aaf2895786fe7547c9c005b46833a315cab396468", - "0b04b841c636fb32a2d452206ff8162e4e50bcd727da0fad5a592476048854eef00897c64e2e679babfd28df933a9a276e7e948f57ac43e1ad592e184f50d27cac", - "0b00a4f041503e374a666e9010e7996f42b92209e2c819ce760451f9b3acda072f0904eeae64860817fb2676c66b23fd8df84a71bffd296a8ad4ef839ab4e486b9", - "0a0229ef8213756a23e9654bdc32dee9f71bf73b958f8efc1041e268904ea2bbd6a8da7e217cc0350e4574df39166c9f609bf169284a5be09c6ec860659595b093", - "0b01652f2e3419e2e16e1e882ecab1b30099b5aa9558dd06cac6decec346484880e19259399bb02dafe5e0a1ac8ad5c5eb4d121779e3fdbb5e601a8c242eb175be", - "0a08a774de9e3949082a7361d6e9607750896e7dc2b410bf61a07a4712767db72cd86b74a2c1fdb0c4cb0b52688a797993dc3810b421e12570bf868fd47b044cf3", - "0b08f6fbf188a615eec6eff3349b10d6c85d1eaeb1ce94171c1e290d3199d3aa256ce1bf13521e3ea6f350f0bda51f634d0f02c19cdd9fd031ede6690a54c8a8d4", - "0a040ebc36e78c5ad6ed44f9657fc4870aebfd82d5ccfee67cedf98c25e5d1fc64547e407d5745d9b6d2a6e37d8c5dd36cf15ac6212d2d8f39a9ab7d58b6e24c3c", - "0b062d0fdc6c373d29c8f72192a07e3ddbeba23017709ffe6ccdac887c014b5abf2167d4ca1729f3e9bf08f518ba60849d25d25ecbce9e1422ce56a6dd1664fe45", - "0b041de1280d8d1894cda4c1b07d8bd10b56223c3dfaa01294788a3e00352f4f8d94c1e1ffc51f351396aff6e03e2d140f87a64b183a7ad086a401e8af472cc693", - "0b06b29f98813875050a87a30f73311b559af34587be82f1d34a6f17de6ef474bf43f1cf7b2e44cc143dd5ccbc30b429b1e3e62a3367c310720fbae32e127c8445", - "0a0565b51374541de14588fcfc429680f9a37fa691f7a98dfa8bb2e9872edf51078c60d4e0866bd56c61dba57b878fa58f1e7ec82f9dfa19f54046198d55ac801a", - "0b00106a2db89cc3018d27fcf70f27a6598af9bbc14a87b9ff367ac46a5f7d01ae391d3bdee5684585d3d97ec95e3bebbf62a4d823e6fb456019f3165d0193d34e", - "0b0563daa440ef69ac169e77a574dd80aa04fecbcf5169a0e8691dbaf9a74cb9c00adc93a07f024e1018d699c16f5f539a8f9e5c1522dd0218f73561873911417a", - "0b000951a4b1e306a57e582eb7b3158c6ff78ab8aee42963afd5f619c97457a0c162b91b02fae55452546383cb9d0a7e45de4f64dccaa1f7972cfd8df2169e1c35", - "0b03d96ff0ec4331f59df8c5738032538a0266ec4e090470b546a9dbd9eaabf5d209e7a8ffe008d4e494342add730959b6b942bb14d32113828ef9830c0e565b0f", - "0b0011ec6117439125366481417c38c58ea2968a8e33a56e841fad16b84231b27552f000ff0a21d048570129b6e7553a893d835864ad0cba273151422018d4bb19", - "0b0369cc419d115132e056a5d778182946aacbe7b40f8f0b3c32313fd8356fcfa49ce8a51d2405546050b43b56d7b3332cd7861201877302aa376bea82a7cadc71", - "0a0338d09fe91ef2ad5ec7525144857e6d5af8b222271e6f44894bd3955a53a5e099e7afcda799b6a310480bec913e9622fda91249ce8f304288790aed90316a4b", - "0a00fea38407da4ef3fff2f3d144c1e73ec1048c3efb91d44e94b258ac5396d72e9d53a33f77528309af077f404093f497ba4e72db41a765d128d74d533ee0c785", - "0b00fd32c062e69d0171357abe3f90d648734d65c9fe996344dcce0275139283bbda90aa57bb422a2a66b4b6a73a59aae78c582d7e5c6222e7928126a71d68f79e", - "0b08d60d766333e8a0c50a25c7fa747d73e2f124c0caf5987c1f17e0118fbb4c5cf402190ae38c73e03eb2cc92e869e4636abc021d2af5f7d8b89c32d4b2ed8ce7", - "0b00d25ed43c8e42f83015f54095d0428ec384abc2f14a52908b74cd05453ecc257a3343d9cf8d9525251fc1a193d1fad6c25342d86e5fd2c226ddc5f56f2d171e", - "0b04a7c6e8a95a2eb2f05c7acabfc1c6d0fe0204ccb84d80718328783f6567f46fac95629e5b4d7fdb898897e3254bcead41bf9983abc94444979a6d6e811ada1b", - "0a07b4f731b986d12636a976e96d72e374b533d3abe052004b9700877422688d4ff6b407461becf1541c3283209aaf099a488e6975c7821d03936b84e3e7f7c0f2", - "0b05d5a74ead0505c32c01faf245d676a70751a9b125af4982ea4a5b0a291f367f764af388fe93ba4e9c49bbe84a9fe12e447e6b067f892b52ffbaa90489871738", - "0b07b748b2b3ba4133e66d86d0ca7a77cbde892982ea22a2aead251a886984cc3739f03c08cfe01e92886211d2d65b886fec548b1df4a6c8d7b0c1a40ab139e322", - "0a06f982f421a7e7a526834940a5cfa88ed78f18ab316380236a946f54dba3cadac6e70523f8555efb7f6d11b4edb3077e2945e28e6db1f44a3a5fce79769aeaff", - "0a029f7c835ed23f8c5f44b38c7cf2c0b8969d5bf815ccc4119f230a58c0917d882aa03f5989dfa155ffff57d1eaf13a1b40f999719184138e75423ea76e7f985d", - "0b05cfd30c27da88aa14410a4673c17c52a2b8179c6b0149e4769ff88d943da4762936a7fb7c5a061064dd39db2d0b3efa392a9fc0ba6307ed4f0427708032bf3d", - "0a080d7eab37dfe541d84ca27003d620b70d6973b4003524b9e1316436df2772495832c4aa21b1a4de4d3c425f84f863de5731d93ef8c945dc47ce229ab97fa5b5", - "0a0259d463761f79d1c57b2b7c1a5a98cb1bd87085532d4630cce82bfea5e3eed07cf5e45d4263acfbc336786bcab8a803ec453c392f1065e770458f05f37d65c1", - "0b024ff5b381a7abc7d5d44d1bc4c85fe0656ffcf0582d342dcaa0ccb7e61e988c931d7a4e5aef23152ae5432b916b8f5b06d94e685b9274d442278b8c75d45068", - "0a02c52eb577b24b3966e86275659d834cf8df4611510424abc65a54e263b830d04257eda5f3e99620de945c9790bb5e1889392f62033595d0c05003bb3ff70817", - "0a081b09143d380a3f8fa21eccfdde6fcf3bdb6a37018612e02adf8ab7392b99d69aed6d6fb2a46475b310489f4abc4baeda43b81fb2b322ad012aa66049cf4c0b", - "0b019baa4e4697b6c15b931f53f67dd96ce6cf3fefef23e3c0c2454d6b6a301b96fcc1aa66c894bbe3ec86d34ca54b07113be9e0fcd1b05a8a0bdddffe3312e3d9", - "0a0111f6478c10978a26beb43c89a1695d08b71835eeceea2d1548c55804effb39cae92d2d6252ef2f68e30915ceeeccac9565369e7e17efd9453359a0f7d648e0", - "0b0225a3b97bbb71e5e521df20ea0cc3812c14949444f9d574b0bf04ce4e3e367d65a872b4fb8fbc3d05abd6273dab3b022fbbb1b9a61627f8e83663cc82f1fbde", - "0a08156e4c3768e60fbd2e2fafbc2c815eaffac6b25ad690a79c6471874e12061bac077414ec83639c0e9d54919a96f0d08648493f3e1578d2b2a96aec09dcdc83", - "0a008e3b35e8641b634728bc0fd63c85de2d0dc85bbafa683ac52c84a244e7e7aaea191be61e6ccd3ce1ba57f30db3c9be82786633023ecdd6759004e1c9144025", - "0b0339c5d9a9f15890cacbdb6133c1edc9cba57619e6ec611ac3b5c6c8d8ae8a4d080090dff80eef600535f3008c5664edc7ebf23547aaa2f33cdde1010f2fe070", - "0b063628b6ec5f06c7c4bd8653cc46837fbfb2a55b1aa0cec827b7f302ab7107f92ab0c8c13e4201d17e9fd9037fb5a93bda34ec301dcf5b3c05cea50639c99a70", - "0a01759daebf2cc56febec5eac1d6b846fea15843e94942cecac76288d07680dcd7566144ccc9cacdff26aa4639fcf439c91105b980c1741699121ac8205fa5f65", - "0a034d917bbe5ebf9850199c6bdb0d70d5b8c02e7ae3c6f542706fb230ce62b2326c067084a79814242776199a15d59526197d9d07cb21b6a00f981323783077e6", - "0a0339d6d339f09f7847cb62d80d4a1a9c58681e20c864600eb7ff6b1b62d9f53f15a2f9daf1b37eb62cd9c717812303a4814799bd7b4198d677f61633bfc5bdbb", - "0a089344688bb1d5f2b0a0b6450590e5886a3b20a0f986cfd14858b97b19fd0ba0ca100d910c83b75602d37fe663d8dd813337724673a251bae35820f7b2513cf9", - "0a013d79916d32980b12745dadb17b7e9e6a9f33c8420b88f9c5f2e65159e0a22688c11a69764d594c62e033d79e715e1aba6922392589389549a3718e28c0b02a", - "0a003d501f62d24cc67772085f38c2ce656e29418fd1d8ec801c4ffc2567ccebe502fa9b8f8429e543cc21d01f5a283e1dc9112b3a3ad500b20806fead6b12b0a2", - "0b04d8c446db466ab33a45d2103ad493db7e8ae2ff9d41b86ec70a088cfc48c7d1b43bc3b10381b5d63864e92a4b0ce718f39a7f8ade2ba9872656226b994a8941", - "0b081b84fb1d6b590672c2c066b886f67ca51d772a2e31b5f0e844580287d8400ae965be631b986291479d161d503a098d9f26fdbbc67694b70b347b84802dd9b7", - "0b040d74f8419bbc005a60443d70ff8c871a2e1460e892dc6cd2f27074cf54a41ae0ac947de0dc550113e9120e952b826ecdaeac59864e1539cd689d1a5897aef4", - "0b08877cbed0fc156ab4aad349d4a385e27acac3478104c57da232557747062ecf9bef5ae215be691ec965b37ea07de75ee97a08382129278d414b47e3bfcef5e1", - "0b00e3b81dd56efc536675fb739e6830393bb215b5f415c8810bab4b66bdbcf989b3ba59046dd88e854108101bbe881da884e3fba12f16f7676017d6dca07ce62c", - "0b0383e1bdff994df54ede3c8a8b20af18e85337545c4650eae3b6799da1db3222d0f5163ba6843dffbfa21aaab44d61ecc48e96fba18bdc7057ae9d25fe6fb12c", - "0b0215754e6d7c03ff80c4a55ed462ce30411956d0c5eb486baacc27d0f523775a24fdfc19b3f2bc78c8eb4badc06adf2ff43aed8f161686eb3730bea2b6759142", - "0a050bdea76ed9f41da8e80f3229a2b1fb1e3258fefa3ac5aa7de98fd2b55f1f0eb5672480c8f01fcf7dec16e81776f40673ca98b3f3c433e51baee00a25c5a94d", - "0a057cbb4ae21c2b1d46e19452d14cfd3ab3a001e056d4243653dc0a01831820f6b76820bdf780e195116e4238b7a234f0c7c591c9b7bf0480be1d11b30cf65b52", - "0b0576d48fb35aed40e959166a3e13d6304b0e4055e2028ddafcce53e27ca292677f21408f7c74d8366dd56a4b485e9e5c7ec2333f0436c6b7a6ac4e744d974cd2", - "0a0575d2c2b5eec4140569e3e4e0990e1f58dbebb52f74774c18316d1d9c9c2083829749d97fa16f390b9305ed2ace9906e1d8bed40924cf03fb8a08d0e8095557", - "0b057bc5ba41199831c1e5849622d100fd89cd44ff915cf6727dd3b0ae8b2ddd8a3abd6ebb19613f6396b53691429c6cc60ec766d3b966a17ceb0936c3ed120867", - "0a0900137fa847939b0dbb77eb7c063dd45f68d18709a7af64a1d2d1c448231a12727da3eef7f2e7099a010ae2a2ebecf7903b31869fbaaafb3f82a8513ef4ea74", - "0a08ea7b490d993664a6cd3443e609103aa8cdef5e7fc62c463cd7f3bdc7b01fbc00db06eff9beb36c91559357dceff3d611a070925d671f398859c3d720b524b2", - "0a06702069b093d9223e854455a79c7e23b08d6cee2403cc75b58631decb35941ff1a36ef8dd4b34660ffdcb0cdd30214d6f3f3520c4aabdb898bc0e446520aaff", - "0a03625cb6e96108de74987375e9915895ba214e6ebc6ea2c31065b1a4d438d12e17b8e895b7d4f02478815ecd24b04f998124d1749b42f05fa5743367209137ce", - "0a070fc6166c8fbb4ef29be6bb51185197bd216a31085508be894fba4a2d639c753178a4fb936a98a02db588085ac55d6073fcc29a7eed0b1c308b1681b354c614", - "0a07f12a7d441daf13f1099c4aba64f070d3b3315197ec8667c494d971393247d6f8c03b1e101cf393c013215ca7c2854d09c6d51ede4818c928502aaf86ebc2e4", - "0b02b5ed6238dd9d5030bf09f13251bd632666d3f78a80ab7f4538158e27be207e4732806e4bfdf00ba8393242de1d5a2a53cf22ae975dcfa6649589766da0284f", - "0b04b6f0b6521b81545db5eb4a7e67a03c208457032927d7bda235e2f7317ee9646926a04a6309cfbb5d5afdb4fc36643dbdae5c0d94b68c8bf1ac84837c9524b0", - "0b075424ff1fdbd846f80d8ae80c46df3a158b87fb6c55bcf9e23000089e56eb52053305d2679ad12e405a32f233c54664797f9adf0d3178f6a3108618ff98e33e", - "0a04b20670ca3e3543b0e86b27e3cf2b024f623154d5075f8fd3ae8b82493794aae25fe5aeb3d0ca7a3a8eae791005d853b48fe187c57756d391725832f6cad5c8", - "0a0362290c2c8bd617e93b8d71cfc629a8b660725b0ceb57abc15692ecb6a2091c05180103e636eec74215b13236374cd2bc61f6dd7306986fa4d6b5077408d64e", - "0b04ec279a13eea0c310fba3988238f7f55494045f3db48fa0aecd6fe3b71dc597f371b6f6a5a661d875e55babc1aeaff12f6d1740881d9c5fc32dd895cc6a2c89", - "0a0012e0e77dff82aea8d4868e3964eb86b4224fcfa4fbdaac9333694bcc1b993a03fcf442094ee5140b265dd1e9fd5a21329f1e77c839ad2f91df58017038619b", - "0b05e32ee16a52e6ee3cd145634008f7d379f3baf65db828ae2521cd19b09f8d7175cc25fb0ae9d32a20017185b02963f6028579f1b1e85871ecf1b6e48cf33c3a", - "0b03893836691576fde84ff42dc66e5e35ce47f3f64a1fc02ba57f7714fa99e2fa04cfbd4b7d088508c7ed0f8a3b4a0e07b59d2fcbef58e7ac44885f6a86c0df6e", - "0a07d45f3db0a9f662c5c14a06deacdc93ca4bdce76fa4b36d453858b8eded90a4353da6e514e9b3da4410873992441d1eb510822a030a046eb74c93be6ffd9e58", - "0a02f0a5e3391a74a93297508979d885685444ad121a68cee73572bc8f59de1037689979833a3be1fc387a3030f407d98bf4315354670455bfbe05b3b1553fbb15", - "0a072ea221bc94407b9f5dbcc3255dbdf49bfe3aafff0cfc7a8f752d1b843665acd99d7f12f31a283a13441f10857e86d4547f7ee9be00b9e55e8984b2e717ae9d", - "0b0259469f65af9a742901881da857fc046bdff2ac136fa918d20373ca82ed8a87ba1c24198fdb8098e980d23b09076dfb264330099803866e2be31d19958276b3", - "0a06c5c8a077b5cf87fc5dc87a8631fb0a770f632da8a7516cdf772703f268c890b2524dd7e9af119f32f6e0dbe7fef97f49699999b29e56cbdac8c367d34f8aab", - "0b050e880443ac6dd60845667fd9556419ad28a6105e05808e7f6fac9ed6138d97091547343738920b6d98346a61a59807d5564f16144bad269d9b7d9b9b760379", - "0a08f70b4bc054a70944828ab57ae1258ec812b955bc70c4023bf78224021fb65d42bc9a240eb9d112c8a7495abff999be7dd94beed7c935c7f8f145b9b638c77b", - "0a01bb16da8f15f5caf3d85a31221fdbbfc5e356a2834b731081b42881bbb37dfbe37f2a037934fe8a94fcd547679b14cd2fb28b0c39ab334ddbcdaffa5b3725be", - "0b079e2d73de130834b7007cc2329e5b2c28baf5f55c7da797b4416d684026e8bafa5767c60daf3c45c47b8af20b0c07a8fdfee76ab0b3f3fc68f186cf5f0d6f7b", - "0a0762a89997346008693006815cc9fc4af340ae7c438cc81c431bf8345cb20849ad1e92dde6bd9600bd1880f4b72b6c5ab694cbcf737e0f4c684295b0bc6a7561", - "0a02121abf140e31f7c9a91c8735de1c8cfecd6dd8d4b8cd1970307bd2799f60bc99ef7164290f557ccbeb174d45891ebe40599a331d17e1d964a23de48bd3af72", - "0b01a285b9ffe689496325a151d2a2d20df273cdf4a339b9ca8bb36a2b94eeb6cab415aa5f7661d244e97c5262cbc781f9deba06f2fc71e5e1427a4c8ed5909fd4", - "0b05749bdd7f61ab03f0739129a9ed696e1bb4257b3e011bf5c396a343c224e8d520da9236c070c1388ba77c801ddaf51f7971ed44bb56dfee2d07049dad8eb453", - "0a04cf446cd8ffea78def0a79c60986874ea760aa590cf13df4769028073f9f32368fba7791a204b51a9bc26e3aef98e2ced9409eca348a88f23e3ed9dbddd26bb", - "0b08c3d6dec778311ca6732c6cf6e2afcf9b84ea4b3dc5cf7de1bb24a4840f0891e13af748c2ecde299da47389b1e1e91e7ab817c29ae16a633f8faf4be366dae0", - "0b08f60e2b354e774459214d31d93df95cf34434c02411709caed158f6ec8ae64b1239200cd125981a76c5e644aeb39d8f2a851580a4b337240044ea00650d41b1", - "0a07f3b16a2ade441bca6479048ead9672f99680e3758f936a90d66a51128dd18912ae4f23fc2b6b81dafb27a43324f0b2b6e31ff4d1ebe11fc205be0ce7e7e884", - "0b07eba105bfa58f15d6266f90e8d58ecb3d59c7878e03d4beb924f3905398ce851aa940e5d4df89ede2fa5d9f45e11de26f1f25991a41ca25a49cf4f9f4760e60", - "0b01b3bd56637d27dfbcd50688557fc7b362641808fe4bd1d5cabc15299676221319e4ee16a3a5e393d1a396dee2fd4d9912174003e24a52867a94adf4aa6af785", - "0a075548270fc1439f690eff303e0001ed522cda9d4604e5d793d238d84bc11a48ca6bfdabd6ebadb5184d9f8c17c384d45b3b32d33140307820640d9f9324f26d", - "0a04ba15180cf413f2c2308ed94377f6b39b5a09d05fd836899189b40e64b50da4d5a3a9d7fb88c0c30ef2abdb51a9a559864bae8382435453171a7b538ad79b53", - "0b00e57193b01e86d9421d2d78268488a9d3d352352edced5fdb135ddbffff1672d2f3a0fc41d1d4b9cb84b594925b7af7b9e7abbd49d7d641ed9dab3ad99326e3", - "0b0067e0da9ffa7e2514984b6659039c254b4a655629331f24b427381c34a39d9ba3fe585be47b11f0578bff26623b42b20f440ccf274bd1a14da0c9d6b35e86ac", - "0a054f4aeb51cf229d5c8c3d7c7c9aebe9dde1ba65a6856005f93c7d1b1d5250983be431886d37327b65bbf21e803565ae344eb8636c961f30972c7d6db24444a0", - "0b01a536f9195ad154a19de45cfd0e952a86038401da1e689d8e1108d025cd8b3e4b18a16521f27f066c47d1c02a4b6bb388603bb520796f7f6d9f0524be57752e", - "0a03814810600cfb9dcb26fb4d631e81ee03ba55e536c43a808264ce1dacbda0c439d400863bea19e237295e5656ecf14b60d3b0da3b16dea91a40efa8800a7457", - "0a0744a0f91f5d4a20b9695033f84a40b7bcf66c9e6382212ad04f0e5d25c2e012efcbe9aa4391d863acca0787a932135ca0719d9e1c4f70fd74b12113868b8f5d", - "0a00d9fb96fc8fdf99a6336d406c0b7a4a6d206d7df265c9ddcd55b27d7662fe396f93e006938b4a52b97a8c8264299fce2bc3a2d32aec3cfd377d871d3bfc505a", - "0a038c660676ac2c45127ef2566f468d0253cb1a68228b409a17f8f0dce837547b553dda3ba312dbc59ca971605947d1ca92ae74fdef4869a87fe99f9b504ad0c1", - "0b0568fa2a495a57e754837ed2267569e958e465521b0d31f04914cdbefc7ed82100be2966d166ae602b2696e3e9c1137a6a8a3bad192956d1af4d381bd6d9cb33", - "0a08e3ce88ea993d270853864e6e539ec67df87e89b77acf3c3c337d11de108f854017a72e03d013e40ada94872cf386b2870778ab9e3d4da4eb2766ccbfe61f12", - "0b061c9ba8ad28d71a1fd912d68b34ab15401156e2c20261be425433544ad224c8bced788a847207e3f812a3079d2bf1c09a403b2c98ccef161b4558cd9b3efaa6", - "0b036e3ebd3bfc719e7c27483f474581860ae1b3a609921fb07459cb8f1a559fc7a917b4a924696001cb4937d403e300f525bd59e67a0a5920b5609be290c106d5", - "0a08a3f0be4bbf73422e2d5ece0825cce0a168505cc760decc5b869bba30730fb904abba888007884c3c8c060d2ec92f425cdc8008c951aeafce958ce2aa1858be", - "0b018ff85c7aa8510d9305e148551e68620658ae21341ecb52ebd123934ca9223f790901c81558dbea86f70046d9a5094e74111be13c56dee7a750233589078b12", - "0a064adbdf354227032e84ed69da20e42cd07cb39e715fe68181505fde20ee49cc4962e8471c4010b4142b3e317ddaf9cc512f3371182ec5c6499bab181139a81a", - "0b05cf8e6a4d6af212928c3f607e79a8f6bdd99d327d0727b17202db325812b74c323160cd46e4f0aa8f1c3e11db1477fad35945486d0796f616a28c2e3a7bbd9f", - "0b0507f89f71ad0b63591d5417a292e30eca52776ded4c4cb5255c8662c6624ef193128a4961e3b88ec7e6ca70e34d85c730758aeb89621aeee73a1d04ebb3c796", - "0b0021043985a88cef766b424774c6611c850604e477ef38dc2f0bba6ea025d887e271d36a390f4aaab3959157292e4abdc08b0093b15d0028f6df8e8e26746e09", - "0b051b182235de35ab465461f31fa42e21d95c426cd0a633de577124f65270ec25b01b45eae173f72d7034ed0ef914cc997da74f50fed00c7d6e0b74c80a2fdcc5", - "0a0633cbd5c63ac5bbb5ffc7685f5e6131a55fcba365ef80fd5ebcb6cbadce930dca7a27e97b4cbfcccbd15f0f38fd20c3ad6e3c134b30997088a3bdfe86ddcda8", - "0a038222ac3ce4a7121b56676452b2e87457d213bd38b16feb9b4a0d965635fdb3de4f7883aea3ee7d124d679a2f8261e1f348b7904536e8f2d19b3d0210cfa9e7", - "0b091d3e8e7edf2d7881ed44d373797f89ec0bf6c6e7cd3595cbaba2a6be44008ce171d85d1889ca1f564618dcd6654d01537e5d80c5bed6f44228cd241531a6b6", - "0a001390e155740edd3a610758585176a60eb17a8e552f82cae25c315dd85673ecba0ee28c2734d8e1fd54cd0db0e6f351f8b59a94dd44a72bb9116c5878896b40", - "0b00fcfb8a98bea39a4137d1d97f7cbc8107ff320729649a19ffbfbaf16da4abd1108646d368c53b7c7cc9c19030e371d162aa473eb61e4fc81386ae5f5fc72404", - "0b008051d51a410229f6f10ff3acd60f2b43d42681cbea79b081d92352b9b31e3a23fee9fc513c3f3ef5c59d0c87b9f2cee64021214810a6f9b480d9dcab163827", - "0a05cb559d1f41f97d0cea2d919a6490c4e69e48599e5cb1a1a75f8fae0014a31ec388c47fe1a6b6b621c3979b134989d6eaca0e8f50f4258334786a6c2718a0fd", - "0a08f23b27ab09e22d36a0e809a2362367473b9aff12c971d7f259f8215e584f4a087676a169847b8d6a884088af15e5ee9b146f348cb2e4d2b724a598347050b0", - "0a03b244e2bb8df3561e342f644203d05b9283f44caf65a886223c42441f6f05ab07106cddc8a7cca74a0e25b1c0be49940706e28a717eea3a427ce0a73de76184", - "0b00c80dfbf4cff80b883dee936124ff98611308223abeaace056c287f5e9e27a13159636e75253e131f5c2c11daee9ee166de9d2209b2668cc22da686699b731b", - "0a079c573dd9abb4f0ce13e75dd833fed48953fefaf1100ec8e08d14dd5e4132789a25b2b67f2710df016bc22092daec57e058c1896aac2980462046cdcb0d52ff", - "0b03a2e6cc93cc78e14086c05f8dbd5acfe295f1a6ae18ded8d5cdf30bead21e90ed25e6c825694deec9dc9b7a4f38106681d0090eaaa28ad3f0cc919549ebef70", - "0a06dcca9c4bc231172b40af631435e9c52c2de346affe5ff4d047897192e16cc5d07d74d5a46f764eddc73d21e5d1130aa62d0775ebde4e0ee9b70aa21dfbfedd", - "0b08c1200f22cc52ac2834bd2e9d33f7a4608b5467ebbda011ac4ccf7c0070052a4a29975a8f333561b3c494423c3dc709a308f4d9c235e823e042173b255b978a", - "0a081ec5d9f68ca8a508b645d426d39028d05c6c321ec7a582cb1da6627c7c9074253d5869e2c3e783b43849f40c70e4dfecf166cfd6093ca8eed436811ec317c2", - "0b07e5866eaee0f7491bf607a14563ecae35e42bbc14e9b350aacec0eabecf86df21e7e0e9656237c9b8a1dea98de80ecdc12693a76f6d74f3821a861ad7540e28", - "0a049b7f9d4070121277299bb6b4f273c5ad3b58a148ceb77571e646b0c6cebea1f3c06075c2262387c65504cfc325bc4d259eaaa20a03968a03ad68710ed5ce6b", - "0b0645218ece58f214a890d559fd56af9fd83df474248d9a868194d11168b6731a4586bb854666261bdd7ed8907dadabeaf9409a3986bf5cdf041dc7a315c29692", - "0a0551194671575d6411775e47dfe5155eb4ade650a27532a71c49cfb89e625080c82e573e92db3fa6da6a04f9ef2456d46cf75e035b528b27e1b9b8e8cd846dee", - "0a07a90007dd63079530c84714f3974b60c4a6e7b9e21e56a2b44e6fcb336493fc235759da6fedaf0ba945af7fa2136db05348d139cf8a9a1c068cff17abd13910", - "0b089b3ae4d7af465eb891d118984ee0205741c935f8c06447b0b6277a9363ece3646a0dddbb68fd5a1ecf272469077c908c7ca52a0fd8a2a6dabd4357b06d65db", - "0a01c278a540cff4b09e8c2d1a1cae40657ca1054bc9067d08af926cee592e82e8d16d670b682cf43bc02d62b14ae7dcf940ca6c7a8e4b9536e1ee6737a8de51c9", - "0b0065e2e5b6c70e04cbeaf6ba3257ba32f63f246fdc8aa7627540f3e171b560bb3302b4e6f3150fa14446e1265abdd01b7600968c5f51d875faa87479d6f135d7", - "0b0032e9e2a02d95dca0c066f5bbb0c9f7689de373530f306e72697ae45be2d6f15dd204313d4ee3cd18c7edfbbaacc6044153aaf6d6f2f976ff8e1d8c2d4089ea", - "0a042cb2898cd6143cb654634bd6f6d5ae8bd428ae1c66ff4b476f6b8b995f287f61e832339c5a8e4ea5d6481f543156e538c0815cb5ce3e893659710ef782fae7", - "0a016049e425ff3232418ead8915620361e289abcc74aeeb2abba22e12c8690fca329c8505a791ddf127580da80f438b109b45d59e9ee3fb3f333e18b51967da5e", - "0b011059a4210986a583a473a04b255df7d8391c1d163368cee54af9f75f2df9decc71e18b45dbb1c47ecdd1028e5706e2b22ff376a6e849ddaa2ea7b34bae3c3b", - "0b0841aafb57240f158af88316c6ea7c06ad6c902115317e89ce7e1d8552c8be8c0f00f5ef2b1b3ae9b228b30843b6a0ba023bfade7b3b5a5aab076a8209934aa5", - "0a05e3afdcf93583fb058ad17a45125262d2c06b364b953ae89eb44a28de4d9d1741d3df929ba3012a373fe5d163ef3463b3c48eb5baad849d32d315bf122d999f", - "0a026246cdb34f43fdd7f0ae4f66c4b08fa6190ebb8a230d1a115217e30dbd098dd72def9bb1b1809caffdd165b4671786fd09c01a4ba328a2d0cb8c6f3cb1c6e6", - "0b03520052b6e58a2d81b7f379f5d1284dfc3c17579566d29510206c50f86c19f13235aa56ceeb4e71c14fc3880b46e9bdec833aab61bb49ed6445ecb1295fb7f0", - "0a03531ff800a11ec25d4478d108f0e817ec2b49413eee6fb34c25f376944b84fbf53f3913638c0a327cfd95f4349f74efbc4a5f69c69d57d7925a04b693e070b9", - "0b074147fc17fa0dd9804db2dcf39021d715337c1dbc4f370e5cc1a6bd5385d0e618781ec86f3045b449ce698639ce0c6e919d144debcda548125a610ad6a5c715", - "0b008eb2eb3bc93475fbc38829a2c9eb98f920320a0d17a73434cf7f231d6ecee79c6ecae470c2665d82b1320dfe688521d318403153d610ec2729bb3dc6973282", - "0b08a24e9ac154eed582243038a0eb7e68f335aeb056305f2ce55b42b5aa49c7217c1434c0398d9c532afa7c12c7c8a3c04e6bf8696c9a4a55a60912047929c30b", - "0b018bf3b051c2b213da22ff6d35c9a3ad68eabc20d4dbea1e6d63b6f0dc487edf331be375681b43394b3659332ddb1f4b90b6ba19ceca550496cfd9de18734a8d", - "0a07d1abf85f422f5d23567c10382d5b8a964feb6366fb6e2f3aaf295aeb97bd87be87b9f14643450ff94e5a3c5c36f7618d2062e417600541661ed29cba5f5a85", - "0a03afc0b310502edb82a47aae913b177942b03f2ed0633d60fa7987412e69db69a8d07e49c18ccf48f00f126a77ffb99b1380807b867a230d4df98e92c72bcd1b", - "0b0081dfe4000d9997e4be2ddcb8fb6bf7cff5bf835cec358d426403883d5b41d9cf8f01d99ef8f8d94766c6d91e80ad6222de2cfa4adb4b1f83e59cef3dcbe4a5", - "0b016849b2a31afa234fcb4d2a30a2795c27935515be2479013522f86cdde07242775c3e6491d2a3e3989af996723e7af1284b4c45702d62772d2a78f671f1cb84", - "0b0249ee774e81654424b4e0df82d90b81bfe97345b24c6c1dc1b781dc7ed5b42a342e7b674afefe7a3ca45458e7b764934a137db68fa4a30982f7fad0c8d26e5c", - "0b08d4bf7d2f52fc7eba51922175c999d69e1e5e54e0a92e198b1e185905bfeb2412d4d30eda3a4b4d9a08e39593656485610b9adb8c982a4f863b07e865dc8f77", - "0b03770a04c6e648fd78b549513e40157fe232216c220c88c449c08d878385c7016ad0d1225d4d04cff3432392543c1ff0de4e4e78570473beb10e5d5fd2832538", - "0a0487bd41af5f258c6b3d4216098c65c36e9cce4e5e3dede922ce83bb2ad32bc666fc26fc162f59b032d782cf34ee678bfb6f1272956a674eab86cd79e6e30b2d", - "0a002830fc96da3c7d1ff22331f19859aa473cbd958ff4f086789c27b31cf3a859a73beb543d67338f867bd56d16aa8970d613b80a3168554b643358a36cc4ad07", - "0b050eb91f69b50faa18e6f014e60620cf66d9dda531e40ced51e21f7ce993b9a7cbfafd1ed38945dbd8a2a73d17e7aa2c6a97e2db446d0e2275108c86ff00396a", - "0b043a41e7ee3e7624746631b1012e59c4615ec3d4d9b255162742254d9f6072e71a9bd5efdee27d4c84afe159db8e76f2bc802bf0aed8449f4317f8526f109c71", - "0a04b090564df9f7d3ba0f7eaa5158053b1bfc75e85d06e30e6c78a925c5d6b821f6221b80db3443ba641796914a56c3d4d595ba8e8ae7e4ecead06db169b9fc49", - "0b053b2fff37780a5ce09b6faac82b107a0d2dfa5598d98e81e4dc583127ebf706c4f14a055994f9c37d3a421f796ef7a1aae6982c9983fcced0310b594a10cde9", - "0a078d2119ce8224615fe6ee18992aca90dd60d0bed418a642623c22891846fa71b67f567f1c9d23781005f7435facc52dd2548895086cbae1ca6b360ad955afb1", - "0b085a22ef4d3205f253f4cd94c940c4682bc82e7389c10aa7e924e9dc2ee87ef7aaae6352845110d0be08ce4cdda2334924a043797a8c4d1c7fec2069946f8d6f", - "0b089f9936e4846cf593342674fc379da33b108a12a23cb6016e076fc49aa6380f87554aa8588648dbd65e5e1252166ca28df8f1415d7820d518863d87e6427c11", - "0b08485f37fcfbd7db9d066fa910b8526a94721a6c4ca099553c91dd44ff1ab96703d02a7d46ecc9964ec31d7df0845f1adc8ba186d89d2d738ef3a3719e8887c1", - "0b02a00a35bba067faaed24cb326fc6dc529eddd35c73ff6016e3f120aab46966f4cda227ae5c7bdc1baaba94bf910ea2b67c9a24ddfc9f28a52c203cfd805b243", - "0a08b880a43eeb2b94c1c2fa86ab3cd91762292f005a4137429cb2f62bc9924d7f8a7474754ec331e71c4ea2d86dc94ec793db8619587082f662cf1b3c2df218e6", - "0a08ee197d87d3605d4ee8be915ab9ae9e481ee0e0d920d21aa8f27951653f685fcbf3e2f0ecae65802ba7b85c8fc8ef059d220ee863e8dcf7d59866fc6168bada", - "0a054cbb4c2bd340a7a1ae09c934ef1d46b47cab28825839c344a96adb1d85448410ae80d3ed1a81eac884a3ec4ef8fdce73bb07307e8e08ce793f34edda47f848", - "0a0746aa7759178eb35ba8e735aa7a1ff1eec0087c5ea6322190303579b9a20292168c158baf969bdd5b8018e45ab80f0a8561619ecd4f4e8c10b229b986b28cce", - "0b067d0d5736d3d42fc01a652801ffb5961446f5ebb413779fd5fdc838a417d572c6966bb39d5cd2c30f5665f292d9b12c4996820863ff3230b39463690d54c69b", - "0b06c78001c7aad5bb43e3850b733e2870963a595c3a0d0aae1822714f4fc231c97a19d0440d3846f5aa82e0d29e73317d41054f4f762467b1c414206bc304c9c0", - "0b0901c828b3f5fdf8fadffc0035a8fe3fecfab00d97365254225e994f4e6e06032d8d9de6d06215b7b0e53f1ac776ccfe9097d225d29d7d71ea99b5f49f06b681", - "0b02d30b4d9c558746b3bffdcb16c21f6572d5c27ef8192bdb9ad2b27e228b86d669470dc20eeb427ae70a73aa31b87e91f90684a6c72e0d66358e979a3c0a58d9", - "0a0247738ed3e3d10598f1cdc14f2d0d81aa00125c2efcb4527ebe3830ed42f53fb8d0935ccc2832348f87c2fef03ce790833e5fdd0cf496e17690bf3210a02ca1", - "0a0591e72f10a9054160a16566d3b7243c15a20aa8be69efa7747a3e62ef5c0acbf876ef9e724a18b9de248d1f11483fce9e137e6ec872b1d55bb9167f54381dc7", - "0b07060b6f68ad434f804edf32c32ff5db291bc6e1a182614c1d8bc3bdf37a4ff60a02a80d5ad7f78f62a7092f53263477f82130450218c3ec6adfc620e7b9b6e5", - "0b00eb5928c57649b2ad8d2b65ed251feaf8f37b64c42e7a234248d7f50a553dd9432297e0e2a7352d89c59213a60a5616887b5d618e63ed45168bc0dcef751a05", - "0b08752959a17b2a1612308417ec3f4ee3d21bad99d2fd561e524306855e472d6f4078843a12fc5d2f4cd8c118becd9fecb47bf171b42e89c5c9850add9650b099", - "0b0483dad59b9e25be491bae0b79142f2a76f9f3676326e50f09c5036c5f9ae412185cbd9c75322c4851c95b3167d97f76a4dc440971f2de6308c090ad8a33315a", - "0a016c936841909b1f36970a4eb6ebc21882cb8f4b487bbd727faa2dd5fcb52ed920b80871f986c2d8875280621bbef1258c58d0829afd14d3fea221a36574d961", - "0b03ed171fbcd92dee3ce966148f740564e3585c3f9034815e5de39edaa4815342f365ff9eddc3ab65ba76e5f806ef80afae2d93ea9c57022407721daacb43ba32", - "0b0527027724ce45e8286f138a0dadb7a7fca68da6512ef9dcec31e5cfb8a6543e043ede2f94815b2cee2839ee21cb79060b0be186b5ad2a11be426b6d26a4657f", - "0b024762697a5fe3c1249eb824d2214b97f623b7aed2861cf81b574492f1b8d4f89d14dd98855ce8a904a434fa69e9a50b32c399a3dc431bea8e400214408d3da4", - "0a080fa8cfc058eced667f69991cf903b4ad0114be6f6f6de00bd4e95851f15026f370f90321cc182b524f063e28380241eee405ba4abb0cfe7b2e159b088a0db2", - "0a02498a57d9916c9b7ab3ce962f4bdca14b10feb7c3b0d2c02b417dfe5da8676624b4121aa4eba53373198091ebd296f563500b8c5e1837dd5bb32ede1525662a", - "0a0607b3d1427f9124b0897c6986a269ddf8e5599f161cc55c6d75802a7047d274cd1d70f6f040166329073c761d5b34574f590c9c16d0c0c7e0efb47445a0e51b", - "0a0738535ea7096e84be06099caa0d2d373298d82638bf180ecee743b3b7b327c3e5acad859a6731ed84f72cb32f40446c7d9b5b65b45dc70e3ba7d1a6728a93c2", - "0a080c81abc0932812c887f90d4413b02ff8ca327781b7e7703d45b08224a53ca933d4f0f17fafcd1e18e39a9115e03a601240f8d331a9bf3337ea8c4c36ab7257", - "0b0834d561c170486590e09563cb3bbc037af68a5c3e13b705bf7b69cf5ead227fd46ee27d6fa74e36c3aa60611a725891b79696072dc85f377265bbe3bf6e2378", - "0a072c336790a672d48bbe97067b42cb44879e9f8b609d07c8b94d8b509b1effb666ff29c94119e996ef3566979bae8a9b5ea3cf211b045f34bb693621892bbe6b", - "0b06af9f7196391857f68e7679de524a44eed3be0fbcbd03c078cb4b29278374894a8ec0550c8abf8e6a151b20ee6ef415f6b8e2d13c16e441ce192eebbe8f3206", - "0a0713cf89a714bab7933d43c6a9275671c44770615eca504df46d95a18eef6ea37560d349352686aea027febc35f6dcc56c136a7e75a4d7f083e824f26cbcce3e", - "0b027cb973f28c4c8a3cec3829fe3e1f72e9629f285d226ab1c4c31fbbe29c087ef25701f9afad18f3cf0fdafb5a5fff30cc3718005092767e13709085c590c095", - "0b053125a923a54a543efeb1bb53e1fb59b7e386177dbd707286173ac840893717ac524e347304617627ab1a9ca4017c9b711d5a0adbe20a1c89b8460e9fb7e3ec", - "0a07f66949a3fea57b40460ae48a14bd04d2c798f2ccf4ae54326533fdd93426283a3314f52a298cda1ae90107e048f65cd67da0511b411cd35433fac5cc5cf224", - "0a04f41ec4512f4dc09596b03c9e253da91ed1141f7c02e1817f8df62d19e4d9a04c938d1f2a257c7f3952e0a7f1a409374f2115e2332a7e2c6ce80dc1fb456e45", - "0b007a5bc7a3e6800cb35a2633e8a680c2ae7c7f36a8c31adbf4b61e04b315ea2f3264ffcfdce8773a3c984bbf5fac6e1c21afe6620672875a19477a965a41b3e1", - "0a015b8717b770433c2ef82810bd88ddff961de22c34f2e1af217df00bdbabc6e5de3a57c3b8f4448b29cb619ac2bf8892b9afffba1403611d56b06f78fbf49b83", - "0a05edfa4804ff41ab5628d2b73c0373b207a11b24f28897f9d67a6398376b20356796e8e7b6be41face2e63a5624fadab9d08967ce72ebbc4e6f0ad9c27128323", - "0b03990b09905ad29b43fc68dd792e4bf7efaaa33928fe68251f7ba0047c89612968f260ff336f17c084a4e59df5088518f246f12a8762edc4671e0a559dc1b8ea", - "0a010b4a00270176962304955dc4f3d7c6a3b62d75727ca009dcb4f6d8230f28dbe6aa5ac17c334580810ec76af0c9027fa68c2688929e00ecc3d6a9d811bcba15", - "0a072d2db5a63ee57a04c242bb8eb5d5d6c9dcac5286fa185609055e9ff2249eed888c34f3360ef755e7c2cba3f9db9c93f9b168b83e2adf495e11d5f9702759cc", - "0a00b74752f5bc6bbd8b7e28288e5e112eb935d530f33bd55c3db2c637b0d980b25f53d19d2e5f0ef0eea92bac45f6e9d4c7c63236c8178d9fdfcc7d17257cf1c0", - "0a036be5c37260561c20e265df76431b2e0861323ccd4e55c0265d853960323da846cf0b00d39181c2e0a127433c2a4044fea12847888a8168e01a5c0f39c91a61", - "0a088ccc79cf6fdbef82896aff3dcef224838d952413714bfa400645dabafba7d27258ea9a14ed179549f5c62bee0e391deb9c64eaad0edfa31bdca7cf9f9cb88b", - "0a03fc02c4ea56b00a1d874495b02a3faaad9edcd428b4907c99308e555fbbe89e5b55f3a3da04fb7cbe808438f3b7401e861136736a766e195e08c260a8f88a8f", - "0a02286861bfc749ce694aee50e66dea2b827a00c4c9244e1921cfd4de5202ff7351f6b2fbe31201b86b2ab922f49db4dd6c3ff4d16b9c075a854fa7f95b0122ff", - "0a02ff6d6f79759efcb63f454c72b8d272b0d86a2be260406fc07a19b7a0e1138eaa6ae5d569cf8dc26e2fe572bbe6f0805616a484b6997865dddbfae18ab62f7c", - "0b06f51c1046444ca1e1835e178b1c536ff7fc7194ca958680d247c88f340094b869aca2087d99766b713b9c2c436fa38d1018b598a4395a799f0f94f92cf66df5", - "0a06dae11b8356cb2bd0889afedc2cd5076db7481e355ac257b3ecf77d2dda9e52d4bb16c8a6afa51a49dc50ac79ac9f86becf3824be78fb05dd897a3d341be89c", - "0a061bfa5623ee032a12596418d34738d3f37dcb3427a61798d97c807b97254c485dda4afcaa978b1b08007be77f0f6205f628c3363145f055f6d6aa7ef1a7daf4", - "0b038672a74dfab36e0b2014ddf58bfadcde8469db8fd722892ea08d4a69a5c337d29ad9244b0253e5b99f50e58365dce4d8810aadb9cde2f4ad603f2fbc54be7a", - "0b00dcc9b9db8472a2028e2064851df8d6a5be221cfcad58d5ea21a6ba4038b5743746b4dbf81926767c83bf80010847acdfb2a45139531f523413c0c8808ba492", - "0a0035616b5e55dce037d492d706bcf7e679ead22183cc0e542f443bdd6ce18033ac574a483fa395b6966bc5dc0802032ffa8f7f5fd8495ba7c7bcbd02c9ad2382", - "0b06367f91dfd720c513485e34414ccb7f84dcb8bed8a82304895b690bc15a96f50520164ec12557ebc10321065a323399202b8ab5058f34a2bb248c0e6776304d", - "0b065e7bf0171b3a5f5ede677b2d09980c4322af2bd35629e240878d735cf0bedc574de6d2dc391ba4b59b881b3f89dd82f4672d617ce96976e2c97495ba0052ac", - "0a07e2b0c47acf21e91480e7835b05069b0add10d7444ba1f1447038be2022548feb036244380f8ae4501bdab46d4afc97d7918bf4aa190f49e1c6fef0f1817ab8", - "0b05979c89e2e3d70a79a87debd38dc2ebf6365098d1a9ea3f93c202cf65a8350560b0d9eb81e28ed85f4b542f77c205244ffa6c844e77f59ee0fc521755d8a46e", - "0b0166fa4362e7afeb314dee6f874937278779661f6e248f5c0311373267affdb73cec14c61e6629bfe7568f4f17395a9ae0e8d7c78ce931510bce12841d5dca3b", - "0b05a1b0cff3e867137c437411b96de80b21d15f0ed55d15a7bd6cf4f435d9e1d0a0b614915304904e9490e010c302019e18c7633dae68a920b95c3cb8b7eeff70", - "0a04f6392cd11d7956f5102a3b2248e17470417358b631abed4a8b249e70ca9bf83401c56b14a68156211c3eb324f0340d384dc53dab63638e1c4f27365a83dab9", - "0a032274e1cccf5c13291d42e0a754c024f42fe2de6a1d1c63a13d3d4b4ba3a30893476deed9d1fdb928f1421df5b39eccd7354e0bb8b23123e90e65f92fc5bf2a", - "0a00cf3a5c7a07be3c791fc78041ed6df1e64ce356b51ab9518ec62b324d898ecf03e21ffdde97c2f22482573985c018d4039efa9bb786a7b6a81887b97a75fcbc", - "0a00a6723a7949ca50f7e3b9958e066dfc44184902ae489c4ddf6e6690b34295f95441fc0641d8036906d309d823f6c1051173a44b1e604c0b45d82cd0a7348b25", - "0a048970738fb59743a316b9c55346b17142571b9d714ebeaf7b2f27b35850d9985c851338019bbd97c532908f7f6c3ba628c5b177e15ef4b301a276687136abcc", - "0a081c861755920d22af85edbc5e14d1b5fe68d27fc77a639ceefda447b88c02c7a0ad6ae80f48ac8fe901f3f67bd7ef13b5336fb164c31784eaa6d75bd54ccca1", - "0b002c8c5f4aed872808a4bf159d82e54c9626e11b4d52d5a1588e04fff433718556181296588fa8e691ae9797e5f5d7775ffdc254ffda4dbf145f1e398f1d896d", - "0b05bc04bb97aa8f1b35e7342e0ba436fcc35ab6db52f04dfcf19946f4112390e4e6d02b1465b483e6a4c2623cc5637f2ed029853838ea865677fa5f5447ec7a03", - "0b0600b8a2b17461fb9b49d9d37050178da6ac7821399ede7278fdf351c9544191f29eeec5653f6ff327e6166722dd20649d373e5a6891a85c004da106362182d9", - "0b07b0ede8e31afc48b693bda65c85301e7d4badfb5f3b8fe1e5f3503e90064384848c6dbbd6975c6e5754dd7c52a7bcb7236705f770009ddb4f52e150cc36ebc9", - "0a04a198bc17f21b1ce1087606663b605c73eaf945cf38ce307a398ea65f6a06efff5ecd2008834354095bf1682be1588f4d4c866bf97a7a99aae3a043cfaa946b", - "0a0308900d04ff4b2eb6c65736449464a67b3666a9a7fdea71b3b75529b2bdc2e396183eaf3347c0c1e841eaffaca3b1a40062243b56fde3cec3bd99041e8ef183", - "0a05359d4ac32aa0651d916649cd96460c3a50a344f18e2f0612d036a8c7f92a6a88e252188773c2512c6f9599bb36c39338e87907b615db3cb7ab8c144ad4da4a", - "0a04dae2e9474deb1d0157622ea00bd74d0c3c74581e426b4a1c78c6dada9d0263309067b231ccdc00c12ca5638f4c673a79c55306207402b7b9c9665aa1dcb2f9", - "0a061a959bc2b3f886d2fc33bd12973331283a49f0060614e36a10f0f623d8e71f7906e6948fdf1d90aa1f3d711b4c6336b2fe5232fe36c82716fb1fc532dfbca6", - "0a0384b3b29bca9030445556231d77278c4a6fc00812844ee9fdb4f968b9074585b98d0f069a6539f241b139eb6088265f15ed2c99b6755a8a50c0b08733f7ca70", - "0b0541529e88aaca3b537c5f89b65cd0201830beff2ade8c2a24062f5f19b5c741a111f7d614e12e6f08dcb255f8c28014ab7f09dc54350d6788f41db3aa3aeb37", - "0a00a52ae291357277aa69b4ad45a529e4741a8ddd5105596400d6954e290f705662f1bb49477ff1ee3ade53ab3325ae89834f466110d203269e1633d4960d9e1e", - "0b0628b66665c07a741b81742d1b7c9cb303ea28a8689984587749af9d22d350f51412f6df353c36a75e41cc1848c05f3ee865bf39ced796482fd83679088ec277", - "0a08539eb798eaf8372d1d4269c3a1305fd40e4bd27c5e09736f49a976bccfb43b2fba4f627f7dba8fa23509c10074c4d3bd8dd3323376eda11419e9e8321e7fdc", - "0b06732784fd038b1d6c679a28bc5b470c9a32dee100381a350fd9126fe682a3f499709a592ec0a1c0ef735d1589b1350e4cae0825f0694e4212e76d5d98c3bb84", - "0b06bda655dac399ae8ba1194b11d245c9c8bbcf5761f33daa2a09215fa8722be5c0b7f2952dc617a1708be51300f2dd695602b5bf76d753238845615e25e7f976", - "0b02a71de74bc68ba3b1437a5e2642a8fe65f2ee6233af21e50ac36f7efaadac501b9e3f5ca92bd4738ccb6dcdf6336f5a0a92bec28853f6a65ed33aec26592721", - "0a0215db61fa37b178f4d74f2cabb845fd7d79e10becb340934735b314e0e0d31081b24c21cca03ad597f03fcd5a16986633a402a0cb6314fd2b9e4c7d180f881d", - "0b054cb43bff7aa87ccd0f790dfea7725c5194e0cc7b1d6d6d69f00162578d0cc1116bf26d0c68f4602d7f86c10881cbd35cdf55de5433934c3b3125d61bf9cdb2", - "0b02fa7da58b22f6144848106d1d6119673e7e3381ca3d6a9274a426454e56be460dbc871a54c9c3a77cd02d52d80cc323735fccbffb8a3b9894827589205d2174", - "0b022fa9b3c47ee014ef3befe8d62a72ae24be008e25832ac92d8fe3e8b39d27b6d9d401b49d8107867cbac623697831762a5e5a152206036cea32e663868af95a", - "0b08e6fa4cfe3584cc4d6c19117da86177eacd4814887a361ac430967d8c869b5ff4499e6fdf7ca022fae3bc2abcf85733ab653dac0dc4046685c6ff92e0abcf9c", - "0a074dfa5e33111086400d0620864ddc7fc0112ee897184f68f6873a203c95d14e7e22af9d381d22a7fb7d72a83e9e84a782319677f5a0dd5ad52a9b442759e57d", - "0b06a52793b5ff6ce5e53087db841960a313d3f1bc136a8560aa4d0cce6c3a2c5ed6703414a2701342090d1e15740a84ca9b2bef7b385057745d33ac05327da902", - "0b003a6a12a3f29dd60354290169320581415b3f16e02d9558fb1978fcfcaacff0458a9ea41fb94ae79685e2cd3a81600ef90708a4bda611cb1928668a726657c1", - "0b01fc6a99ecb3b561d67c9b708cac794a48d7d6b2447b484d17c99c064ba8a40be656fcab5d6ee46ceb558dbd15088aed8f630798f80712293cf44e326ccee386", - "0a061d8f75f973d7827efe7e9aa84e52eb94678027348033e412d0aa4994bfd663ca8a1133b3d94e692170320172b51022490dfb85a2c17c8ce3e973145e544614", - "0b00211817256fed20bd2817e9ba9f024bbdc1aed1028b210d9aa68acc7305efd61d78f06392b40e82d79758339247d4dd2c90ad8f8e6dff9d0df776b4ba7d62ef", - "0b00a34769c4ed3910c7e0836d6c019085f8efc52c4f5f26a1a0d2e8529e83f0b185d8797c7c637dbdcfabf9ad178a42457e74736e2d30e25ab6385be25162274d", - "0a036b9ac5f0ef19bd03431d304f5b2bca81d203f8d0c912b17a6b81f50aef421bc7b993b9c0d307ebc87118b7a341f038329a9466babadfac062899e8bb938850", - "0a068b196912bf0146694014786847d27edee32d8be615d9b4b3c6aecf8b04e5df72c38afa854a76274d17f622e70a0e1a09e07f3c804d666e1e61963d9bd269ac", - "0a092032819ca2936b9a3dacabd4a7629881cd43e5ecf0b5767f69715031da17b18fc83ce11b4c17950a4b231d927cfade4178778aac399c8a1a75a4b8e780a85c", - "0b03f667c6b0e227198d61161bb93d683b371a8c547561168eff8e96805e566a72c4ae9ff404c34b884945c3e4ad71ad198015916a0481ef1e36ba324137809326", - "0b01349b820f6a6109959e000e04c247fae9ac2765bde008f2eedd4bccaca7deac01b0d44bdecec72e618fb3036999757e2d42ff712338e0aaeef0eed24127e0e7", - "0a0156ca328665c35c95523a43df267ec7c3f1cf16cd167b825b443c71d1c895c073abc2d851a8356d008cc0e030e8f1196a3c230fa4b542c3c0ff33e18f33aab9", - "0b0476e7643037acc0a69bda92b40ec1fde2c86feefeae72f961956e25d3c505b5aa48e74943714e653539f60b9716afc1a2ba3a251c7cb6b88c4a6f7158f4df17", - "0b0083197f870728ab83c1e0d5f7f6bc89bc805e8c3141b73063324c78755721ec1acb02ac3f336c978854d1e15d6e21510d2ae52e151b6e30a9b33df1b5d620e4", - "0b053570282e635a607b362c836ccd7c898dfbc278f211ceb50f15585315e12a109ff6e9af0c5257ac60bbba94d6c0e33e1fc2cc3ae29bce4e4b7b828a77a2d361", - "0a08f4fa42ebb91e085d6d91f91a2862ab35381d4e9adf5b351dfd67b41b28af663b0e3a1856ccd6f661447f166531872b10b2a2bd918d0cdacf024d61e6fe6af5", - "0a004e6f5985bcf64978d9246313d282748529f581fb799b17d2dff4769662263229ccfbceb3d90e28cd508f7b5dbd5f343c7f9b0f4795c5dd53b91547aac8fccc", - "0b00e98024683579c619be30f74f423e2b83ebb5a91d75e648904f9d31e310bb7062bf46fd33fadcfa480a63ac3704a8f8738669ae6d5f8d1c797ba6c07bed7101", - "0a0136091415dfd08fd8679117627ebf05c49b551a7abb13b30b4cc49bc0653147cd832126741768c7cc85871da1973232e2dc37eab69b6f68491ab6115e493664", - "0a00220ce2c576599ed3768e73334ef9afa53ee3dd316c655c6e8a0b73242f73a9c3aa07ef4817dac75aff50ada17236a02e7d17005d056ec9adb446c241b79518", - "0b06f9ab3305f81e1956c3f82b09537e5146a289bb0e7b7caf15cecc808890a4e5a21ae2b9c1f4543ebc2e4d2fd1decb35b8bf81f3f52529ee3e9ea7202fc7b992", - "0a046e3d7e4e833940f4f37a3eb7c6e25c0eae25f83c75b42155451db2c860de5517f7dffff8e96248de8c2c12aacf52c9b3fce9f6788814f1ce9a8b0ec9438e35", - "0b030ad3255e5d6f3e76c1ba054ca3a32b578788b83606a2d829b70a548f535a07874f09a0dd230a5af8c6e99164e9a191475e68ad6082f7eb816b0b88676344c8", - "0b02bf6b5b4ec95e67b273f5a4396de12e759205e4db2fb4c6720f2bdda47250e995a62e114c22135409424ac65737e48fb097a73b4b85e1baa04ce3c48982109e", - "0b082aabbaf00260fc7f57309001c77a150d6c30326453d14b0876fd89267f4c9200fc27e5a1266864d43ab215d1c8e4a3b579f5a81d2bdf5f27bb9ed3bff445e0", - "0b026dda14ae8f298aace7d5b84a5c5ef42b1ccd802c0a2e9d0906ebeae9e9d827a8bd2ab65cecdf4a62dfea1c66c986f3307edf278ea4591a337855d3d4ee50a9", - "0a00d86f6e0888a767734ab37b325a55b5d5033c05cb0cdf98059afe5e972ab03c2fcae7973a81df1120d2f92e4ee1c1cde920af62e42d815a9b48c1c67eeb8889", - "0b05770d6d8892801bdf50b918a6b56711e14d04ec1083fe8b29d1f93e7ba8cfa8aa74dee62290626544a4343ee4772447ceac3aeb09cae4292ba921311e758c28", - "0a032dc6ed93d9ae277182c5ec470a272bb2684f07a09b74e98831b720a1f280a0e8c0f1740ea8d01f8cd3e6d81c44646a9e4b1680feda7376bc520a2f0ca6e7b0", - "0b045de6de28274192a186b326b7391921ee40397e264283a86bd500616f1dcaca318cff491ba71bcb87fde5946201248f35aa0c8b3328b5ffa97d1242513f9de7", - "0a07ce87ebb216ccb20fefaed66858b31e46cc5d918bfb32422cfe268128c21c731d2e89662a12d03101b573440715912108ded02f39c06524e7c5325945f55c57", - "0a038869705db2a6241f66c55af2a688ca0fad57c1b4a92e57d58792270e66bd00de5cea4d77d8352d08a931e34f83d045430dd3a1ca10a55b7285b2be2c63e6d3", - "0a05514b2dfcd57c2957723ddba8387742f2a5e5a6ab694fc3101c24376a826a4d33f2f26e93ffcbf927e153fd5fa47cc20e6c458467f62859970752003a0728dc", - "0a044055dabfe0daa4bdb8f4331a21ebc3378164d443df075d65a24eac684602d4d9aabd738cf1360d8aa973143000b52bc9b38eb2d0c5bc0aae4d11050492b2db", - "0b05aacfdf0bbc2787594ba4b60404bec6ef011cf9c6f082ffc933f933ecab6f358220c24181ffe80498d73f6a216146e7d545d929a5b461a4c8402f9ae0e690a2", - "0a0064658f6dc5ceee96ba7bbe8f801bc309705194dc2d763b6917c90fa63030900270f93eae24d71fb6ad6af967c52a2f45d80c8e332008d400b8fa8f3ba331cf", - "0a05c8aa347431660e5dd37b7f492f71d9532019ee03af4168d6c018b2b34b56ede4dc6575713c2a21a66ba242c6991db9b837bc68dcb80cc6a67621b6686ec57f", - "0a056e16261d89accf9561c8bb18f6746ddb83d1c9c97767ff6e028b415a11ad176a109cf44613dd8966d24ded2b9aaffc60eb5ab745907fbc36138aa8aaf7a86e", - "0a063a1e4adcdd3a0a35796e12782e62d5ab58d4a7f4a8386335cb6c68298e55e40249fb9e33ae85471e1f17343da11d03bfaa5177c287677856f3382ec40420ee", - "0b0599f04688f6d958b2cb9ce828368899b77ac48d64de153e7de69945dfe9b7b6d3a24c97564de7bb350e071d861d819a5f6f408ebee200485242ae52d6f9e2d9", - "0b0547a4f2e404b17672a9cf73f614857783994b8a9562d6672c49e11e971ee364dcf89c2a555f5e78c214a0e9f5ff4786a7983b64729ca4534ed958ed6c4cb83c", - "0a07c1f63ca53ae4d537e7d6505f733307138798a986067aca984233201196a6b5cd5f8bdefe1d96809a67df7b0f69b6d85df445b2abac6dd2d33fee1be0605ea6", - "0b03eb38e98446dd3ca399ca152bb9615194aaffa32f6a5ae1038ab96b06d8ef63995a220fe86c453b26dd989578c1f1841841197c9342e2a0fc5bc32fefc72329", - "0a02e2a453a4501a3c9743e8a82b2ab3648f4a8537e918c4d7290d4f9a4988d178b536673be8517a5bdf270a41bd40d27c42f707db1a28849cd7265a03aa79bb29", - "0b030f6a6347717436fb9fee25b2c1cdccac32ca31b7f96c6e7d0bbb6af928c454e703024ee9993002b87b79e17b11dbda6ae83d187a60f376dc74f25c3cb8c1ec", - "0a01743b613dd4f0f15b64910914cbb8283e704c5ecd54d367a39b40542c59c8076e356d27a5882afe2b5fec192f6eb114c7dfb7ee3e5f551ca5f8942bda10cd5e", - "0b00b99c3d7e5129ba4b81bac8f2f63fd776fa8fbc63af6ea3a5ab2021a65e3dd495a49b093b6555c1fe4469f3aa1d60769e3e10bb047b0ed5792e6bca58ec2694", - "0b090ed52b56c62b9bf0c4277584bd75be93445ad8161b3735de4c06423bfc2a4ea68555c7eb5515356a5b7e8ee57ea27e341e0c97f5c597ca0334ea7be8cbcb4b", - "0b00afec5f7bb9cd257988b2818f187fdecd333f7b7cb5356574f51eb7142f361e58ddc63ea047c7f38b99f015c932dbba8a99286d723f381ac0c930abea545dcc", - "0a06d4ec95d0f5a8b82f52f7b1fdc0c324c1df21eddbb0dba58e81eaf0a782000ff621fb7585dab8ce53629dc34e5db9536e188537bb7bbf6397e7c2d9c9384df4", - "0a0312130f6cc706748ecf5813602c7c8b7588dfe1d23dec17669fb1b42747367a4ac5029ccc54dc87077a3d6feb7f398432e1b1edbe6b3842f2eac60c48addc89", - "0a07c0f170fdad38b7a4b9f449dbe4dd7bd90d82f5fe387e1e42b262f118fdf7ffe74aaa7f3b03c424c609f99abb4ee16bc79a56bbdcc1f6e66e26d4ffbac74445", - "0a065b8b43e3b91159448a2de22bd636108805824b97af361968eea328b377dec80103411525874dddc011bc3c569065b76eb0283309f81f866286b3703c1de7b1", - "0b0015b00678fb9fe36ec013e73b8f133074653ebc4293428525d082ce1ba50305d857f598eab3b5819b0371ef7c4a745af4747bf18575c4bbef71a12742bc7c77", - "0b020135c9eed23d17cd46e4387881caddbcb1bbec6a3106934c8022932a308e7e3e7b44ff408511837718f16fa1b801a4b67cfb95beae7b8fef72450f82fa1874", - "0b02ea891dd80595e8e4e4ddd409054c38d3b3544601dafd9ae49a34ac971d2cadd3c56e78137545b4081175d18d06afbeebee7dfc618482ff0d6d9ee392aa563d", - "0b06278fd1501427d9bbcbd26dae92cdc2f35c35605358424404b1f966cd1d102190d8edf9bf8eafa2ac11f5016f3e80d87529c0b01cdc766a1fb0d9f8751bdd62", - "0b066ef0e0aa569c7ecb7291886a8d4a48c579e21549784ec18915b7f76c9cfac4427d5ec5850ea6b0099edcaf35be781659b5ae9d24b40c28df27c9ad9549b445", - "0a066d36cc4149bbefad3e477574333b03c5d424b2ee053f8de8e6fc1db1dec1c42e1f14e4adfe995cfeb1f24967bbc7e5d0ac35459574b9569a460c293750e9c3", - "0a075eb65efc82c6767ec04ed80741fee41293f50597f355784d29cf2a5fe0b94215fa2fc1d7ee5b9439c15840d1a2be4fe971ec619416e76941be70927093ac95", - "0b05aeedd3076500ae767d3e5b25aeb5e0b407df6161ef3c51f799fd3851c962136075848fa5e1c6dca06ff2a4c0543ccbc01cfe13749be43d42d1c669f8962d99", - "0a08e6a6b5ca2856f7abfd556dd0b859a81302e099fbb26fc5ee8364e4be9edc71bb4121b0dfbb1d8bfbfcfb94e114fc89b93e448752e0573c1371cd6a7811f9e1", - "0a092052ff03911416f7104563f5d662f0e5ce720d77571c7c9f1be475a9376fe9f30aa4d052d5d2a75aff711987b1a2ff2af68a885415db2bc87e7bac61e742a2", - "0b077d66dd95161f36f2d0103a55249f8e12a7df9c81b902bced779c9f5220ccdc1f4bc6dd5adaa07cc556686dbb477fedb24130d685dc537517f8c5b12d23b046", - "0b07f55abdaecbeb799cd53ee050b677b36752975963dd44a32da0f70889bb8a146b4297734a40112b25d72c3bb5b6116955722912891a7d4dc69f26cb5dc0de90", - "0b036c15bcfbec38b45f5e89f35aa8af8cee2b91935f16a5577057e11dd3b3788eede87f0c99d973f1fc1e980742e615b61a8833470dae657d96b69e3fd42789f3", - "0a078b5eab78cb174bf0552563da444e516d66f1c00d22550dd84eb15debc9f635623b0f531bdd5d3a89fbcd6b2f0fac67c15a2b51c0d6556281693603b4ff8ff4", - "0b0921bde242b3fde9f7ae7fd29daa2da5fa323f04d59862ab56cae3c56466390b206898403164d4ac45232cd1a6719b1711b95481dd979a4f9f2077eb95489821", - "0b08bfa398e5995eba56492a0533708894ca6b2c76f74fe0cd3ad73f8059078ff09294b6f404b8354e3bdabc6809db67f3ea1a1eb20fb1fdd280a9cf69ac874d16", - "0a010a856d1965239428b233337fc91080d102221cab726ad2bafd0e439a692af76d3246a24e9aced00ca3a8a5c6e9f358b0e9e57e20bb3b4363b4e633d5a65d10", - "0b04420a4cc9ccf5470780e5aa964996a2fc8a680b2472ec552e2020b79e5f8e78c688a21a5aa33023bb9abf4025eb2b56cbb956bd47ef33ad3bcb03484f2cb7fb", - "0a05c3b96aed39da8ba87867164a1886f7f37739ba38a5b20fdacdeab9ec6037fda3bc3d6006922360c4dc7dee5a9c793954b8db7fea02899c0985b788faa69f3a", - "0b0025219a95814e40e4386fe663d2b3c3bd3d203d8aebae8190945cd477261228e67afd3b3e1c6317e0528bce8cdc4cc1a34c87baf74ce380407e4c89ffb84747", - "0b054cb1071cb003d1a7c854ebb0905a79dd0afeb64b8a9f96df86e82c04a27727b565e9300b97e8f340ceed95de1562b7ca6625067b1d7f694fb058f1cd9ebf23", - "0a00e4c455b6a1750f1d27771c370a4354b551c3c66e69c49a2a959ac9eaa90b1066e99b4e9cfb48ee6f668b929f4fadde894a53bf8aee62593d5aca0d0776afb4", - "0b042e3028965ab758ce41cf8d75c663a56b92a3a75cbddefeb1ff35d7935c592803e270065e980f67c91a7da4437518085eb28c22d7f64e3d0f0692fa954f1be5", - "0a00ec46761129342803ffb40f7ad6814a83c7ac1f1ee8c60e2e29a660e27a78d2b1de0771b6b4a12537ca45f4012859789cf173df668f0fa5656d767bd3ccd6e9", - "0a039b8d16a637f582b9ef25b4271aa4cee38e197e979aa7908ded5ac224ad3fc5ea56902063d1e3ad796122b3af8049a28a0347be31b060b1229ba617137e3682", - "0b0366e8399b1921da000b5d63ebd0c01618666f70293316d0b69c0250662b2312276cc6cd3def944a9df0ccf53ae71b39ba5e16592a2dce55b2403562f8ff9117", - "0a070c700edc65502e7bf8744d58862c1055656683c340efac51fa26447d920b6e17068e4dd2fc3dfbb88acf83a3648797cb98db8a06e6aa04db1494d671f14c57", - "0a072cf4d01af5d290c6022268ba97fc39a882d90a1c736da35f3eb66effa02724f1c9ca1b9b2bdb2a8e59709015124c295dbbe06d64db92804e9c747b0344ebf5", - "0b04188bf1c0866abfca3ea0d5abf72433915e71ee61fec8ed5509cc7d07f816a754a720b475ba8320a049c1cc0cb132bd880162376c708c95de08f58d46c14388", - "0b020ef39109c1c690660859b95a1778bdc36cc0db07c2eb57d43993269d1fd5e31f9438208a0d4c47af045cea471eefa0398b0c869d29dafe381092812acf9369", - "0b065e6bde87a029f24e146d9d760d8929cce68855be67dcaddcb627a39d89e3b27ad11986b360e32a42be44cf75a1ce65ec7db5fdfdd8c04b2cdc5a5547f339dc", - "0a055c9e93cb070a3f88a81cb490a31e7ae5398348962b6d879018658810332b1f100aac72a165b5210fd30515f402faa557701fe9b5c94e0a94c77d46cb187374", - "0b06c6fe2edce1427d635e0a7b9dc9d9ec7d136f570fec7b934fc08ef6df4e105c75841fd9bda1738cde72222559a1cc4b513e1dce2f28ccefabe4bf51d09e8d44", - "0b033a3477ab13710c477393fc94ac59fec984cf6aaffc38335aed13703d05bd7bc704dfa909dbaa0f7d3a890137a6f4887ba280af63fef964879f75f7933705e7", - "0b02263f86632b855a5ac742dc482bdc104d503b761f64618c029ab8d453609d5086258333cece7fdd0e360841d9c4f42d1f5d364749410d869ef1112dfc07c927", - "0b0907bb6125b2ff332609468e81b9ac9d1580581f574db0560ed07d2d558720c36f75edd2e74d2d72660540f1d4e3f577f221ee6030d11a3ba01ad084d9071c57", - "0b0427a42fce613c8b1a72042b9678ce8bc93484fef1823d0c4931b046178694f462778ff16b36e20455bdbd8c91855936d140c239881e98d3dcb69601f616c072", - "0b053d9b5cc64a5a06f4bc9b60cc562e9cfa248582b57f503600dbf09a73cb8ad71dddd9afd801b516e561d6ab2b6dd92396df7807bb05552a07b6e21589794922", - "0a01f58e69a919cd21d3c06689ef3d8e7bf7af43053e9db7b3c0fe9582a66a05b5460664b376565c5c03c91230ee3210dd591fd98c5a672e5091b6e7b2581f31b8", - "0b02886fb102dd22bb0d510595b9012ad6a4ae94a57b475e14deab7e77326204464db275c3f3792f10530da9e3a62837057d40202ac181a71249850d9731b32cae", - "0b08c4ca703bf2bfde09bb53ad41754b9df11c78b76a3ac24d0469c03e3fcb07fd6e84c83312e4b01eb927b56831193e592b1a581c48b02181094205741311f12c", - "0b07ca13fb6a4da4b367f4fe6db7fac428039860d105d321e1ee01627effd352f52d8225b3c3ba6a53040086c02d8be6107d0aec18cb7ba6fcb054ea7235a9b9ab", - "0a003df1ae02523dd3105a54ba60a6a12cf8fb54316158c9bea7d8fa6446cb37ec9140cef01d026cd355ef76d2f3c164a189083c0915b92e246fac2aa88dffc959", - "0a0690a0eb19119b0762a1bf8ef4199c1e5cfbea48d132837a28f382a4f5659e8607ec22c681a0b092b69e32d61502f22a288a90bab2a8baf9add86af04e41974e", - "0b02bde4cbbb982cd30c9e51dabd442802bfc2b4940c18767b8d6ee5559a44cff4f8d1e61582ba95abaf050456ebc209c638e44ff2efde3eba629434e74a4e8621", - "0a0647aeb1622cea93543000648bb6026653906709d40878e37a21abb9b6c4dba536bfcfb9fa981cd8eaea57f8730679de6f4a38fac3b27c7c93354e04d469361f", - "0b019a0d38c4a05a575bfb88c0f6047b8f2dd8ae2f4655f4b47d8ed2116116d528b3c2e6747f850b6a9640a601f595e42f40326f232f06f5530db95c0d086ac283", - "0a010ee82edd827e6bf837517fb3b36ac434da25fe8e61850f0c50538e4e187041910fde0f076c6de91a235b426d185591acc5717c9a3691ca06e1aefdf234f7b0", - "0a067cea7587d1c41c5564ffd34f08dc36374466a053595ba6cf939aa210b623ea0f59ebbc168dd7f7b541385b1d56e95bfb4a094d99e7351fc63d6749c15d3252", - "0a01ea707eb1a7ed6494b7f0863a0ebffd6ce15a5f3e099f5dc3defb29dae476038243b04bbca377f60b97fe700a08df19320ad5b222c056374f167357043b5493", - "0b068c52b4a06b3bb7ddda37fd1bff01b9202424d69aa3828a5a84a5a443a1d87b6abd20e7db4cde18ae4f3166f8c85d9fe7a0345d892cfdca0ef80fff1d84cd22", - "0a08f60300070873496ddbfcece4505ea48693f597e8a2775bdfb0c7c8770eb6a052cfe7d13ab831d40bd731bfc4449f4fd65e8dd276e98bd62b3df64cd7b4fcb3", - "0a0163de164fe0e5fb3703ddfc618b57d5c7306d1768a6ce1e3b56da5118b1c0f205e346357dd5550eac6022f90e319e06a4861b0ff04598395d891737d8ed9300", - "0a040d9abc3d1bcf80b028ea6efb72a972832c7bcfc9103c51330b8f9b8b96733ab3b2b90fa46c7636b34f8212b9ed92b33ed2961725c272124487ad6086f91d6d", - "0b07db33eebe837b11c9c739102cc65627632ab1af63023b60011f40bb70824055e370d4a9385fb825cfd6f4e511b47ea24b9ce1e1d6638b8eb9ddd33eead5e3d6", - "0a07ac9294bfa9eb09855b6ef750f5d8c8017689a1696b251afe7206c320d439d506f7cecb4280dcda9b7fe35c89085af198086d6e4a666a17ff70d3e06b1d6ba2", - "0b02e93be93965f25b0193f3ff215265001a50f42954118cf10029f1aec9fd15d254c42b5811d339b8c3b771345c649c4dd8de6e95b224224746c3d529ada4c0a0", - "0a0321e14111af0308123fe0b511d0ae74e63dcd400e4d5d01185b8bcbece33c6fdee9c1fd0b2eb66e16f2e7b74eef688c3b5e92e288557e586a1ff8fb12dc1f02", - "0a08c6b7e098f663ab482a069404a920a8326cf2be990fd8d86461940a8d879b560aed07c8b0e032580b701bfbd720b8ce1f2cafb27d333e18aa8ec3f19d59a2db", - "0a060a0244aa02b2bf1001ae72cf610d9c880ee883c0eca172acf63735258a50e8e88c2e4e1facb37e486d5e8094a407e2524638936fc35c189c25f046c2b93c05", - "0b070fac605a8848b0e5ede10dd61bcc8823ea74c284b244bfd0905e9234449a2626eb4fd688ae9d511821eaf22d0c72ddacc0ba156464f2a70945524a80905a43", - "0a08915e23a63186e8f1f5a965b07555beff2dedce797fd91df9227aa96a1313cefb00af05e8db7cacc6ffd62eb583e9b34a45635b99d15f2d16ebf689cca21f00", - "0b0599d3b234c1b4c02c0091eedccbc5b0428699e8aa467dd28a636d2583ff65f32e7f5dc4d3e2959ee2dfd0c7d4e20e74b2bff068abd2504a4413d6c2bb3d2cfb", - "0b0604bb891a4882623757a107a36658fb09321a0da840f13b9a77fd53c369fa27ab65839860eb8d751045ae28c1cf9ec08ff77daee923bcb4a335b65431ffa4ad", - "0b049b2a15dddea0df8d7ac9283ae4b7fcb601efa424fe0c3edc68b8f1b733b783f708e5177fd10f1025be6878ee1b52971debab7df72da7310c143ccb596a067d", - "0b03f38cd4c6c50cfe5d62fb1fa702b69eddccce3ed1d169b42cfe7e53e33a632250e1505293cc6d9c2392bfc930f7629c21e5de1df3d5ddba1bdb7f63ce23ac26", - "0a000dcad69bcc04ff21704fa90c03afcc0d397faede27a5cb8085fc44ed7b3afef9eded1a046c2c1927cfb91323924282db01c8d4e4545b5513ef5699090989c2", - "0b052ac095e4ece4948c4642599aec0df4346985792aaa4afcffa8294687bdb045b7020131a10998db65d83dcf80e04d39362c2837ea43f02961ca6fd8d4b4bca3", - "0a0916c990431c0907efb287d545a360e2a78d8c813f39a0029f10fc559a618753bb2df2406d1c7ec26de6b5bfefcab4ee97184b63e5e86eb9692ce9b79ed3d9a9", - "0b08355dff59662315728d24d08b9a8dbaa682bcc8a5c9fca4d324468951b793e53e194ba92c8a61d299a0f96c4b4b4551a46eac76eb9cfeb64870cb2779fff52e", - "0a04450c8c6b5fbf5d6d4a0c76ff953885686dacbc0309575246ebacb36e321f06374fc26c49d3dbf37b6324833b53a013424782c3fc1ece51f8c8c69d0faac04e", - "0a082d4f948686cfe74a13bab1f61de8602ab4b1fa923112d82d6db6aa4574fa24c768102ae8600d0f8e155810412c74c282d5b80a02dbea4b091ca34cc0cc59b9", - "0b05dd8e14726d0b70aa3472c92d79e2d32e4c9e0cf8db52318de2d3499dbeee469ea592aa3735a4aaede03da158eb66188f81aeef2cffe547b03947549d25c975", - "0b0835dee0deb5dafd688df185b9be10db25ee0a541fa955dc17c59c77ea475c29da7aa5a71cc9ee676d23656a5d904d2ac5569769e17b51e985ee089a9a4df9c6", - "0a02624afac396ad0e20febfa76497c8b1d51fce0172181cc277fbaeab370950499b53ed597feae641e6dedbb12df15d878a54dc512e8724ac40fb96381755debc", - "0a025587a89fdcaa9e847180bc8997d847df2a42b7250a191ce9642c40976fea535d75c86aede2b1d147da5436ec40aca448e30fbc94b593a6edcdf4bcfeef3d0f", - "0a0145ab3893b12f09a484c14c12b8a8982f007898b490a63029313e6ce656671a078de027cc3600ef75545e06fc4350ae3c444afd42f9dcfaced250b4ae401019", - "0b063626d0188d1ded7e9f3c89a95df3011dfa2811a02836f47c5229bb39ae86d331361812972cc231a2cff2fce1e7ab3bfb57d4bae49384a6522f19d76952ac7e", - "0b087fa40144bce97e94dd8d43fbfbecde53449e6563d36e0dfc365413568effdef046b35875722240ef05558468f4baec0a0504c2fc2827ccf4c96b39a8c96640", - "0a0476906e168ae0852257d8357cac330dbe1f7e2a645968991f6c28ae1183d7a219f69bdf2ca7aa272939b64cd26f4047b5c2062c0207eecebbed815e9adfc1f8", - "0b089fe6692b10b26f75415d8db2e5ad989ede56ab435b00e6ca37af39fb029c14cd46b3f900f5d44bb969d34ec86b3863f0db2f2d17552bf4b75e4a822faed69b", - "0a0120cd7079db119fd4fa0b2c3474bfb4e16a25442d7df25bc678775ffb7b1549a3adae50155c5ce312101e33360043fb712e84cb65070f4af7b360a5aade9d20", - "0b0523fbbac34bf2489d8711e81a18bc7688ed25cb179a89df637f7d61537072aa36874b1c1352d2052dd38876b9f002d436ca4567c267a233e2c4528f3308f123", - "0a0198606ed94118742d293f766e17b3cdc868439988752f750fd84524e323ac33d543c60dba9d1be62b986cc33fbe55f45eaf352f227bc63724b71db9b88a0b80", - "0b010b0cc41fffde956d753ddbf82a93fc23a5f4439fc9ea4377664294b52f6da39b7a359244270eaf60e417ae24aa6057721668547331157871c10f7c33ec5c7c", - "0a01a014a3d8c075bc3dc59632933e767aa375c55fb2fb49d130ed2e8b09283dfe2b65f539080ced36519a6eaac3d529d522064c396ee6e05122dcf0f2f69abc36", - "0b05192fa6d52418a360fccad7097ab4eeb47aaf7160a5d22c1187ce24adaa82af58fb37089f1b1236ffee8149c051af2053a6bba82026a8af9fa71bc9f25624c6", - "0a07305a8ae48dd33a88eaa3606c78306fa99c821917f4a8ea2b4b133cd92cb90ebb867fb63280b935759b64c57e5b8ed972cc90198588aa134df97755fc3cf147", - "0a0018b35af5899750d06c3cfa3b039e2f9477e1fdcba634f5faa62b08440fe821d33db2901ac7a519519ea6fc2d7e3bc671e62b1a2a5fca00046fec6eb18a1160", - "0a0129965f0c5a36f22660b5bbdf3680abfa278a67268aa6cd93cfa055ca7f1cbab446eab6ca27401cf84de387115a5c59c8c972f05f0cb8dee45b6b5dd73b7497", - "0b02e96a0aca426a4241ee8dcbefee573206548e36abf35b22813477cb27ae95c41baefeb3f1559391f774a58aa3c3e0a06aa3107630e5c2ec006de4d5bc870104", - "0a00afdc1ba71a78a05b42ccc277fbfe5a49e733a2bd6ded18e8bba0557ced6719152dd5d35d3592a6ba4bd0b9737f3740d954eb56e3668f396d8a453084cf36d7", - "0b042bfaa3b29296cafb10681dab23444e9b4202b77fd65a514fac4b81248dde0c2c15ce0cbda4c171ec51a79722cd0938e9e28654150eb0cdf669d41834717b19", - "0a02d7a3de99c4ffe915ebc389ccf46bd49c67ea0a67b19f9cf2a1a2f82a2136ee78dd20452f6b960bb430c4081802b9f92c6b0bef6c09b84522332c088761b9f9", - "0b01f0e623c6dfb728192cdd744d8e181ee73b00fb70f847554316225ebc68398298dba957ad5f7e69b7c161b73c0403959e6fe4772fdbe67a637ec64fb8f2a3cd", - "0b06742550eaaa747780d2568a64d342784c865680ee22339e6e584699f531267523b9f368b873a8fe073a0c2c7418ef0d7fe24e797660c2a5baf9dbf271a9304c", - "0a05c4146ca0cfa2fd8d86a90c97d8cf66951b13c90cc7530c4cee418ba9e26f73bed3c4ecb6ebeb6e7c68f7e7a9209fd8d291b6ec13e2289131e8af4271e2cbfe", - "0a0302ce527c19e0b29055e534fec19bae179e64ef5c7bfc8f025d2c357f237c9edf1284c3cb978307be50c0769fbd07bb5111e8ec3a07598c812840d1aaeea6dc", - "0b07160a1246116f96fd5f9bd941243990f79cd21ed9d12bea8a4e3bf68c8d1a51e268fb0a5f5e248108f83f5ac867122285bfd8ea91ca56411f3de1988ca99e00", - "0a01a59854eb19bf3021406a2df027d75b884ff78a9aa14c33fbacf2a3a13e6863b8573df7a985c27cde6cef976a7cf2d11b0ea2b908120c908c98b71928569d4c", - "0b0563df52b29031f89ba74167ac6f295ab39a515f51f53c901420fafea12a95c447dfccf4361c410599d771e9108c34e6a7ae197166e98b041f28f6774f6fa89a", - "0a0420de6ad14e4e43b920357e46c5d29c162cd087142bc1da45bc7750e797d24a139df337b38f76a89075c7ce349762482ab257ae456ab0d2038ee8119db8b87d", - "0b06d8652ff4cebd732f6c62c37c2fc2d3579294a5c442e8d87b632277f6879515c3e579767196222d9c793400baeaf2606811bfdbeaba9f54ff38e4259e49d202", - "0a01906fe3baa428fe01fd199c166a71d781f7810cee7fd6c5309bde17ca8fdc5ee66d3f659c0f830c3777278ade2c708a779b48da4834a681106211e4a101fab2", - "0b0694c8410fe70855096b2aca973bf98bf735f1818a821e9526ee1ac6b634a522a87894ce0ef093269da1b54127fe9378e30d6598b371dbba4838969e32e1988a", - "0a028f75eb3d2567891d04613bc5582bbc6d6174efce191285a5f5ec2875322d89076c5a8b84957be917105622bdb593c393f9ddc6c9abe274a69e538617c80138", - "0a02f99e67e0e3d611cab65ed6669ef2293faeae80ba0695f9e5823029cc996e332f1644b99f39a69428685799a17c0d24fc89a743faf1285975cfeede8bb4ec6f", - "0a0060a6831e79e49bfc754bdcbba77508622d03b1ed4afe12961a63a50777f2b5ee9d2ab8549ddccfea2e8b728bf59d505efd9fbdd6028b42ace28a7593ab5fc6", - "0a08303371d47d6c5c892078f04da93f14cf779523e53cbc309f58e66a7dd44b8a0be3c7ed8d89144a94828e6e6965dc8542aa33e75b6091e73d055c6a5236dd46", - "0b02420b7e27f2c12592d396179be92a7a71fa34cc2487830623a929c3da0c2c3f7504f1cf88574482b4b198deb561dcc955ac5e4bf46755c12c167025c3176d30", - "0a04b342b45fc94e155f09ee3eac05444fa94321424fd39e9b7a19655b13fc5f190aad9c7846a66a8d50c523ba1e4763bdec6bb709a3edffb1f7432af88d9dee43", - "0b0256c8c4a3084629e09a580964c2787ddab2957547f64c75f6c46f795dc9903a5e7feac779ba57c8b4793455e8cdb8e0d7a66aa2b250413a11c7adf233b8c04b", - "0b042feb261540a2bdcf8ffc2fb68e4b7c4924f18efa53b0a4a0c8e04a146c9b7fd1a633c7cd7894be5be4651471c9b852c3488d9a261f222832167cec64a95ab1", - "0a07c88250db309988398c1b43fc0b02c007b5bcd677d3d59bd5c5426d5024d9d5691e2036d99d0f6711e27193cf88618bf7a3fb2352fd5a5d3db759dac3652843", - "0a030b8b8359183b5f050cab3a615d3b272f6f51e5900ca44e9072c76041e611f2985c0887f9df89114c1d24cb2de890dd592943f08f3160b2a9c9b74cf3a732f0", - "0a043e41e10be0d97fd499e0c1b657ee32aacfee5597326b0049a28ba7065c483eb86638f64f83c3570b9b3d8799169f3b7c07a546f020548cd4cef642f172ee33", - "0a06eb6e65b5e160a8355e92d8a90c25f8858a2207ad82f32f692c2437d38cd1fb5db45d8dfe7e2cc79b75285bb3636a6613f1a3f6eb6b2946fae5ee8234c92b88", - "0b038fbdf9d57c381e0e24c947890777ab03b3f4b92d5e16ab99a5178b17231396266330901f82d02c351fb83651eae90b371cca45a2f974a6d1e2f55220312a85", - "0b0173aeb34ab2ccf0ec3c398c725ab8197184a920db6e1db7b9d085a946910f5402663c16df8f927e551e2c09cc740fb113abfff8187e3cfa2045d7f1fdc9b48e", - "0a05337b6466f58ecfa831bfc748abf52fb35b64ebd9e89e55d80b54a15892cf1e37fca83fa1539303c034111d50baae4716c48ad70f34f1f21be56a2a9c91c2a8", - "0a08045f11e3bb48b1f5a86a31b2b76b8a9929f023ed475d9c448dc32e23872279e9197e0a9321b8978ee0138a26424b02e564de59f5bead44c0ee9063417824f6", - "0a06826de0c6fd7a853612c7dd813f7cac904bc8088eb96d9efe158c6cb5ef18f0ff2da41492714d3d905869710544aceabeedcded01199f79b4c8eecfb15c2180", - "0b02dcbd35b2c9027be60488d6514cf38c24ef5f8c6965b7aa87b521bcd62e9f87048eebed6b1bec460a30148ac97f4a355cc35db20f79e4fcf3f159d71edda99c", - "0a07b0bb3aafe0bb0ae3b4d2d9b0ad3b78a46d7b91b87cb17f190bf456f2a200d575fe52319d35fafa6848f871485052aba27bde10586663810a71a64ebceddbcc", - "0a0516c15a91e4635ae8c9cd25448cad7fcccd76eaa82f55e034bdd72a5c96def715571166585e17566b0a81df5eed9b0633e20618cacc88e2ae145bb135127605", - "0b026c4ff4e87508eaf4f394066f9a30ebab15d941b587f24ea5402fe0b5bd30f8f43998551ee73a3206bda25684e7ad30a3335e32a4c1cf5d62f9aef69595362d", - "0b044ac54d414317e9b04fd543f32db29d39906752b975f50c8c2807085d492301c0c4c8df26b7807f27d705ef70657760979bf4b031ab9fe57d5a22d446a193d5", - "0b0488db644955730e1ecb4df98ecaf3c435e27fedaac76c20b3bc0ad380a60b3a804a9b121345743f5beee629be206f05162a1e76f83f8f65323e54eef75104b5", - "0a023d5ead29be1efd0dc41245b67495fd0ce326aae74c7e42e6f99e6655f614cedb9a1059a7439888b14c25c48b3604dd1fa172063f4cc9abdc46e430890ef24d", - "0b033aa2ed5b15e8f37f81aaa38b7a84e41a0b2f6344daa2cd8467972722a46495f00ecc48105c4cb1069d679b427e9e842a7de3d8771bdb31828d95ac9c078bc2", - "0b08ff3b4ec20fdf6d6c04a665720abab59a7694d0cab10d7f15e7e0f8b217c13366d823735ba51dae3e250fd6e4b401c329eb35c3b12219f7bf601df9ece60024", - "0a06de6642f79a20b6238e16ea28b04113836367dd70afb62ae8a8b34ff5949bb24631b0d96319364b022e61aa2408773d6a3b6891d543a48a07557cd341d9b3c4", - "0b03a4311fbe4db38fa2fe37ffeef602cc6921610dc00321feca16b96893819be7e87f96639c48f78f104108b60d23595a2e82ab806af4375d11d905817c0e4b75", - "0b07ef197dd6b57961b17400e8880581b1692f3a8ead4d3ce1fa9e5b5c6de9f9a401b2421bd929eface46618833df1daa5f89ffa6bc05e4f9702a0256a2539c2ce", - "0a011b6dfc8a443ee774182f8e6455064b2aa50d1c9fd6f1993d1e08e50491da69886918c31f8961498229d079c69bd52a04cd50c650ab49985941409fb57c5bca", - "0a05d3001f5ec0b8c3ebbcb39fd8ea4ea3be2af7f99388391c8cf9348a906a57f824fa51cef13f00dcac42bb7a36c0c28a311c1789eafce5034775806ee4a51840", - "0b00eece397e06a3cbc97a4ad07cb6a46cab9cd32daeb7b56fa6121d484e85066e3c5fb7029f9d5194c7be3a95e12c99c68e7bf36f62e08b88f7814ab98815a672", - "0a02352a9fa8d5f92bddc09798259dc2e5f16b3bc6cebd803100618ce625d4aa7c2c00af07329a13c7dc7a88ee21de66560490836651fddd12e42ab37f1c54ff46", - "0b08a71294cd733c37518ee43024df2355c0f6e7e5e79c57645bb7e5dcce01546d4f9e44098dcb42462d2ca8de5306c75f261a05e86449f53cb0f9a514f2d566a2", - "0b003bd65588d092f1790f2075f7cf75ce7260c2e0987a16e39c8b61024f16ed3cecd11199a775714a1d47e54928b56165a5c3ae5491b2c3ce4fae5a3e95431707", - "0a04b3714947007876f2d3c9392a0bafe99edb0c0c953306150145189efb126ee8b0fc3a4376e5b6523c2ff7fe23b0a5781b5c3506b3275ad2a4b16d89d74fb4e3", - "0b0406287e3e87fddc6a888cdcba2ad92f1282c72c1d60af828701af73bd47fec9fa9b8a751febe7f02d16e990f604ca3cd606962bd4a0a4ae1638beff0db59360", - "0b00845a4373a96c723ab2eb92dd4b8fa982b509d4570110fc26e802857a526f358fa6f8cd0d93234a4308d8800d1ae6f59269e7c15de6a492b5a02bde1b31cb41", - "0a0201dc62d9b512f4d5976dd89005edefa6018b41d327c635c5064016baa04419a0a8c5acdad02a0e9192d96d4946653d843643b8abd87828dc705cbffc1590ae", - "0b04ff4c2ad1159bd41da359f6f8958cd6c97e9cd4073c74264934ecb06a4f23178ca79fdaf03d3f82126d0d6fb7c44d55bb40b7a63fff53f04ce60034424d7f95", - "0a04423dd18ac39e6c968cbc2be0f0d09353d08d6204304e31578dd16874b94b510f7b5a768fe7b0ed123f77b87b262f7a879d79ef9c5ffe637598d504b3110df5", - "0a06bed5593b1f806653194df48d13b2d2331aee41dcebaf3d3504fd4913ce4c11bf6bdcaaaf264547190b95ba8388c814bb67fd47367713c672e50ccb7d2346e1", - "0b05551c185ed9d6146c4fac7c89c5c384e92f3b9ea3a6843667310327c5ad225137e0639d7743e5a60f799e54ecc233b6fd2c95f93b090536ea5a5cfc515bdf8e", - "0a03d497312b62c70772d8c09441d91cfe9fa2cf34ba7e4d9fbbbcec809737c0add1caf036a18657a1163ad6a1acb7e30165f193f996ed5e7c03d7d9f2e8017d76", - "0b080d786c2bb507b546e67bf0ba9646b3ab7a0eda4de9aa86813f3aec0bef3f06114a7d9d493a485ed700ffa6517db1dd544d53a34335d1d37aca129d3e4d90c0", - "0b075fa62d08fbb4fd0f0f40acbccbaa0400d24dabfef7a5e6e36c935d1a1f041e41ce7737cc0efaabb7f17fe5fb251322a231e5d6656a27e842170c7b0ec9dd73", - "0b05f1c7d050d5afe00acf5e752b2ab5f4e2c873fb2e638d4ffd28654c996030ad8b3f282eac88f1b710b326fdc3b76043f827836533b228f1709ac97624c7e104", - "0a090460d404297f2fddd58a61ef17e7b66aecc8a8a1e73400eadb8aac86d36aca8ea8ecbbb5a9111e36240327647108748b4f7a5c044417d858934e755c8a164b", - "0b08f5ab73e9fcf33636f3c0d7dea6056db67ff4db2dd562f72e1be1d6e372e71bb794f2fc63a3b7ddd8c163c01ac29b37eb5256c03471dfbbdb9b2e8ae3d89b73", - "0a0550e2c5344a32db4cb649b6812f5a1159f8e836248389230f259ca90a88eda87f34c7f63e442224606f664752810ed35d5ef0a0322409d59e68bf612d51a44c", - "0a0264dd28bd0339ec26b20438d82d8fe8ca1634c5ed89ffa0bcdf113e4b4b626c5d1e6ffbdfaa63723b91a4a45556a535613e61e7e1c002f7de09913c0e0b4404", - "0a05a4cada5f2c95eab73c7b4786fecab58fefe011db744f4f425ecabf51af1dd49539107a90842552c68bbfa52dbb4aba6575abc2e358e4ebcd67e23b9ebcf74b", - "0b0175233086a6f7742351dbafda41fdb9dc2db730626837b182b4f9092ebb3c1a31fa45bff38ca66c314c1f27743e23d78af6a2e0bc92fecfbd7c155101d349c2", - "0b05d3e742dae8998df63471f4282352935d3c3623931fd3e6e53a67cdce28dfb233e4e53e422436675a5268d68e3ec50b3ed92bb08e78b3cb2760b343b6611130", - "0b07b27d3d636a86145ac232c96c48f017bec2279c45ea0fbf7b044f472afb9d0964bd18950c9cecd1d3b872b25553506bdbd4b1713a1291b3d48d0521ea26abcf", - "0b0020109608252ddffa8dcebba17cd3f85b18cd30dbb282d99f0d7d27606657e8ca3c5e6831f1ba492e671aa4512bde836d471b78a9ce0a87a0eeb742b60fe57e", - "0b032a804fc89585cf2284109a19e3c7e0b42560445e5fb3a03ea254333595bd2a64f70477e53617436cd927cb1795632b628259de871571b6ba5800ec0620d8cf", - "0b03bbd60b4a104081754fe647f2753f4e40bccb18e81915a2ea580979da11f984ab68bd58defd9218668ec53f71903d92b223db55ddc96ea1ec3c0d599298d49b", - "0b01ec2359c5708ee100830c94cca64ca25c3415a0b7759a169101428352ef0bdd18da3a1b342cbfb9d6d48435c4c99fdbbcd8383d255142dc95ac02607c861197", - "0a0307f9d8810dd983c00680d55130572283b9e743acb2cf48840481ce583229690502c59b8728c1a1ee153ab8bdc3cc25e046c9cc0c34891ff69a0cad13419b48", - "0b0030d3b0f97ecd604b337cf477cdeb8e73f1957adb33cb57143d751f646eac59c053d4e306a8e24b32e9f1d73073294c36231641ba1726a8a998d55eedebd2cb", - "0b004c1695dc57f1eb4c194fa842a576ff896a8a53cbb1aa53804cc73115a6c352d205611374abc2044059a1ebf2670985330c233982f32c3491b916d49bfbdfed", - "0a039039582f30f013cad93bc86ffcf49c236e19037ff1cbacb9390bcc0d3fd84b01e245451a229123f4f2e1c4f73bd7704a2251047adc548d1600b1af09e9ff67", - "0b04e7a5a4de300e4627c8492cdd37496a45a3c9610547293b7f418e721a3c6bd012f46622ba2acf006c51238559614ca981a1a39c1487d2b176249d328289e15f", - "0b055787bd0618e36873cff30fbd0d619e1bfb155e648ba53759105b2463f2c9ebc308a73c503cf32dec75b78337a9ac28c6d2a6b246d6f72c19f726bf5781d638", - "0b080997378b690595aa6ac6bdb278b838720e018641ea44990d01e6ac6a89f359b3959649d912f79464816253d16fbc05f3c7f7933a57aa9314852ee1c9e9333c", - "0b068e578d5c73cb41a48937041e8c037f10c7c1abeff349e5540dad04f87de16201f6714b19731dc13271480ab71c1b74126e76a2165d90cb649514b997cbfb40", - "0b01dab3a3a1c10ab266235ebc4cc85dd412c3cd4dd64769a8d1c95c3dc866a3e8805b075ebb581a8b6c79117ace367a9266338ba20558f13d1cf12f94a9d66d35", - "0a02514ebab0c1232cc9c3fe70eac9728c255bc2dfa2e7f6567a7bf919555a2d7ebc31c1ca98f76fffe164658aebdf401abb169cbc6a4ba98614065c5b5a45c632", - "0a00c0e71985573cccb6a66327239d914c3fae04a573be37a33be10cd2909b2a2dca4916a0bd1b5ee08a35a66f22ea8ac1dc76d02a93d57f29f204bec60dc32d80", - "0b07fd785404db4994572ebe144c5b7db076c3a08823bac25278eb6eff2259eaa3456a36f277a18f08b7e0eceaa7449450471fef22acf0b2f9afefb23a5ffbb0c2", - "0a031860de18b248223603118e6147e148c3230709f31de88db474c74af956cec72013b718ca903adc86ec22ba5bb756ebf08794105fe7f7b7cb990eba6950b2c0", - "0b0258cea982a7e8efa3792b444912500a92391f18b9b2e2f882773127a41c825e3354c3b4e94c70f5cbc9139d0d24ff8248256c8f7292b7be46773ba8a9158962", - "0b00d9d680da1ded39c8dd7608b129e0a6bff6403784a98d34d06c2e712b29a83285cbb49938c139e80719836414ea1ede82b356d38948b43c479fdb8d1da1d113", - "0b01c219e4a563b9601459efaf8d00974a6ff90c2db6b7fe8d7a2bcd6881cc66d1788b6055c5530f17bec4b815e5d5de892865cf1a57351977c2e75ac96b3fa0a1", - "0b064fed576a906a56badcc4e1c968c77c9fac81740812cefa975b4be635866ffeb7c978c2dbe4a2ebf5201c43fca72f0798dbe543e4467dbebfdcf2476ba81215", - "0b078317698cbc5c71bb59157580b11293c1c1cc87039a22e950f5711a1213c4af6f44af5ade69df4ae1bf936eb0885abd4f8049d2172697c6c4e0e2f955172f2f", - "0a05b77318a310f4b305163f43790d74deca9ace76eb2e80c288630421aa6aeb6a34175c7b11c885927259d51febc8c72e9c4883e61d4c20e3e10aba984bf9b9a3", - "0b08da66a4d11fb0f1113821290eff5be1a64955a067ee6503f789f40bb542d1795a499e7cc43cc6945a6c053e7ce68319aac16fecfea3a813243082eba2b68b1e", - "0b05595602f9ec0173be5f6c441bb73e511f646f5c224a7b3d17157da7ccc5bb06f08fc3717a37fd7fab6a53a30aa5493042fc0221a147fdb0d31a68ca99b92d16", - "0a064fccf3d434f56ceb9f017d3fef5e66d08e89e162fbf912d018958531afd7200e53fb7fec4700c977aff601845c664d23329c9ceeb59c16f6c8bcfff419e12f", - "0b00d478b9991f79b747ec7649c3daababdc782d124b3547d66c34ebe1030ca55ce4e4129ed778ba5d2be3516b48045fca493dcc10a7ba4db58ac94aec1316c9d6", - "0a0097f707b8f292cd3ef851efb16a604d873fd5de516a6f5262b64a99210b788c29ca1d283c6d33f85bba91b49a6a810a696fba9ee01d5b8aea258e989235addd", - "0a0756cb279fd74998e47fd25ac35ba63a175d26ff3fffa856709abb31bf486eb2720b25090b8663cd649de4546827fa12ae8b9339acd1857166b35dfe7772bdac", - "0a076cb0c0468fb854bf64c63050db014fa3034f690418cfff2eb2ef0d4a40b17f94326a0307f0481a31d2de8679abac6062cbb9617244707f58b48779aa888d69", - "0a035b9f22f6e131518472d93d787a91a64dd3d1ea2aacc55272abe61a253500a7545cf590af38093405f6e88c328cd76b456cd007671f5116b78a132f102cd431", - "0a00a458ebb71ea1b0d29afd5afb620373a18675232602b5fa497afc27d0863c5d707679447917332ef5ad7eb6ccc1b9da6f029cdc251b96669ad5fe640a69334c", - "0a04ee7afaaac598ba6c599003e5346ed2e05bfc85797e2d58b4fc24c562390f32d5c90bf11e12f2b29f665db552933a0278b13339ed17300c2372ae40d3890c41", - "0b061e57a700b8eb77c63e24ba15250094ef843921001d4674391cb71e21f108718a19bb6cca372f3ecc2ae055641d92fd2b6a4ba248ca3024a0e26d7351f60b74", - "0a014800275ad7d26ed63aac228574080dd06d2a72c7c1e4ea186d3b4f8d20e5742c3963ddb5f1adb77237c927b444afaea03104d31da21b36a04e55549795095b", - "0b0234572dc1589cae7bd52bcafada06a4c8e459afaae26a3b52cd2d22b25b09d9b5a910891f37564800d65afb204de4bccad8319015df50badb28a743d4f02975", - "0a0052d5bf5b2d98078b1afa71674ed72e58b8c720d2a5f9313cf4cee1a374e5e112ef5d080ed402cc04b0727bb6e4e238cfa3c9cc3a9ea5e1adee42d01f3df171", - "0b003d9ae808a384edb9cb5dc286d6a5da21dc89ad91f6a3e5f65da1e1b12fc969617ba28994738d9ab210883084895157ab8b95d89eaa17618e5275307fb0b870", - "0a08e0c407cbfaa5bc8d65441a75c27fcd49d8b50594d4031ca51b3cc1bcc5f08511fab2453aa8af714ae4117a038bdd3aa926e4acd760ec9be3710b7a1a8195a4", - "0a073a42b86e3f1e40d645de827fb1dc8c1accb7ddcdb83b1bc25eed4dae22d4655c6e4373d9f8b626c805cdd9bb2061f4b93c1100d5f9858af481816d730f600f", - "0b077bb42d22a9d6622d2edc1c815c557011031fb2be197d134b961e8c532eb1c3bc0936b68791ef671ca5223fe165735f71088f8ce7c0b6cd23429cfbea71a803", - "0a017e41278f621ad1c352692648ff2fe4ee815c0384fd96378c08ec6a933877c00a1a0ae27afbd2384bdb44f7ecea3429b965b4df049f3db808c34faf31c52bd6", - "0b003df4c5df9b06363cb2f7907da63917fbf4c872b45d0a7c64a5a6ef4b163bdcaba5462d3e28bf411099c5deb0856326882d24f1d761e35859bb723c3cef4742", - "0b06c2e65a14297198396dc82b0fd89ba2a2c1566886748c5ec63e799e90ff25c77d6ecbc1aec478822a141c573cb0558b6d1e71a4ccc93e6a88d303dcb5ba7c3a", - "0a07649875ccca56a85f76e0f3a762f57910e69234fdcd69186e4e0eedda611c999ff3b94c0cbff9ee8842be698d0a803f677e49dfaa5f50b2a7392b1689d4895f", - "0b0688f2e71db8e06c551fa0bf932af47c8e9412e5f9e458652679ed9db00f5b8ef3bd9965e1c46e1d8c3c8b8605048da90963e63f3a5191b5765c3feb0bf12ca8", - "0b00b694effb6b358d8efd34e615d9001f7c532f04a1429ce35362b8fc815d34388aef889618c8b4fe482a4d39f983b22d420d6c03318de93307472d3aa477539d", - "0b011bbe9e829019078df08cb651ac98d65b58100fe4bc43a79ee72315c4e41767f8af479257bff23895137ef003b8e328040b80619b6342c0ca5dfe8d3ae5e1f5", - "0b03964c1b9c6b0972aba96514f8edae503911b1ea922f513dcdef1c7ff0c189f9ffbf622b25c37412be61c381c7d74bc49cca988faaa8cbefa932c15a90e1bd3b", - "0b02f323ef544c65d351dab98698318e758529f6879eb0b3d2ded7b953099b4f3dd0fc208242c4c1b8dbddc4121631e24b5e2ca97449c081974dc3a17d6140f08b", - "0a064fb764a960580f05169cd4d143199ca69db5328253520bdd853e4dcdff757ec660b498c52b7b6d1cf2f5defd4cbe702e287cca42a2e28e1bae3eb58af6dee3", - "0b08e8b2f115e5a3a8a6339d639d644567d45874a35e5e582cafdb6bbdcde79c1568832dc28728e0c32e6c3a417361a8e96bd5d8e8bd83931b54a71b60a10567f1", - "0a0416467d60a16bb1f2d185aaff7466e515e099f54a4296c3a15d38fbcaf53a3fd55fa0d694a243b5e3c08d780388bbdbf69faa209c4ebc6200b6ce49e5557219", - "0a0433db497bd20d7047873892a2d07ac1d1e32baa3957190bceec4323f0198f9fc20ac9729858f03cf27a50bf456e8ef3bbedc6176ae718910da72816cc84b08b", - "0b084fc9839a1cd79338ac9330b0aa6d99a190ffb5a4253a20a59ef7797d8383a030870944d830b728ef231e2b33d080648d78c3089c39c56e7be9b58e95b35cee", - "0b02af0b042779ceebe676745050b05fe8d8b48799d983055572fdfcbb2790febfe6e09974a8fbb307141917ef0d0a9325616b7f11f4adc2b610b7da572c5f0889", - "0a0793914bbae8d28ab13ca2c6abdf082db90194defb16d7b2d0eb846b3cf9f497852b025f9188771bb6357453bbfb65006f90e4035562100eb8441ff0c6809204", - "0b06a1d6fe398f819ec1d777fa30f698863735a51ff1b138b8c731802101580ec86e0bd75d41f2b4e86529793ddd5c3bbb8e2681947db5caf1ea010450eb0eb6b7", - "0a07ce621086404c5f1af86363ee781e433768de8ddfd0a48d35f85d093c5a60b2c379dd3e8b45746101ff9dc840deb5172acd460f3ea4fc5864676a5ddc3a4ebb", - "0a08c6c31ccb2bd45709dfeadb13dded3bb2829dbb772ab1a84b8478105d8b80045cb84c8a7df1d70efd372f376e943963cc707ecd53efc02d4f2b50b115c054d3", - "0a0177fbe70fc04d63073d7193709bb0e795b007964abf071c4ad4d2a078a143cd1cf5628d5d9edbb286ffc9e63dcd2fbb070baef9b94556894bf8e62876db531f", - "0a04b0c341b6aa898ad9c297877aad92b18ee8e8d0f94c21aadc5427df246e9e3c1ac6e5f98ec6aa0384128a8593d246686e0d04f5a970eabcf1af3622a09575e4", - "0a05545f941aef7c0c10a6c430aed5be0db1b45b0eec73f4e7fe8645d21f31225054721de1728c9190020a2b11124aa8200548d1cc051350acef7a13b7e164d7b8", - "0b040175bc78e15a63f5e61a8947a62809c432e56a3731a4ed87a1757309f82fd7f151abf263ed64e5404916717f547d4b2325d85332593af91b923532b396f541", - "0b053e78c69148aac6d7b36a872ac03e8e16dd1f4fc50662c6e6f3654c17bbb2cffb2ed78d99ee2fc6ce7db6361fc913600d75a51a73069510ea539860e8deb905", - "0b027ea5cedb1e69f6da126969b609aba9c183fa515ea7be2bfd1f5f424adc9bba189e3dd9fa71d309e2c2b1e18335dca5f3ab4a14688742ab2e004ce8c5b8b21b", - "0b0320f27f39a08bd1533bfc11c3d8f133d091a048ec57d014ae6ebc5d83b1cf3ca9749fdec035efeb67235cf708faeda6f7d978fbe882c1879e17840f0eb23d80", - "0a08cae009ca4a40471640eb4c9b46e2ddcd9938f745e614b947b01b636589d5f515340ad34d8c9944c5c53135021a3665598b6ba7f595af1860bbd9b5306cf598", - "0b041d148bbce797a55c8dd706a8457ac8ef64a6e1bd0049c93f8245aada0ca3a23a7ffaa7193699473235fc9036389923e7d2dcca5d4d091fefd42ca8c836e930", - "0a08ef42e0cd545dc0178d529a61fd2f52d458046dbb0acf76d994a14553d9ce788db420725c26ff478a6ce5cfbca028b83e90eef40e90ae6587d8488b4e4cea33", - "0b016e7bf9cbc233581efe5c72ca02b4b9387554eaeb4c8bf8291ee004fc8041820ed6f44b63469aa7efa06eed6f0735193c90963cafcdbe2854afdccd8a43c450", - "0a04c456c696d536d958d9a3e1d7b476a2c591eda35b349f79dca8e64cd39ff33a1c4cc8c0ca1e0945ee35a3dcd36739258929d8aa262ef2b898b52fc02795b840", - "0a05272d2a20fb3db701700cd456bf4e17ba0e88789c246fb133e7218e8bbe4aae1bb696b31c92d03acbed52bb364ffb3b62dca5644a6cc2fd01f8e162a0050c8e", - "0b05ce325741e90875105b5463e342b2c5a020f32596c2fe2daef0cde6797706666c6fcffe1362bf3d627a8ea449a02b74dc7350768c9c9463804166458234ce36", - "0a01370a1175ecbf277c8789fa6cf0a7f426e14b672a97ee89bb73d77d74376eee0a0c0756071dda587e1029755b23510a3222841f52dd855c571339b5b08f9f37", - "0b07bbb11e579974bdfe6f1df0c4e36a037c4083526c20022fe52874f7b28350f975befabd9840ba8d3759bcaac729b7570193923fe7d7aea1794330291cb42cca", - "0b01e6668f19b87fcd0b7dcfae9c005a20c49f66242f19a166065be4d28e529f339c6c64792d360a9aac7c31621a84f7ee3f94d58206fa5e2857f727b593b93814", - "0b049d8a70417e1b3281080fb4f38e17ec7fec68f82319b7233e346471afb4f0d4a7cd9ffebd2bbd3da83a7c794a254e5663ed5d5d98cdf23855aa7d0ce45439d7", - "0a089475cf389f81790c41f3b456722964bc03a490a993c3403a37d67543655c5ff18a3cbea055d77335be138b5cc7c0a45a1884e0e54d0bc618538713ebde21dc", - "0b0885034c2a35f09e1b11c0bd500dd3b4b7fca54413409571ad73f3e6f8b32718993fe31437699266cdb5bb4bcfe9cd22cc20e66ebb59c1452a69211cd017db9f", - "0a0117657c5030036cbcb223aca08238e528054f71b56c84695c8dfb62484287289bdb1432b72d005f4b7bf2384cd9f7efa53ad0780b9f7d4e194352309eab43c4", - "0a067719df4df3d4d46451c6a2ac53cb2dca9195f3d407829ffc5a455b4a875d3bfc2e674d91bbd4b984686099179ced1aefe5886f367ed8ccffacf2ddf5cf1afb", - "0a036900662846fdf785fc0b4250600a71b9c310a2143c02281c93e72e6b32d539573ee20c522a180e299cc5cb20f831dd40e089b8d07dac1f9102d969fa3c6ba0", - "0b02147078c3b32cbb79da561a139d71a38c81706b7f4f731d797b3c040cc92c7db8301d03ea36d3112255acb1b9ca525921d894dd95c8c9b3027991cfa5c614eb", - "0a002f892b49ccf5c389ca9861e7283bd4742461b6d8b2db3b25b945dc12794373e91bc90d032a02bfef7a77e43dd41aad4bd740f817b932b1e65d08f62830dd3e", - "0b0309d5d3301ab86bef67aec950ddcadcc42221b62686e0f164b758c7c570f375cefdb56630d0013ab5f15f3ba0ea9d0612d8111f1105bb7bfed57a57503dd89e", - "0b070700c46b52c9f34e982b2144b586578ffa0592d4d6519552200e201d7a033439e694fed6422006362d3127442639efe7a1e4680e1dd562a353bc5c10cb55b1", - "0b044824316143abb7dbfc120860414b453ea3b2e4ce31b24a2edde86a166bc239f0eff949a5a6574a3ce090fcf120ae5946271ede159ab79ecc080fbc4cfee4e4", - "0a01409defbc27560abad34f1473f9e48684531cbb556f822e53a7fa2f3232301cb745160faf9ba4c1aef45e0ddd4d98e1a2a15e90ff7c606f1b1522b0f857d898", - "0b01fce99112225aae58aa5a3fb32d01c937dbf0701a98dc3b9ed3bf4cb766efc9ab8755c01544f1cac2cb6eb8a10cf50088ed722b0af8ea1b8690fddf184e433d", - "0a08eda904100c477c77148a30a4f2bd889a37830ba1c52328e30c49b131e40566554bf21c5dc0949117ccfe8d591440def2e5f912d02f5c54b3f16e0361e89502", - "0b0007c1ab10444f9d9e147d0640a5ba9565ac474178251d5c13e51c443bc3413fc4bffd731e8a4eb733998862c752acf67459d4d6378278553912f7c7b1821224", - "0b07dfca1c8eccd23c0a1ca4774c86137e1c42fea93eb60fca87a8956f72a10697a880179638db3b330d7acb8219df452a68664fd1335b4e34bd82c040811720a7", - "0b0643e87834d82eccb25e3e5970f17e2a7c6429af091b6aa1d82725f61d587bd6aa3f8d39587213221f87f5979c60d52398b92257083259dce7026fbdce01a7d0", - "0a08b9de738b8df88109294ccd6c6ff0339244860517d333524b5e6d49d63206f63a99884ca59b3be79826614b13a4535b15a1bdcd364b2e681ec3341465536194", - "0a00f559e9e818318b98496415f6ff0b178f97c226b7fb5735527b53914108d06aed085a65fa6963e87abd7de75d7759d3a142670c8b0e326f3850679a54543a31", - "0a054665db10c1fedecc82cbf6ff86d53d28ba9964ceb9057198933e862db795a236207f8a27ee0cabdfa319134954b9ad61f35410a3855e14b8a05e836ff5cc0a", - "0b01af5cd218ba4d10a74a201f4693adaac1a9d1b9e4cd52e96c141c61602861917fc2dd1e984787ac0632d3026702435652ecc0f7e9c17dd3eb47478f38e49125", - "0b06ef0ab6cb9222073f5b9e77881b3abb8fefff3230eeec4e55bb3395ac47ff4345acd5d4737c4108bcbb267232ef3b46dd70198a6c2deeea6f2215344df50392", - "0a0844586343f3cdc83efb345aa7e352bae692ad736d8e0766c0dc6bb34684a11379747a4aae5c90cde07d654408878744d55b0bef952476b834c9ae46d1ae4813", - "0b017afd64d4ec386e45769fd57dee3e85f150252d65aa043078cc81c1cbcbf6e2b828863d1bce5c006bbc0ac07cf710dc7e19211693746cf2847ddf454168c625", - "0a0068825ed24dca8815910dce03dbcc7f8eec51ee6226c9cff21730944874a0ca073f7057bdb13a31989c01df29744ed7dfd7c85c2b12b6c3d05a153fc4023b4a", - "0a05bec7f469cb7ef350d816b47b7a284d9227bbb0995f8f567f90b8f973c76402b16ca45cd04d4dba295802be34191368a2a4b3881d5252f564fafa18f29d6335", - "0b00260d2010bb165613db2df96bab9b5d85124d067b21a84e1d9cb8a1d1139ebe9d525a26a6c34369e21891052cf7189f02e3e32c560af57c0ddebaf80256081b", - "0b091ae0338702fb231a103f0aed70c750aa1b7d13d887bf59169157e52e585bf934fa177966e8f3e299f8166ad30916c1db381c859e4554efbe4e8fe2ff23fd6d", - "0a032171d882b76bff66867b6b4b8a2f53056f21660a6df8d1d69c6c6b513a4b8817497c17907278984b97df5e0e7f67b14940b678fe4f3bdf641067f249a9244a", - "0a0164376406d1985187c1b4c15b0f570721b6665b24415216fdc31d57fb46dc6e17f0409f956ff5133f1fbc541e5118fcfe4aded0b6038fa10f85e9fa1a356d75", - "0a051403b46297d00d267bfb85b448dee1ee0294ec0d79c1451f973e6a9ffd9042f0b30a6b36307ff522868575737dd5a9f276163efc40bed076bb58f2ebbd3bb6", - "0b0192da02f3c2a423ed725bb6d48b87ddcee95fc1278d1456437032beba1b37dd53c10293235e5c422d0952063294d8e62d852a6c6ac4a1db27f1c2f3bdb0166b", - "0b08f5a32ebf9dd9e11bdc167f260402d634a942d3a5f876dfb6911c339d9426da5eb7c8b18cd87a340d05bc6e63f0522448535f2dfde0a725bc6b03436da2a468", - "0b0540dd29fbcadeee9eefe3648d4650b45b47bde2dc76caf78777d52ff973e5aa4a5254d55660d350499680f635d14cead0c0e5eeb527d681fe4235cdf56e5970", - "0b02718eaa2100be6b9f813aa10d2a3528739009217f9d80d0c26d4854f5897ff4704112d5900be103c9d24d4dd0697daa531ab079f7cb9e90602b91e186ec19df", - "0a0164a2625baba4963efee2a3eea3617512c6ab50d1e0af0fcab783b00c0788a441a8f9c38a98defcb56c98ef8d339fc3f3245e7fcca694742889a76c77bb0f9d", - "0b04baf2498c21776574f6f3e9bb5d9368b7082dbdd02117af666b3afb095e197743f6898c555a5983e649634ae3d8c6eb5ce6e55c077f8e45ef0c7e30745d2461", - "0b051c8ea530d0aead906ab46bdc236562552558268c151cfc291798962fe3bb374ce00f3a13fb50f2ef27a3656c95c05c3f9b353ca4270c19838d3d249e8732f2", - "0a024fcd7ddbe7c235d69edf9a7c8570a52a8f794e981abb17d41c6515e580f46d345b52b8799403635f930dea7515f3b1d593339207cc52dcb773e9f4f9e8bba1", - "0b085224c728e0c53b0295c0190f91ee913d2b88af023083b318be9024e6d5439d87cae3afd41fc293a9846698565ce16037194896253a888e41ef42c96cc5a2b7", - "0a04da848e801a71ba39104b8db3c38a460ce75a20b35fbc537b0afa603bb65a1b54b7b2018b1b0ea3acd68fa06dbf949b65cb7119de431ba977df350c256ae7a8", - "0a00c1bb160bd497b86bb8eb2195ff24d36e49049a2a957d676c4228074fd42868bd3dafa1c18903277d9db4d5b688d04b0fbd441313e5061437d8b3f53dd6c631", - "0b04322c4c1ae08c11705ef5f998f31eabd54781137fa92cae982c3d5cf0dd7a9a549d26347ebcce7b2bee24bc3e1ee5001e4740eff8ef3cb2b60c28231bd56788", - "0b0031b628628fef16a47a00a65d68502a284a77c3a715726ec34307a0f9326180e528883c419d1e95b0cf7570a95ee91834b7ce3e162c7b37a73f043dcd687a81", - "0a003a84b7ca75590d18923b3a5e96caa1567bff7b35a7209b0188cd0553a5ae69a42a1f2ac80056928bb9632c565dc62c5f9aeb261ee50081de6a7c311df034d3", - "0a0676f8cd535c0787bee8bc2f6a730acde3c7e5648afc48dc0cb667e84b0692916648569c7df04e59b3cd08cde78771d35169a5c7ccc08399a16c4ea93da62c77", - "0a0429f6ef24a2d4dc627e2b4b8a56c40c850552307a53d88749961c088a838e5740a5f3db4dabc6858cfa7d059d53b29eacaa7d241f28c164c199d611be778a19", - "0a04a8cd6d41f0e48d476c30c0c4b7f7764815bde89eedeab81b1a482a4793adbe3db7837dca008bf956bdcb5b19c926e4a1fb16d746da4be0754a1ea56ac8a719", - "0a06cc898fcd9a81b6040c606229f2da9ed83fb9ff1b11b40851947827d2985ba8f07ee6b2063da6aaac5d2d83a7e32f3e3fc6fd9d9f513dd337b78d70555be5ce", - "0a01ab72f89f11ad3e256ffeb800c3afbf34a46c46ea5fcbce9481bc9ea1161ee698be104f5987d29a5ffbf8c09e34cfa2d355828eefa77b24faf258be9a1302e7", - "0b0671e2052409685645d1309a1040053af05f7e3fe63f112505111a6cff9cabeedb2ad39e08fef5002f8592dde522752163733b427b94bf38144ab2f74df6c3e5", - "0a0848ba842a5d09c00b2619aa4971259004c4f00d6f800ade3d56b14b977c4d4542f6212f1f040b57a4b29a4bd66bc78acef89d2d6e4c9fb4270f7574454abca3", - "0a010a4e830f218e0b0e3fa04edc42a3fc7ef042ad39751a2b003837d70903f2dfd3d7f8dc878d4b63a66bba4060dc421f7440cd94ebd554d988330f1cf22cc671", - "0b00f462530c850545a67c2670211211651471d2bd1cf26c815ad83a1b6810aef9461f96a82138366e969915bc39d1e8b686c93f6b73fca9511a585c58610cc354", - "0b05780bacd9780f623e6aa928845b50ee03e4a3987a4fc74237af903c963fecc93c5af770d19fbb3f549019f4458847956f0e661970e301582e6d3c91dbdb93cd", - "0b064926236f13f19f79e91f70666ec62e48f819c5080683ee1b5a96f9135913386e978a2e264f5214818152ef82125bb72e7f7e31091a729500a5db7a110fbc20", - "0a01c34c0781644e17db36e0d9a8cee55e7797bd13b37d469c768df1de600fb99da353265b97b2e787683ef62eebe52e165a813f3bc973255a759f77731d736b32", - "0b0832d09acf37ce14f24d0ded471095f927765fb7e348186a9c76bb457c1eec342d80b2dd44fa041bd04202a90a6c5efdff1ae9998dc7050885a6e41df2a97f54", - "0a0792ec3ee91d72b49ab969bb6c7dd379e0d47a8a8de5090b9285690577fa502965a2b57aed536c066e9d8c1f15ee1e0d8b0c261b58c2cb694dfb5b7158cb1363", - "0b08369c21022031926607a1c8f4ebd4896f15503f6cc3ff803cc7e5f88f269b1d68fbc731b1bc7ae802f78bc68abecd21438e78b73fb6c81df11567d893129a6b", - "0b0240cd637f8473fb77613318298f6d169057a61429db3c6208d1a3e245b9a1c40caa6d140cff629101ca0330de3e68da0d8e8a1c3fcc2dbdc721d7ed82795cfa", - "0a043788890a698f2dbb1536cc3466ba2cf2c1295b60d1efaa469bff38ee5bfc876ec2bc6d5429ae154437b97188fe1528d7004d39b718d5e84110537f6c420d63", - "0b03877e4f0f0b58853b63e4b557b2780b74972d3cf4e26c2a7d4108b78da2e6fb37514de06675c4b7088e3d94ddae00a9c558623a484f88cbecd89be7fcae69be", - "0a04e768ab981e850dbf052045bea394fdb20c85ac69c04286948b99957033203aa13ac6ebd1cf4485a71635c1b21d6bce808818c49301ebea865b4164b761fcda", - "0a05df055bf74fcef43c350be32bacad03d2a80e27c1f1d3ac1e5ec9545b6de3f77e335754bff8b30b61abb6b14b0d49f808c8f90c30eb0ce2709556b17fcbb557", - "0b02c68c20737dd31a9a7d77a720f33840fd8fedb79024bfc6d1055e4d9b76bf4f8cdc7e3a7645b402d822076719e56a0bb771f99e3de060e9820bb016c4734c11", - "0a007da62296d7e6a2115830f924b7ce8b3ce50b78e53539172559340ffb2d97e2951f56209e264dcebdc37274d1e3b34ebdc83281a7439a7773b624b6d87520f8", - "0a015ec0f8973563d0746d67bf925790ac5e1013a74dfe9fbb58d5be4a7a513be2831fdab418bf7f475d5cdd733d2b5f6ba880db4566040078ece57a21a8bcc494", - "0a007722078ebf476680db972fe5b5f17ae7c745be9cf9b939438e48b2c89411e8eabe47cb7932d3d3fd67b28fababcff65857f8fc5aa0604ba31cf04aca166c68", - "0a0387bfb9968514ec46df6e71266a23901d9f94a890578aff58315298897584bc2b8110243a1e779c1d6f2b2b5e27544e92ca58bcc179bd1fc60bb17eb6383937", - "0a032b9ecd5fa32b7b3b890de794f150428a01bfe540ae78ba07ee5d9667385052133104a2c4f7f7cbcebae5d9dbc56f1b9b4cfcfa0c3e71803b71af2fe511b3fb", - "0b02717ba4b2783f4f12780774ff180e20346616dfb84829e2b8aba9c1f24bbb861c46ca2eb3312cbd9dc0967b6b5e34953fb9540a4581e9b7abb438ccada7a16a", - "0b021f96ba55bb73c5daf0f77010cbde088a1e06c75aea35970293868f3463b20fec9f7b73117554fc668f91124c12d4c54870f3f61da0e65e2517335f73263db7", - "0a071e870067737c0e85de3b37734f9bf8c9082e6a6d669f7e34e584d9dc88957d7d07edb7f6259b2e7aa87a14eb99fd3129d7f0a3cc312f540cc35d5190b20c8d", - "0b064cac519d4e0386c1d6790e5e492e9b79cab254fd5a103e496746af7a17c87473de31b89aa17d9511077e7b79ff9dd3bd89e02b69ef195ff928cc50aceb1b5e", - "0b04fd731c93db1c3002033176c15afa413b93724e5fc71befaa8e626d6f36fe855cff18a777faf278875a1e10aa3280c2cb71cd2f2dabf067d5645296b6325b0d", - "0a02684eba33290f9020dc1a1e30def12d0d5d40af2d0593ed5288d557169eb769924b4ec69b1f420e021bfecb1b2f29807b651d8e1f40365785c1bb4e73952f9f", - "0b06936ffff79578c7c252086378e451fb05a865c3a3fadbe3cd24876645ca1c66295b9808f49baa9f3648729b8bcd85a9eee51ac39d8874f4fce5a76c24898dbc", - "0b0054273d58335a5a7633fdbd3e06d69374e18094a33ada038aff15092fda0abc4516ad1a6694a697211951980cfce8f4e3d34dd848052d53b43c92d585990e61", - "0a07b245978c64dbc0eab02ee728b5bc43a173c69ee5d9e08a7012790cbbfc9e25bf68585c65a4bc0556797e12046c3ecf8d81cb7b2766f31ad3bb033a5be7871a", - "0a0220784326073eb9025bb081ec29e4a72e17f55f4ab144a80d37d807e0e93ee2482cbcc8b3726ecc074e543224c87ac7c68c6d5b0ba10418aaead39f75214a34", - "0a07f7c878312bc77d957b281ab0fcc1e2bb6f0060415c6bd2c3be2c4661a36c68ad122314420364c43e3656d98764b3b3931775144ae427dc73773a74a98637a5", - "0b075e50d35d1d95b76e6a24f7a2c236b8420e0e63b78b6f5ea58ff93e45b719028f1dfb098232b959e8e42da856f5bfdb040cf61441e9fc85d8e1809914ac7a7b", - "0b06ee4eb98cd51c1e14f7c4e3ed704303a690c30c114b9bcb956d8851041cd3e689ec68800146c0897f5d769fda8c4f1f189d01da5f92d3ae95689f322a424d54", - "0b05e5930c53c12fdb6c017ae047fb45a6778d39071e2abd09b0af4c14b9e574ae7416b5c59e37d88ce64333793002d36177cfc495c7bcdb6760f3f7045edc36e3", - "0b008ab9000b2e765dc34ee0debaa4fb3b7cb4533f322a2a03f75033599e6932a90617b117db7ce5acdc4f437ddd6ecb6b7eb4975003def3095d736e9afdff7213", - "0b023975c962d0f9991d2f141508d610361e78167731131e191e985ef16a932c832d0235c5bd85487298ec73dd3370ef804956955627a62adf42bc0b11f017a1fe", - "0a01ba7c35e4d0ede2178cf4666b926049618c90f6a3d4d46de7d9f6b18cda8f7fa80bdcdf5ee3bd45e4edbcbfa6ace012036207caa87b3dcf1e3edf6718188c58", - "0a0904852072a3ab24a1527e1b105f80127c94316cabb8bedc7fc65b4600fbdb9813faa35a8f87e9d09d8ec24b9a0edf8e19014a358b450267c4705935f0c3e295", - "0b089e737fb8e4c8fb64a9b6e694844e5de5e108fa277b22854f21a7ac5bf9bc1e5984a2124636cfcf461c223f0554486f6f5409b40555a0ffe70f93f3ae52770d", - "0a07161f90e0a69ea16a6d5eaadefd82b5f5721dc25bd7909b38690c0d2a755967717a28fe48aaae238ee05c7d55672230b88886bd45c1ec8a1af75876a4bc7406", - "0a0703fa2484128608a5c8b1b25db31055a13c3daafd63a50f446e12bef5537c8b8d7b07e565baf28ebe7cfe4b3b0aa16cb27039ea741982328d107f1e69494d6c", - "0a04cc23d3d9a6ca01af75754e82825e0acfc84d92c2304d04bd749c3c06f632efb3f7b4a298a9f9392f381b6627181250bb8533f85e33724e5fd8d531e11d27fd", - "0b0447e98124993a4cca00efffc281530cb0c88e2a34980d74c9c6a7a1ec8ce5e23cf5d7bd4f0a6eda72cda33d665433d8c842117c73b2f0d7b2d833aa73d6c966", - "0b02bd74c013663c84591b888c006c09b7ca74b9ba3835cf5f3d00cf2160f635954c47b03d77d028c9be73db09abc3c6e6ea6dec76c0f82148236f3c29201c2fa2", - "0b05c3928dbac771e16031e78ee06f89a5dd05b0561bafedf90fba69da5120279c324530af1e9c0a07771e988c632ec097c2fb416e45780d1d70886a01dc4ed9f0", - "0b01037b7ccec621c6cd681d1dbbc48c0bb8e466c49314c72238288e2cfc9a828b5ec563a8f87c01508410f57411310a24eaa1dc31d801ace594055b3f5f6a10f1", - "0b024e48122476a267445ad225295740905fd72619d9966d0d68fbbd1d37e0f0abba546e81d74455cd6592c2f33ed59f1a5dc44de98ecad9c1b6b9c31daaeb3c01", - "0a00e63ab7c24e1de7ce33773a24e5483698c3028add8e73b0243343f0058a62aaf7992ea229679a53960a56e347e32ed16eeb460c77bec5983333034517b0d155", - "0a013d95d6ef7ef71d6708fc0f160537e36db6e45ac08896833804880a2102301f8c8b8f9cd4423d717d60d0f66b5f2cd78147365986a52e8d7207105a4269e1fd", - "0b06d4550499e5ecf315e1c1a093b2632ae421e1180698da6474d3bd178b0d1cd097ecbf4db3d3fb70b4c3af2c52a87a7f2eb42880f10fbef20494fda3a974c7a7", - "0b02116b4e705934f96c37b7c6f6d72a5c8af93b04d0dbce5483349f928363fe3817bee4b7b4bb0a38b4d7104419918014db589b048baa84bf17e1b3ebc4eed688", - "0a04fbf59636f3a346ef2e25a3aa42de97c037326a079dfa99bda2a1ed31711a7ed259f7f4bb6faa317cb2d134ba64e6a760e623e1fff905f6a24777bae6084769", - "0b061fe31d1b9723c6f9f85fe1d5c2bf3e68c54499612dcff57d0d57ad785fe57751000863d428e3cb7a182270016ca19d0c679d0ffe85b1cfcac2906e7b5fda7b", - "0b07ed354e3e1aede3a2d402a8800c1536a69ee07427fa57ae277f35496f1c42b00139a44a96e0463a3ebe261cd009c72191d55780a7e0f4150f567abfce13964d", - "0a07df90d668b8f0605c803c0b1d67aee7203e9c766ef9f9bc701a96aa0d187fefcc6bc987357873076995050333f020ed42f7783a351799ce2d18a4bafc7ecc9c", - "0a08ef0bde56585a572563a9fb616821e5b780f418c61def3809f90d93c29599869afe3cd7b3df59c13a3a24a4300a13df7d9e7d5bc5800c0d1b79f54f2ca913e5", - "0b087a2fa3c639b7d9d037e942e8113735eae0803db694dcf59f553d8f66dd3a7adb8b2e2c81fb0044dc9dca06314b72a8d71361135b9ad7a4133571c770121c0d", - "0b01ffbf25c72fc73b42818af77babbaf8ff488d96707fe8f1172f1bbfb40dcc25f407d679c04bd0fa1b8a0ca0082916f9eedd9ad775a49db042cae74b534b25f0", - "0b069e9a753b035f9dfe9288a97bc486a614cc4a30d2c2da4e8bb7b183eb9d463fc545a2d8e5957a06de83e2f04518d2fed61bb064cd1574835a354426bd6abc1b", - "0a03502ef0864f808b28ce12730122cc826ed1071d6e98bb52bcb89f1cfbfe17f87e9cc14e330ce0f0647e9d2d6ffe795b2803a87fb7b02c2dd679a2a2fc71ed57", - "0a035f93c3b93f29e2cb2d4f38603efd51929c89c3bb7d2c749c7d34e6e5e93e814fbadbe37ca23dc70c844f0dcd419a6e67411bcdf8d78e6e9c78b62ead69144e", - "0a033488c98ac5d94531f713906bd4c53d97c3f07a13ec29f2085652847936954043a002c791f2b54ca50aecae0a500fdf429a4f5895328631e0e77e9ac1e8191c", - "0b082b6b429ba085d0159437027f3d82b3fac99a71ddf0347e723bbea247b373e484181ab472885507d694c13c3ca36ca93010029b23a3c53898cce1839c856ff7", - "0a04cb4620e8d4afe97b72af7a7f637b52917530cdf4f515bba7eec2c3bff280ccf2ba21aaecbd45629e7746a554b352f1fc5325fb15046ac05302b2653ae02a4a", - "0b0615bb0b01aadce3cfefb055e362db6bcb3c435ab67c61d1f47dcf12c00517c1808762ae7d4b3b3b1775db88c34d2ea0107adaf8bfefd8869c611a36487d2741", - "0a05690af32b66db3b8a7e9d06ccb9b40a6795ab7bb87700cc7671ee9b50d88905f56348d2248c1ab83632558ea334871e6e00c1b13fe12c7391f7de946da632d2", - "0a0045288aed4aed5384d2287c8e92cf061c84a32aa1b50f8189ea6109f3a674495fa78fb209806b04234043ae893a66b257e7e63435c2e44f2c66110e9387a045", - "0a010540acf829d1a829e74c9622beedc50ffb632ffee8fceb91cfedfa84cf15d9496aba58f3efbaea749dcd8b030b670a5398c1afa875ee66faf3cc3ac0db8f98", - "0a06875ef90ebf036f4bedce1c2e32db4701562761803cfa4e74032531b0a4b41647102c0227bce9fa6ed662b575ccaceb8cffc6ae13684bc3f3e87a19ee3859f2", - "0a0752856fa219bc2b607d2fb5624bb8f0cf9560534fc3b983b6234c2c3f07e49dc0c39e61e60c24082de536bd968673a1dbab0bd0b3c60c23e7c97871b30817f3", - "0a0123c45b4695f87ce8f3a6e2152687d6d5af05e126b41168b23dc21d54bd07b223b6d42cc452c2d4325d3076468de8d5771061f6d27bd2ce9054aa4429033e65", - "0b06d8d37eafe8dc5d638c6f5e522628d518aee08e427d00fcc1e65d24f3735170f1bc98f176aeee7220fcabfab3b47543770a98836479df1b20ccd53fd63901d2", - "0a014cdb29b80ebf96053160f2da5361eb3a7dd5b24942f767fbd6c18281d6187efbaa38b9399c0192a1b99ed79680d37fefd4a69d4df466ea9012a9f0eec46781", - "0b08b6c37d65f7919043f5c06c6ca7469e297d9c5711d670791e3ccdd52dc878edc5d77bcd7f0fc5667420a9684ac84a7815fda0f25e50bc6b81a405f2eda6764b", - "0a02ae77fa16f1d22f59f379bfcb4c08414cf8d5b7a9e4139ec0c5f3d147119d89182c26161dce8503ee397e642ab8e45cda71500759887115f919ffbe71cf1bfb", - "0a08a30de698d6302ea131e19ac821435abdfc589484d740a1ae3566ef9af57d9d1a1dcd076fc4b9df5fc59c4adff04202b3a083c63b73b83b1371288260cadfc0", - "0b07c8ff5764af7ba24ec2a73a6e1dabe861b9cb9d7a42a30e91ae329bdd32731c3a11bcc141f74975a709ed76c94ca2f07992d312db95a41122082c436b128c40", - "0b0090a1ffed48432c839ea7cf172463d61dce99848950c15e5c644f0acc50c910aeb369d1a776d8d0bc7ceb68cce3300a5824b5e22be4f008ea68e7d39f5fe923", - "0b042e4bcb8ba67dcc58520595586562c2b79543d5467a1de3598ad4eea93222f506b156f5759a5a97f1b2be49b085bd9eda469eb7530fbe692e4becd254b1f20a", - "0b05a732186009deb6815b33ff0daef45f4bab777162d889db5987219180038fb04e54e1e1c212d05b76f5d63bca73a2c841ce650e2c70f7c49c0cebe4b0f9eb90", - "0a03bbd2588adc0dfbffd104083bb57c4ed05ba396e26122db6598dfb58379b787bdeac8dc823c50c0c26b79373afe12e952e3632c79323775426943c34b0a01d1", - "0b015d5dadae8c0c0f86413aead795e2b5c8f2026270cd3d80f519c17797e08cf6d1f887ba042ab4177d4a11400022c1eb8de2687ba7eb6cb7d86d886f06982cb0", - "0b02d9e664645c8d9c0bc7ea31a34b1e6de7a09acab1305d69dc6c73090050db7d0638d331bb2127524861a6caa6a008793ab36c9b09101e66adeec4ff78a7d991", - "0b01251a7defd1818540b9441e501eb4d134836c29a6cfe90e4ad252f4026ea09186df6ed1074f4618690491e576c900f20e5b48431bdb4d1e24aa1dce20cb12cc", - "0a080590bb87ff9d05db126372ea78e0919c01ea62d6bbd6531b574123bbb5930312d4b2e51adf5da25f99fc5ea88dc14ef1021596b6959efff939889f1fefab08", - "0b02db6fad7ae804f098ee8815e52672308f8c6b1c4dd30769a83e52e91ed0c52ad594bb840966295ef6a839817cb2a33ca23d4c415bcd82d0acda612f4d24b6df", - "0b084073817dbb245a93c873ad7180ccf415c0140232be428acccca56a0538bf8a9e859c7ddf7a33eca9d467c866eb904c298cd9699132698a181bd7a169e736d6", - "0b02666b199f253bb6cea836e5dcdde7e268df9f9ecaf9cf710c36be4304ff106a3465b243576c08e59f60b1ee380788c19c9876efcfb09430abef9f2d97cbfd5a", - "0b0924a28123aebd6cf68e014964fa338ba9d25acf43f8320b16dd185ceb92010c61f214331755301b173c285e94b530245aebf3cbcdc5b12250e59d21abbf9230", - "0b051579216f61f05af788bc55ca059f125fded3a0671c8397ebec619fa3a37bca71064541af0ebfc00587379abc647489a242da5b669def36c75416818f706cfc", - "0a02e3785617fda91f0ea1dddd5213fc5b2b933800cb04b10c078810b48a00b54d052c3ed2eb4cde856d6e1aa9d7f94a03e530b22ecff851f183b08116198ec376", - "0b0594c91a9a940614aa2676811e3896e6aaa020f18a2dca22e6594997ff2d599fc12d3bcf98165dd06db2680e7efc61231c0dc84228d97d58397e54f319fe9ac0", - "0b038c7cc0c5e33fc128b3a1e3b1ae31469b3727955ac5ab65df71722ee10a5da4806bcc6e8ba7c5ab1cd7a410dcb4aabe0f66df5ff9e78210cf75bf393150c885", - "0b030d663e6a2c327f3b1091ed310d8d6157db85cda005fd4661722798511ecc0b7c91f496cd338eb16e1b135d89c3bd5dbb1b9d1506a860bae9f639b1b85f4e46", - "0b086c2583c664a5694c5efd7429676082e51702f2aa90b6d33a3d8416501efe8c151a2b9c951bf0710df64a0da839742804de58b32d07b46eeaef5ce281f8ac65", - "0b01529b37d3048d820ba65a653c8598781500b558c8818a34c1ab3e528a87c3ef4479440c383c2060a9d5ef95e1f811ad845518de570fed2fa4f01f1b6af59c96", - "0a09031c7e84270df3e1fd54142c53a9f42f6b4f12ed879061904046e580caf0ad2322160f9bf43031b9b083cad21f58e90ffc792bd687db3b8ae39c5bbddf1307", - "0a04b45d937e4d54063c67dbba856986b20752ff970241e220b63bd051409411324bca059349428c8e8f51688a14b6f136a2457d8fc879487a5040bcec0b6d246b", - "0b054bce44845b5093c44ec9227f5f0de553e51520e2c98e77c770ec92428d4f489febe6374ad1bba531f68f5ccc96a4c7a4bddcd8910f68d73275bd485c1ef6cd", - "0b022e7511ac73d317487bb74fcc61b88fdc75ddec193ff56aaf217fa037aa19ddc28d997328dab51ece1f024b3289d28e323bb94a997b827c4752171c2abb1b6d", - "0a0655aeba5372430fd0dfb37d170f1b0347cb74801601ab5269901973fa11dc3ab02795e751a7942a682d25ebe5a6c1adc5edfe8cff170d60a73f74b0cbb59849", - "0a0187b69b911121b3a82ca43bd3b071e0b643ca84ba3c1a5456f78b99146a597fe8a499d0d41e49d7dae13f213a57b5b04107f66fbe47b7b877a4cec4a71617ca", - "0a047ccb25d421654454cc452d54c57000c7a5e4dee85d032dc49ebb08d218cfe69149feb6fbaafc6ffd1ce84b238054c4d2deaf9d2465fd96a8b51f28658de666", - "0b027afb906fe2511fc1e3aa205a66229b2e159b41a078fbe8ffe3e2c0251e9d1c651895d6293f99481e71e04f905ab670a836df004877e11204c80be125d8c5f8", - "0b0176336f306060ba05046bf2b392c361625c8064159c46d0839cdbc3975eb46970ac35f47201f0e94fd6f2aa4f55e6ff1aa616c50e778d0116a5aeffe6e2ead3", - "0a02fd1d37da6304ed9f7d9aa8e2eb1430ee6846352d7f45a59f9192f0e426683b3373cbcd01343cce974a04a6cf9312ea4cebadb80cd5eea44d5c2a7255ac567d", - "0b0505a2707d3831951e47a1a389fbbaea92ae156abb97ca313afe474edb2efe3ae61589ea6ea216cac8283f050c81af4779d5c2de5b2f0682fb3c32f2cc9cb71e", - "0a06cac4ac3ddc49e0416a16a363389f5c9587482082dc32174e7d9def54db28c0b5b7c7530527c993e999aa98c2703e041a33fe422918da5b8b21fbabce91b9e7", - "0b0232cf4578ce3474be115b3b37d0fa93ea2de9f12f2d3207a0d9bea825efb211313ab2ad41849865d1fe59c8ebcdc78f63ce2b6d9e705ed0b7f1b55fbe8e8c9a", - "0a038d930369b040a068a6b63c19f3e7428e3ead06a34aecd16873e30138b5a1074056d81c728be8498e283491fcf88c18663bc3cae322e37c427306157e8ffcd3", - "0b06204989632d03a6417287b36a740de3e1667b48877c0957c37c533a107a02a2181e9bd652586cdd11212c0da8989cf87f6de56be86b8c4d1c65bf0c330ed279", - "0b0264626a94c5df9773d4fbd643e639d073ac2496b40a935414d735f39b35be7fca29838f18254c001eccd368f13300d850a915c8eee13ff59facce80c7c68d55", - "0b0372493495021c8a9d9527e6abdf00889f2115bd4c1ae5676af41282dad091d97499ada47d15c984197700f3ce0c184dbb5b917618560b3c7c38d65fa99f6d4d", - "0b03e44f0d4501ae56ff9151d038236a91f4a7e19f9e8c9230bc9a96e3c5309a43c1ab1197034011a5c43b6d9ae4a89162bcd4f786fe163112cc4a3ee2c7857d2f", - "0b06c43268757921158f1b9794fbf0a5d5bb49fdf56445a88027c29ef03ce45ef4fadacf099f7972e151d20999afa971e6347200cdf24dbd737ffa3ad1a5dd3f61", - "0a070d214a16154579dd2c2f6c1676727b6e15b0c5e9e89480b0ff2e05ffc4cdba57ec509f56eee58b92702e65e026c748bba3889317ee19207129e28b53762671", - "0a03bd7814280c12c490e877dce7d3aba6e544f0cc300db917cbb1e2047270ea287cd56c912c8970dd7c98303bc3ae54dcbe8e50b415c217f952f012d1efc48a55", - "0a079fb71244eb6b000be090818c867c6ad7f94d7342293bea3a2a5db3f40131d190868aad3e094b86b783046dc930d9736b57cac0c68e40d6e0ed48fd45017712", - "0a00f606ba76470e134b512619124d209998ced1ff10f60840a1b15441ad064b50f8f96fe19b49dfea1d9bf51b48dbf7cabafdb05ea7e4c02fcf37e8c572027fd2", - "0b05bfd9c0065f7544574d2d70dc47eb96147457192cd4ccd422f0ebaf6ac37a5ad75e77cef4ec7c60ae43905a6ee434f4bd9059b7fa99135e268eb395f6305807", - "0a04fb20eb14c4e9bdb7925f8c2dc1c7ed1e9520716d444578c81cc6fa16f7f2557c5d95a825cb8589d8bd9d55b3ab09c2dccfcb1f6a9b4e401bec4bbf849fc938", - "0a038156e357039838370f5a87b3e356824977ed1679b625b34ecc00c3f1879823a248b90eb0c47843710ea2376db6281cd7938f5ce02e3040b09cabb460ff40db", - "0b04b4d75be950a2658183bc827aacb44641222421f694f407df46b4acef37b66fab84a74f6b5e5b285a59df289ef51469249f96790d0e0115f8abacd667d1e541", - "0b0151af60ca2edfc551e5dab0fa092c07a5558df3a41bc478566c219e3305580ba12fde71cef75efde6fff85f3993da97977dc688f09f20451b135ec19cc24d6f", - "0a06d5d89ba9554c550a93a7a94f6353826e9cce1eb08e07c511f267c7b9967c03b32e84f876c183d1e5f563a7b0189cce8aa5fc2e9c7302f1c14d11a23d7dc806", - "0a049894f8b83306f89954879a9176a2634b37d02e998ee05b53233eecb62a1a606ce801cc25fab9c3ffd9544a16a30580a23680e42415295be6591c2e6c713f17", - "0a01ab14eadd41554ccb24547eb9674307a64d3fb94d11f1a778d1f36cd9c775081bf68b33a8ca0ba0797ff176e4df9740a5eb84e97a5a3dcc1d328d4e23b8dd3d", - "0a073a2ad3c6e171de42053f3c41bf1864caa326c9d1278eb6bcd75ab9f83170bfd8ab82be2e5204fb4cd130477ab4b8a33a07f569706582e57ae0430dab5b2193", - "0b08df24b241c31e6ed6edf79bc63fbadd09dd4a3ad17dcc77329a6b49731f4a7723303b194e575b5df10403faebe2668480c970ef01c651fa97de6f35a0bd85c7", - "0a01a27a82b454a51e9a47688041a659dd8a34463ca5e768afe7aade0e4e5fdac55df9833197200e6bb2846b8a3c9305b89a560458caa449bca0b8cb84812ef0f3", - "0b019e0123b03f94499f63bdb8a6c5a0bc6b97d36a8974a06a535a397d32dbf26cd3de3ecfb8af5544e9a7bcc85ecbf9eca76da2e255a83ca90c504fcb87f4e596", - "0b07b5ec9f2b8029feec77f3a4350c8eee77974fd6f8a6e41eef29e59b5d299ae7613d9f83547f64dc69fe4cdcd42f331a00a1621e7bd0ccc7721d40c02b26d9b4", - "0b02a8c850e1cf583c660528b90bce702b4e9f0abb1189cfdbca5b684dcd54b2fe26ae61292b8064bfd4cccdb37468278cc6c12d062b088ca5de3a33a0f22fc019", - "0a03b427e048ffac7acad628c394a10df0eeaddac053ff34b6e518fb6ff9ba82cda0dfd27dc772c689447fff231f87b821c34da30dc46146d48cfb5adb92852db7", - "0a03e0a303dfac59ffa4bc31e6ca2c0bf15d67247d55595538201839a947a6c22e62afae506b08264038ce745fdb948566e2d901dd9237cb72b2aac8d49fbec418", - "0b07615f3cb395230a0e9a1fbb96d0facb3de5e62ff4880591e7abfdf2f6d79c15ae0f6d20b2629c829f8236f745da37b930f6d5e0e61d3f4754411e7158f728a0", - "0a01a5d339eabb3a790e085be4ac5c04b4bcc739f5690b7a73585709e5f836c1a164836dd77c065de07de82db619a3be16f722a1ce682d7cf92f61a2bd3860c61a", - "0a0136197a374e6af78991a826a9e714a4e984d3b68dd1be7c9a00a333b53494807137ae0430c6439407da39d3e5813ac040f49b022f0cbc1eb575cb9516c0bd64", - "0b04d47e3e54d01727e23f4d410f5238e39276ab2707e7a40e1b20434f87fc77388ca68d9b4d064df4d2860d5ad6f2ce958578aac6023a33fa36f8082221d9ae8d", - "0a0707d80c4bdd130fc8c6870516fa00240c7ed641f1a3f7a1fd5c816e235afe3ba0c5772686275a95647a6814675c616f00daa6b36733b754f016cf11340c93f6", - "0a0868b765276e077a1622064838c70742cb5d57a98500568fbaf2e113f655100a2d796d78509b707e92849b0c68b4a2cd53f347038ef5dd2de4fe18142c3b7bd4", - "0a02cbb2896c77dbf49bb3221a9ca84e24303c21ccea65da5fc837821b98d038fa08ffea2e96b395b51edba4f5caac217ebfc396ebd69bcf7358ab748eab6329d6", - "0a0909bc8afef0493fcdf9ed361aef391d9ab0ef3426b135e90dd2a6a067510c1021e30d7334d61e3894e849859ff35fbc0a7f7956f8705a4d99ab3997ff2a3874", - "0b03b760d20ba72d4c83de14dd592038f31676af617f5724abb9bc639d270b35a6246b155d06f1a503960567572c0fe7309384775269b52691cf97bb41301ddfbb", - "0a08a96be70f78ee51b1a06b3b58f7e4335c22a4a93004bf14375fc1c168bfc24bdc49ab2ee73bc8e920e0576c84540546c2494dd5b4b337a878f9df04d3fc4fc3", - "0a085168a17c688d71dbce42901837a8521a51d41299df897c23dea52d5d414d21faf26f7ebf12bb95db10b7931671a8fac98b018136afce06e99b0593f1823332", - "0a00f3611a545d0c39c13468534827e4de6184a9c1a898b33af40a78ee16d0c13c346eb1d4cfa3b5902c4efd92fffa3329e51de8fba5e205e6ad9b57a4c63cc812", - "0a08064122a88debc00caa0df5f75850f3a7217f84ce49e3b15877983ab27436c196a2f47691ebfb7e90f92088ad64087b610b7e1188a7c614c706ab3f1a003f17", - "0b051123d2d094639bb18142830ea2162eeb1ad5fd16b0bd8a4872ba7ef91e13fbdc40e4ca1ab3e61143846c5614b369a17a41346422c5a5aa78b40e7af6bca3b7", - "0b01863f53bc657d64c0e222c965217560175d30f3bfe6256c9164f7a188166ad496e064eaf2301e87f1290fb7590051b977169c97ce3f584914c6da7ffe8ec336", - "0a0350db030627e97cba1505a08a42e4c4c5eb784529f8eb2dbc9b805e02f12b28be9512bfcd17e98743ec4ed745d9d0e8fb14ccbc0a4eba926f545a61296a9ed3", - "0a07ac92bb05ad750cd35c7821bb17da95c9217b23f5eca36c1e31be749e5de788570196882e7f00c66cf0c02022cce2755e57c123693b36299ae4905fca2ef289", - "0a04641866d5f05d27b974eb45c7f901add3d0dcaa6a04a51289d4ee4abd01020cfb263dd1c9ae91f9f9ccb69623d767e837e144413726c48b7b593bae9d83b2a2", - "0b00797f239ae44c24e67202f795a112ff722eaf54ae023890ae7edad4328db3abe02b77e1aff2898e9cce0d904658ebd62f54538ab9611dbfd1135ab8bcc33477", - "0a02262d8572d4f881dedfacf462a277b426f7a8b37f88249d74f072d969a910170e67130a26d3d0a0841fa929427c0b0648897a420843942eed8d049070abfb1a", - "0a08920adab24ad33db62b8b14fc5cbd2c6bce216b8593f395a86fd3468f8402766c105e1cb82c1d5a82fac740006dc7c4c371e54d42ea0933cb04e0f1d9cba713", - "0a02da26ddc216eff6037af77bec22cae6fe2ce16268821be540b21559d2620b16a1090e96d1a27efeb7e373955bd565b5fbb5f4895e1a580aad2e9cb46cf26fd5", - "0b08ebc52418de7bfd0a6813dadd103c47eaef602e071dcceb1a7f776596aedf73e3b211e084ac3a2ced40ac02e6e0ec7afaf049039efbcb5f7624b94f5fa14998", - "0b03b599e295b376f813331e029f6afff71f02dc12aaf73a290cbc6aae994f12a94ab7be8f504915a1858d0c965e7fdc5fffe9d319df7889c4fa4496880c854926", - "0b0601992ba12bf00930d1a8cdbfbbb25c000e40cfb96e950196723141779eafc039ffc37d278523e2a4d16b526058082bba3be8857edbc6f4d70ea3d2626e7edf", - "0a037ac094ea0717a08a2a28bad9e97b795510b306a1e800a89618faffd2a65d69df8c4557fb106c372001bdd054f11cdc38f70d1a4baf4684b31f1faee6836ed1", - "0a0271725c15ae5833e858e494b7d6832a7296edfafa6fcb8277663bd21e7d8ab330c962c54d26c3b4b43cdeb41300e484fec76a2d512ea3e5347aea779d748b51", - "0b0015ff46f58826dd1bf839b270e7d434a2fa6876fa63948b6d2703763172928085688a548ceb86c458f92fcdd451471d95647fcf6e0b1096442e9fa4f87b9dcb", - "0a05139323042f08e0d96edcd41e80f6ba6477289cda980183afcd9dc5e00faa70d50714d3600b2bffc9e046fb7ec707f3db0a61b2c8bdc37f957066831fc3c708", - "0b05bc88ffca32b61fd6308df3a3c4a6f0e0d44eb86636536ba078936dde9c359c8c2293211255f445772e3def72169536615b9797a957c12554d04043dcd59b8e", - "0a01f3fe4f5285a27f55edc27d40b208bbf23168cdbbf5557ec6bd473d56cc37b521f97bc6f10e59215aca39ea351778b124c5a59e4f26144c282693c5f7239cb1", - "0b05884a2264de581246361d327b6ddc2337dd60b8441f086d062e36dcad943c0de11b5bfe3ab91a0a0225d8981110cc6db9d09b36ea8a4bdddd494c06ef822a86", - "0b02ae9d8a719f260a529217bfc34aaf3915595c734e35268e580a5f8af758d291e2b4497dabf49018293227044d20e6c0bcd78ad24ce9d04c26f90e86c10a1535", - "0a05e5369a387a7012385787f3d382a4a0f2fc63d85414a4c98f6c513c1b9c6aa17d8948636cd92bdf0944b95d6c550aa8ee2f8b3808f5ec24ac494c4ccba23190", - "0b00f0e77edfe11646e1a719539b0bcee1c2a1236ee86ccc9fa418b95bc3af16f0efc64167337cc51ae6aeb78b50304f06147ee44f6add002570a0d0d0a5e5b168", - "0a08f888ef02dcc90227c2792feb84bed7d06e45f557f41bd6999840982ae208926ec83f9d08d1875ec955836311a8ffa4c26983edf25e4995f19163137423cffc", - "0a02cf5203216cfc24fba57b22af78c26f957d3d77123f532c66a0626a6e2158db67777d2628e8342c8258517aae53662e18fd73e1ad818bdf8871fc11fc30d1e8", - "0b08122f40088bc5b7b60d34ca8cd3bc9abcaff7cca8f3116a4d49c39fad31b704a41787b924d0875447bbb18c0908dae9b04441b1dfd4bca786924c83ac3d79db", - "0a003738f0a98606f3601e9dcd60f1638e19dfb628ebbca392a01951251fff713c71c4473d844b58b44f183f52a5bba255e74485b153bd3f47cd40d3006a744468", - "0a07fef9e20fadbfd3e65369fe27f022840edab95f6c8e003d1b71bbb0f2a2611b52289dddbc7486a843701b1ca64d3c4d28e7bb3cd2a8e4da2301143e22cefce4", - "0b04261281ab9518353fda6403219b24aac8bbc61a3aa5fdf2e56249ee39f65f85df2f79462609afacf623910a682d13029af8f7933ad64c04bc9e0639a0645297", - "0a053917bb5dab84e7ba11355265e4a03cd95547c0f2fd05d4b19d792b3db9b34990e092ab86ac44fb4423f307a2b528c25d6e6696fd62a7deca750af7a1029cfc", - "0b081e1b246b57cc089cd42f0b2f96ddf000a5b7cc7d82d6bdc85cfc3cb8f54bdec6b1d27039b3958e47965736daaadc64a1285df874b1e54582737d64c33b0680", - "0b08836adb874426f6ceb74b28639fb80ea360d04f9eedee62721fcfc7ffeae13c40ca801719dd05f60780dabd26ce41dd181f0d3e5801ef9bccedc3fcda4ecdb1", - "0b005307a43548bb7c32499a6a7fa4c481a3b09f184d3790e5414c693f80ddb92d59a1622d1ec06b7bbe7f017ed7beb4d3720c98ed0ab8716856ff162bcf87edeb", - "0a07c46cb52470cdc756a745973880ab86c127aecc9c0cf14e956588e183ec607557d53526d36281fdde3aab34177cfacc2ac22ed876624a37c0d06ecedca7d805", - "0b0218874f330bc806e3388fcae1bea4513cd026ff5263c50dc6c6620d2310babc8c1cef95b47c4fc7689588aea6a4531d650e6f4d2f19f12b12bbbe9b12179425", - "0a02496750e50f21ee1bb6ce492a262a0a1e4b94706f156f45a9e2024a2712045361d269fc54b6418a6013e9d78c0e254fb13ffc5c4f6413f6d69a5b151f88497c", - "0b01a804e79abedb61f89842c04fb0408aa8b0cc6fc07afdf8dabe9f270ecf26bddcd7661150db03ba7c89a620ce483e5dbe16a9d0dba69587d04c55bf313fc3b8", - "0a01dcc8429361eac558da98f3fbce68721f72b6af9c54eda8b0a1684f0abb4b40387ebea08f3524be4e83e149d7051aa336f344853cf94c570e4bac72739afae2", - "0a0123470e7c135602169a7e26bcac0d7f6f7dea425738c2e840b62a50c905c7ac4c007b440522ca517e63c85d1b23d066367958e1a60ca84a9ec6bd6db6eb56b9", - "0a086c07701c433611c5193367fabf9665aff4be26c7119abb8b0f51ffb524c370fc66c81141554ea7f492a03acaea89a44385c0aa48d3df3dcd1b1cd3f27940ea", - "0b040856e969eebafeb22b9233a01efd6f943f0d563fdec7a4da976edc59c5cd0132acfb3dfcd91ad53335e9e154e78d8c3dc8423951766b77ee39e180b18e2dee", - "0b066ad46b24b89a50734750eef2e1b5b7a9e1af86c5c04cce1e3dcf46ec844c7b788c3ffed82c53113e2e7e299dc3031ca8be12a9ddd4fcfb6496980f37f56e2e", - "0a0461e56cec2b61a1b3b283e3d1d976b4d5ef34ea4ffa4cad43d8c4b88f90e1b5ddbfe96701ba46f9196a07496154749ca0a83793b12d8eb0f4c3828b1fd2bf42", - "0b02abe42e20bcddef057186cef057eb38bb44dcb3f4772e712ac4d9412eae87a7304a418aa6847ad1a49ede8f35f9fb66336094f3d3812af1c5bea9616bd98ea9", - "0b01b8ceafbb7b57eba04b049723c20cf14de1c887f3ec12c74b7db6bcda4d0439e5aa793696c0f805ec3d8964ad95c79b33207d43f1a25c8661c836cf31d08184", - "0a08894df731d2e31fd6c0dc00da7ce036e632371a6b801a3b64434e455778bb8a7d9a6cb2f8423c1ac4cb76b01610409bb40d7fd00272ce5e4702190e46253045", - "0b037c4946a264f6e8f273c6ff4a65aa5a179486d225c3edcf2d9d6f90c67c6032ed6c21da405329111a7dece4addc4557af7dc4aa0a8ee1f67222deea7774b5e4", - "0b00311d2191a09f543914894ec05e5f6408fc66f2a9ed2e7641d937851e801277c00866246aebbd2a7eac4ab45564415f148820bdbcb9999fe557770f18086a72", - "0a01d91e4f09424fc75488ecfef283aac79df0ed7f29b7fb2199c7f787c6d35e05ed8216ff91308184bbcefa1716709eafd7aa966aeb6e1869868ccf2dc68770b3", - "0b053fa54101555f28f877de666227e4263920365511dfddc59fef514475b1ddfe8034f10d4ca6f2d1e0e719e6b4393a6e22d013c32c9f228c5c537a5acab0716e", - "0a028aea99c9d8afd64418bf3d5164b12acc3968c9141e4a6c3531bba78bec6a9d093dae46f7a5a7590881821d72a34945d9d053252997bcf6e157d3988890657f", - "0a0565c15eee21b61baab99f7ded6a38118a924d40b0a6d4e56673b8249315e787206f677ec108b7cd88c13736d515dcc12b06931cb526efe296ef01e5196dbf32", - "0b00023689a5eede803d0cd16ed233cf161f4ddbd3e00fe52ff95c3cefd6542943a2e79806922910e64cfdd09e9e47a86b77b1685a53dcc449b3c5fdc0d6e01140", - "0b03e4183f6a1d1461268de927fa6eba8b07c65663f624b6d84fdc6468a0fe09a48cfb78f9f72e30e864b3c9fa87972de579380fbc80fb942b270fab22b72a81c2", - "0a052c9f9422ad91b6484a300977ae02468ab8eb81a6241078877f75c1bcb90b09d5a5b33056f02a8af1ff9b20b33a135459bd5c4c0d41faf090f3c98fe68da750", - "0a0676ed20a864e99624d0c4f529b43a819e2dcb3b274c9b3fe92e4d763e60ab5a73b22fde11fc01467aeffc4cdfa0faa8fcce2d375e45e6c1fb732a6479118d01", - "0a08c3b549d341c256778182f975d122cde5c19d8cccd2709e6072db98b40f2c6eaf456812adeb093d3bb34ba3283488a1c5820748f8e6315c068493f00ecb954a", - "0b068ffb9ea6da6f985ae96a8bcb526a3efb3175987d3e6f60fa7d5b87c61af926738d423c722361816f6e99cd580ba6f54774b26e05e032dfde0397af77173cae", - "0a06d49f1e5edbcc0fa7134fbeff35e2179cb5ccf509f58d47d021d84718883c69e95e30971972135a25c33da35cebb039abf67a1681db6ae2872c5a1506fd04ab", - "0b054f9e40359ffab47d9e48f4eea95ee1a78fad858c4cef805aee91b54cde1f3ee39834c5d96c4f6d5332bb9b63736514f8d80c0c9cd20b02f97e5cdaa4043df8", - "0a0635a1089c7b497a6f0fdc6937c460307b34b164a1d6dfd01e4519c62d4611cdc5293f5575591c7447fdda12485c9c2a35df65ca757e41b125cd4f7f7e256874", - "0b0655669a69a27e663ab841cd97d0e671726586b2ad4222698aa0617b167a2d9ca0cdacaae55b3a9a31dfba32f7058c680d38cd4a946a94b3792ca6b10da6c00f", - "0a005965af81abdc09c6b3534f814a7e9b71443458fb262b2750646891c5c45a9f9d36a9ef02c17ad33d6ca333f651bfa4094bb0254af341cce433d7c1d6c1086e", - "0a04987f1ff61553feb7ed2451140edab82a1221fdced71c3c9f672bcea6e85c7f191cf170d7c4890e9a0770ae387d7a5326d3df68186da54dd88ecf0caf014c0d", - "0a03a7cfd99ebcc2a23564e9bf38b48cb8f0b8bdbf3b03ea695b3912080c5d638f061583f263b19bc5425ca825232b0914224ce1a44029445702df39072eede8a8", - "0a0283eaebce7c1acb9b08052f8ddbd715f8c54157ad8a02389185c660dace99a65b13cccfb441135c8dd9f53d22626645d3749891a0a6cff30f2c396a39828ff1", - "0a020fe5b109828547241cc05a8c74d51bee2b39360b0a43bec38d876a2ba54302f3559695a22eef16565eb53f5636374d8e740428997f585746cad81611d11ee6", - "0a0433cec4af26289738f90c9a2c5810023230200132ba99ceaed16630fa1456c0669477b6a9fa814ed55d3a8c8f73b59a71aecdd2b33679fc91e63f74b3dcd145", - "0b064e33d909579cd32badbbe24f88fc81e4da753006f254f16371ddacf2804f4cb736bac19ae8ddc45e2daa302ba211499efc3c3cdb880a8e5b00a017590328ad", - "0a02bb5832635868dbb85961bce8daae3faead8f50ce86bfa4f8ec2fb81dccef40060bb67b80daabf2bcf0c357611534e4d6c361a087006ded51f490a23b8a7bba", - "0a03542e83758f470453c2e9e907ec6bad9fe0ad46f7afee667c0b5d6dbe5d2d25a4aef475d47c29d485e4bfe2b9d88b412a35518c969b90d4906c66b1c8c3079e", - "0b020f17fd630d7f1233eca542b7b8a6a17f5d761aa653ca4ae3ad4f6ff6b38e4c577b3fdd8df3754ced321a9ed0b13d0ba586d6d86b4ca844b1298b7d4128bc56", - "0b0171af55a6b6a5a88387ba737c6539d7b86ba1ccb5dcc1b6f9bddc9dcb7a093ea306910f51882eef426bdb2507b5af46f46933985c01348fe606f0b2a9f2a258", - "0a086ebef1819e9e5acc28450f235d5e538416f8ed35c7f6426c15409e335b5c9ab75b25c07ed46d6963a3593a4db38cead2872c588e35edf3f0f55f0dd91998cc", - "0a0051ab2d6d6c5313cfc5692277a7c16edd49f7d2fff0e379337406e549bfe38f920fbdd012ff397142e5ab45fdaedf7260c68d13e992c9ca0a1bbe7f57a98ead", - "0b055d3f6c030ffcd8e67ea56dceb35af658927f8581d7fa0c4a81099208f8d2b524728961e55e0ea13af3cd07aa59f5ed0eeb9fbeb98df03285d740ad4ca3e1a2", - "0a04d7b346f7bc85f373f5ef765b78cd4160e39113ea93e90cf2da00ee28744b60f812352204b524aabe036ec3ea3188e005d43bea4f847cd0a9028cd036dc96ff", - "0b03f6003502b4f02c8aaa0cbebd1655c2680a142a0b4bdcb0f09ffc51f5333d3fc0614bc07ceeec414c80c8f5151886f2d81aa5c4590d28a4e09b2e4a6d3b2d0f", - "0b0059fc63935caebd31850e3e51c8e23be94edb2439cda4e6d17a46e9d9b57cc2e6a2d84c4e7b5577a5dcfb69c56728af8fcecd3ffa2a9407ecfe3f0f57ff4e31", - "0a06881b7ff727217dc0490229d2096a26b62dbeaba9e0a65f4b1957661a9582f19d80fd86ff666dc5225d8954815cfbfeb8c96782c9e8d5cf2f081a02a75fee40", - "0a02eb16feea351ce1c5f05cd6d1e1a02f5e0dcd0009f92a9bd0f3815bfbce1670d7112dc11b0175b88e4d307075ee97891e4d3d9d0562e6c2f1a4db5e4dc0e83d", - "0a07e52f0c05f65ad2e67b0b7f1cd6597b015de7f830d33d30448a4b87dcff1f8e6983ddcdd3384308060a8f8b030acea502d8232f360a2438997f9a98726b3656", - "0b04f1856a8f9484e141b385b91bcc6a5902b7655a9c3a78256701388c66660303e846e132d14c8c84b80283303b0e7508a88525cc5a332f3c4547a67d3d46af46", - "0a0577490d5f9628ec8169e9064639e8199c04cecc311c3e1b612c8ce764ff7963c0e52d60985dc7c4f491129da0984fd3559226eae4c0e027744dbc4637bcdc1d", - "0b06a109bb2af1068e509eedfcdee71936fae6a19d3f1f7df13162b14d9664c1932276bbc67b9a017deb64736905274be4546b1cfba4891e44f79555b9f266f543", - "0a07bff2446b1bc0535a89fa3f3eca925f765b777a89042c5436a0a99b25046bb2cf6041e6f327ecfb2200a44335986c39ad97960089a6b37f374acaebf7b553ca", - "0a067b48ab3640ca4bcc296a965a3512611cacc2ffbba45d171fc877777e08cdaa13c0ebe73f10ada5c4f79efe837ad32ec3093faabc62b4ab16d8d77c24fa7e62", - "0a08302276087a2fb447945c7d1cbebe97d013938fb1dfff5c54fdac7cb53c894ddbcae759d747d45af31109c804c267ce57942280c1a4d734ec0e3ae3da136fc5", - "0a03ec2e58b0fa37a4cee71aaf8f5fd86521bd152dd0129387371f9a370b15777fa87cb952fb9468fd06637fc723dbba95883898b04e1c9bb376d89b09eea838a1", - "0b04962808c3af9c03d26f4b8170f40be1383d8f96f53159eefbe36173629ed4f6093c22c5520d8d2ac4a4c2ff96642b00c56adcf7809eff47d4b462be13154879", - "0b049fe42a9222cd1fda436764577ba70aea9e67ed08bd6c354451e6b29f31dbaa36a8aa8ef3eccad8931e74756545c3758deb00aa8c80a1444d83cccd86f49008", - "0a083d8abe32bcbc1f68a741e988855e62d42a439050f201b4bb9eec65dade215f2edb255970ad125671d61b396339c7fe262bcedec53db09e983fae6cc61e6a3e", - "0b0682ef212aeb4089350bf24d6303dcf09410fb8b33be6612037240ea165f8c674080dffab3e5a06445dfa4b6003fa570685ee27a7c8c34cc00e3343667b3755f", - "0b079eea5ecad6d001520e8c328e3a6b1963ba8998ce276800ab3b83478ed17224df15677898c0ee3f62f2546966c2444374efd7d9c620f6a3e46d149347215fa2", - "0b08c3ae233fbbaf0498e0aff03164914de2b72214229fc50b18e05ee03b06747648d4a1ad02c070779c030f492a9743c0930d39bdfd766f428a24e7f55afe34d6", - "0b01811955976d4d829de61d4f063094a36beabf1b26bc930cbfe3947a2f2d7b361dd7807d158dfe87d0ec6bde407afae844d55409dff7106cef8bd2b22285d329", - "0b07920137b8d1d83148366bebfde09b6b4f1de210a15895bf5f65f838a911f607ed53a5d89ee19841110c74264deb7b18b5036bce6d5834ce0685bf0884d1f993", - "0b064cb14ebfad635df6284f22dae05b84cfed686d1a6736407e2102a4e6dddbd5dba0b4bb8b2e94f1576adddbdb18ef73bc685f66c41e2988fec6e1ca3a19b91b", - "0a03f1374b2c0adc1359a4f1aa8000b771b70c24e5ae6323308c2630949bb7c2d3fa943f50f70f56e1786ff7d6b41c7f145eb73d4b2d56f836c9f7c05d4e1b2d64", - "0b039c7a535b16e38d21fbf8f1b231117147aa9d8e1091143e46475fddf8a18cbfe48b66cb237109d92eedd75ed54eef1c5436f6223f0eb2e78f9a4bde495a32ec", - "0b02a8e6e8e4e38ed2a345a2efda65d02d67ef96d9fc23ccaec0cd8022f863c2a0b00aeb40d8beb315edd9bd7118e3df19b6866b0591b186a23b4909d4974a1559", - "0a002c2a304d4c3fd95161af4b2e32dc4afc8fe1e3d13cd8904ea2910ebd9ad42d0dec4f173b0760a7ae53a900199803a205d3df5283d77a242fa0c71c38975a24", - "0a02f8ce78764418788c74a6d66725eca510242328ca32c89a992354a5e636cc5efa1b097e1e1c82cef3e83e4dc0680d8c5ad5307cddbd40c8d076298a443c3e4a", - "0a06982195fc742282fd10cc4cf6aea1022a7c7cfba19346f4bb6bd5548e6f2f5049c636dd7420a80bfe1758940ddc6516db2b2f83572ecc9ffaa0b7b8a7dc9758", - "0b08da7aeb0a9b199ed319b806b48c39fd70f44ba4fc2ffec41a086ed7a8349785c644fddee324a32663806d2d8d72426a87f148f873eb17db3027662e99a40f87", - "0b043d835cfeff74b6c0bca708069e30758e4309a941cdc8ea0bd01f5f305a9c72906ab41e7a39b7c427a9cdc927e8a561c2c7c712b3cbf2a3795dda96dcc5c75d", - "0a0215beeddf5f3f9281c8d09f54910acc134f51b10c418a7320fc850b52b73c2de24b5c15144f88f415dc7fb3b7c3a1296484a9536714c54755d18716b3199a92", - "0b08f9997367ae78b00c5c11327a0c752c5c2dc562b6fa4d5abe8630593608be869949ecc892e136ea5a55a0b45cc9645d4f9116ceba80cc4d0b6deee50d6a610b", - "0a024764693bfa82fdfe90b8b9836af864f4682caa6609697ca98496213328fc8638aa993e839c122db517c02c7d655565b7b26f8de3acddc97a38411d359b90f2", - "0a07d11c1802d035be33137cec933b94afa12dc8291c599d62b72f6b1bbabfaa1a2d534dfa9d30205372ee7a99081bc047205797665f84524c7b11aee32ec8c9ab", - "0a06989dfb0699d89994802fe8383eb50b284a8e406245db255576a3f326bc4ecde21e88fc3a0694e8744ab731344325680b2c61fe2535d2acce6b5b1f120387c3", - "0a004cc34a3d708f10fe39c7b87b28fa923bc8e367ae4cae885c92118f9b50d6630664945b93dede224a33ee36abfa555a091278dd34c2280f19863ec8c4d6a306", - "0a0185c843f531cac8453f1db06e5dad9b815b59ece7d8db8bdc4db6012f8ebe536bcfa64bfe379d0a71f28dba6d9203d7a5ea09fc2a35fdc0060d561610cdd8bc", - "0a07225538a9ce907def630a9df89c7c8f6d772a0c6a8cef22d215ae79d1fa5dafe1c17c99661ae380fb70619d21fb47433ab5e72552c841eba6c88d3eb22ce4ba", - "0a00030aaf84250adfad44de4ad9fc910670776b4b41f2bb4363d59e9d33d3b22a97e8f85e7f963edb02cd0966037acf1f8548973ae14f10df28232f7628c803cf", - "0b055e9f96405280c5de72473a810e1ac751c4a067990a893474a59d7cf03d78fec34fe8b1663c253f966002e73724a56a325ca4060fbccb9cfcb5b352601396a3", - "0a03e5bcd712d1018936c97f55e91e1fe62209ed1c2ca5d13e78a24004ce05ee1b7b533c611105b4c9ab299538ab6d07faca3a4f04fa70efa28c85f4ebe90d1a17", - "0b0514823c401a66aa461b076e3074ee9b6ac08c94f54bf1153b89af3dee28642257f8f977a7c09a8ade7c160804d07b365be62ee75cc8aab87b15ee5b5d8c0955", - "0a07d2ea84d1a0af11972664329ab4febb69c156a3674e00eaa53c3af2c015f9db393f859edddcd646120cfe695fb22a7ef4998fa2702ce33f77905a1fdaa7db0a", - "0b029cae222fb9a0ab92f6848fe617653fe3b4de850d7c0055360db4f6760ed1edc892d267cec93492f5e2f3a416a6bd0f04e63e0b7b65dbbf755f3c28748ed5e5", - "0b012d04aa106b5fef2557bf29b37408e7c09c8610a7fd76299c4d5d779e0a90b10a998a20271d08a08e5707caa99b703ec8b665e9233c546da3f23d7df8784e4f", - "0b091fab5037341592d88d146a1032e4ad6b83a046464b48fcd693d22fe2df522a100793b30350c64e66fa65973c9fc6b8b32c906921d81280f59718da9af44c72", - "0b02d24cb0d775c0759f41c3439d1c853b06a24645b2bc6d3315e386ac3ad4f2c702795191c2d383cd058d0cd0b3e0a500656964f20ac711e4cb2e3d4802c52134", - "0a0703beed7c880c3aeadc793677bfc406348a308d5a04ecde35472ddbe2a80ffd08d9f69b4ee2a6be2ae3a04fe48059277fc30a1f44dc13b018b6b68bbe7c94be", - "0b04364e162fb9e97e82dec72667fab0057423ef6776ccc342a3b81ae3730335d0350ccd9ee7b0e40466ca970a5211296c6708383f4c2a0efc09b1d9e3116fded2", - "0a06b350a7ffa34edf0d9712738174d6c9ad020f504176af43b46a308be084b4ef23ba534a2e9ba45f22be4dc2f3fd85ff8b809d5841e9a93d4d47d9eb7a0073a7", - "0a00a66abf804ef790cd92a7c353fd6c016a3872e6f5db45aaae2f1fd443f52f1639c1d45e33cc922e42b684cb713bf6e64ee4351aef8944af1a7824ee5ef362b2", - "0a00a8cdf9d172f7ffc083d5b7f5c8ec49c209c3fb42fa259e466551d289a3284e6f97957d5a790b960b31eaf6154497c3e4190f7100ff050ce29f990e68b8f423", - "0b0591dec0b168ddb010f2d004b88c83bc0a7d511e309fa5b04d6b650c04f2653bb5d1b0b5ff29c04b1aacc048406a5c56454c4895b430e4a868add44355077338", - "0b019638d76e12acb2713c3dceaa63876a237d188fc5972015c12f9d7980fe7c646fba8d647c1c1a46260d7ae39088a7a1eca35e5d5272f9443ccd6ac1c7ee9380", - "0a043a2c28f08998a2bccd1de6d4717d79a94bb1f206ab32665f3c0f78e5c9a563192580b477781c8a8a7a445648c3aa2ab187a8b9998d616a698f79a28e68ef9b", - "0b017a9480725ece23d37f5bedeaf5a1aedbc97deafec98340fa078a84e0df8525de2069291267d515be81f80586a4bd80c0e86f3d55f45e5b3d216ceafc608467", - "0a036bc1b00e521eca6e530cc06c37aac12541eae9918ce6e881e6f14141f8625d97e5dfe06faddb6d3d13fb5da8fdcbecbfbc5417635e52502e77cd9634160db7", - "0a04ae9f627268dd76e904282db86c8cf18e97c85dd6f52d37511e8cf272576b1df6d844decf1c27572cdd0f970aba9528ef0b5248c5bf6cfc66b26c67aa99e00d", - "0a0161a94e8653b097e4ec7958f38e9b3867620f34d72fde71877b08cfe84b3bf3601df71b0eb46ac2ae231caa7af0421173b2fc64d8638d619cc4317edd8fa661", - "0b00b15871c8972dc6180232c3252e84ce9dae8014fa48dbac318850e7064d33e0a1cb1b338d4c541cce382e7422a330249e8380aca0efa960216ea1c1cced4827", - "0a01905667e18fb780a42850d190e4bfa48828309d862bb153b3cffc483dc910fb7844b6be50893b34216ece1fe1b9791a4fb5922c4fd43b8958e3b7f2e1412e93", - "0a0911a3e4f207de893685ee3b861c1164c630ef8df36ebc15f50df31078c083f2cc0b0f9b1cab15aee3255ca0ac198f176bd8d7bc62364bb3e8aa095657140f63", - "0b072fba26fc3f71efe17feafb73e978733c712db2c7675d1721c38f20d6fc25cb57813f2a9bd3cd10949e85536c3f6e48040b9c26fdcc444e7335e4497a5d3686", - "0a080e94efafc95ba9fb67831e8f388a392bfe0efabc89dad791883851aadf20d9d977fc3ae6f45a3cf6fae2ec22e17472d5d303bc4fb989e7bee6d092249732f2", - "0a04f04affbb5532dae9d34b7519b7d341192832996a963346643f69c96daaa3252bc3f8f83a79273498b12f1ad2af077794feb7a97ed0f2d710925f2be8739266", - "0b053a196648c341aba6b8f810099a626609e1798a30d2c6b5d40994af08d998ddd4659c8be7a34f5d7fdc1b64aa5a1090f0e131a1a994d66e769a74d5443ef8bc", - "0a03a10ce35ba9a57cb36b00e78bb538f4ec1964f6fe96c56a782737dfb9c1ef8c57c70c17677d1d55a21342699b8e3b844229f138959d2474caa467d80f4db694", - "0a07e8e3456296ed722b4e53aa3abac1f3eedb0c8b186d6f7379d1b819c1e789efdfefcee66ed95395ab7eff0cf4004051057fc702788401035f1c337511665286", - "0a04404a8553a77c96874628dfd32b480f502a416899ee48763a3f7ca6677bad7bb399a208a0792c0cf6a139157b2e2e285db87f2fdee78ae4a90cf1d853c9fcd9", - "0b0075ed32ae0e36d9a836ab004e1e133fe3989a0b3668b879178cdd8159c8f806bba78570c39ed939fc3402c6473b3af72d1f88157646ab38cafe27747eb1d3d5", - "0a0129449b00b499de082fa6ca032009fe7273830c40bf9e2cbfcfe0a05f30a8de2c35f6beb0aa563047bfd400c916692ecbf8aed80bac2de5d174ddc3277df507", - "0b020a56bce71f1d8fa13d6590148666a562b5442d2342892bf5132f8839be0d3c0177ca0d8b3662c7a31c4fea6c07f640aafd6b353a0ac5aa0b92463e4adfc3f6", - "0a08547ee79fa3f6141d0dd552b672cca8909d1a141ac0c3c2802ca7784f05fc7e9fd208abcab9ed43eee4a2bd20355c2f8206eca1ffaf4e3d948a383b248af8f6", - "0b0284d8602660fa5854b6a21a4f7637812a7b6556ee36bbca65c64f9586e45434d77dc8827c39b5b0019074a6d8f2fcc3df671884849ff42d5bd362fae0096cef", - "0a0302fdc3a70944821b6ff077f0f8b625d8b55015c978116cc6ce3afce6b807c24f44667f06f8d51e1adb38664176de8230a8cb0049e40e768e09dc5da7427f12", - "0b0815d94f41e3495674989bd04222053cd8ca7658868673e05cf5efeab66ae3f0953edf334097ac64423bc43c0a8f743a9e2b33fad6761fc3337c54edef1e64c2", - "0a062d9d3192d7f66519bc05c9dc10f7e3f79216ad69736f4a4d34d0c5e02b5aca3b460417924188ca50e5274659320c02ef8def9e57bf37387bb0a9f13f261f65", - "0b0787167ed477f91111075dd34f70e5b80f21dbb0225c251d223d2f68b9a6fe64d11cef5d9216a9373d8eaa7c47bf7dfe6dc02b0dccc5280024927708368f281a", - "0a07b2dc1de5ec8a64b18fa8d3070f3c4cab58062293ab1a4d89b861dfdcb3dd0cd4ee88e308ea2fa9a69726990295c3d8352761166e54ffef670195b287cd3f8a", - "0b03231c40587bec4c6a5e43fe1be330116cf51a9ebbbea8089521b2980fefedb3d83fd48de561f204a24fdf2b3cdfc4a3e5cd92dec361963bfff590a99223860a", - "0a03c75e9c6a3cea00a9eb3c4d4fd33e248909699608795cdc4e36405ff41ec0f5c43d47dc93def529d55b908b430544170a8d74677b8aaa053e9b9de1cf734e59", - "0b04b7966bfa2e79c3805db6601fec53aa187ca3ae3ce8a3524a87411cfa76a094db3a1b29e1076e64863ac9aa82414be35911da05e4e5a32f4c3d37fef3461605", - "0a049fc76118d97ce502f07a076e158da45780e3176d0feb5069c4435019de7279510d991f2a6ec16b6cde8159706c2756b3bce6acb449f8dc9ae2cc8d46a97295", - "0b00df8a90d08c2a0246173764883bab67d18db97c6d813499b3bfb625e4122458200eae87639b609b1a8dc627522f0ef4b418b772dfdcd1bd33a2b70cd30fa130", - "0a05e58575047b12b06a02a25e4ac1323ef565feaf787db2821a88da3d98ec539e73ecf425967cefb9847ea5bded5cabb186233e373ee59d4e23522d9548abbdcd", - "0b04807f860ec3c0c651b33e37feff318d9f52e68f261e10326e9d9f79c53b246f84e957ea65fbef8ecb3d4159246835af1c824684381ea2b737d449054a9047e6", - "0a00b593f5604f48a64be94085d7e60cb8cb182be042790bebbc648cd71b5cee3642e5e2950eb03c220a2ef7b32e124380f0b4e92bc66140ff19cca79a91a99d04", - "0b0200a3c8b07fc754e69a4b5399734f785b4f3e8217224eeb0c4908b58f02e56631f8407b3ff08fa11fdb4569ff85432d790291cbcb2d636c669203a1ea8b18e4", - "0a00dea1f10aa503797b992a06c44a0e72bdd6a4cc6206b332727a8992694ce7c639a41d7ff533c72ebbbf83fe55a1c24d8c6d6d5de131a12ecbb7d0fadd69bf03", - "0a03a170e07641b2e6ae0f937a93ea8b8c91123b590c7d36b7aac73cd41858ccb770605ff0055cf6ec2dbd36c2a9866128435ea8057b510c25afb73d6f0045ec14", - "0b04cef03fb1755ef3180f4bff94a4771ca6da1a954780cdc079247f21d343823d46592cf27c0e7407ead5443636123280e302428a09ab1c4a6ebeadb4b5d31456", - "0b0347d33b8f8a26cb05337eea4a0db8dec9b287035683453751b2db8f4ff01ae53cd5ba739d77aabdc9c564abd95911bd04dd30b57c92aa46f19c34227ce1dacd", - "0a07c2848692fd3b3d18c8170d91331341961358d72e7d1e20de72903968ce92fb01c8602b113bbb1b74c990f1a93c1c823ff6eb9855a9fb10bb51fe12335eb485", - "0b0325e323855b5feb9e1473f4169fc30cea5733a21be185384c48752f83740bb42fc8f87c304439767eecfc80e945247c114d6ee8a8043c57dd1103cd29431896", - "0b04ac0be4f0618165936c71d460f43c9dcf51ce1209434cbaeeed1daaa58edcb382401a2cbeaa123eecc12ea1b004dd2bc451a14c83cafb1d38952cf456484ce8", - "0a083a44d6ccd6ff9ef5a16afa5e7857e6365f7c04f23c570a805906fb0e0ed0e01f1f3435f7fa562f506a3d52a5f35d40dd58420335fbbd8207f3b72f178ef9e3", - "0b067bc3c28146cd6be782218b6517232a1ca3536e6f5f0e15e0f5467b21ecfb955db8f6ed341394776a257f28c7abedbbc84fb592ddbe33f3957b22349dfd9e1a", - "0a028eec37287c719f01eff70db31752a8be96daf13e333a0807b4bc5257611b5ed09b153b29ac95c85881881fc0ea13f4263a2a1155d600b65c5407f2cc9bba50", - "0b05bb8100a498359995f5b0d093aec8735efd79d2bee2163ff856c7d0948d3199014432d23d89439cb30341d6bbe603c23c28ea8ced3a9f50f7c2a788eba18d75", - "0b030c7f3ef92469f5b78033cd2f969057516f497e7f1c1516c44254754bb3801768198e7d114ff9a540550772a335a179d980ffec9dc248c0fa5012962588d929", - "0a0453c3f5f8e06e4556fc41c3b0bb49c517d12fea1dacaada277052496cdb38732ac20ca3dcf2eeae6a9e79b86c16e5d34a5415926947f2fa6da38018778ae98e", - "0b046131e1f8e5b53eee753f89469f8d64a82542fc259338f0b19dd82b0fa157290ced5284a886a9071e9e0fd2bdad160be073e23ba246da0e1e968a19f8099640", - "0a06219fb889f738f6fc4b3dfba00e8500fc6fbd0b2f626b5ca5491ef4ab6ba5aec57423bdaafbea53b2c1c4f24fbd2175791c6615701e33ba7ef739c93d2d3949", - "0b05d85b7bdff07e02114cb6b06ac87844e102cc0e93cda13d0b09c231e4e0b77387baaba57ced12cbee5766248aa28e8835367a7bf5a1aba243570366d3113543", - "0b01ed5df12de50ffe68378d4e511ef795ae89d43cbaed793bf6f1831b8c156d6deef3ce39ee1ef79f57666e244da0f29915707be2b9b46a3fba8f16203ae5bb2c", - "0a060ed90a54d8eee86170ff53fd26466701397030e3a35fbbe8eece72f464bf38294b96b7499a0ffbd463b60d3657dec70088d34c24c4190b4194a1537b9b8220", - "0b05767e63aaa4e55d3ec085b82362f6677becefed8bb6410d06621a38218be7ec7df70c0e1e27b329ccb7f29c57c7571b3f696eb5ed7dedd14ffb7fae99c1c0f4", - "0a092060bbfb45cc4bc9c55ff770eec58b7f947b4caad76c715faca02bbc5965e301bf05464eb6e980f23bfb4eea2b85fc25220c42f998c68938e4c9d79cb6c297", - "0b07f474983b940eaf5b3e9bc3979329c5ed0071781df5e9c0656b69d7605a062319bac396441ca75f602a305d283dfc800d61cf6fbd8a9eaacdde147e62978a9a", - "0a08a25692a74c6262e3cac4efa11f695af46c369eb4dd29cb8a7065d8aa935dddbbc8428b7dfc051a7267ed70e0a8db65a137a83981eb0b16fb9338ce6bcfa3ad", - "0a04b54b9bf6e41b1106f7106c967bb614448791fd8461ee7ad4cc1435fd43a70a1572d94ab1919f2ce0fbb5326e8c2597e9bdc5b8d8a8134a2737f5fa5dcfdbb5", - "0b04dd24c21f7178e559f70e830e67f0480855d9a57381a989ca4ceba1e4ee2dd3fcbfbdcbbb8a08c9c948f64d084cbb5f772d6431965871ce118a524e797bedd0", - "0b046f293bc0786c1932bf33ed3d701febfdb36f9d5df6d7aa50f344ea172d7040260d728df9db655363528bc8a935ad724d7a63f822973cf02748ac1045f1a93b", - "0b04d8a76fa5dddd461efde0105637b6ae4780dec8cd07c82838da98757a6c5b64d58864bef105445a17feec799741b5638d08bb120e2abd86f82594776755ea2a", - "0a0661d00b98472689a50890d89495a2e6d1e7bfb7d8fa79088b051a2a8ceab58baf9ece5bfaeba18abd6c50a86ebcad2d199bf1e688c447778d044dc925df166c", - "0a08f60202c3852edc399b81e7060f465fbf2a9cb069d1a790d0c0afbedb14711f184dd9450d4bd9078749d44709e87d49d32b033018b7a0fabe53257c21a5f01c", - "0a0033ff9409f0f22c2e231e2afff29d36104c3402e79effb938939bc63e39b652c3edd7ca70e73221aa8f940e3ba21670d66963ef164048febc635f59e82d73ba", - "0a07bac0c139f4c7ea79c82e17b0b56e75bddfde5387aef20e7f0c6763bcd6d9a3111d7214c41dd0b6ae67ed909e29adb68cf04f3d0fb6393328561f734dd6f854", - "0a08d147f52c51a72052e1e224d7ab33e4a13cc99ac2770721a6c341faeb5337a096078ba670163755e0a062b2a9526335ab0995322ecb00e1e2c214c730cec0e2", - "0a07e8a751f01a3e0a0ac3114746b9e3cf29f27a644e1e1c5a09a9c81404051a625470a17325392c2098ed9f7335d75a49be0fe6e7bd25ca856b18d9ad883b4fe2", - "0a08b49adc6ad65d0005756f0f9a2cef385b016bf2cb1f339b6128a5b0637edc9052e87793f97baabc4951ff020d20c262ba714865ecf4703fb12636eedb038e3d", - "0a075f28c62f99255d13f3890eb79d6d4085c376e19b4e887ba0a646f80014acb44396938220f2f226c12b64adfd98f9a78f0520492dbaa9d89e9b47788ea03629", - "0a00293e0a743ba47e1c580653c6d7e09826f4cb0cbde5648aa277e3ff20d91a87697cc7236261bcebe7858428ea9b20634e1f0ea4c10cf25dedf332fddb3f1724", - "0a08eb27c2f0dea8e8cea4c73e1b0cfa04261a82dc2b30ed21fd65bc8e771e37d8d11bee8986ccc7f859512c37159bb293f6904d17e0c89e6c01d4bda8dd34d964", - "0b01286d200586d0b52d6d9d1acc9d69f8046287afa8c2141c18d6f92ac32f56c4164211b32ad4a1d14ec7056c8b5ca0af8130011f9b36b6ca2965cb83a2533b4a", - "0b069151919a874173d4bdd146055dd221b1bf826e8261baf4deb9339e127318affad9b61e635bccaa490154d3f038540dad3f22e0ce8a3a930ab16c99075184c0", - "0a0551819a0a7196761ebfacffc2b483131315a5611caddaa04c93a5f7ab39bd8e0944a5427d06c5639ff3343acf2ca4fccfbe0939ab0f79062f7f449156e96d4c", - "0a046c2a9e0993e0255e0851bac123ec457aa913bf9b38bd1521fe049e0c30d7a0d349073c841a3c04c73285460be5a7cbf71e33fcc5e8fb8b3fa4a0a7c6810211", - "0b065375846252e07a55b6fb791b65a5bfbe279d44bfdb2c73eeb62e6a09a4b8518d9c30de72166a753ebf7887658048af358161793bce09e516bae3b3fa1d9268", - "0a064089235f4674ea1a26c52118b01de76f9116131c49f67436dad443e3fc2e1366c08e8df7de1426d1043c697e1bfb1f58f5c52b8391fc1081a6ec3bef6e5af1", - "0a07048b9de0a6228f739b029f30c34a1919fe67b3e00f181a780bebb2350131ab0ae659f0fc2aa42aacf89bd273fbce3a7eb68eb1496e75184b05d0facf5c99d5", - "0a07cf61b885dddbb3c348d78e62ffb523c2de5383d2c0923bfc9f49cf5692cc54866b6ce14a363e2f2bfa4ea0d8579e442bf58b5d6273b465393aaae3da584c31", - "0a02a9071fc04a8afe56110fb881cad85848553c6205737575aaa0688e182e3ce23a15fba941ea14ad5984024b42e104eabcf8dd04328aca4e91cad9bcc663c04c", - "0b04ba42c88d36554206fc735e67233fabc558ecb29c4c25599df9fdbb54c20b4fa5066244e8d92fa56bfba39a31d58977d1f6bf4a9b32013f400a67960c0f650e", - "0a02dd2403199174ee4830a97dc4d120eacc5f456852e5b33e76638c7db5226d34d9b4d3c335a74cf161f1f06fbb60d45252eedd043ad91e3f920567b8699b4a45", - "0a06904601506d297a472f933d1e5327739ba2f9dfa1ff05327894aa12b545288d97fbded4aa47c59d9e42d10457a91c1ad668e0bf3b4533ebe2de82817c12a338", - "0b00d6bf6573e4cde5e7724d58de7bcad0b6039fc7f47888167684ec022d66f5c7a0f8bff1566f1f62ef876d9697f14061431804bf13db06461a93f97170eae15c", - "0a0487762bf72a0ba2f3900586d5ebddd8182f4f080093f3dc8c78ed2a8c5fdd6302a6c72511d079b0593035cf29c79c720032d92dcc001e15077cf9acd513994f", - "0b02b752e75099b9259f64f09ad03832f1f66d825242575af38ee689f8c2daa99da0d8775cd48614efc8b3e4627c19f0285d9d7b187503226da8991d76569650cc", - "0b04ac7698c793dcaa6ebd83f7965400a170ea319821b0510080699dea65e6ebe83318ddd13d0bd13254349134de6060bc94f5b5eb44a97a797f6d45514b2c2515", - "0b050639978b78642ef07dc6ed33c321c5a0bcc4e766a5331424a4216c798b9a3671b738625058aa2a3918ddea6eb3cd7ea1189303429c77fe10a1fe326912ba0a", - "0b009e2856f6f80f2a89027d0ebd6e7718465a9e5882fd8cd41df97d91f0623424d6e41eea783d77f63c460b48e76ac7a243bb7173878526fd9b9a39fe966740a3", - "0b00f24447f9bb0dc2d5def5bd30deb608d04c3ae274ea46e06553216a3b8688133c40ec10eb89633aac077fe4eab88ecf7f02cbcc6309798280ea795331abe35d", - "0a081f8b26cf258ed740044ab1186079748cba0b937a7205fac0b854171042763bb9587c21756b2814f2507587c85fc2693cd25cb2ad8f890b28d870efb06bc36d", - "0a068f3b43aa70c88472764d3a8c4d471480cc483f9e547a55a89ce45a4a5605d3fa1c5c87015883ca1b2105aaac330c52e7046db456d84e9bad0e5d37b826b094", - "0a05cb0eca69bec1302862ed58b7b95e806af0a2ef357e691d59564e3247a2dee88f2998a808a2399078ceaf719b1619c9854b5f60cdff5fb7d1d758f67c3abbc0", - "0a0426df1cbd4a893954060cb860363855e3061f6b97c4743eefc8e72b660cbbdd42b685f8fe6fbc75529f9e847213e74f2ed70c1bad9ae8683c2b90890aa39945", - "0a0691f97fde963f826b17bce7fb3d29e1dd1b25d498909bbf4c724f731d31063294a8a4f700cb1810d79dad04738439a6d81174351b6f2a586512873c91bf5ca9", - "0a0018df69bdef1cd8bc742446f15004dbf5bd362ba77f4c14ed1eafef19fb899c31410c9471ff1a1019d113ca171ce74932bd1275a7dd404215d6ca287a2ea69c", - "0a054bd5ac525ad91390e6efa058a4ae54fe3542c466f450846523e9e22a11598ee09bda98e0d6a113b7a30c6674db2f65a54cbad7fd0662df9ad0045486389ba2", - "0b057ad06bc7571e50fd39025d0aaea7be4a88167418e6589ab97d45607452773c6ca1d52664a8918234cad711536230c414d1636da9bae5631cef5d93c2a5876f", - "0a052d0556d4ecafc5557b19957db563b086b9fec46d7722d3dba2ff95babe69052e5908f1c20fa4b5a9e49f27a0b731939290879d530f0fe4b4d47d77a234aeaa", - "0a038593e9e3cad5929397d3b266ee75f36774ba08a0af0bb061a42d3c1508eddd4c59c672c60b065393e39fc86bedda103bedfc98b6a512cb34dc67a820fac0a2", - "0a02c4ab0cc8e3444743ffe860599bf781d84cf43697d3930560ddb5f92795325c6c5aaf0edd8e6bb8fe70a9f0cbe83be6433be0f7ed9ef93b8d1a313873f1126c", - "0b06a2811d8bfb94972a4cd4d32da1f2a0a10dd21e7c43399abcf14fd64125478da386f3b7dab8e3e91dd1fae0abd7a8182d0c905561f3a2e66fa089612a2043ac", - "0b0645b21f920cba197ee6160ed590a223eed276c7d6d9603cc11611d013aacce4402d959c7492fe1481f9735ba3eb3518ec5b014d52f2bebcced393f0b1c431e8", - "0a061b90594081cc8bc08830f63810a9e762677592d615fd85c5d22ca24c2631a35e330ecf30048891cf5ddb4ad07b752e411e5791e2b8b4f733be4f307bb1c519", - "0b016348fb18f06278b6e18cb85391ec17d2c78274a97354e4bd1a9e5a4448169a9790b70914172c81c4f156ed6177711104d16f2dd949f109af6bc147c4e52c56", - "0b005156451c5c73f5bfefe963fa3eefff87bf02e4f4bd591b49086c06fdf3f33d1719607a0d5339dc542e9b34b45db5b46d237d1e331f62b36d1be4d8afff5e38", - "0b0535969c1718dcefca361ce0ff14a92d54a966a28b82a4f55660a918ddfdc810c485e4c59e5889ce27359ed49638d25ec920e7b42586f1a820e0e2fb3a7eb41c", - "0a034499b843250613f48c78352e869e2e6ab3f5cd91b1131f81552b1888f0a25abf31b71cfcb751940cdc6397d1da06940446b305f507387a993811b8c2c24f13", - "0b009d232d9ca480993673fc89d91c900e9b2d34a41ac07ab909a683add912474f5201725d2293cb807b1fd89dbc33093468d5b33271804ef160844b3e7e9ce629", - "0b03320285640e0822b02b15cc1f41a84469f1c9efc3f2f946ad09bedfce0ac9ce7a57403a99dbc87286cc3978e2cfaa16cf3d3a421610b9f8f858f005a99f3d01", - "0a03bb07a0293f7a4e742ae558cd79ea06c51a956c3b838f2ffa4f12daea7b1e5b35f0e04709486ced177886e5ca53fabdbbed1a4b76f3aae1339291f12d1fc41a", - "0a0738085c90cb1be4e240391881beb9932c2f2cb39ba701d54fbde073abe38998c7d4378bd7b6f4ab486c0e2ab6d5766ce1fdce924d5b6e45f12ac0fee33084a6", - "0b0368993ba5ba0dd2cff979dc2108a55fe11234507c0562bce9ea9e39a9589577e705d3c4d9ef72daa44327d97b348dc44341b98b5c99bddc46dc06984e47c0ce", - "0a03c384d5586b4759d27e91c5089be4a7a3254bf5bb20206c08a928f5d55aac5d93f61a21ce0b9ee5718181210dbc7df3650a114abf35d9b23ab7e468bf8c00ed", - "0b01a425adb0c574ab331d2a98e8b0c96d693d8f5f627063aba6bcb649b1680e804998f20b13d50c05fdb57bf286f6fff6daca873de00b0063e8909cd0d2a80a1f", - "0b009c2fb07a0e74417298ec5fcb304b9d98742736eecd25c424524945a52ab434abd703248b8ea8aebfbfb550b632799dcdbb2212b81fd46705a03b71c0fb88ca", - "0b0445fb400ef59e80a78724ae86c180177807fcb99be6e490e1de72c15007caf02a241e24d763c1fa6efe9a45e0db1b652cb5e4eae6780f3d816002288f167bea", - "0b00fc80ee101fa8e8db6b20918cdc86a2994c5fa0bb9d64aa3f79853ee1b61bd7c836d33604f8f4a661ef08359557ae805b0d236e0451d18629017f5ce36addef", - "0a02f2a5dc052755d2461b2176abb177462d143b5ec975987d5a4dd4aceb68deab3ff839f4d77bc96e8e630056089bcf72531e415ff07e8f390d93e9e95847e486", - "0b0100e61007b6a3385cb85a3f14fd856c91cfc0e5c0fa250cb94d6235ad5e9bbe8bec1b866d56be63abf42f2f2b88f3c6b207dac979bc04e6f6c5737b69dc1c57", - "0b00a5075c3741799a2fca8e71839f16930d4d8f64ae33609871f451da84508e731e8903257dec14e8a417bf456f517b7628c57a0f573f11c88b3e9c93f34df552", - "0a051f9dc2bf4121f09d4b65a2d901479e9ab62d1bddc848eac07e4f9501f3f157c78c4b4950383380b70801fe2458c84091029a5370c19b96f39a9a7456f20f7a", - "0b0292a52709a91a95da8f40268c71f37c877ad64a9236353c559fb3b8bc24a2c286e57653d78e2a7241c427539b9248e7029657ac34fddb360dcbb17be0c0d70b", - "0a02be72d2197b7dc1b5bf92d4b4a53c888d294d9ce8ef8bbbb12fc9b0834118d1e40e67653a603541c55f8676f440e440a0933107712bd8eed833be9bc630bfa2", - "0b08223e947f93af541fe788e462eec44e4c779e2054ed18bd1d5c87201ede8982d67824dfc7e1cb6284d26acc391374b340e81a04ea3da3527a4c0580eae8e22d", - "0b0738c29fb8f5a87931bc0d3168c83aaab8f4ea5cb12217117ecfe6240ea9b2bbe9e51a320d9e7eee5f6009dff5c69dc7ab5a13a89841a107d006967ea92d9959", - "0b071064c6b4c8d9a04f20c0726357eb92faef7a31e010298bae06fe789c67f8225e889e0946ab3229dd154dc6cdaf50b7bbf6170a08a15bd4d68e8bf01cb9cbd2", - "0a00cf5f52cadab8240c1b99dfd280105ad04af47cf48bb84d20f963bcbca5c04c0dcd35a4af5d2d762ab624740fbcb978bb6fe1120429c16e6adc3587cf1c16d5", - "0a051a8ca23a1c3bce79502297379cffc0503f13f91db0c680f07b28563e8c0ed01004af205556124fd06d9cd4ab5a8a4915d59b8ce20ba71cee622599767f3f1f", - "0a06420b9dc8142c43a99e7cc236f6fce9ae8f41e43723b5d1869b75fe1cadb8cf9a4e2bf0729d053db966b4819ab2b56c2308b9ca13ad7c0e829db68dd990d34f", - "0a020633dbaab1c5f6cc4c800fe3795e5214345d29aeab5f7701d3610ca341708177a1aa65fd806b5811d7ba10e4d2a4a49c60c97a2f6b8281c1626983d4099920", - "0a040b79d5d11ca2c4542c8b76480baf3e937bf4916c253f0b74031740dbb40e64271ec4bebe4313cf6817c21604f706346a4a09a58d5deeb86733027990cee436", - "0b054074486ab3948d722c652f4f4d0bf194e18365be1ab75ae6371088349ceda732ff6160184a76886bbd9d7fccf928b04d12f1efa29fe8888da911707ccd2bd1", - "0a06035551a70541cf2350b6851142065dcf1319df2fae6cbc84a47edb0533c52e8b2de8a96bd8c3cdc947a731a20df948536972c777fd5670a179c65bcbc3bbe1", - "0b043c4e0443f6c297d65f057fb93f9bc97c4f58479efa6546b978f102e45b121a73329c174c775086c7f39da65ddaa8f1c496ecc6369b7070146c2a66e65c3af0", - "0b02fe8efc91f685fe509aca4a0d557460904f9d7ff9e4722e1df6bba5aed159388c7164bb2a946a27cb69033007c0d48bd270cc7c9e856d98813bc4d03d64ebc3", - "0b04894570d911417fcb3c0a307af86d68489c273d7b6ae7bcdb0bde6219797e94c6d1234f87846aa27d281e5ad05154ffc371c57725f191127419344bb857b786", - "0a08d8a5824546bedbb38313368add7462e20fc1b3e0b64acf81a4e68499eda01d5d7a771a45824b03cb19038061871845559d80cb748196312b0f344b46a750af", - "0a038bea6aeaba791e051002121d74cd0bd15fca81c53f9ab1acfbe255930ee5e008db52ca73df1016c2ae3629d8a93e980ce2a8af749ef63bc48aa5903d595d78", - "0b009818308b6b250802e37530c2b201aed12800e4914dd3ae23cf943e5012d60f7bfefd0b0ea6ee08bbf61e6a659c4a2f7cf3c1cdf69bdfb240c117f1dd054a64", - "0a01195ca122ba98cbc7021ed1b901d569ec2eaabf0c692ddfb9eb365464e430e87674d140c9b8000b256f79e690b46682721f6e0617a589259e50f0822510e303", - "0b05eb130493d762ea70417438da674d08a66063f3609ed0ab0d16711b872e5ae3a6fa2e710b162ddbca2c30fdd45b3824c19c15a3c921c0fa772b4c4c885a9ce0", - "0a07baba0e0be4733ae1cf75ac17082c1d6ba8babf8ba7169050af8eea4adc2e1de767c4ae25b404eb423071a8a2cb0f11e755bff78b04dade43ff834c60317aaa", - "0a05a1f80c272fb517e7541de0d038a90bcc9885185e711c96aad78d896ea365c5de847757e9b5a65038f1df3d2b7dfaf0265a81b4ec0dd87db7eb55accdcda033", - "0a085f0a41982e9a6fde325b422adcefbc05a5f2ee4888a8dedfaef462e3bbb31da7f1178a4c3bb7ffae5b136d9daf8fe35bd4b664d76b1bafec907b9915d9caeb", - "0a04988ba7baa4de66bc021e61daeb8c150ec957cbbf43e40c6dc45b8be0a4817f47ac8f7fac59908a0bebbaf7895a636a947132cc9f9d2a9f1a5759528435c08e", - "0a01dc8509eceaa8e185e6651f7f4b9fa5564ba001c3bfb69ef5c15046cb0af7f864508e3292e8690ca25876e324616c17c6f850f12a24886966a4d270e8b7a7cd", - "0a0334c53bc24d38e3f78930d923526c25a72a6d684f2767b3e1bdc513844d733737c9dde23491320b5ef318153c49810bac83dbf2a201ee9e50bb62ac135e0c3b", - "0b008ff7541bac9765818a625404f8fee78db59936ebda5e1710794aa27654e898ca74acc5657f558bfa19efbdde410cafa337fef5d3f4e7dc14cc67f3c146e1ef", - "0a04cd0440a500f1b77d968d10cc6962d06affbe9f86440fab2bd4818b80b01e03e4cc810fd59a7427681f00c6d68210ff90df06d2450c1086234159f13c6a0ecf", - "0a00b32b39df3b66bd1951beb305bb1680e7334937d1d961afa08a670d7d4fecf120da7a870a2ddf2312c16340eb90ab5ff1e14b02d432d365556316ade2ee90ea", - "0b07def458469cc7e043129ca019cbbe3c82f5822d35fede3d9ac42ca6cb43ecb0b6b565a95a826ff7d795c73c9f4afaeea371f9cc2523a24dd5190a811ad40cca", - "0a07e6ee5df8885df3b17baaeda3791d867d2516e58f5c28be94c0bdc81d1c1620504b1635aa4e35a9d95ee1ab289be5c42acf80130c8a12d2feb64224d24723fe", - "0b05c6d233ac0519308f5373f0209bdfacf0b4870dc9655d9b043bbfd59608ebf9d7f7302a8c131c17e0b99c05b200871c71b735f6de9ab7a9d0bbe2b134b29cca", - "0a06eb4c65488e012f06828be7f706bf82dd5747505905762e9922f15436f003c177f434ae88b8f951678a151de09c9d980061d0ccd0e05c0c7dcf8fdb0e8b5123", - "0a03add61ccb66cfa76680388ed907460f1e9833737de6f8063f8f38fab80678b5ebe82a7291f0f4dbcc5d590f4ab86295bd186df3ffae1248d7b0629a1dfddecf", - "0b087e0d8ab719b3a77947a89a704da4367285ebc6c492a9fae7ab236cee64c941017b6a302ae964a5cc79bc0737911066bf618de170575df4f8c627819761a177", - "0b0177f36cc6cb2d13e159cc3da75074ade6323eb9e3cd48b505a72dfdfe45b032369a87111593d7496edefe53ed60e0775cf94bb2c6b1d4b28b20b010cb270b36", - "0b062e53ed7891c9606db495bd94e86b9e7519c80383b1fca05d5d8f2f74cbb9cc225eb2613e4987df56554c114cbc1b0c6239f8f4c98988df91c372bcc7483fd2", - "0b02ee3bc15e1f6c6b419f7c91d3b4a153156052d36781b85a17cba47323ba4d71b952d4b21b35f9a438e3878dd3ac77bffde28262754df3f4c776feeb380517e5", - "0a081737a28224837d8d64c138701a4117a700d2d8030c98ccc3a91ad6f4c13d504a17b965436851f1ec5d39530471e5ba13d2e0780da4077d4c9360cf15222f5a", - "0a0761e0aa01f6f342488f2bedebdfa544793ba2ef84d58ef92bdceb5eba91a4f35dbe4e7f0c27e226ffcefcfd3b5418782a53ca480817f31dc7e304f9886bec1a", - "0b03daacac63e69dc6bf0456d9281b7f4bff307e391f0939570afab64b78ab4443dce8d7b9bc0cbf1f2173e13060d9d40ed64eb2a05d68587ea6e6d7ac954aa155", - "0a045fb07c7895eac867b994efd053a15d81e94277b5bc73270179016e95ccfd10d7933ead29af0493c3a088d2786c40ee0d9aa7ef0c642ea4e534b2ca2d545881", - "0b024c05df68a28e057757650ed1cf036f1ab9a36567e199b99d267b3ae06c2c308b371eec5b395a4c3e92af2db48778da031d7acd025fc836c183bcb3445c6069", - "0a033ea1372bb17ff4729352980fec9b05ddadb29afcec9a20414766567e581b684534ac6cef221003aa4670b241f7a25e2fa993f7dd40dd792efffbc33a9ff3b4", - "0b03909d3d8e0b87d3f5a517a87e6847f3d53284ca88610f6961b88b5defb63e6b3457907341a88a0511b7c9785bcfc38012f48461d3e6756c9fecfaa541c2146e", - "0b0531172a2f51d9ea82f3e7571fb6ae351ac3947bb0d4905a9b69dd3770d551b2f0424d8f650bfb7de9110913ab3142228a5886b02682ce08178d5282dbb43119", - "0b025d6d28d868c5651adddf0fc29df3def989d3aa40e78f7e7c6674aec984798044c1a0b3c7ee8f4c0f8b175a5d132468e356e6ea71faeb35df19ae999980bbd7", - "0a0322ad2926425dcf831425a2cb6852b8d68f3d87b6a9cd9dcc5c907e33daa62459b8c166e493ca9eb49a877e2dbf28d379280a2b3ba6e5ab3d447d8b959c7d4f", - "0b028346d28160f5d6e2ba4ad86d0110861fef3241bc63638f4373c64a1b37ac8e963d017da191f3574a80d386f3e1900e669afc2cc684e29a2f0b0c95890bee08", - "0a01508a3281b1dd6cabebb79f26eff61d0c49cdadbd7aa05fdcb9872038796183a5404474ba2856d07db487bee256cbe37258d26a12b503c0a76db165590dbab8", - "0a01f4dfcb157fc1b5fb08bdeeebfc222b08315330aa34f99a5f740da4825180269828165f4c7afa7cebb5d09eaf65e1facef2e6dae01283628f8f8a47e0a8f003", - "0b077326f2ceb9fda07b4b3f2f50b596b8f78672294588364690d1130358fc36310eb56e331ddcb34cdfa0f79dc4094bfed6dcfb11411628e199153eb3298b8e20", - "0b04788118c6ec6173cdbaa7149d9cf7bb092a24ba17e09f905c7e15269a74ccb1ff80493cfaafafe8d760363f93716855ea812612dc0856ac723e67c6ce685a9d", - "0a048ffbc116c6ba96c071becae674318647155e2851cdcb49d2b3562a4c9fa65bdd7e6b017656f387a1973a4887a915faf8f3a62e16e27f46bbf858ddba27fdf7", - "0a076d9f77a9ac58c3df8744a556c34dc5b10ef1ecf5838ba19b5a1939f1b07ee3fd1e3419b116d3714bbe6bf9ce1effa3237f0e8bc961c42a75d19f6c452bff34", - "0a02e4143dca99b21474837b7840ebe7e848dcdbc495e6072649f28236509e0220c8fdda2a6a1b3afcb7ffb50f394ec5bbed6499f276d96fb29620a968e3bcfeb9", - "0b026df6b8a773bfc129fd1e8ba19a004611005d0c53b3db33c33d9dfea89adea91b71da5f32b335c26df2dc254b4239b381429988f4da4666c660b80f590cac16", - "0b06687a70ee7414e757834ea62405a53ffbc27bca104062f8a7c2db6ddecc0733cb8b2c45cdb60ef06ab6327ea43590eb009abc598aa79af9dd82c9257cab35f6", - "0a04ec110852ad0b2e1f3c3c717176899fa992d1a5ae0ff01896c6e9830c7ea04079a3eb60d1890ccf90862642152b9f641ea5b84c19c7be27f2a768e24cb6047d", - "0a02435ab5b486f6557e314f63bf4ab8e2e0b449814f4dfcfd80a1f2f8d011f10032ca790e2fcf7565e77181066a407d398b9cea47e854d5b2179874bd0279b6db", - "0a08e7a12a6d503b44c2ce37ec123b6402826afce48706df5a539db6189bcdac52c15688a5d2e6f7b19598cfc66e0087479c6d82954b27789237ea37a32a361884", - "0a021b1d1f81e215e54ba03d399742fd048ec963be48e87bb8c5f597140621cec89495eb71dfb594d95cc34ff8a6aa38782894026059e0b4113a056ef73004f2c5", - "0b04e6965f0cf965cfd8022e6ac8dc582bef6c24db2b94b8a35956ce04580346926ab2c748ff49139b1ac228876bd57b8c7576344242732084aa719ecc8c097d53", - "0b05819f832d063337866ecf1f89a761d66071f3500394a59fcafb1a8ff204c3fddafa15e8b5af414e7afb0724919bdc6c8db4de872350955ff2294f78606c60b0", - "0b03b9f46f91b129de470b87c93d1f60b157bef1c48f7f3fec7ed3313d21bb4d4b7e31912cc2438e47b94a804acc9e0fedccf79cce076c62189a05a372278ff018", - "0b014377d029775d0abe3e551e746f5f61bd98b50d9b26091fa143ada620b5265149fdadeaeccb0c6049360046609855792b046f2023c29d28baa16f3d1a534758", - "0b04802551002d0cd1caf8b8e59d34afecf65e47df7eb5cca38f5ff0618e33790e40d67af94b7a9b670a797f107cdb899cdef1645a217e9a110253f529278e574e", - "0b061945b391944017a9842d95ca4e052eaec7e1e19895a8a7481e64340dd4d6e60b954b2dcf9fc8e7e327d315336a75b0646f72db83c4e4431c542fd75190d4b6", - "0b02172dd98315f4a0f107d87618b644e9f1c432f55a36a3d2dba88438718dd8a9e3e79f0a74d48e6e6c52ec3119e403d83ca4766d129cf4363a50d899b8778ba4", - "0b05c610b883b61d07f3aed7ad49d03e387e67fca862b0b5911bcb40393fcbecb6f2946cacda5eafef5d5d3e052dbfe95dc2d2e98916773610fe312b7cae467a82", - "0b069603df985067cc3ab8ea4ed3485384b14ec64ff0260d26e1338599cf9201ac804fb9bd4b77b6ab0e28935a31cf1c77593750c6665b1867077acebbe20d0ed7", - "0a01ab2acaa290360ca9d0c36715c2e42acf9a6e7e9c3ceb77578d4452a26889f51c64b9e60cd645d06726e3e1de525acacbd2fa121be78abdb1fdad707d07a51b", - "0b01a4ad5352c81613f1c2ab7a441a790c371caf944eaa1184f6051a9039780cacb74d6e83252b2a60ffba5b9d1b6957aa4e0f01babd60dcd0a80c51b5b9fe1ef3", - "0a090b02cc3f45cd63862063889bc2487b8bfe9b5ec0e18127a6522f3f33ffa52c0cb689be18270056bf72fd5fbc2e36df327c67f853b0dc678926d213e3916bf8", - "0b03912a02b7cafb5e55696d51771f2af8d56c27ba358ae9cb9041144d6efe1b53baaf9e8cdd4eeff42d7e236465d1f68cb3313ca99f6ab8f572ba0187feced581", - "0a056b35412b31f71dad86638216736d0b702432de13f5e22cf0b0f827bb13649108f08addc15b0d470ee9a82d1d97a207650c6f9010ec022fb5b5a2cb0a14d11c", - "0b0300aaf04230c1d6f710fa62ab9091c6dd3663c4ce99f881a1f94a40110b2b5164c02700cb4f3d67089f1e28594c4bbc6e60360d599b3e429beb3596800f56f1", - "0b086fc13acc0f097a27cacab9ea7bc485036d8a9bf7c265e9a5261606d76aa9531a7e93ba682fd537138d9bac82386aeadd09a99b8c31e68fda7dc7eced88267a", - "0a00255cab69c8c6375bb7bf0742849895fd8b7c9b17a7fac1618d7403ea69855a22ec1a73d0e62f46b913a0f5ad12a1f926e6a9634edb4b51a395fc1d6335cfd7", - "0a060b45afb36917d179468f19c1c539646150f1bb20bcd5a4f03ee06aa98e76d6dcdd811725df517f4d7721eef95444009f2ac81bb6afd9fe89af7ac2f6a1a838", - "0b06fbec9d84a169612c178d5dd2d0d73cc277ccbb9e6b1f60e6538a8d7135bedb14839450b929b4fc23e7dc0406efbb46448e23c98b365e151ba991069cd07b9d", - "0a081e52b4d42bc0df6691dab1a1d67b4af6be28f5d455eb079f03b07b142d506a161c58470585f347df6822041d38fcba2f23870ea63cb49609fc0fe506ecb760", - "0a05091a5bbe0bb23ab916355ce11f485ceaa5692b1e937b17cb293d8f34061003cb01612c1eab8cc8bea2737c372226ccf241374d7b214a8a6b0b54571a78ce57", - "0b045d615bc2b495080df03893adfa988af84a618ecd15059a1eb1a692241d819562b5bf268d715a5ed0f4cc0fb59da720818c8ede282008bfaccdbe187a7fa637", - "0a039bdd9e43b70dcf01a66c0f44eb19594c8055bd81c43cd86d2d1301df5a5c477ae5aa103d8c41fd6197a135834c8f3fa269a8e4436bfa53d456ddb03a8f37f0", - "0a04fb0cb246f974f5d5d7c90ebd1b04605a00a0310429bc334ad473e462d2dd6d754249b0fa7849153fa12725f8566167b023408f34e3da39d0ab12472b95c997", - "0a0439348fbcb8b0b67174c845a1868ff373a7539afb656dcd6a3115c3ee35c5acb084a9c8ff3fff8646f62cdb1c675a35030a7ba85330e687447c1f254b471471", - "0a08e469df5fdf082d45f126b94c66ab2469c870b836e0a338d817667422f03b793eb391f6ca23e33a51fe8368bee8fe466582ba636a0d873ab08eed1216155ab3", - "0b064a1384385b328d4eec593860a35600d06acd8920ed3843a8d1a05d7fdd404ee0cb4b9c09e5fe6e8c44744057fcc5eb2886fb3505acd8daaaffbe87ed04334b", - "0a03f7e3e4c5f0a20f4460f7fc3ff91589f52a890bebd48a95398bf1984d09b5fa35299e2a94e4e4d50361277b0333951567e0949d983ff03673a54439e456fd1e", - "0a04a0b8e2f057c3173e3e55401a16031d6c94332800365129fadc34d6104237ceff56b423f21bcda3e40ac0c615e2e74b17f5688031d41fbbf2c57ada27278a7d", - "0a003dd71dc60d14e269f35081f9f79fdc1d9466dbf73032c9965702f6150639fb31a86e5f2568efc475e1a9947b6a2b01e69f586462cdc9781da5272b024eccd9", - "0b004b81f80a90b01098486a7079ad710ac69e672860b5424528856eadf9db93dc8f8dba8602b9086e4a7f79814523a51c103d411fed98a7a6407f010cd10ccc92", - "0b0628876475280f2c9e77e7cc23b1ceb320e81a2661bd775ec0d5a2c584cc9405e12876c9d1aef507daed3c25acbacf07d3ed9e28cd02e84c371c4cae708c7a8b", - "0b056503eeda460087372e4a53a1d4ce2af254fc3278667d2b655638ce7eb02cb55f1fd33028359d33e7b77a174033d4a45766f25d8caeb7be0d730ecf01c20b81", - "0b006a3a5c041e5ef3027061cefaecaabff200b83c47570a7ed203ce628c3b9844ecc545a28be69f0e8b17d9c9c83017157919edf2d36a53df5301b9fb4a48cd1f", - "0b0239e34d2263c7e5f01694a1842e39cc780a2bce3adc24fe5a35fa091a392d9284c9da2df3461cbda825b588f21f310854187141d6995833ef8446a70ebe3739", - "0a017207bc70a8b81488c01a80b67329496551013492784c59bb12db082d449db25b1ecd3bd4306eda99ca4b6fca5331d30bdea9a346fdceb2bd51c791685f4e80", - "0b0141e579a8e6853d7bd5570fa0f4596ebfb5f4079d70eacaae92e6eb0d7558d89791c535525b20d2542a9f00762b5e51e26bc2d03d5a2b04db6d41b561dfbc74", - "0b039cf81c38ce451127b2dd3bc0ecfbfd13ffcef25aca2edcb1c90d76d0f0836606656497a39e7754a75fb86d55c173e1448f9516064dcbeed73a738a3645a10b", - "0b082cac05785e97c325661a032f55c5dba7dd83233363017652b435c2047a9fa06b3c300e44e116d0388db20c62a7ae3fcff6dd7e191ecad4e6c7b8e9db9b3fcb", - "0a072402416d9c5d7930d0b648cedf728fbdf25a94e9f7e2b7ec7c9843619aefb70be09d85f0542a0f87b9800578dc1c9db944e7e590557f85175a673c17a19ab6", - "0b0538bd6cac9e7413ae5239460d2c686e113971089211e6620cb81ee670b2bd365f371beb160f0664023a5e2220ce196eec32d061064f83883f7b3fbefcd9c989", - "0a051ebec9c983a443eb5ae91d94c8dc6ec1fae12b05327f135dec5bb24a8843bcbf4e121d6cd5ff1af8e76c17bb5f596adb7948ed9a12a6c5641cf5c23ac65e90", - "0b0041bd222114a0b596c80ea3ccda0a9568b96a2fcdd89bfd44ef3edcb9836f2f286dfcbe82616edbabbe7254fb024bcb12aee042545af52a3dddef8a7635e982", - "0a0123dc9ccbcd7ccd1c44e66b440a96feb6f999b65a0b2f704c9011bb9c05f4e2d5b3327bbf805039ba4a4536ccb9304dd36d17fd83005097f7fd9df2fe88bc33", - "0a05ed68d3324842732dbc5c9f4b3f02bafc7c881b6155168126961cec3f39b999a98e7cd4b3ff278fb6ef3a775dff23eaf130b11b15a75d0464b636d9aa801690", - "0a075584be1e5df1146a49af73d260ed536f8ba62bbddebac5305b6b5c533a84d47c723ed32a5a7b8e40951b0ec7d136586ac00c435b61cba100131f6d85b46060", - "0b05ae35b7ed508efa374c604b070e2bbb23a9f649c1258933bc0521d7ae5e9638ddd6726b31f19ff2f675ec7c68a5a0b34f3a6586eb587c114aff7635222675ab", - "0a0911a32c71889b043d1d8ae5c7369e473b6793f28ad5500f1fbf9b1906c8757d2a2e327e214c124d5a7f0b9c349724e70a302cb663f4e6c75751661097e2ee95", - "0a06ff4a99797c9b965d66531a5de3b12b518061e0cfcd36ea66395bd2b385149abd02c7867bc0a40cdcc73973aef6cade95ad36b6c21a3dbf1bc3be2ae02abcdd", - "0a033ea1cccd5e3011cab5529496026b119f55c8ec1b96ac8801eb5e81e38c6de3aa93d892a57c592ce20478e26138cfd31417f8587a5e7d001d061c2d959591db", - "0b0090b9d47fc9f8aaec5556b16076db939adf87498b02c102f8ffa0bd438f3f03cb080a5c1dc7704732e3817fbaeab1fdaf393f79c7251c9f0b7602511eb4aa09", - "0b0551c07ff014837ad425aa01693875af9ae891733ac507af04beadf3d7eeeee3693957ec1b5fb93b17d2a86a491741c15863a441177a6ee3b6d7445a0c51c2e5", - "0a01e7e317d7d456f5b2070249fd245bf5ab4a37ca07470148634be49dd3815870ce09f3c24b5fa89178fa07a01375990ff50fce5413ea53b42985cc85444f22bc", - "0b0525a265f353bdc666e5ab48e8d8ca8dc1936188a06310943ad170d17c25f1ceda1da820a7acf3de7ed6f51184690e1cd636c0621798f62306eec4e8d1a6807b", - "0a0750279227db83ae5b689e3dfcfedc880121cd9129e49058cfb6b5ffb91539ad03d3230e6d38af4c9a0b9623497c9c106ed0552d9bfea3ce7e82c9da4e6c8d1e", - "0b06df8305f5b1ee7f05aa8650779b691941352476b40f50a73934cd939483212f9fdb5bca1f05b0250bd8c04b4f111678553afa9dfe6326d656bc2f78198618a8", - "0a08b1b07b22495e88ed264242f51f485dacfb4d93997b16cb54a2834a440c03352784301341dc3295f498e5ae1c222f771cb183df7748177d849d4655618763f3", - "0b0136c50744258d6cc7e99bbddf5853ac2afa7246fdda6158efb8c33aa152613508ca52d9a5850c714b8818b5623c258cec61e8ddf06381320f9394255437150c", - "0a08b0b512f921da68d79a5392911193b4b7cd796e31d4aa04ae1a3c3c64e89ff61be7a013098c856e65ab5a55257c029e872a9338576dd910cdd4468b3bda6db9", - "0b0682faf2b1334e554ac233be12636e03fec4320ee7a63656a5ca701c281b88815683d54ac1b90eef8b10856991b2801908fa265c26195bbb027105744fd7a234", - "0a02925292edec024f43c9f4a69e08b6f5eb2b6ac3ae3eb1ef8c2d3e6f08e5f99d3f6bdc3302d50c8e83d673c6d28029abd395f40af578b7710070309034ebeff2", - "0a06b7133e93b14a8db15bedceb2382a2556a851b1493e1afa8be56402ce2f2d2cf4540d3df56a7007232146a16e1aa4378486447b346b5e39d1aa47c7878ef313", - "0a04f5c2aaf9353c63c89a69164a51e2dd43f75218ef4c5073dcdc92b84ae9cf3e9d919f6f38cfd0347b912dca2b78f3215f25486a8f9b3bc00b1c1a86ee603de4", - "0a01bb981ef671fdefb5a940bc35223e4506b7d3e091ebcb38b5e77e0246d4a609c4e6ac9f32131a4b335039a365dd597b89c7b83dd346db49ca58b0e09b7192ed", - "0a02a2b9688d8d4546b247c5627a205f0e485eb4d5c4b99ae115826db400d7c789446ad3abdb2565873cb56136d4ea894415e592cf0d9784bf7c884f565fdffd82", - "0b02f9c103c1c5d79d1adf4197d8184e769f20e66ac06ebb87730c9887faa8e50cbb63f01754b5917bdd70ed1fc1729171f7c1ba632cc87aefc8d30af5aed5645e", - "0b00c67ebb09f7f5338836a10649866401f45fd4afc37818b8124508416bd7ceb80fe592e528f22fbd51b69caae04dadb24b8cbb484f313cc813936337d551798f", - "0b00d15959fd772c66ad1e6372d3560490f7adef5e40f53790f0b7ce0ae926f3d49eb431470688806753a5e96141b89008b6283ef7fce9f77441a55136edb13e23", - "0b00df90b066552945be1af39e4e560641db2e9384498e66961ddae63523aefafa90a0c0ff7a1efc79fd9ef046c7eae16823cf5951659d44fdca79aae99bcfa8ca", - "0b04370cd903a48fc68ce26a3bd3db7fa5f7950ad3c17bd5e671c019121ddb36932bb9e741e76d016f69c30908a34eecd23e4b646dc8a6d221a6ef7941ccb8a3e5", - "0b065db464e340146963830e796ea6656eef8c7e9fff63de12aa477dbf5d9e7875ee085777c154ab73adc8ac78844685cff4a1f45f013872f7868734615eb8ef4b", - "0a020bfc69880e5051307c6471aebb564f9a8067b095878344abb11037e454938f47f581e68c6517d616e953e5f30730315660f724c4bfadc7680ba9ff0e430928", - "0b01cec6076679cd5422b712ac99ec3483ff1e2911ca783e034e343e50034a9a5243f510f33cc604184908b563efe864a134144ccbf99616381514c33ccf00ad85", - "0a030a23dd2f1c9d933c31ddfbccb948412b8203a955a6833be8241ca90898f934740c00127f2a1c2dd5ebb0a5ea2eb93f5b588ac88ca9a024dd77c939f21a0b45", - "0b026408f990c1d6851ab5ae0278dabb29c21e07ca747f615a1946546df2c61a1515b4322d75413c885fdfec39a33d7467adb78762a68b1b4753926d9cdabc9009", - "0a006bd4805c840310cfd6bd27bc1aacca100bb694724f9093df9fc21a22781239556dfb6710994b5338787e1f84a188f976168213d727221f83875a3c0dac6309", - "0a0163ec21fb2822e633eba3fa1f826c1508b523b5d4e9b4430004cb30d21e48b0ed3e2ab4a7cf9a4306f9d6b02dec8aa9555cf7d5aa7447974603beac8909d3a6", - "0a05965d7cf37caf341c2faa85810c1f76bdbda29d3e68bcedd76f13e62d66122bf870f8be8b719132ce89e04dae676df985a8e96e6e517236db6d284a6d0de0a3", - "0b05e489239b3815d5ef8932bad26fac25439d3994cd1027107e08a9749eb65627e1f7f977b8bdcac2ba7ccf73733bfbca48ef1494890d6e5c1f06682a80ed7769", - "0b084ece5c21bbc8cf029a95b61bdbf487059cf4a025275b5ee5d1015456f270b5791169aafeebee4413ae182c2c2e916c08815cd050d3bce8e1d1d85818d11e0f", - "0b02c322530a7f62bcf50c219b53422bfdb517714d541a1588b5e38344f734efabd3ca2ca30153b549a0b315ce4b94b4ba04aac0deebf57832edfad022ebf419a9", - "0b020ecde8b0c6a0a9a447c6cb616e27f6d8daaa6475b0105a0362f4667b6e77c12d0b5d30f66da719276b55d0af1e35ad1e693846a12c40c161265150c6da19df", - "0a03182aa6814356bb57cc12909c86b1df9cabdf4eb94299ed0e630d1c8da741e1bf6b7d5c85a24a7daa911cc84e76f5119b18991c17f3d459bfcdf11e4762714c", - "0a0441d58b30f296552c572b382b02444fd2745bf34e4130a2677038e3a472c75130c61d4aeae1b593b4188dfbab924e5489c8535e361dcf0db51a3f23452e52cf", - "0a08657fcaca239c5bea487a1fc02a47bffe89e2c428ab2de2b57207bf82b68c8c1934a263d53e590f06d3102de7a5d1a078dbf6a27ef584f57de2944d7a4ed6fc", - "0b030598c8a15026a723db08d2d926e62e9a57b4516b833fbaabca6d01d9b837cda606c0d4cc5a700346e6c3ea0945d4867deb8472693420c0819da79edf89c6e3", - "0a024a1f470fdc8799d9436590508f88aff15b260bff8640237a73ffc3628a4de4f0f8761d06da099c2d9acc1bb282038ff2c0b0bd0cbe358f2ad50382fbbfb8ea", - "0b08cdcfc5cb2f34d767c59aa116779908cefa5d11528b981410e9c58f01a5101f45cc572fba047a66b7be63f700a88135697d28f1d14787504d6ed8c609506b04", - "0a01e4bb56fa0324114a555849a1d281d2e4e97df93ddfef3bdc31807ce3620397e4b2c847b0f9fa789f29b278a8d4f74bb1b2a8bfbd2803c175a1541975268df6", - "0b02da561f5d2a0eca2a17993d626179716d9d87a2f8ddf6f729eb2dafbdc0ab4917df5395b24243221a58ec6d958a5d822cf9a495016ace113a11693c6758a4fb", - "0a04103c1b5655c0177e045cd4eadd55a90f354630889d48f59fd129c7a7a3df5b6ceed2a60338a4326e45be63a5706477d2b78335ae2353399722c97effad57d3", - "0a0088514d102dd923c05da9dcf05fc9ca15f2fed63e24f90391cf5cada0195b79573e35c8e6769ed3db8468d1f585cdb8ef6a8ec7dcd6c9fc699fd8484e2cbf97", - "0a09233e3576658b036b724c2c637b8cc72e146fbcc3073e7debd7570cec1d4e89968f2340f72d598f8d7095eb7c7e37702569aa63d4dca3e622feb6be492981f5", - "0b081af399d005f6421b38e3df6c938144a7605339741949bcb6952c556085c3639166c2ee8258532e640fb6a39dff55a1785b0c49bc867faffbce116fe38428a5", - "0a07b3703e6d6418eb85be18fa2ef819d59f8235ba6988a319f06b69b2c13946a5dc44997e7bf491efc9d3bde19334dc533a5782765bc726dd4fe9fe20fe4da7c7", - "0b03b72f90da50530857d12fd42e9f05f48bd82068ee64df11e03485b7d57396a96428d6553a129a8db1446811db978deecacbe4fd656a92b3f7105e33d4833060", - "0b066a22579b6eb237e729b2ae71ba19aefe4e3b53503da04943a23cb6589163c9bf7e26b301a9d0a65291d36f09102e244fe3e9f6cac0ce64acdec709825df31d", - "0a013a69fe492abe260ef35e6f23956286c7334cbe5988bd4f08c471492f5e9154f300573381066d658e955cc8e647dbe03e246d4128433f76eeb9111adef56613", - "0a078cb0434565b9b3313c3f831b59a91fdcc225ad36d3eac02847f47cb174bb012949f14944e49142afb7608494bb178ba133cd57e4663a015f190cdcec5fe5e5", - "0a06e11f2bef43716d268be53c2d1a86615e2d1f232505aa1fe08d063bce7bb5ec16c7ca6670fb6743c83b573f338b71563a840f4d2a28a4538e4d61eaf9533457", - "0a028837383c1ebfa6589da16a45637c4103a90016854e4a5851567faba0bd6090594e6894072eeefdd609e6565ba0fb0d512e4ddae468a12dd7b12f2b693cd8d4", - "0b04b740e225f82fb62ca4401c10fa1f26689f3c75e7e4d574c3e8f98707350a70ba99eb37dfab2979d447cc5347a5526ba2118632975954f0746c4de82b996e56", - "0b0733a027d353f6f809873e874574ceb8bb949ed5cae4da1526162e1596fc5e1652235ce569e0b1d4792bf3f509049e7277e5254cb8793222e26b77d44665813b", - "0a0762d8cdd176aede1f1f70c2ffff0f059ddb5021ff51c51a4191afed2f0b1ce7c2dd78c4aa7322ae3f766f69f4bae9ec08e0d9bd6468502fcd0f8e2ee9050f50", - "0b04eb4d1dd78a493e3f7cebadf1f21a46b3e2cd75f6b0df21d10a7262a33701a4587d48e7823e2bd11a2de8d20c05e5e81de262caed8a2644f1ddda0ba7462230", - "0b051700e75cf62c00bec8a170cc3922415a65e454ebff693b599122b54b158bd7fd3c9b35db6e42549454420115e001a0e62db75e4b61566d10e34ae5738e03db", - "0a0259c95ecbfa498a57e12ed8589292abf7434fefa5a69f0c00d89099872061756089db8c17e5c63403d2fe4bd69c40d6ca7adc7812839b0fbaee2760abeab412", - "0b07bdcb3b97174e3fad15de818213855a86a27d3b2dc4abe35216ec760fb99fcde59abfe6cca2f57afc8974b2a90e8eed393417c2adcc34bad0c57b86a0b2a2ab", - "0a0158e2d8a6cf059cc574aa690287da6c4c68e0ae181602f7d9f4fd1d9b57a04575e9acb11923f40eed0dcbd59b7f13a1a778ecc9c60faf6c90dc2b54cea11df7", - "0b037d98896e6f016a6ed796b58ed5bf3c4213857cf73acbb29f54900bb53371bcd6f78fedf23564c4e1367a5b997cababdec99906e9a6d73d8a618b1fec698718", - "0a07ed7522b8eacf21c49097f8c145ade0a7bd2ed08d4d84d99beccae6f0520afbd17296348d94d51d94fee5a2bd69a715297f05aa5111f93f7847c16501b88eae", - "0a0671234005cacdbf94f18b527abdcc55f31b45b90b48bbbd5a7b623d412a5ada7b5aec1632185866ca3afa6683932bb6e20598cfa5922d48cf49c00030851cdc", - "0a04f54278dc69443b05861c7858dd0440c4aae0a778e7aeeb67fb7d69e2166c0bd3e2fe4d3e34eb3d3e016ca709e59f11064931b3e4b24145c1bdbbea3e6fa7cf", - "0b0866fba8e44d0f57df0a8d9f5f95b3dc4765f9ceb58f4e5f64f1d7746e641ce8ad16cad339dafaab579bd44d98c3ea623324cb7057c848795dfc070245e3b9e9", - "0a04fe43bc3a086e91d73cb1ca4fcb85bec2c13bb27a31b7e609e06f3505f73db3344ad796effe8048139964dd9e986da2d5ec83fc76e47f2d5e36503f80df3395", - "0a04f255ff4024c32f7331f218ed299b0998322cd091e0b102a2da4b6e9eb63cbbdf588179346b16044d268f6ca17d09bb46a6f150525a00cccd41fae555e2447f", - "0a04c73c13d719d1c705912ba64fee5f97fc6787cb977f431089d3389a81a8f9be583b4647a86f2a9a2acc0f8e4d8f29bd6dd7f4d1ade4126b1b65c5ba60a098bd", - "0b05e59374d365dea5c2c98bddeff89e578c55dc90241490601cc9804284ea17c50ee1a787787669152cb559ec448bf9d10b70df2503e8d101ec597bd2f741a7ca", - "0a067b7b34f24f846d300b79310c7909c6ae3109a57bd64c36b83342c80b1ef7375d93d2d2985ccac9abdbd4f96dd6823de97668b775e7dbf1d056f5695e446902", - "0b02567c04e1a8e382629860059038bf93dc2d679f32a9e963853865de878355067b2a4ff7514baf95d0b1d1acbe7e2c8ae72fc9e9e3ddfe32eb36ceea8fcbb052", - "0a0176d65a72c35609f0eca2bab8687ab545a0ef361fde922110daa2450a66fa28a7f7a1d903ce7dbaa650c58c47d70707122803b43ef428bc1dc80f667ec7c3af", - "0a07454a8c2eab20dc2dc21a25030b982e17c16f48d4cd5746f533b672c1ad4b75c8818352edb029fabe12e3d48176306c3b01292033538b9db3aacf5fe14a6b16", - "0b026003c10ba39041e24dd2d788f644180244a2afdf07b7cb37d1381c89dc24ca3967d2d9ce7a360ba629576b82bf003e9a18c279e98488a9a0c8ccf64dd87d43", - "0a058f020042283bce08a91031f1ac196da652d020d3db387946791901380226b2c8ae66a76b48cb77d66457c68cdfa4c18fa2d173ab79e7ad4515ac7743e76f06", - "0b04d51c7c9288f4333ad684860bb6a39bf9a2f6931270b64e4f826435ffcd1f5d908dd3b8faaa08cedacff99333360f2ad21c57750b9070ddcec08d0bd3e0c835", - "0b00b069fc67ee1a1353977550c256aafd51e2a3fa6082bf6c59f10c69f9f332dfbcd5003d11dd217446ffce710d925c113dc773a53119c5b60ff6031a59eba807", - "0b019a2aa2fd29364b03d2a18d43a1fd2c9175d20ec2c2391f89ec8d0b22520018f6f4011d4affac6c1d916af3d9200117e71fdc8f7665706016d0ae620d3c7308", - "0a0747eed213e5d975a2b88936b78c6ce7d0d39ae6fa12395208dbd8d52535783f97c90d53f616f93abe669958cab9fa82a7299d27129de1e383e9d5623070d608", - "0b02bf298c8d07cfd43f2a9f1b072a7f331c25e0a9fb519291dfad13587ef771394e30bc8d70380801e2a7a1f4812bff0cf2567b9382adf4b95f637b223c526be1", - "0b088b3855c742f835d90492c3477f79e8f6281dee6a5b80f632bd6a8b065bd7190cf5b6fd1f4a5746372463437b54b4d8b55da2ba7772b267120ad50243a005d4", - "0a0575a44ece65e0198bd953344dc7ea44b7be2830133e68eec8b05a3a746e67055195f80d1132cac7d2da79fb968f4eb423c332a6c15f41be93555b38c5332d22", - "0a004357528b7745caf7298713d1211f5fbfa0366461f5f6a5251340bbd960e0957245532141f0c7380dc9449ec4194e357f1010e16ddbcb977f67e731045bba5b", - "0a0696a85a962730a9cad92bfa615e66e5b564bed7e381b7b37ccd939d4c6a80fdf53353e22d537adb7fce18ccc70418164e1aa7f1cb8a1b9be7a9ce72ad287eb8", - "0a06b2497df5343e961b74daf531863ac476ecc03376c09fe3cd9b0bf77b203a978b364ee989c5817059061fbcd86fcf7636f29e75bc59d36c5ce01efb15ea784d", - "0b08d40e730fc1dd90b7df1a4b0432e9c821e9158e01b1cb45feadba541e562cbce8aea6ca6ad57b4ef95ca8f27dfd12b3cb877c1432353cbac31fadb7289519a5", - "0b019bfdfcfb5cc474d8db16ee6141ef16fe2032585d3aed064f030eb902dc68ff989c7c71fdf9d218d7afe9c36dd9f0814ab52d37a1be8b743b18ea8edfac4e4f", - "0a019303ddf92689624b4f946ea4feb052ba8b62e20f95de7cfd8168876c3a68b3f2bc9dce8a6addec5df2ffe042371bb15f62c85c8fd4eeb657d310f2f636b78d", - "0b08b33b4857533e24d1351acd5d39813e1656ba03f19dc93d4561eac1ab01b01f2ee1c9008531d39a7d67920266ed2a135f7df9b45bc4a5b1e7a6e497b8fec8e9", - "0b036483a14822385614372d1134498cea94983ce2647b1ce11f6dbe2926f27a0cdfe85b55ce21c705b7e61eb04099d56c4249e8806185e085f2796668b175dbeb", - "0a085909eedcb46c75772c349076dbb553b8cdc7dffb2974890e94630a8ed1bb62732d6b351dfee1e6a17dd1685abb117d2f29dcc626d52ccf498315cbdb416065", - "0b00d23297ce99e9ab099a53a29fbbf095f42492fe69340afe3f93fcd1cdadfd2c155f9e8a35e0c7731d9b5763ef915038646bf8b1de99161b17597b892fc03633", - "0b03a3d53b50ff04afc37abcbd4bf99aeab9e0a30f8daa8f8444f8d324327ee7564483b2349ed74109837e5b81a739c9f32702eafd622af7728d1dec31fe81c181", - "0b052e0dbbd48204e7c9a9f4ad7bd36f4c320ebd21beb2022a19bc2f3de5fef2c05ea10b3907cc93e7a120fd84762a33ecf2438bc8d19095d75102c7f4f4be7b24", - "0b0837dd25027690188fb86e2e1e4d093720c464678154ecc01ac9f25943318ec273f60bbc6ad3a60ba07ca9f42916e2ae90c48d2a793f3141748dd9019d0711ee", - "0a037d68b702292ad98e0a0cf6035184a0fb5083758a3924f77824e6860bff564ecc6461f1071ba1a6e596568a4957b50d6ffeb0cc89b22a71ba89dd016c74c5fb", - "0b015b131a9d926cc64fb3e5e7350104e738c599c5b7466dcda1d2239994dbc49c8fd953a94b433452948700ce55af9cff1ef30a415a618a5b8d77a515fab26126", - "0a06ac4300663b20b0513c414bab4a9fd16fb27a18298f21ee629d6a4547bb9a385a11f4f3f165850e894321d8006a7f4caa2c77680572e2a0c2903a44fd57159c", - "0a032355d9e1443cf9268a1e6f9f53a346b8352b043bf71f42e6afed5ada0ce2bce0daee90975a4fee008d474413e307211a7c2a74c1d6dea4a9e55f96e5a8bcef", - "0b0160c9e2c245a740f4a74b8fb5ba3dbfed31d34b20520a0c0f73c9bd61d455329db2c4911892d5d5f3a7d4f840829ed3a55365b3c4b500acb08c6c03cf2b9df2", - "0b02a1b46eb251ca96cbfa014acc43d7b68357b4875f17f368a4b0ab083ef82e641067fc642b4afeba0296f91c3333c8c4384dcecb78f88b72b50903ee41bb1a95", - "0b06ed73daf6edb0ab91d6b0dfcae215db078414a75ab07273d0f1dda1f7af2c6550343f042d626c232f2017cd83692ff31030828c34898d2622525b270595e853", - "0b070be6ed78afe4605ebba30c34c3f44b034e677da17cb6c0bf3ac85954fc64fb01431fff7dd048516acdd8fe33dfa9a1c92565265eaaf2d53bea18b988a5a913", - "0b00c1a284f2c021f782df302ac4d25509596d38c46d6125e664a623a8f0a2b2df08272a8ce973f5208f15c9f35f75fafc504f9961da01865e27d0b4433d5aecb2", - "0b083fc51c28c397b790e342309a1de7610634d44919cda9bc53208abee4aa247e65173079a40aa87dbf055f1f12ff5b99d46fa55f63599702ea9cc1acaf49648d", - "0a0903642e0b4b15e68641e86d9d97655e8eea7299d9a223a1c75d3527918d75a120b618b68a48ed8ef5e55583848578355c7f4bb62a8812045acabbb280fee758", - "0b04e7af2d6e4e2dbe69e071fe4a8d305cc3c7e7acd9fdbc9695453a083fcd6638a2061b79a5ee12798f70b323b8263780cad85ea57ad756c5e59452190c536020", - "0b0306f402d05e4606e720cab526479a110d0a308759cc500f93cb6ba1bfdd16519433dc440874e41f87cec2e23fad02c3fc483bf0616a4618bcea3fd14d3d5276", - "0a02d23c865fd86c9bcfd6468ee61ed3c9880c0941ac7c1330023faaec41beb0a8b5cca1f3d7cca42d5ca1bed4646d114727ae53a3a32d464ef48a71ec2c527b7b", - "0a060023dfb44b98d20134b3d677dd7e97436cd2997ad2ea9f15c28f46931170dfcab9a5901f9d8f69018f11827a6a7893a785b868befaf1b646178aabde77d4aa", - "0a013cce77d755fe4f1e996209c3a444bc6c960e765ddf99374543d9da4d588d3b83611762982633fbf97727680c3a9b71b4293a7f8cf84f2b19b11543810df341", - "0a0516dab3afb72b7fbf0180c556f911f990da854f2334ffe897e0dba65f86a16a0701023b95e0258f81ab8baf59c70825217f01b2fa0c57cb66dfa7c5c2927a5c", - "0a0407e674819a4a4eb435305976bd453f8e7f73a670f2d117d4f42f3398c1a2127a0ac0e9fd26972afdba015b6cb638b319aa6a4d8daa692af862fc2cefd6af73", - "0b035b0c6e4f3308b40f7dfff7a26a7f665ef39491c1a126d71bd91419f7c5743c50dbcf4cd3f6bafcc93c2bcbb2ce79e2ea9d6fe8fd6d00ab36dbfe872a36a8b7", - "0a051c71b2e2e4492253413f0b8f34875c5fd5f09fb662b10a5b65e64d00a74d6d80015a04f3698be9a46029a23f5cf889ffaf2e5b7316ca8fc118faf6286dc7f6", - "0b08de7559e2380444db6b570a39b008dcd876c1bff5dc6d566fbdc80f785dc0942d23e51056b0565fe3449ac61e6fbcbd180f7a8da87c30045e9719af698e0091", - "0b0888b85d73b37e9113ba8224a08e1788f125b6d48d13a93fcd774ba7f19267eb84e1ae564dccb37559564d91a7faa0dc374ca6c3396222871c9d5b62b4a1f51a", - "0b0263c8cdd3c66201e1577f29193336141a671d3bbfbd6c3d0fd6973982d5dc6cb254ffb7d2d926bf4424fa7105d6919af2b254938c9c89fe8a628bb2c7b19deb", - "0b00fbc5264dc31522c183952e0dea7071cddceb0a17e752605fe2d615a8e938dee9017d5e6af6b84e07d0377eee3e4f0e20dcb0d72eb90d3933fab0b44326b0c5", - "0a000d8a6b4290f9c3df9162c31e8fb78e21b623cb920e0aebdab3b603ca277b9dcbb369e489c07013fafff5cdcd19ee2162abeef2c1b46359fe142163588f9393", - "0a0510218c8856dcb640b5f6b83546360aa313c79866b414cfb5f19b63456a90ba8280ce5e01a8184a8cd23dabb467381278bf7101f5028ac6a568f418637db37e", - "0a02361dd0af6581e2acccf3a9db73e04cb15912a7ea2e6c8a27f7b53f97f60369ab33fcbf98fa9ade224c14d4b43502f6619228107e0310034e6f9d945fa043f0", - "0a076c7601ee36fd3abd40b16c065f524d8a0804e7f866c7e892500649fa74db7078c66d55971a31e427fc313fbbb7d0d0d9af2b90ca58b409336dca7e67205eca", - "0b06410be4e4e5e0350c35d55ef8cb792bdf7381510a973e376376536d407e24135c46db9f058a661dfea0eb6e19f86ffba98e72a21fb9deb45debea9d0a825073", - "0a07c95d6d46f26e20f6cc0a1213fda35fbd2186c80ef9f3ae0058112cbc91dfb8cb2bb7e3c5b5cc89f45914bef1c136d7158523b6860d4f3c0df305a416078e9e", - "0b024def066a3f6632fed3a92ab65948985bb3e6a2baa86f51deb4af7166543c28f38bef191f55de32871dce76bf6c47b5c67ceb5f923bdc30ed97d6fd490b620d", - "0a0899e4502030168032b52ab82255af10f5a017f3e33b43509e5b51fee286e04248918c31656209ce199ad0c09780c662eb6192196a7be92a2ac5e4e0f98a5b82", - "0a089854f7e866237b375d4a737470ae66a58819ffecc270114edbbfbc7dcd202d0c1065ba28aa753d12a0f19cf018fde6af6bf581bf318d3c27623e1b532c1710", - "0b08799208d63d6effd742d5cb68845411dd5852e37d7e3aa0a03d22694c0cd04cac23909e258a5d457e8e23abf02398930a1feb83f800b3f5436cdf3695da1376", - "0b043f182c75981662e5b8183f51c88697536e603651bd285d2f9175b70d7ad3eb27b90b55a375f936223af84f2af2d92dab723beedacb56f720233cf7022db23b", - "0a029f1d8e263d398e71c64f58cd7dce30a48b233c3708c33822e4cca2e706ca9a38b93a33a24808c34c15e38e23ef958775f4454993893c735fadc5d175396616", - "0a03b0c16da080fc40d5d75a0748cf7a3f1a4d6ac0b62b4624ace3ed5136b9e29ef799232984d5f0ca8bbc38097e8247bb12abd92b6a08dfdbe84305f7db03d8cb", - "0a08ed2a5c3d3bd71068cee9668ff4e3f13973c526e5c6a0cc2fdca1080b1fadec3b63404b6bcf9848cd6c89c312da1497382b69221827786de2dccdd49c1dd11d", - "0b0786682d0a8ee5a36a7a774787f71400baaa6f13d946ab7fe9b0de0a3dae1cdcb83353b4e9664e097850da5e1fe3165198063823205f9ffe277eda191571bca6", - "0a064d6415d20251193836aa755afb0ed4b9115b663ed1be56c4b5bc7f9b066e2d6a491ce84f361ea53e99af59ae2574a971a69864fa1393faeda9fca4b4cea5ec", - "0a04a367538404756cac8c6561d8620c31df34d9819eb0aaf250360caf8f2dd055a1060822e53252c2f28d88de91e6939a7ac8ebff28153072444e065e83b991d8", - "0b013ec261f47fc01c08f7f75e2d2083240da8296ea6bc0a0f65cd0087eeb39fadc6e1d58f1ea5060c95f49317883035ef4e081e269311ee25a82b717e70588e9f", - "0a032e52ef6646b509cab35ef4076ef423e6a3821035a9c9671b02d26d30e0933c0123e785b8090056d36fb4402070df8d89e7b36fefd2dc52bf80e01f4ebbea27", - "0b06373267e82fa99ea8744238f1ee7730cff8416f099aa79afe5bab40c463b56b79e427faef3edd09f09b5f5b3dd00603cb923777c2a6fc7a7b1f09af6d59d1a1", - "0a08bdab460c1439100a8eaea5162d28c843d2e48eeb8f44eca8fae19943d3acd2e0280c11fa27eb663a3de05f45f8aae2ee834acbab74453a7b4b4eb9211229a7", - "0b0578c9a61d1bb9e2c80cffe4f733cfe8aed7d06547d1b6483e2e331e21ced7bb725296570fb2df49fc8836267a7a6eb355a88103e12271452cbb9914a0a2fe5e", - "0b030abfc0368ebc20d6e1c61f46c62004a64a40439d65fabd7c14d37f058c62ff9d1569a17fb94889c8ee53ad1050ff5211fdbbb1e26301de6fd4f6e1ba651994", - "0b08123bb3017ee58a94aebb2508f627d5521ef0d567f798a5134346367d7150c23e103ffb744442520e0f1da0cbc5da33e903d61b5ef2e22d0d49812649c79be4", - "0a0625434afdac869b3e9b1747d20c269d16b006e1382b30718e0686c3e9d3010148629bfaf7248755b357f7379cba5d85fb2fc691a78c10b743d5d9bc310eff29", - "0b06f2a7fe8f2647b473cc993f081d560930a2b9c7c5c228bb14f783bb89b03af901bce57ae998040f13d3c3f1d2977e0730d58185308e78dfa0d24534059eb819", - "0a00c4e44bfbb5571d2755158fb5c1e55b5085ce7a868b06b5e0d01c2e7a0a07d17e5d07bef5fd841e4b20ee6e4add0ce53f1933291f053ea5c288ac04f889ba55", - "0b033c0139f2210abc338a5062548e28f3c9a90334c1d9553c40653fb12ad1c6e586bf0c53978ecb71776075b6d8c317f938137eb32e3fb229fc47625b8454542b", - "0b05306c9246d8dc36b8f0dea645683d087a48fea81b7fb65e35562af3f6b87138ff913390d246e033e308305ba07fbfba26a4848dc7e4630bd95ff7d77dbaedab", - "0b016b926d7376cdd99a6aa7097f4eed6eabb6768db2da01903f3faa1a9ecb0058b50df7331fcf773805db02066df87778fc0d03ab7228ce0c93df00b4f717b4dd", - "0a07ffaa2000b90ddacde318d352920f4e8f049681bfbe389ab280c238186a80577f089567c63635eea926cd1b76d324cbed4f01daa26899be6f7d714c405ec06a", - "0a07dd34159801328cdebeb83bfd58eae8728fc3b449bed4f21dbc33421784499cbf11468505188824289f5b3061d3fe24aff322129433bd05ef9f8d3a88e3f257", - "0a08f30cdefa67b1b27471d892e8bbbf65dc741abe74cc25867af1a028a2cde50efda7083efb7c850e0dc2a300511562519b978a70491ac12c56c1411a6ea3422f", - "0a07d71fd1ffe4534c2780c1149132626886f0987e1cff6702c8ae1824a9665dc4b1d84e6c5c6c9c247922033ffd56114b5fd6ea7631182a3dcf20758f2b9d02b9", - "0a04af73f4b8f373fd68b0eca5f02c9bd71c14617bdf9d516d6d60246e2ee3cbf62209aa813be2f8ef20afd33164c4b96db45725e54991d950a22c4cd08bb34609", - "0a0508184fd78ce5c65f882cdaf96b3aa3d6a69b774d334af7a1c425d353dd945468649ff783d9237e07863e2039100845664e71fe6c8313194454e7613c72c2bd", - "0b00bef3f82c93516bddc92fd41decd3738c49f22e9e3bd328e33c0c1a65c90cefebce85b4b9e973b4e42cb3f103f446be29bfc6e980f8f9ebf3d06a3ed7eb7cfd", - "0b0177775baa95ba739a2d33453c0ae6fa5a049ba2146b2010b81923f586a882f689a8c214d5d9893acf6973873ff1ac0482a9780a459dfcdf083c9c64a7d7ac19", - "0a029cf24afd5faeb8930c205a97e67eb1b4a6ca6f3e6b945fb73927314d864ffb00ab04caf51c4d2c576c5cf68ba3e14fc6d53bed5c083eb80435f632de19c208", - "0a05f77f35360e23cb759299a1741691cf64a1f4d6fb6da71cef9887d31a491db94812c661fff84af647ca54b4df38a9d2a36c32ea61f9510fa13593d69082ae25", - "0a016a095d8f34ece2305f3e7c2aabfb3efe446fa4868d7a15962243f50869c9bb799e30f735c5db475c9f953350fdb5bba34c96bb5f2d4437d23fc07a0e6fc974", - "0a07d6e6dad38b63d295e7d2808d568ca37b1228e4d360a6a0f9e1dcff0faa15002814106810e1320d21bb76a56b85515fd65ae54ccf8ea6b144c71d20becbe8ce", - "0b00adc8af529e9a34cb3b25dc4996cd64a8d39ae8e1bf1b9e2d733dbdd80df8b645f63b763f13a58a3e2825dd73a3a14f2109c15e4c13002312ea93d5a48f67d1", - "0b0486f3b6292ba24dadaa8410b70dbdee72e764b6ab6f379254f4639d9e38d1f95620e719335fcab92540aae19d00bf9bcd7a933ab895ab065afd76cd18979bb8", - "0b03551753fdd0bfb3f448831bbc9b4600ba38aea511e086228869e78767c172a3450050768eb0ef1aef4d0941eebd7ee34970e26926bf299b28d754d2530044bd", - "0b04486f8db3e5cd07f7e4ac6e4ae647cf9c68cf4c00f5c03d3583f5c37400b2482cc462a646ddefe352b9c3c660a6df856d9c691d10617bdc3b78d3bc4cb4dbfa", - "0a033a7dc0eb61ab5a77828da250af3f4826faf549932e14fec11ebafee6ffde62f1bef32fc2c8b0f82d586eecc7e21b11990487170d67a0f142b151ef12527f57", - "0a011e2a403d6de11b6d1796ec18b06a61e3a0f0c8474734b9e674b69a2760056501febf4b569cd19b4b5bb119b0f58fcdcaeb5c0411afcc00d5dfe0c208723cbf", - "0b00afcdab265fdfd3e08de7e834c20591c574919c518479cc9e07486db4d3ffe671885367fe8f066f17e9c32148ec0b79e6ed84171fc92ad15f28a3b29e463e9a", - "0b01d9c1528dba7ad88d79a781a635a1a1bfaa3b3a1e88d706de79e25726ba87e21acf61a2938e8c0872727ab266b7c3218f96ceae69dc4da50a5b5b3fc53238ee", - "0b00d0053cc63f4f5d9d67ee4a817412e99a41e0602d47a711da27ded448079fff4ff07be52d55110aabd4ab947225c2bf9062c53909a805892d916d8e58be508b", - "0a02b9cbfdb6dcd4d51af3819b6526973c5931196e2736d6fa11ceb4af44e451e4bbc86119a9382710e0a6fc67c6ebf1dcee16a31247b8ad80c629bc4181b043b6", - "0b0042bdd7d58a683f6f0f619efe0e793bd614576f81d8d2c220d8a0dd35d7bc2c882b130fb3baa7746c61a4c8751eb8ff871e4424b3cee975f758dca724e7a910", - "0a04281e663c6f934058333773708fc4169aa866e105ea592f96bd819230953f0957a56c7ea3a0c4cb6440120465ed9e2cd1912fc319726ed89f1c7b6c813248f6", - "0b04b663aa4ca6694ed0bc9d5decbbb5a07a10510f8aec7179a24d961d46a2a0765550a41a54c3d59e0c7f20fa1d55f6816b4ae36429ad38d541cb588a98ad38a6", - "0a009c1fc927f549848e3d1135c12e6cda6c31a8ea9601e3c83a7a021805d45e0bdddbb018a2b44f80ffd727110e508479a1330f6504ec8cd1718c0955faca7861", - "0b07625897b64c176660733617c5f5a18475b990766e6928efa79f1b62252b33b827605c41c39a2877a6e1c17d0cffecca18ec56e1e84b5b8e96152f0327c5dbae", - "0a00037161c8eaaa68c42a908f1d1cc4e1187f79b697ed5b21a38f562c884c46d3049b0700b5f7f5731e030efbc196555dcd9bed432f3a468c59ff0072980effd0", - "0a052df688906f67d4f28571e1b2fb4d2109c89087bf4290e1ebaaf612bf6a699cb9733c4ac74a270fb100210fb5253c3dc2a9f489d90f1b64e1810ed6849486a5", - "0a0471edc2976e18d787edb2a1702838b2000436d2773bab416c1361ffd73ad71e793397ede79095d5afa3e713756244e7fb36a4b88f21c15a4ef9f398e01d2346", - "0b05991e32d0640ca03d642af8bd4acce356df951127d23535d9b0aabb753726b849c67250802e208ce973f65f58b988e080099b3e403c778602fa4d4f6cb99cb1", - "0a07ae21d7bdab2262a22f8317467887fb7d0df894e2e5f0d77afbe670db8f4cccc7362a3069c2c274890f292f9d920ca64927d9dc8715984eb0f2abda2bce999a", - "0b0028e1f8861a9136e9bd7f7819816d7dc6677bbf50c015b775d386493fa1df79b2caea01ed45f4b9d0267306ce2a09fa3003b83938fad8875eea1fd3a8595520", - "0b0199661e5f4def36580f380ef5c768e5332fcc11c247e34af875643797a69ab1dc29ff3be67793c4a786d836bcb5b57f6d68124140a89eb4f7c2f1f30c81d63c", - "0a02eea9e92b33799aa6dc9fd2a7858707612c3cf3b163bb837888332f485bdbd528b5e885e229bc1c9bb78835d6697e91632b39f30be527a424654e5eb4b6ff13", - "0b01a4a79ce317e5616e08b6eba5b053f1c0a85fd61828dfa23ee589f7a32129812723e51d1808f29e4f20b2b34c7afe30224c1db22e373c0c2a4f9d9bdaf15dae", - "0b0218dbb77c517fa6e4fa0353d18a83cb815e7cb907bbebf3de29c6c080aa17846078bc4f8023037274adddbfdd93e85c77a8ecb3540a65882d57f15e55da3e3f", - "0b0724679426f36868be682e543af96d19c5e3eb84dd6cc0fb75e99ad6dc4e17303d440be4631080663ed707b51d755564d4514f67b9c6fa6ddbfe08eeb021170d", - "0b06b39b0915c61d4fab4be17f02b78aec7bdfe114d30fca2a8089c6b54975c1239ea3d735294d604b9531a38e0f17d01cc250492b62f9be17b0819e317bcadfba", - "0a0325eda96c7965ea44e956376b08a37211fae08b5fa6f47f9b188db3476f5d1f88f38ddcf4da6a431f0323fbefef2dd7b5b6ebf3693febb8780f272d971305d8", - "0a043a227453d048d84307db39f51f1ee62b0972dd58de41bd27751cab4a2f331e0b72923f7fab260c6d35eca34fef9b3bc9a1f86c424e0604dc493479ddae3aa5", - "0b04996a4e152db475fa6ca4df50845af156bb95238dd138f0197008bbae64650269270eee05de2239f0077a6744341d38f5214ba8152b645f8c5f3cd6683e4ca0", - "0a0168c397c2575832b01714eeb677911cfd98885be3de59c2454a94acbab451758e8bd6d18196a07f8ac3b0d598aaeda7b2ae99afe95dc91f159cdc0122199578", - "0b0181967f84dc5903fef583ad20b3e8287e332ce6b8cd924f10b483241945ff6deba90a6acb11217c28b95956769ab9ee0d2c1107a1947c54d95c49d4786544b3", - "0b05e07757aab645fee42e3092ab1303aeaa46078416e47b8414340bf15a5128753d62a87192bbb12e6ebf45ce1efce3e4335bbfa403b003718c6f1386518d4c4d", - "0b06b6d4bef82d7eef2f44e7f7e91c8b7fa1fbcbd5d00f2f05dec3442d4d52016e83ad3295bcf4ee9ce48dfd5cf67a7a94c4a150b056a784292eae479f26ea3fd7", - "0b045e1a6e72fcf9c631c48c38d449d397b0d0baec343f6bbefe4dc27163d5ba2d1031931c164894688879d0c035be6ade8a60977835cff71c3eb51cbb0911d7e1", - "0a089b61a7eda5ff7c0d5f89b71c199d71ec4f11bba901fd3862f8cfb6b90ecdee8daa23d512b76cff9bee68e658897207d966c6921a79e6360e55e8367abe8fcd", - "0b0902b5f4e60eacd9347c6bf928d390937169825f719f45070be5c94fed576df907d76b2e88a081aa7d936d5247c3fc240ba3e5bcab67ddc1fa972a27f2de95a9", - "0b077980629b2da102052b4824818001da41c7ef8fb8c9b4540c4f655ea676118ffc5fe16090d414d175ff01b3bfca99d5b01464b62c5ee1f7c6b20e71463ace15", - "0a026aeac12066ffc230a9b7ef4fd7dd3a177c60339350e304519a91d0462699afa62d20f560a32462b276d63092c6626d28f246f766eac06dc00cff465b775536", - "0b014484750ae769e5f4a0be97e9e3bf7f5575ad88a2f7eebfff1f90eca402d21a28ad63e71e1aa23496c2f4a8fff0623e0fe503c41bb5bd49ebab8ba0f56eb0c1", - "0b01ab7598b850faeedc20b32d53ca515f4012747b11be1865ecd891cf6d853b8db7e57e87e5a20dca58b56b2483b28755eb5f6ce2e7c58dfcb594d31bf7398314", - "0b00dcd2f10dcf93ca69115b6aed9664107d6e121d4e72f155bbd33e3a0f8c95d697d08163dee383ccab4c3432b2d3d3b96a1a2bd9d87266ef678758300e5630b9", - "0a0555a463312402be37af5aed3170aae9df802b0f964937fc3d8ee5006037ab97d9bd4b2f75bc230652d6177c759efa02113e0f7366dc4883b7064d59c7aa9994", - "0b0588711e57ad29871b03d915edd3a72fa6c2d7a15e50f10a553b3cde3de2243b31ca69030bdb2eeea9f58aeec0dfb1a30271b47ddae19a75c1858766052901b2", - "0a08b2d8cc7fa0e0585688560eef56f98cbd2af9e71a39bcbf16e387a3b0ab193290229acbdb4503fec5b02d99ff01ce43e40e9791271dbe9ecc64b360821871b9", - "0a06c378934d135a40d2da375b2a465dfe940216026f4393132d427a405453f96535a7ec01eb65a9bbe8b934ca6e277127531905f4548d0b7caea96b99ffd0eac3", - "0b01743677fdab9fc0b33afdeddcf2b0c9e1a6873a071f71908ef79efb1148c5d8654dd38b7a6edef5d1ad6fe96beefc417615f9f5f07549cbdd80b705a4b5f159", - "0b0634bb4ad752f66bf87b9bbbea6b06ceb1cd892190ca51de2ecf8d2f2febee8ecf2abf8c4c2a317dbaec2d5a69583ae5fcc6c955800fe57a02f897914a348866", - "0a00510014eafb3a0c54036f24916e860e6d953264263bb2b5b7e809224abeea5992fedd8d4dcfab8a0cf4cbdd273c9b6852ab41bc2015fefdd9038300ff71ec4e", - "0a0821c6b3782c3df84d2acafd5f14808108d6dc88ef7d4487b36196af0f00e3d38847cf8643b53c622f7de0fd7ad3d52bff9a19ee327f146fa47a0d24497b45be", - "0a02588b9eaefbb123e2d5dde1f3fa6c5fd2f445aed13beeae700641022e4458701a4d9288c5b1c3f92387fe194ca5ba512d89c8288cf0ca3be92b125078658ad9", - "0a069de9159c9a099eae616a88f73571d71ee5b0ff207691680580336703bd587f43902bc80df08fca30737040921c3bb2d867e4617412180876c697ae350c6fdd", - "0b045c6dad317cdefb3de57c5e513610eb4b138946304bf759b42bea0c85a317b1dbe63fd534e1276eaffa207c5a3b37add49795328ec1665cbd4fa7846bc8b160", - "0a074a4d16e87c26dc23df0ad61380ba4026b5f85bc1e5bfc8861760555753540ffd537d153cffc5ebc560b103c92f9b98f6320bb9ca9700adaa09db9fa40c6a57", - "0b051732d87d131cd22a178ad3ee7d0a3ec327b393daf9b47e84257c8eb9474cd4df791f374223e204d4d1a765e8c068005768ab3ce79b778cf636e239104d232b", - "0b06a40ca2b2b3117956f66e4e8a5750038b28b751609f5f68a771b56c4eb79e05c765cd8471a0aaae2da960c1c73a7f2e42d6a536585be9a7033bb58c6b918dfd", - "0b03c654ed04dfbb6ec04685f8fa997b0318ca00dc307e1d60d02d1f530d5901e1550bece938492af8a6ace238f4243855f1805edb8ec6e9bbb1923093e9f3aa2f", - "0b05a8d157701f12af344ac8d96024f0f979a610153d10e1ee87fbb683259caf4aa7ad997743cf24c81960dbec897824779ed45f575ab7f0a797f75930f025a546", - "0b0596c8bca6454359468e52f9db0469602a2dae63b0d8db36da1cbcf09d24ea74f990d7e19828f64692beecc8f1c6dba202d32e5261dfad29122e02c8f08814a0", - "0a066e761b2f0c2693243a0bf7fab69927fa4bb345b85c103f5052edf28531319831ebc4c604670f96d322e0ff455b101d1cf11773f6b7483c54e3294a911d4bab", - "0a01cec3c059a456d590437070c8a0cf820b3b6fb704546210458359b2aac625475f37efd11fa973c603ea2350202b92b5d54ba8d14653ac0d72a7bdbd9dffe796", - "0b045540738ac4a29cd45f9bf5db06f706a0369e068779b950082357c3ba78400fee65e0c65f1a0b83d3862895c604d5fc2b21d518646942635e8597f687a634c6", - "0a04187e9b3eb04efb8f7c1dc3561f2d48c8042cee20fb7036be16eeac8a73aa21a175e01f4515bf6cb9556385aa8435f7510d3a93ec8ef60de0c1d9638c5141e5", - "0a051f2259d73e087c8664887d9f8378ea62801c5edd290a7e187c7b7252c4459e1ef71971e5ebdde4f6d4669aaba4f86bc58c0ed2d4ef8e9c6cec13d6701360c6", - "0a0789f7a2a2a2e1b9a19a4b074217b5f1030449be109b8329985f0fb2f5f6b562fcbf729ea7f9a75b95afa6a68458e73b7532e5221a58e68fc2c6b373a4814c58", - "0a0502c96c0e041f11de33b653f57beab164467f5316ff01d82d075221b0db45c548464fb878796655396715d01dd4937797a3966f239985f300634854cae15a47", - "0b08613f9bbe804026e0fe9308e122e12145d82196f76ff1a415a8ebcadaa298e9510c92155c803a706e84d6c28214d1b4a560ef9ce6876c7a9221ab232e7e040c", - "0a00b4e74e5f0ec4acb6347707cb7a980d822b6aef3c8facf4ea68b2df0dde3255a6bef28aff434758bab9bb8df5e607634b561c36c7956c051bbe7b4b5a98c749", - "0b04df0379aed034193a43f1e76b3d18395d5aef7db2c289a59558bcdaff498ec832496bf65d46a186e6aca5b801875b989ddae1bf4bdbb7675b078e2d87d0a6dd", - "0b0887817b86b2f2d2014d62d7a7dd42fe7c69272b160a6af8047c4fe72924fd45b169f95b320ad8543d4414b09284c9bca6d1bd9d57dee4ab7358057e975d79f5", - "0b049bec2436821e17d0d522170cc16d1d1ea2217a186710c68a174564ca09e54bf7ddd993bf87db39a3f5f33a1b76614269d93991f4c61617a79145fd1bfa888d", - "0b03b9d54ed06eb1a46f00d2425d781605b83f2cdbf8154a3150e031d95ccac605f85aebefb3208b78573a23a211aa4cf1ba89a60cc8cf084669d4763d0d891ebe", - "0a0023041e0afeb4e1982e41f16b76bf820ff0a6d910dfc21c26f19daf2c99302a7c54dac96abc78c7c9696f6fbb682b6faeb49feb8db7f90f6cf81a28778153c9", - "0b0259036e6ea7af7f46db18428abe30eb27e3b0672e154902da31988a2d7b2f42f42b4a4e0cdeb8569ac49f1726a4d3d91538337fed5748f87e365a633c3b0d6c", - "0b051974dd76badd49812f95600722d65d7301c622a5ee6c97211a9cfeee15112eaa685b0af3a67393931b128927344d08dbd3fca8a9fa567f88729ffa1e454e38", - "0a03ac2990ecf1324b25af29095b5fe92e96516e7407cee3b0e1daa6f6ce99b4306256a159848e807eab2bab3d8fa99e7e2e774c3352407bde722d3bf00ba2532c", - "0b078f5dd253465a9d65df5c184574652288da6302d8f76872a02a9efe914437aa6e6389c37a2fc90b23ccee6f2f6d50aad5d99137313d49d8b5ed8e29333b1ffd", - "0b087e11bce55e10ac3c17fd0e74a89662e12aff225e73391004ed3e8ff31aebd66d1dd51b339938f139deeecfb30393ce1f87028e953a96c6e11da1a6ab1001b1", - "0b04b01ad27bc0b7d4ad1d5af33e0cb64e42f1dbf53c69292d5b974a2182073c624ed65d442a182c4d3a77d8c3a06c67d5eff6877780ebdc6b1e132c7c67ca339e", - "0a051a7de0ecc5ed8b153937b60e39bd835ed1771bf3ecdc8840cfc81651e6bdc3fefaafa1fa083b9d7e11272280999bc2a899a1d578d83810c108e3d094085849", - "0b0177775b45277c1fb78b308375b79830f24ba3f2c0621ae5551703a52c6e04e079773700e2ea03187781be215f1c9fe62a1563d6385ef167abec8823c8a1d47a", - "0a0561ba73eae89ff4357842cb8c2af45e0928a2c59fc6e9091331174fad33f7b2d03448977059981db7e87c0901c6b61f57bb70c06371fd314785fe0fec54ef6c", - "0a01b22cefe26d461ba304740c2b268f87fd1ecd830fe67f76e545dfcf0912cec8fdb5e5b9861a4894a214746eeddd6dbf73b333b93b8d01a302352f25f2d02975", - "0b0211efb7809b99a74122e01d220d9538efdf90565ec174400cc7475a2da46c78ccdfbb616116dd438cb06db82cd1198cc3e1f3a91d43d7f8735b09cfd35f7435", - "0b05e3c4640a31b3d5f18a82008149b76d1ee923c8e89d656a2bd65fcf7cd7cd2fd8d274bd95a5ae637bebbf4ec62f60fc402e0834ad2993c87cf7220d2b12426c", - "0b08434f87038d854c8a5fa74a489004915d2341ce05f19ce9a074afe82a2a037d2b6a925856f2f2dda9b1334cb59d017364d81d7c1f610a5b60a82e0d1bbc9308", - "0b070228ee10df4c70f07cae9c685b1ec3cca3acd1b8a4ca9279915e5200610ecf56bd378b406b92dff687b09d34e3101ea4a8f08920c5d86a60bf99e174891e94", - "0a086a692b66379ae3f86493f97e5229c397c646976455bb1babc83b633339cd0cd0e9991d263ee5ec0e37bad9439fc9d23dee771e9bdf0851c12a60a9011a265a", - "0a075b229837bd2e690e45d00bd2683c14316eebbc424b092c5069f15424a6ccaf1253c3f17457841ce48547bbfc34102c59236cb78ad7a8558530d3291eb05fd9", - "0b054d9ec03ecb72184d6b558e65d7b2b1f0ff6ab50a7cef9168c245d2d123fdc077ae5ffe927239ddf0b7e1c39a609f360d8e164dbba5466f21ddd80ebcb9c291", - "0b02c5fae1b1302f1a70e1f48319fb5cfe1d860ecdd0b1f95d47d33e6a28c43766bb8a7863d7d08da582239eb753deccbd6f397343d9b015cfe9144e4c85f798f7", - "0a0049b2212b8b89de751068ac31798a232727159380cc4157f340f290a96cb15d3ba154ba9e2a929e3926ed1d5377686ab35dd28534c760932afb84672a017593", - "0a077bf3adc2d9fecd7be0572aea6f9fb4621ae301802dd1ba5ff22212b5261c3e41df3edad52073ae1a1eb0936a894d8d44cf575d10c5c7c490e456c7bf35d4de", - "0b07c98b1d997c315e7536f7b997aeece9b82981b76c584c713011114d3df69ce16c09b54862e92954c824f22da6885f53de00fee88707556e5caa4e1535308335", - "0b05712e007d9c97f170495752f87c113960188d12a8bcb65cda0b3f6f2af7d6dd75fc11487a8963fe5030700eed2bcb2b19aa3a1b869b49455c1c6fff8a49a50c", - "0a0478427fd830ecead440ab13705190c08061d94d70aafa5397aa20c0378996c6204860d1279323d11302ada1c9da85508606ad19aaeb35cf56d8aa66059c9bad", - "0a02a660bd0dee641251bc5dd405b187f1816804e5bdfb1bc9770b2dbe718e3fa196ed1b87183ccb99ad1e9b7dc21fa54c7c7ceba7adff7775b7ceb77881bb8348", - "0b046c4d71b20873db88b2e6c0b74e39926eb6ee7a6686fd24380ac4791dd840b52c9175c46084e37b80934ac573d238758020e8d40cd934005186fcb8ae7c175c", - "0a015f35371a31f63da7ba9b74c2567a2065a3091cd0e58f5e4836659e5acd483ec46f3c5302ba7caf21f01ecc7528ea084180a215d5c9bf816b9844dac3c832a9", - "0b00a7ea6242cbd0ca4077347f3173f5e47b96aeca4059ffadb23d89fd4efa6cab76d14992e2a63d6824b58cf3e6667ec8c6163fedc9faeb53f060026cb119ec58", - "0b03ecffcd0283f8a339cda48c4d080b5d5d122c876e1f877a68670b36d6af134e33812ccbfd1a906736e406485622a3cf23c95910da554feb1813656f4d69dc75", - "0b05a9fb85b5fad2b04222e0fb34dc3bbf359e10150d20c42bdcc1b67cbbe58f138ea5e6a006dff6e3c5287f1c2d1069873ecb9871c3c251bb974d22283ab28cf5", - "0b02eb25c497cfecf604d5d560dce566691f082dbd2758809a9e134e169bc9b9b348793f61403a0eb7268e6b354b3bcdf32bcd7be902e18c446d67d9e632afe99a", - "0a002dee14f2dddcbb99a744a16541efc679d1eeb337386fef4ee8b9e423b821c5c6557d34af081496ec1305dc4b46f939a88a7961cc4670b1ded3fa16009d500a", - "0a01c6f87388b04fc45127b9cd39512dbd9f28945d03e48a810cbd6ebd2f14b5343208532e2bdacaf0a9a074e72d5284daec63b2b759506f3032f56476323c2bfc", - "0a00c50d63ea1516bffa483bef738816885c48c824fdbd409f43cc6163c974c89d4c4c2265edc9d89e082c1ea17bf6149dde2a81e3cb31cc269b2f1397c124dfe1", - "0b068989a2b1e83cd4bdfc6b0333a563d9980459a47ab3d96a230570ce99e71cd63b9bc99aeb584a4ec97f56f38a5fc32caba321684702510594b88e74ca4c42c3", - "0b05fc57f5bdb53c05ac134af980807fb56fb0ebc742031cd211af6ae2f5246dde012f22a4015ab06e755fa995006faf49f200381b01dd59ad3c572550c92db6aa", - "0b0329e8455924fc04a44168065dd321ab318c70180956a6d32e80919a74b46e4a20af297847dd98fb9905a43401b95221ccf6d04c3c516cd395e4e04ffad8a6f4", - "0a089df3ba17c1c876858a3e368124259da2b4d43f6062fcad655cb324c8e01426368e48ac596e0fbc5dce901a4c800af0e6cc11f24777613d868298b9f43bea8f", - "0a065d8454a5cbba0599cd59e3eecf6b4998d6bba50ebaafc6aae55e6315e092d3eedc63bbcee387223801db08bdec92df58587a6d2ffa6d5785ce0dd462a44358", - "0b036e053e2c20595136cf7caa2c04b218b57c9752960b25ce32e4906343d1b015d2e9129c1c4385e78d48dd296f5a96f57440178c58854a70100fb60e559f72ac", - "0b07059ab03ecfbd1b88657c48e09da7687dfd3ca7af975bbdd6c4c98bed31ff07a6219ffb31562f53de3d6bc5d267cec94eb3df1a8a563c07e896313d39a4532c", - "0b02f94c18c1862080aeea196ef2051a24095a85a7ebbc13a2e66001f4f7a479d1aa35a843ceb564daeadf8ff7b1b0e99a2bd880b12520f2e2eb4744d8736c1a73", - "0a065bc8b9e98716eeef2ee268885cb83fe6e35b9583c8f6dd6fa0cfba856518dac9efb13aef93c87746649247d9754250a6f31eb58606aed3802690b33bfef092", - "0a021f04e30699078bba677e39347e4f729b9566ecab289c8fa430ca5ea05a1f604709e49fc9f6dc84f5b7dd13045c6a49b020c84b5a8ed95f530f916027e1328d", - "0a006351b6e00c3d8560b7e15ffa2ac49c987859a8075709a4fbd3f7f99477b097de522f604ae23315334f8369fe4243d91f1c32f26cd663a5acb2bbfd2267b537", - "0a06ee31c8492f2977113eaf14df70b8207b5dbd262ce0f2e90de63ffb38f748fe09157cce1f2d254cf0aab133e7294eb3ca9be6bd9cf75d671e9eb7c3f0d286cf", - "0a0507b34edc62b9513e89f2c4e18e96cc97d2aca4bacebdbf11e5da313168377bcb0160f0056ee6f34bbdd7d31b937931f6b33bffcf54bebcf445e7fd249b8d24", - "0a008eb01d4793f201af9fac75b105819e3b1f44108f7a99024dd458b49f9f159afe7ec540f38e5923044dc2f3d59b9c443c984e8859992a97457cf61660c9a68d", - "0b072f94655f159c64457498eb70bdcd5b676adc74061a0925aced5dbf3e1a9d5fd862ac052b4821ea50c33a9655fd5d743032356900660eb66b30949decbd95ae", - "0a050c43a8b19fe3d2e24d8f953ea2b4262d15193ee298dda0b13e4a6394e8a7f88c663b4e2fe588dcec922bf738af40b22af0a06828778d5c99d5ea20e8006067", - "0b02b8722c707cec98634420e695db2f488d628153c0a75e0fa0b4bd79d37cc25c2235d8bb4a9d444d15a762f10abe9d0ce026d23a520b6da1c7020b62266a3bb0", - "0a02659ee57db05c2a7a6473c06c345e816623f0036ca38bcb809b431a575de65626635e735d5c9529c199da08c154110d5e4b826734d98a3744be02afae4be6bb", - "0a053b7e1f525348b7a972bc0643cce46b2d0be544a26a2524cf996a49b01d592394699b83e2f5b2e2eb181f35c66c9612188fa5f01e4a3bd5e7e18e0eb98e4c46", - "0b0554190b3e2a169be4d4fd0a97b166c98ba7b1df8e84591d5857f70d4914de72291b252a3c62125343bd79f7d03d88ebb67dc59e3cc3370059b8ca070593d30f", - "0b03afe623412c98f3dfb2e09b2b274a2a6f9bed3544ef6f9663411726cf800064e531024341efcdf42fa6b8d44e0d3f15fd05425fbdbbf111f31cd20e204d6d51", - "0b0593c63105f4c5001976756d8261cb0c39605a206aa271f7545b5b1102840106e5e5c9839673f4aea91e1a6850dd0fd91c8f6823c06d6f2bac478a0ca2685455", - "0b09169cf9359f6853b003c91e3d3d94c1fb7f640f8a60c2ffff7e841b748c0066ffb377c5e2178cc2050456b73cb9db03f0d00e3c67e1284eea4f7936d8c60ae6", - "0b026492953e771cbd148691285e2e0e71e94e2ac4e2c5ad7a63b7fcec97346837ff0a3ea6f22a1694679c890a0cc3acb26e67400b456ffcc2cd270e728f7bece4", - "0a0314e488eece5e9dd38c6043ce8317c0c67962efc40314981de56c242e2c14fdb996b4118022e5b9849bdb3ddb72c6beac8f95f02d5d26120415b787fe8f1184", - "0b019ac664b48b61810595ee64ab58197f7b86e5fa2506599482abb90902b294f0869cb254850b114450b635ba05e5b0870036b92c4ed44132f6418ad780381355", - "0a049fd298fd1768c5e22aef23ea8b6979133fb3fe4653dca6178855084d6e12306c6c6ecc2068dddc3ece62cb0bbecb9282d41dfcecba47d6849b070cf75a3eac", - "0b033fb3aa0fa9410e6cbd0d4e628e7b250120a9263347b3162bd73514cc5051f4e26d3266ea9de0e76d1466890c6db7b411b2a8aa44fcade10691eb90b5e60503", - "0b004acbb99b72e7d7974308676cb3435bae908d60889ee5cc466ed08d9fcb33009ef04188bb6639dbbc61019154b602716f0ed9a98a54b976bed73595134fb702", - "0b0253c0b5d4c63b2ffba510a458692103171f3df650c6b3397b52fe45815173992b0b09e16e972ca2b445c12b684b324999fa7d72874ce2fc15f6872bb6aae835", - "0b02d9e42a4105f98dc527be12b9af6eba6fc9d57c3671577c8df7db8d6ea0c14be03fb8ab522d1c56687f946b82b0879ac7a55c6d849cb0b6d9ab23e8f037c62b", - "0a079db17a2512664d26294d957df83c650b769140b7c45da55cfda6729001a99fa90f2618ca97328c1d90a4ff3d0bee17574ffa196a3cc2f610978ad57b47e657", - "0b06f64fa62f0c49a84b38d9b2851dd4ace82b800cc8666cd532bd62725618125519f1a07d10700fb3b696ecc0f26b30a77d3f789b8f3f9e2a95144f14f54813b1", - "0a080983d813ff53be6e555f7af7b0551eaf41a767c0a871d1ec9f85a1844260c70f2773a1071294460217b053308d1324c0c55e965871a736465c35e25dd4e0b5", - "0b02c8e4e0d61f8523a3a3a39114079b7ec83cb798e64c22622b209af8c1979cdc25b6a43c3738a7cdf4e2910b23871c9c381efdc703cc6135f2215e3ea9f3f108", - "0a0780c8062dc8e82e508746200f164028261fdbe1b4afce7ea9434342b5d786bd3ef7c613a37d2bef8e2d6c778230f4cee2b2cff18fe822d841b54e70e9339bf2", - "0b04be4ba0b3958572318bf32338a81aa19c4f967870a2a6915fdd6ecac48ee2feec3454e2be089a03b1b431710694470a86cb4f350fe73842769f82d4da7f69ab", - "0a008ff782b13b22828b8b2d89656f053521251aa64877c810fdd616f09f4e9e92678f5ee452f67264e13b3e397c5cd2c525cb8f136edae78db0fcf86450c4f1e9", - "0a07dfd704cede74508add2b34d8cbf1a010d400f6070398cb7275cd339a1e48660794cb8e2e580c6307deac71adb59380ed0b606ffe476ca31b88f69376437555", - "0a06744f3530363349666c4281bd8c69e0af55a0a93e8037e203e4e3daf2561ce8b7b848b8c84f5cba46e19d41bf69d0b2b3367f5d29824beeb2a2431db91954fd", - "0b018dcaa3771e850f162e95e65d3e422315eb1339e1b563aae1c68dc27fc213fdc14ff5bcfefffb0a0bfbcb3878e5491a3f513a7a344f10fb216bea80db172c4b", - "0b07c9218272d22a8662a55f33d1f99863890a49437db9328f08079cc5e0a302d5bcb2ab154dae8614cb6fc5d33892636618b3e4061374295c52770555f9e921fc", - "0b08f858b9f359f95382115896852d5f775955567d6a196452b66f37c182d8b5a980b814a749459ed722310f012322e55879996a591a2d5304f8fa586912a0a927", - "0b088a48ed1e8f6688361b46c784b73b5f71443016a707eb1b03ec81387755b4c786018c0b2c72f5b2fc0ff95648b79bda03b99b32ab17e96158b1d4acfa441517", - "0b05f6ae30cd2c466ac50d9f0dd8d2ee4373b7eba00e4820d0a8c5037730df15cda70fd11bb8858ed8cac1a6409bfa0c3fdea47bfe5e428ff89fee6b4356493dda", - "0b02b0f6a7f0bac3f446aa160837fc68e16b4bc457d2624270ed1acd8fee1d3de666612527c033882d301c72cca739ba6bd9ac5cb7d374bc8317696ba886122652", - "0a02a14f463641bb684eeb221974f86696d2b2ed5348fb21869e7b431cfa7c814f9af66f1c7bf846ed65dc75633876b6cff805bc28b07389dae170610b20f32fe4", - "0b03f07c11259ff3c924123fede338c26da90c5091475321e05204ba7a97ad65028a91540f5aee6cfa43ea6794474ccbc19944fa91cf796a8a49cd151068665d33", - "0b073284b05d4b7fbe462a151919b304556ca055548c8fd2ebc4381ce180a2cf913a9e2a6980e67597d3810b0f5c1bb1372f99bdb26895f05473f9b3270cc4e54c", - "0b00db70bb70430026668c000c46df0e5663ef85069467f09461fc1d646bf378d5d1524a04ff0d102daab40dab7a61ab4b136885ee7fa0acbce1207717872a462c", - "0b00d4905c5698c02ddae1c6c9576d633798df04beae7dfde75d5d922dcf506f68f639685cc511bf105f821872df038917e7d4dee69611ffe07499a4226414dfd4", - "0b05bcffab7b35848ca4cb93571483b9870bc7c2deab82262ac3b4565f07587c6ff8b860cd6a386be118aed11ac50af2a0b1b3ad792568cb8efd188693c907700b", - "0b0886af69b544a5e6781e97f62ef59c5a34a2ec10d2f98e0a4ee29ef313a2252bab23034dd5be68f3be769dc166e5c6a0f8af00296249b84814a65741f0c3244a", - "0a08d35ed52b7cb9379dd5f40b5ad09c6678b859aa2bb2fda5373d87f02912c13181074ddf06b1ec73101214677e9ae11c9b657ed8c1169f6a7673054ccb529304", - "0b04f98871728655c03e473c23163cf865282bc827a5fd8125a0cf1ad320aa272aa8c5d08404d0b8aaba917a656663254caf583ff23ebf543785434a6793c27933", - "0b07ffb49fa1a0f1fbfe63715b2eff9a6f1c7ee23da49b2dfb634cd466773afc5448a69e22af22415465ae17fc278a81a6160837bac29abdac0d602fc0204f5ea3", - "0a048ff52b6da04beb998202512cdfee39cf6538a7789ccf6099d64df7fd329a437a3aed627e1382d9e644cb0c4294a37d6bc63c5fd6621dd48fe8085c9157d190", - "0a04128b5f6c0586cd195c43cf433b1631883a7c75236dcf7ba350ccda649a4c83a6e31d2aa8c365a2c0cb224bfe00b501febedeab23f8dad7e3c4a97389f79691", - "0b008ebd2f835c489231f7f72ba45c4278d82d85ded73deb3467f48f53917bc7962d46454dc260637149afaf92bc6fea19173878659c57c47e948a8138fdfba14d", - "0a01d19dda68edd4b78f6a9dc9a107a45af3299fe309788aca8675919836708e5de02a94058387c8d5e1d31b5955ba190921dd656aa5cfade72eb2c94cb413be01", - "0a02163f01aef45e0a5afb0b5804fdf1616f9d64f828c37996821573c538ec1878a5a2d48b5f9962e20f299f2b901eb862adfff6fa08fbe8d1ccbfa04efe27a3d9", - "0b07bbe0f0f7f85c001792978c94c20474e68e674f8d0324cd9f5a8b027855093c04d233e34554d8ed1fb755da5ef06b24b33567fc790f3dac210b2f9c6e523d90", - "0b0722c8bee931dac50c2e294dd8a81e9af03f20c9f810b69684b3ed06508703fb788bdad2cabaf33b4ae9fc5d9c28a958642b932fcaed0c20c597be364bc844eb", - "0b04af8037895600931943cdb57dd3f922127364982eb7133543378b695e205b7adbd93050b13653b00890b7ef035d20d9a2d888dd139398b92e29c015d30445cd", - "0a04907a50a1934b1d75ae6245e5126a8bbe71db0472ddce4015fa19dfc585f293b172d6a19595651af97ea27094a0e2e51e5cddbbc170b5da3bbfd9a4f996ff97", - "0b0097db0631546249e7d19197836517f5e054cf0f9589100ad84ae10ec3eb6c44e2a0150a9930b97e3a62680b0fa6730e87b9a3f2b1748e99e93b101bbc7fd828", - "0b0447b69d15c902fa89684bd9f36452af05742c0b8521e09bf2753b91f5bdee2901535966aee11e6f88e3ae9c2b617daf27a8133bce4306081bea01b24ae039eb", - "0b01fd71e4954a002f4c00ce68407d3035e3eeb4db3bbcacb544f52abc7099b2744c2a9221d4eec1382d4039278da4cf7a32fbf7977882f13f5544b395de8585f0", - "0b0485cb9c69ddb93d9fa635a819bcdf92600c9ab792214faa14db4ddad630b3ab2a241d0237f8a40d65d68ea3c255de44dd97d925886b4df1d260f80e09808cbf", - "0b05305e2aa35c9987fee4af8faef476a2bac95d793ffb259f9cf7fa531fcefbdce3d70f01f58aeeda8107c8439b7497218dac7258007101ee89627b05a1f5a5f3", - "0a0214bdf25710808497804d8bc51e6bbcd838d64450a7f0dcf41b342e66b57177badcdde0aff93c0a081a79029779f364b7154c75389eebe44c8d241a28d3ff9a", - "0a0334bd1d502280728165e2b5de2813d934ba86ced958e3856caddaf410349de8545379ecffa4fdce70bd1cb8753f788b839d6cded8f9258a6e94ff62900a81a4", - "0b084b1f7c2e6a554cd292e1a7a0e9a213b3878fbd85390a2ddc596ab20543bb4cd895ada92aec8dddbe88173a71142af5d772259388798e1a23a551b2ac7d6d71", - "0b000bc8f6e32d5147489605dab6f9be04f03dd344d94886d363f8c35a4cf957aa2b217f21bfb62134889599c8e42a48f83b6611793877fef5b900d4012a6af962", - "0b02cdcaa9cce905ff6a42d9ab64e08de92e8d7073c6cb75badb1f802830d3661bab8d1c164e6e4d31d4a55630408b84d6e65d35b9c65d0079c7f92d6fb437e7ab", - "0a06028cc02b86cb973b008fcce8864680d270fb9e1a4c542079d27ad39070958c406caf3294279ce179f827e0e990775220303c8f358f23f6d2973ee514b1b6eb", - "0b07b9b90cc2793a9c690a7809d46c5e5c4a15800588f2820e2531a9552e3693c1a2f58b0aa3050127d06119795fe3b035ca24bdee5b4aaf2033d692220584ffb8", - "0b049b3a08c03d1cfd38ead140b5d7ec46701547ca478559d280eeefc5bd1a9722fd2ac30dad23511011635fd698f00996c30ce8455b279710f3760e764d94c486", - "0a03fb7e7fccd646c4738c183c9b22a17d83b0364b56439d78bf78f56b425ce01d8d61535d54879789402de4fb8971f6dcaa6435a91fb527afc7237839054294ff", - "0b02beb794577962c7555ba52669e0ec57c7956159a73df77be23c0fb4815941af621cd332c6c27399f09403a424a72d2eac25be665363c80e0a05d3191012b143", - "0a06fe638299bca2c44ebc5fe78482b070c51c854e8357c5cc5e69bda925f641ecd9c9106951c1b6c8a6595864e2f0fcec8b119876b6cac1d2a3b1f75a09fcd122", - "0a030fe29321b6db70721be1f28cd7cd546f57016ebe66338eba0dc034ab3743d75b5feb412d9a8afab22fa1c42c6603a1daf67362205a78ad145324b5935297dc", - "0b05ae138863283f0734fc75d0a9b5d897a3dc14ff4b1248b7bda2cc55afb967f0225a742b81229fe756e7a982371619158663f05f2cb2ef25dee7797e1ec24ff8", - "0b06769ef5b8ac96eb965bb2b5c9d5c42437a14c3b1e40cb5f598689e4678cc95ce095ea8620221670ce52115e45133341cea4c0172832d3f8707a825b251884b5", - "0b03a968228fb83ee55d366a74b020178fb5a3672247b90aa780f68dc05bf735216ccf9bc2508f81adf8937ace2f947aef8a4173c08ab5b9629cd1cd932eabad69", - "0b03ac4b6765bc2d8fec02f720b1c068eae41cc223d4fe19b1742045da244d70ba26d2b1aceef60d379ee0496203b5bd6720ef5725a5b727f03b4694de5f6d0dbd", - "0a0756e2dc0b5b6c375d358a1c567707690e8205d8fabc279b226add11e5d304ad1b7c13bfb286bbcfe67c5ad4210a416337a8d2c6d9260e582a7577c0edf34746", - "0b0322463c25d447dd92524e830d089b9a792a03330f3390d304d2cb89ba0b8ad20ff48b248919e1a293fe1e046f88b35f59d5fd88b31903650f4b4ae8eb9071a6", - "0b0521cd2275999453ed7a6452ebadfa59c7cef4a3027e4b95a6c354437306da18a52a6f75c99c928f4a014705044dab64fdea9fa3e54fcd1be3d7fc7247fe8b58", - "0b07cc79da95fe4fd8676dc85a0df86387cfa049e60b6b82d26834fd17799640429826fed177f464b50a021a22599be0894272547f19c5041d5263a0bf96b8ba06", - "0a07dd5a7be0fc3d595a8cdb12cd900566471a9b2f3fd88f651e3f6c28d3a08dc994ded5c5c6ffdfb39faf99001f649dd2d77dbed0002f92b787216533ec69afec", - "0a02bb61948c2afdf2738627c030a7bfe72cb05ca475a8fbfe977222548b1692f67ea65d9421b0d4b036ec8bfd3c8a2f78197286a3a9fe2eca7587dbb9a56bf617", - "0b01133023f187c568be1fad6e0fbeca49efa747c77d8e70dfeec6a54bc070e5abeb53a59ff437519b6e3eb7e79af86202346102b496c404065ef45c11d9113ddd", - "0b0017994f8f5451d2755ce810e1268f218470bb22455e2316d89a42b66ac225bd74196ae1b9e842cf091a5194fdc1f07c219805aa38666ce0d4c5e5324e1c78c3", - "0a02a443df85147ff7bcb8ccb86b4d50f66fd6eb061ae729655683899faf0ed5bff4d61357e67607206ac8950f1aa3199fa19c3774672653ed1be0b79d128844d8", - "0b062d2a0ce2bbb0d0d48c98942d75cc1b580b6cc8b5a6f8e881fb0f20b042d58050a925bfacb4aab0c48c0faee0aa812eba09e831ed4ee50743aacc569cfafe08", - "0a05c61a8f8bd975c9b188640b89a0d394a59835be377a287f2c0743bcff51004ac70ca2765e8c89d54525cde33e6a653d8c54ddb037794e869f017f3d21f8a3ec", - "0a0094c1a0d7c4a678c82b1e5c3ef122af6ba9487e85cf0d788867b4b8f7729556ffaefa3d93ffc75a181fa3c55caa190e2d2e5e728e275f0b09f2539a8dcc85fe", - "0a06477d34c8237204e9f5cd9e9b4d7a8b8c72a766c3b2037ddfb2355564b67a4f1cdd6ce4959eb32f9745f5ad0babc923657396c92e7df8c9cf7545654612e508", - "0b081b47db70a13b8194405b0b443637b9b3bb1604608891bbc1d26ab36ef74680b2d55ba2a955c805cfc80e8b0a522d404201911ec28b7a12ab275e6876ff68c4", - "0b089854a17a048365f447ed4add36a3a9a2e4d72e8ae2dd3d47444354d306dc30c387e398c8abc0cd285c964eb48211723286337a7f19f1ba68af3bc2b4e3fe2a", - "0a07f7439f48710e0c67c6537170eb2a1e747dcdb9a05a928a39ba6aac6f8fb43c07135cc26b587de78d114c09aba0d29ad49ed8191ec4dab43bd7aa13c870f0cf", - "0b023c372ff041ab3f6ce3890162771085f4ba9ba1011726322d2a796a06d4b1122bcb722fb379626242d3b8aa09bf60bc9e80d8f2b3d6ee3e92e280f002206e7b", - "0b04548b95de46d6a837fd7dc22c1ecb4ae55a65164852ae689f320133481150fe3e178b43743ad0949dbfa8d563a7a6219f2789ba0e8c3cf82f9fd62ddf352b21", - "0a001ef5d17fba2fa3009cda9961af694537bb8ef53f8adf212ed209db32f5fff09cc815a0f7912171004558178dc3f5dcd3d345e78c39e871b722bbc6779f4f05", - "0b047a1c6a93124a1a39900f8e4e80f01516dd96b26cba5ecffc735919366279f868dc3c078bc82989be7dbc860055569b212ff39bfdfd8ab9c2f72311ddf4ab84", - "0b033b690fb065f31378241dc316558bf55038bcd01775177ba80469fefcd4e201e4d099aa7e9b7fafbab33a629aa6382c4be94e98508ee9464cc8bac774a54aa6", - "0a03fab617c1501fdc522070770384e485ceb4752bd57c3f35626019a26e54970c1fcf893f1b3a739427694294ded298a212850865eda8ed6a8355c3bb35cc5db0", - "0a049d98546d310941a9e17158d605c8a0e66a3adfaca3944beaa76e745726089f8c52a2a1106e6cca7dc94596d153612479a19e32ecded032c1a60aebb16af5b8", - "0a070886d5a479ee89e23f39f86521ad45b004ea06a4e8407cf54cfb738b6a3ad4f1732e49c007f2dfd0aa69340685f9fdf4a73e42cc5cfce6a70312da535fb3b1", - "0b0532c682bf34b82282cae0d312d288705ee4db5fa26e26d4fa1edfee8e96791bbb1a40ade37dbd74a478f2f957eb7877239c2fdebcd49f873b6e5d00121fc401", - "0a08d0fdcd2c7ff5076329cc6857a45d19bc2c132de2bcb293a75d7960691742c9ca778c02a93049cc93e15c28c0fa448a829f2eb286dfc6ac5c2345096f1d5597", - "0a08fe837c8cafd2d1c8f23447446889d5fdda38872dc131f6cdec1cd3e243adf50eb1eb9491a5c802aee09bf768fca1561e34821bad47749efa1550fd2be3b5c6", - "0b066fc3108f0b531eb499474af3a2593f50c1d90fedd9b1b1437fab61eb24e1df2ee2ed195f0812ce557f140dfd2180793ff446849db8327b5f16ae49abf64b2b", - "0a003b1815ff30bcd3f02cd1bd8f7d5192b8a6a742f2ae43b612e580d92140ff3cba3f1af57238a16416fd95a6f59bf97eb435cdc56647a319b2999148ee8a29cc", - "0a076670f9051069d79b1bced2b8f2ed88fc9061d8a5645fed93a746eedd43caa79d271b8e5220426c904c6617f161864c6c3cb0058a6a0050671557998cffde37", - "0b0507725b7db52cce8f7913dc52e4602bd723aa033b94b0ed01cc4c280ebd28c6cf5dcdd2ddab1119129cbbbf3be389555a357c96c9e0f5f63812393bd1fa4353", - "0b007ccb730d9dd2b7b6da4b4be71cc191164a15831424c7de2b4d392386c0df38a42494b6f4a0141e537d7919b28227154cfb5d768d6bae67a5490df6374c69fd", - "0b0024868877a9bb67c9296b107d70d7719aed73f87d5b18f194be6f005297997372ad04e5da3d81f32ea8e8893cf69ae212a54b2fe45d0774927092ae31eca72a", - "0b0837ccf4fe6a37d7d8ca0a82cacc6c48f2ec7779b80bc6032fef77998aef7a70997749d886bca28f0998d705e0f9fe579e8e06357713bc6a711e8e7f4f1d33d5", - "0b05cb0b7676bf70531148ee843ca290aad5402c030801ec1edeb9902332882781266356876cf9f07d33b06679ffdeb349c34ba5246bc16d42829eefaebd2a054f", - "0b06cc5b250dc14a84c150d47cf41591fa18bf3d7c990a9672b9d8b23c3313f10dc5e4ce3a9dcb0aea1dfc81daaf5e37a9e014046b13fac3775cf20d41d115bc1c", - "0a08fe395aee7889122c856f9621dae3a265a7bf26fc014ab23fe1934fe6d96721b89e7554cb4212fa6db7d0611efe349674a5048f954ac5980fffd5de647f6983", - "0b0644e4a7277de0691effc23b9dd8b4708a6446565fc57c15f74329cb30077fd4ddc735e86b8ba7fc2d33d3b1d2c664578f8c1e4b8f18cc15c7b63698cc5beb81", - "0a0390ed611d7020bdccf43432fc45e9a34349f091bb3bc04dd34e80d17907257ee7a7dc3d5ae2162dcf51ac68ef462581aa1f5b22ccd167421ab260250027af01", - "0b04b5519ffc89704816e7f5deddd2e0522607ce03d85aa4decd5a067a6c2d6be9436894145a5ed496c036e8a1f3f347a186389f9e3e432ca67b3c9badf5542ee4", - "0b085765bb157680384548e4db95d295df0bcba17a8b51fea4779d82c1a9a8fb1702323f0cb17c73a42e48fe555847c11644c0c53bda37a4b599c037966cfd662b", - "0a03707fd66a69995dd32dd08ec9b3291924a608cd4e7399355798326980f733dd91efd12ceb67df3ca729d56ce9c1f351cf3fd6dd230236ac6e5d2592c3698339", - "0a04db41b9749a775a0e6fb86ad35a2247017dac8d4a881add550de63bcc0823f468630c0ddd4467c044ec53c4bfede1be77ab8143f6299d7724c329c9e9ec3a85", - "0a00c375e1d79245aa9b98a26b6419e1aed63b9d80618374d863497c5f03dc16fdbd1902df9ec6bac16691566841b75624fe04757c5ad9271e4e4d77cb60071502", - "0b0737150a18156145576d8d4cabefba6606fc7a4a1191a9083ec9ae0d2532fa318ac3040113dc2f88b9b3c12c9bdf9b97cc533ac98b838d9d3a7cf6da4678beaa", - "0b024244f9a0c198606a78ae235211dc6d93fad46e5748c7f7c3e6bad193a6efea17f6d4adc323f5df3d7f7220e5ce5529911ab8a722146ef2d8ea3b67878d548f", - "0b08abb4f3305f3c1f4a9c2db834bf150a156723c571712e3822b4e9ec5568ad9f8cec1382faf61a954c9a4b92a62894231331425cf0f6a81024e51dd518b008a6", - "0b07999e6a596923373bef329c5681d12355ea27d5756895cc56ba4897de36c1aabf1ea2b746806461078aa4999ed14a30b228a0ff3899c09d4c702134375f6260", - "0a03e5a225a6b7f86edf7af5bf3068b43a8838df425d73ed93e4761c8a76b2feed1e9b247f2546fc6d0d6fe849d9e7d662e07cd03edb9a2cf5869c0a6afa55b405", - "0a04f045d9d36b70fb5c9348f9bdf51aa3d2b70d79d2483cc25589a785d4dddafc6512b2af4dccba9a017d2f0853e9bb72b9acd685ce6d6da2029a0df05f8b04ad", - "0b065901681efcd74fa3c6eaddf4afb02230d5dbe48149e1720fac18e71eb83d9528be65a660f35a420b97cad4ec25bea3234b3286e05885eb259f10aa612cd056", - "0b02e0990474874b6d63099f65e8e49c5fc32931f86b7efda3edd6bc3307a60165207d1bfc050570f32a818f41d557fa02d9684bcf42fabbb6e09d1599c34da135", - "0a06733541b400bfeccb4172f33e1a707e7062743b4727b3f9c3a6437e6b10f7daf08d6de71bb8caa03b59ef30ec98a70f3f8bc7023c1893ad5a874c3d35f4faf2", - "0a084ae27cdf311641bc21fcdc2194308f023c3c03de92ff953d26aac5505cc72fb1683d4ea3caa81eec26cdde9b9093aa8e3318a308b7bb27f1191ff5bb43b68d", - "0a04937d3c74b3f489715118327ff8fe862ee7ca55c6256d470cd8d4fae8fd3cceb67be14c089bec1701abd305221e65dea33bc0c1feb237a128b55a9febd0f80e", - "0b02411c096374fe5e6a6c55f74b4761defd61dff38509e9a8ec452d0bf2abeed66eef7532847e9f2c518f86d004390ae1d4d78e438d38323d3e3938485ff5c7de", - "0b06d550f7a212d12730ab56bedb8111a117cce32c3f091ca4f2d3fbcaf4d233e6960ba188ff5d606e5bdb686a81c28003e0c299d47ce310ae05f6e749e75b4a8f", - "0b07233a8a5f319ca82a1687089a7e0069601d14f9b947ae294ed2ad88209bce7b5a305115d4d11ed7159f9fea67cd0795e55ccd9f19aec42884fd8686460d76a7", - "0b063909fcb79fb82139c6469557ed968371c8dbc71b140a1b984458b457d112a9b48e79484cd0c1781ee8888498b0f9e433677d59106477705c48086548097c82", - "0a050a9121b4fe8c1a8fbaa91e01aefbc40fee03471bf85228a99409bb045c059f2d56ea4240c0053a38762251130d8ddaaa24c6b3ee0deaf049de6e21d535ab5a", - "0b069bac1822a1ded97eca1ff7290a7707dc2343d3b2b0ee72160990330e1992e833c345cb8a85ff5bad1abc0a685687ded0552d36d7c2e5238b2218871200501c", - "0a016430df67af09b7d9dcab8c64b3d137a76a93282f77f0f83ba4ee10c01d007783861384713f7df6362b6c0f60542f1b4d58166eb7b7df802b61b957401e1283", - "0a06354ff0ec610e2f5c6d8d660e87a6568e5120a13080edab440622c8941d323949daec4883bd574a3ca7a6e9e5d420579aa6342374e84a7dce9023fa79c0f59f", - "0a01829d313a09f66c4ee8d1b1525e1bca84bb8a45ef1703286c3a292ea4ca0a0492f7f67d10c60427fb93c91bebd059a42e453466e7eb4a0d9351dbd5619cdd91", - "0a056574b6b934b521d50fd2da61993b816847f10173c8ae2e90b62809fbe05f0809773f6d3ab25ec33e8d577624742d5a2c31be1e5b24784e2d6f5de72f26dcb9", - "0b07fbed2f85d3b6f443f73e069062184df0dc0fbe1163d5f5830e5a25ea46cb577b03181c271b6efe81f32d83c030ece7e91994d95201e1c4a34a413e20000272", - "0a05d2a85b4a5b23d3f514260cefc77b9253db5d0b948621db3cd0e4fe55e2d53a65ef8934e80aebd7cc2ae5623d7bdc45df991a668723e5e8b32329e6abc19135", - "0b00734a0aff6805f6bf34dba4556e1c820b482befe112dfe46e78ddee3b78de1c0da9433996461f9a46c204b1bb5b869ced6f056a01c13155d7208ca6a79b72ef", - "0b03969d6183238932fe879ab2561ee47e944beee33a7f77c0bf1c55ebac804dbbc153fa4b6a6059c608aa7ab565de3708675c1ca5f64bab40268c9c31468ddaf8", - "0a01bf6684ebb3a65d61d73ca0b0b9dd517ff67789151a8d5dce72d0137f89edd174f132c6e644e91286b0ce40f7c6faea66fa659b320cf56ed9d260c36eba1ac9", - "0b0490a7a1db4009147a34d49fa081a39ad4d9c27b3dd0094a816f3804bada5f2020bb2a7e8acd193ea6e92207b70a77b1f276ac37ae2d390a47efa701b557a7b7", - "0b014e49a5f6068f43c763fca7a86b78a7437e7255f3bd8a123bdf29881ebca0a5f4c5d23fed682655b7e2069a42382b35bcf1f5df369bdcd7a411b16f3a470399", - "0b027906b349c9ca8d5dc639bf32dcb21d61e0b3bec74e1e72d953a9fd4d38fb562274e8cf389c4ffae53a3ec7f42c77492a78f8614755fd828e7f02d1fbdcd1f7", - "0a05477807f9a71f90f9938cfe3d1a086720ebb0085c04973645ba524a357550c3e9060f5a30cd8b9a67858d4004eeea3d13bec2c793150388fb4ae0280a42ecbe", - "0b026ffb4cdc0f872f276a3a176aaa558bfc498824cd5523e3790396a9de408995284ee602809c903b33ee465e64653d7422df9668df839315fb8a92d961993135", - "0b065e989643888393727179f5b466e9bd4e32d37670319fe22e68f358c1ae94b5a76ba3cd37e1f1cf98d36842373137e4d42d37533d8f2d25098198b3e4a934e2", - "0a0095fcbe10ef6c8dd13b7812da4e79868fb346573bd59d6d86cce9a7c160fe4f0406017feecf3eaf9388b737276ba889256fd7022b0b5a20a6df92b318a3fd91", - "0a04777d3ce3094046f5faf0a283cb8308eb2bf4fe309ef3edfd7d53e83c52463fa4c38883e6a657a96c5ed7a1c326fc05d781c83042150ef760aed901543f5b86", - "0a079303dd96fc189b85016c21e760ee224e49b21cc66e53e7fd8c1cbc67bb343c848bbe272e40c71583edbc37323709bc3466dcde0bf3639366e6f63751c1c080", - "0a01503316d7054a9ffb75c0b99e993130e3f3bfc514621e203b10223cff78a670d4ca0850c16269e806a875231879b30228d5268e446afdf2fec13f764b939832", - "0a031d5e0be41e5bcac5cd8a352beaf756cb17c558913769674ce934e2956c8a243318d4a5e46c52802664dcf11597a2d3a96aa0eb2700e0c453d044842301fb1d", - "0b051dbe82cc2b3d23d1dd659175a5aef75ff17f0d25f34600ade2c27b9d58d39eabe7ce7f5e464f0607fa5fce7b367807a2f2fe6a5b091159545c66c0ad960846", - "0b064792a0740b8560f5fa7f6d730c607d860eb4e8a0a0d492c5ede6660effe259d6d76316adfcc0068ddc1555cfadb5a6e92271e561c0f0dbfa86882500020c64", - "0a06b06f11b2948ea96ccbe3d1c4532cfa5a093431756ce8ecb97de48e966d50ccc060fdf9a6e357f82433d5166f707bed813b0dff98f914127fd0920d1f7bb133", - "0a02a424ad9d0f4f361184189465b6a297b807e5001b31443cb3b196ee0502a0cfec79f2258db187e6cfec923184940731cd8a62565a6b9f82a035d79a8c567fc3", - "0a090a66f6e3054374f5b2a15799736a35911c61a3645d3b240a1216627ba282962f8b277dd28eaac8a7eb96864f8be85067f3b4057e848f9e3c6c5ae073605e59", - "0a04dc065786c0a7e9c19354e701abb72a2cfeacbe9427940c806c8f827035a9777ee4e32bde962fc6eac035c1a9649f4ce5c88f1dfa4c526b4f45961620de87c6", - "0b00882adda47e6359f05509b0a10455a6a06e46554242c5f595dfedf360677874ac99858c8ba50f1b955f8e4b492f4d79fe357d4d895c393677203538e50e5128", - "0a045e33e1970264582c0db7905d987ee3c718d9305f7578f36e61044977313940edba6c96689b3cfd0e355568214149cf2dc51688fb12497308da23cb130ed528", - "0b063cf332c921ee276683173f5bb8eca92d6279bdd5a924bd9a10f6b4ee9d8fcf42443a8b92210af849869b3da052bdc490ea89eb7e4b64a733b0376ef1cd886a", - "0a03b131bf802ba617ed0a4ea0ffdfea4c00edb9883f1cbfebbdae8e027ca87c0f003c24e93876e98e08b36d82e9e8f12bebb15e53c11ab6d134645584c4c6ec3f", - "0b0554d994f16e40ac1c6524af10f81a4060ca0fd118d68ec59961c68d505909b67e8c5c7ae648ad857343eee40f70bc04f0490b534868fdc6e91351f28d25898a", - "0a05d1c321b346c54391f7b5154c990a6e756febad1c463cfbcdbde6a8cf1138995ebc39a8d7fb8de00da1636b19aa7b53f474d9f51c29689e45682efe90bed9b7", - "0b035a1952e5c5d1c4b270279d07ba5b28ea7caaf99d52827ac7a3cfdf4338e7cc617672dda442aa39e6ec843fcd3d5ae8bd5a1f6dd4d57b6428997a59fd6aef12", - "0a03163e85ed584316063b757d29936588c7314fed1a84f7ead0ac3d38fc3dc02ad38a54c90d9f00510fd5bd5482ac3041aac48629e2f100643ab9545d5a4c5b5d", - "0a03393e717e70913e89fd22e805d13294f45be096168498d00db9cfab939fac27c7d46249c6e5c6b66bc593ddc85d3f5284ed8ea9f9f9f071dc7ae99d22e9fa22", - "0b0600ddf1fb81fd55ddf1ec43eb3899dc4add73acc23750f29261bce8dae0c505229321a591736720ddf8f0e07f265fe1c4d65770e183a46802071084fcd5fe61", - "0b02063fe9a2f8fa7bf66e1214fff7efd3cfdb1074c91bc2759911c4ff56e6ffe25f65779a6884fd8f70e4449f1f4eaa151de7924d4786ac6c085ac785d8db9536", - "0b05591574f2e8650f37cba548a08a113adb69e87054cc196c50a4bc55af16af35dab1458fdd0e234e8203b3960bb88a9949c51d7165a9710cadf54b1d8c7df1f6", - "0a06259b212a20e7e2b896bd898a41450160b82cf9a23ada6750ceaf3c5b867fb0fc2e891a8e5e7532bf1b48d5f9276b202a00e2d74fa8c304d1a35f7dc7cd2edf", - "0a061e4cbf96828399173c93449f157a1d2d866bfb5d428dba97cdc6144c059f82f625ba8f09862deade2f861df3efec10f7d791e64181672e4b85bded02ca1367", - "0b0681f6541c01283dfa8d2409c4eff39f2364351041f0a6af777b876e26d994a18bae4e787e78490e1bf9096d20fac86f9702838469ea9dbe11909473b9d45139", - "0b04fc1ac65919cbae6b8dc2a1c2b99cf04d5192ef812a26370185442c8e768614ea86823061ea9cf007077a25a243f9c95b442812de83f36b185f04e9a43cd85d", - "0a05ba3b2e73fff871dda21c2fc1dff06a4e860364c702a56c7889e9341e0ecdf48468a264a626f07d30e97157173751c520ad83dc4222fdacd21172d96ab90c78", - "0b0055d9763cad647b2fb9eb91aed097904910cd5d590b9635ae20598c6187671dbf06927979d05598f6628f560e09eb1d652bdfd42a121060af1251d78a8eb66f", - "0b01fed069d5245a7d4af2b345e48034dbcb897c3f4d3640967f38a711bf157c29b8b6ff901b2219db2628aef52227024afdca64afe6067f2afcc7df12987633bd", - "0b037209d7e4bae0d8e935c663296655c7313cb3b3e68b5e74d9c31daa3fce38167521d9d2a7257951b4e0cd85e37b1105b81304fe2a1bf38e94f7891332737a6f", - "0a061e2b8b0e096417cefacab7c3e0e93e496035b290eb97a2ed2800bb040a065854f5bb09c63036b2eb1ada94ca4608fece7e20b9d325d5ad7bc456cfaa281388", - "0b0721b7f4718198fa8652b2322b2076507e1617848b10640f4f8129756db5764bded3f7f1a4c50f03d0fa9b8af286eb0f2e2b6bc69261a68c8fb4e0e678dc29e0", - "0a07156e4ce7f679df2f786ab0a4c7396e57720fc573a905f37d3715d523e868f6f5af167bdbde4129d67a2ace49975ceba430d7a1013bd776741347891f299507", - "0a02ac6dce3d0deb29aec6e320f9b152a5ec4cc07dfb271e6b7fe89f547ba5103ea19b1184a49291a097677d52a2f0d54d9302c24e010263cf7841ff2c0041859f", - "0a070999ac3e1e415ff02f23a5a5b8981499fbfc958f2220314426113cb7aad24ca01ce80cf230ce31732b9ad3d2d381047033aa665f289f0984706d7dea43f18e", - "0b004f377f7ffb5ccd877b88698e8e8cf6f49f66a378dca07879f4e63381645265db3f85df2bfda0ea8e7045f724f6d5ecb57456b924cfd702c05ade50cf5d0164", - "0b0351275ef9516e1846c79f3a549e4990414ef95520ad464b0a63122b56575df78d5b33eda70c2830c3581439a0f3a465a4ca7ba88dff2bf211b9eb0e89fec052", - "0b0082033fea1b3c2d7f451d3db537d97a539d597393474a38dc20d7aa6c1b7817d494dd93b5d174425b467d38d1bc538fe2829a02363b9c7231a8d5a4293e4268", - "0b08091dc6501c0128350258fbe315302251aa65ef0571c0711d23b727db695f823992e85f8e2734a9d620804cdc67c57196f86ce1978932deb8f2e2d660e3d5e6", - "0b06cf67a2b72d09d0c1f4831b96b226320e6423771bfcd6c49e345b7242bcbb3dbc7a2d2905b6ba51480265ce3be684a9c1ab716f221a1cd4b25e9e3f9c7110b9", - "0a00f9208649eeb011b7e54c63580e3478fa4a0bdcd718220d8a869adc562451931831e8236bc7db2d2dc138a13c785dd0da825b496ec06f75c7653c083c48ad4e", - "0b061d4a6640f858690cc36fba2f2b4fb8ac428535b09a5c325ccd9e94b990df9b6f034bc9d32e975e7253338ed68670fd2fe1b7cd85e5cfbca3dde4cc8bc081d2", - "0b009bb859a82407221b9d281ae21fc520942241de92e655a81adf044946d83957bb98f145fdbd1c75de5ae040b1b91d9bc296e52f37ce518b7bc6382a3d462f79", - "0b0361b62932d9db844751abb4ff630f0a3308d8a628128f4a96fc363b8dc157cb34974610c66e794f796e256bde24eebc381b4b285ca675e616135826ced45aae", - "0a060853a469c9629875326d125f7bf3a3e8ddecc3ccc180f7ba72054f1c687ef7d31f61d2c6de2cfd5efde9f31ab532356f93d4f550d986063235c598704dcc6e", - "0a055255ff16e47af081bcaa126d26b24a81968f6cc9fbccfd4c7ce90788d639c6f3dfd655d565ac7db6935d995a8eb97b36f80e4ecaf0f2845d02085c9515a43b", - "0b054c0393f3fac466abedcfc7049da3b56dad52678b563c38099f05d87f67fa3b7b19f8e8687b4a64042c227838a0dfdfb099c65fb3268351045081a6f2bbac3f", - "0a0250b9122ffaac03b03642328ecb8d062172b3e47d60574d32303991885256069e24bb5fa44b7dd8760b41feb17b2bacea795377cc47c7e75479165f591dee7c", - "0b05b3acf4f2887d3aa3fc46972e738c24e5b33246e7284ac9fa09605e340d60bc8cf2f03dd01d936f0a06a71724fa2399fe70abda54cdd21d6d5383e734f181ea", - "0b07fe59efd7e60bf3fd8106b8c9b5c67d01d4fd284dd88b451444c3a87ea4c7f6f26e861a1ddb6fb69f1d54d8d92f7e3a844084f45e8f8e89239576a74fd027cb", - "0a081546911c2ffe8fc6e1832594fe61ec665ad10f72f7ef8969278a1354b083aee79dad66a570e21aa716bb15ed10299ce67658e98e6ad3e6d231a7b2138579d7", - "0b0743f80fe0e37effa6dca147332229eb9d6f8a331a51de6a844f73b787e715d97fef93c0d83653bc31ce955d8de3df0a4de0a57968d7c8ca6ffd0cf553230fae", - "0b05a25dd9f0f96e5f912feacafc85f09c87712edc8874ba5fb92addd82ddb62fca7db6421f9f6b5f0f688c15bb171c29bd5e005937783b29589c5712e2a2652c8", - "0a0023b4170d2a1b2e71eeba844c1969659da37842205b261aa475eed4d38f05886b64b7c870612bed2c98bc4e24d4795346ca8dd067cc906690a0bef9e3855f7c", - "0b03976aa38cb389e296ea940022d88f43902549935be1dce5fe96ab01b31fe059d60faf7e68f43ffbc049b3e74853c73afd2cf161b8053120959cf0f1c8d2f039", - "0a014d3ebdaafa0b4d198f5fdbbe13a9ef7b12133bcd24e22be43ccc1f2334a82bf3866605bfcdefb0eb8770613afaf7aee41e6de8dfd07e7dd67080981bf06815", - "0b0339380a35e4108b4a8742c402fc0db7b1d3da488a1ee60d98b31126fd82ef532a983516a59f8db9a430ca2f5f3b672b5f8ab7477ce1d7bb14755b011e2f36da", - "0b0304f0d24bb5771d704ecf414a2d5108b2620d6a82f1ace695e1e26ec27cf4445a27365ee1802eb74589f6e72318cef095992e54f040f009d28965046382e3db", - "0a02a4d2a0bbdbd8868928a9dac479a848ae4ceab404c3f6cfcc78abcfafd1b96a8d606cf39fe5869eef9e3070f81000e9874860272111958f4b3c94928a5f0162", - "0a089f30a0e4c931316e58c4d0b066aa9ed15332c89f661e5f08a3133faaaf47b9f91759a1f306470f82a034f7f77cce5023922ef0590dcdfdf2f009b6ff3c5f76", - "0a05ece1a5a3332dd7be0fb09b1205415af7a7e647f7fea0e281abe1959c2aa7906d44eb212ec81ca53addba227544a69c66ac5991c1af5c8981d1c38f69ae6a0c", - "0a06c628b65b793b063484bba8be1c23aa1c6453f265dfe2e0245a7dde3597d777ddbd151855a544ee2c8eb6acc4dc8feb53e6e6d4ca9a9765ab52097602b2d2b3", - "0a00cfa5f47c7f3b5b9a9622e36f3e9250683bd4a657bb1decd1e04511e3291b023ca1beef424ccfed68c361b64135e1f10ada1be7104b9890b739fe3654e50efd", - "0b026de12cb0e27dc8b64fac689263c227721c081b584af6bc9a76a7d79531dd17ef1e600c5ae1de8dd358e9680881798d78c1cc817df3eae4f217035e569f93a0", - "0a038197f2a8089297e32c9eb3555ddb99311d5831eec72f4a4530f744694a172823ffccf46f3be41fc7f9f17707fc70defb0fb5fded8c176a9357d54942c2a451", - "0a05d990e75e24f8fe183ec9bc44be1b724aa2595569106fee13b6e509aa68a7ca4bbb2081b448acdf3ab2822e0d1efc097a463148881285f3b184e4645ab91f55", - "0b0812ac47810466c3bf882048477983502a04e213bbbcc34bd09dc147577f3a7fe703bfbe8acd8a235733ca4a0f657a67e92d1a823abe3e6037f7ef928108fe1d", - "0b03408c67c2b761a2ccb625b81e3a4c297cf088e8f374f69fc1d90b54122766ce3d367e15cb7b472a75cbecfe267e24b19fc83f22bed6b951ad716a6b1e88bed1", - "0b050b79f35336e779c5b19e33d7ae28b10d51db00def1520fd5c304374a3cb9c15d908e5274005d8513a959273595c6dd8bab248c7869bbb80d3dee16b8a09b4f", - "0a0064ab4e0c112a0429ac59326bfd6cf2b432a7c1098c7bf68e77ea7faf12e8eb62d2792d19539c5691ae2e2caa624884b75bd0e4663acb14472069c8b55af7a9", - "0b07dd1ce49d6aaed4b0bc8167cebc592518ed0c172f44b95dcc38f0db4548d6b9cea6d5f085d0829a154bdd21c882c8756cb5050ca3d82c287544875e72ce6609", - "0a03b6315ad4b24c0e4dbf7013bf022c41f00c52a5320eed0c5160e45069224d463843a1af2451223f209dcd5c4fa65b774336c387ae00cc4dbcac0cdc13622901", - "0b0472c82bc36731488be74455596040c759a00ffba01350d406241d5829426b1d92064602fa261585ee540f4563c22fc847ddc71d508bb94a9c1c806d170f66e1", - "0a0881abff486e32faff308bb41766c401f14671eff4d51aac12fd3c5b3c0fa8039199481dddfba64588ffe89b8d161f6696cbbef71eca6345c6a9ccb5e9e4a605", - "0b047c47c8dd358ff4b2a58281ec8d78fecb02a6c9fa5994e7cbf99aae0054a77a05999e37f181310acac933c286755800060c5d1463a7498e58880cebda4d7633", - "0b05b561f217ad4ef43bdccd40a5547d70516c0f357f60bf26191e111ebb0408a19b364edf6e2a243f27328c701662e101c9213ed8eb08824ae597d68ed489155f", - "0b075927559dafc96bcbd066e13e71e6d9f241bc5047af4329ebbb7b31c6166650aab2eeb71994dd0477aa8fd426e6936fd3bd11192d4006e777614ab04dfd96ae", - "0b02e9b41db71cf00b80ec10f4adbd51e6f8707969db607be04a54eb98a853585896e9f53b97e061ea24b455a3aeb4c342162690002dc71f077b7e01f0a105e6c8", - "0a0692e555e0b8efd7d2cc1259afe433ed1dcda2ee873656661bf8ecdc8e2d551e1f9da54eaa776e97c00d3b7c6d2ce3a339b18d47635abdc109648061319cd45f", - "0a064da8f0de6654d2f9d416d2e8c28cb89826d18d43a7302ece0aff77d61a936f1c36d44b249230bfd4f36393e2a72d8dd54dddea28ad7c13ca7e9919c8786d8d", - "0b05f06d40ba225756f13793932525deb57f7f6b6dee9ee125bdf6d1d826572f7d988fffee8ec1e6304ed81079906b632d5a3a7e67ac34d75205d58e244a742c58", - "0a046fb31c84eaaedfddce258e191cc12f5236291eedb2113a193b9c8d5d3641aa3f2336f865165c1791a792829ea0e21dcaae9f640278fbce7a9492b7fb7b56bf", - "0b03c06a8e34b738832a994e9b338e6cccb2f33e36c8c62e1764774b5b0492c068b4ca0027fa23ee5f0e90fdaf24b93b5dfe8a4510d849b34abf5bf8cfc836b057", - "0a07f66b492c525871a9495230ab76687e33f3539bed69ab9a7907de7736748ba1ad6f0d186f8ff2ccd7e148ec1f363c735008b5a44af618c61fd14cab89bcabef", - "0b0871acc3c0f546d681ef8dfead1ecf62606b2c71d5b408efbd2c43b70f8680fb469177499e1da1c88596f67f3a07b421cca7a579db531031eeed16c1292e203d", - "0a07962d8c321d6ab26964f9c6e61967c4ae2025a6159821e738833030562994232e39ba4a83c6035ec7375a4788d35a8596d942ccca8d3055a4d27e49192c5ae6", - "0b091439682ef11864bf91e148f4e06e37a808305f1e0826a056515e63784c63e81b1c282754564cdbbf851ae5968723aba62dceecb32a09b162119eb58f0a730c", - "0a05bddbed9463872897b8af6c0614bb94852153d2d32bbfcd1188ce4beb9687a5761d4b59b36dcc46db94755578f3535bb77c35e9c1b264bcdba43db84a6238a3", - "0a0046f339b3f3c0757503c6ad4c4c97a57957d1c5028f2269da8a8847fb28420bc7a4808912b760d0a04b139a2e2e8e6e0d279c9eb244cc73b31ffcde0a67d6b3", - "0a02e6ad2dc1c141110a0433a272fedd21380437d86a29f9308d9aef9c9747a4a1b25cd541ab7a2a6e15ae8fa9c74c557ddebec6d62bf830bf139ae0321e1bcceb", - "0a08ee0543aa5290d25d38e0c11b766c2b5b004f424fd9c14c17150573f2e581684513c8d4979059eab55d5388c1de349920a9b0e32217e8b6931151ca2317240c", - "0a025ebb76a30ab16623a410aeafae5a82493c5cf083d89683f8f47fb87c8c2b93dc7009212bed41a90b49d976bda88ed3fbbe09c58cddb393f2183d901f7eb70b", - "0b08ff990f08e04c7c435df8a069717358a2d1a5e134bc55ed40c98e606d21ad705d28b2bf8dccbb4c097e6a72ffc5f78ad926c13b21c8665e1bd40ccc24c8b675", - "0b050a86a5cbe5b5d62c51aac422bd7753c105584a96144ebf8fed61a37d29feddf1576d9ded2e641c54c9ac9f3c1f0aa252b2b7caa08133c93e302bae0584b67e", - "0b04106f2d461a8bcfecd2434611733fc14f72c8bdd9744c44b455bb021b6d658063fd9771d9e5fda3c084dadbe126480b51bd69f2432bfc2bfa2fdd5d549008c2", - "0a03b7b48c485f9e03412b58aefac0b4afd4f9b435ed743003e2c94886fa5f053817cb4a8374a57e4ec2ab1b9b5c750a12fa20a07642038bb36263de60905fe85e", - "0b03933374ebb08157d64ed195544a142782ab09ad0ba8692f7cc330764ee7e63a9cf6346d442b2b720dd980d9907918f1537d8046029aa195d18137c2fd963a0b", - "0a00907f36cbc8f0d7ad8b64dbd481724fcfbd0e240de25e4687ed17c4787889386f9dc8670d1fa2341386cc8ff84ee88cdaaef7080e508dfaa078e2cd0d014534", - "0a060f95db97cb66751920be305b0795abecf7ed63e04988e4d6c0d8236c972374bec51c644f9045e309b25ef7fd636ddc20b1c21d2c9cb834ddd900eeb7284fea", - "0a0083e6e7e2f983d37e1f251bfd58673f924592bac4dc3f5b7511895162246159b587b3e171a1c4f4479f57c52104e543014b68c34ebc75ab8400f53e8f111d02", - "0b02403035cd740bc08dc175bf9215775335fdbc178a7925e1bb6beae777cea3ecb764e48817e70934072f98789daad76f2bb9e62c609ff19f395e275f5ed93897", - "0a066903fb77ec22725fe564c4a250cbd92da0739e05d17e7bdef1ba8115cc787cb5a1c9109a8d78df78178bf75ae49a63f92185ed5d4ca632c2241ad902d9b9d0", - "0b0391ac439a57e1389a6bf1dca861cc1a1ff1d2f410f5333eca2476ea490d86cefd46bce50be5965903526f2055138bf8ae970ddff24c51dfed49f981d139fa1c", - "0a0077760b04f0670571c14843b4054e1771d4703e1ef654b69b99fe2ee3d7d298526c8a71ff9f43250233cf7f88293eb6d4018e3b4588c5350519cddb01878b7b", - "0a00d942aab54bdf274ac105a15ff9df7a95c549916d592e80c3256e808dd1f239d0f71d7b950253950e95fed54ae70360974fc43da190209b8b68a18f19810692", - "0b01050f6db6220fc9dc7ad86177d230bfc4475c97144047221c3f939a7270802559b6241ed5da0ad7c90a6a57173f89ff4ac38ec093ce0581541a8c5621cf484c", - "0a05100ecd66a6ab4b41391417fc83f6e7f7e601ad48ce85345216f0318a85a490271b15e2d0949c12efbb43f52151a977fa52696ba7943b2ba64210733db344cf", - "0a014e31454bdef824f1979760ec558a2d05015e4bd9ba5efec6a0a25185d5d503981316d91a4eb4e1ab461ec77bc24c0d80a71b1472b6c2d6bf95dd2af0ed19b6", - "0b07830643deea876e26ae8a07e53ac294dbea9522252ce7d9b056b577b1e5435632fb4a518ad32c900e79708df5317aa699e94d4080a9146d1a28d4cdf5397b5b", - "0b0366d386b59f5cf01c62d2c8e8aaceaf1aaaad93397d1eb81e473e6aed48d4f7fc72761a79df1783287466cdd4d94769cb34fbbdef5180ac081c238b506bd564", - "0a030a8e8b8f51c04968b39cd30459fc869e9bdbccc6ae9fcdb86d9075b67e45c7b50bbf44923bbc25ef96780f59f415dc72692758abe448fe26eb108d021c2762", - "0b06978de87a36b97b169a6e28b867e9f12d216047e2d632eb63ca3c66306bf86f175dbf5b7fb8c2d529b2b77a9887f8cd8843257b1ef86840d703bf57a9a15e11", - "0b03c2375e6f6c91e1f5ac4c082c947ffcd7d1dd2ff8cd3561d2134c8424d62ba4be0652e639ed734eccac5c55bf4d2e856cb5b7da806b928aa2dede98e2d06648", - "0a030a7e0e08072abb9fc70d1e8137d1e36bc3e46d259019a652fa4d8136819fcfaab207be928eb72532fb82e070c30ed589588e7e42a13bd28f43997f4d11ac97", - "0a08cff5158de87622a0314087f136b7fe1619927227a702922086a62e6498bd0485d895f70d247a70a36a829d2eb2e2bf8675d985d47026d877a56f3f6c564733", - "0a0016cf546aaa6a4aa59881df9058d249fced54ea32bb3d8f2becb53cdd82d1beb87fdd2b76e7d1ee2da2a6d6163fd07ba2ef2a773d5e94f4a55c68fa0b780f78", - "0b019be2cdd95cf75114b62bce2906ee3b475aea51d4846e79d3f83cf6603f1d237218f9c080235288e3dad95093ce2934098502c9e6ebda0bde078cbf48d1e73d", - "0b07b652bd02eb70c18776f933c78d35e294dd7600eb424567c9a7ad2fa7cf6951248662dc4028d5d3213ede2dc3684c88de05be3a5129707eae4a000f60a883da", - "0b02b703c86fd6fb223a459f2c930735f4f3b3b0ff3b2a3ff73b4d9b951329cb49abede1a71b9a7609804f8d993b6871049068f077f2148a7b344f5bb14480ab5e", - "0a08499e452ca5a7e580a3656bf6eda52bdd2b6a2f2e5cc9b6f05fc6a0e0399f64d27b944efe2d39e4e5afa4b4e7381a7dffe109327e3d551730780397f33452c5", - "0b088f4c9a405a80a85e5da7150ae9b87b15ee2c2741e596528302e796deb077afd0c90ae7a88b7bb336a99fd697d46b70e7715889b3ea2d616cec5c8e79a6af4d", - "0a03910de99161008c395fc75ea9504b4d513d4c1ef513131ed465019e7ca643403269837a6cb85b756bbed579d4e1e3ebeb4020ed2694d64e3732394b29d12eeb", - "0b04897a8bafea21fec3bfee2b73426bfdac2492959a10ca6599cc3e93955fad4f6c1e6ae393fc93d51b94678df5b0d10ae7b62f29df468e1e375d15601269f094", - "0b018a6766308ebf847b421618dc1965cf2835e21f330a184eff6781a5f8e0fdbb6b8fad583d66eba0e1508c0bf9a9cebe7e0707b8fd8f0fb1503ba082a6a5853e", - "0a05f58acd9e52f8e80680c3d69ae34e832946777d693806f2dd568a30c7f6e44a9e075da0f3e50c7db50654618e131034dd20e1193ff3a26a09a0f1fe36d2279f", - "0b069918dff75c1cf872c3d8292112ed6ebf898aac8cae6e70e9c356f941cdb934dcc5e2ab2110771d3fb549944277d677414548476bdf88875a5c1cacc4c79e5c", - "0a07514534024ee0fbeb6d657faf1b5ddb170de8999f30a52f885eb902ecc450e72ff6d0802bfcb33d5fd87388db3e3f3bb0f928f6df9ab67e316cdd1c4f545ccc", - "0b085e1f7311b6789cee238b6af89ecc2af83481520f32cb58423493007acba39e42c447b745d0db10230a770e1060c5a14ae930ec29c036e49f0eab0d91f25b85", - "0a00003555830156880c91c29343f67e0c294fc2b013693c2af31858877b85fa2e1d971dfdcd8f0e5785400fb5838bd534044087e8d3036f1d51275d3729e7a6e1", - "0a0795853f590628ad3ab3df8868f0eaec1f01eeb30cf049dcc1461bf12c1543bcfd41f217f8c45ba0377ac3dc453128878d373aaef247f4f1325367aa90166b8f", - "0a07f26dce3224519cd8152f249015a79dd64eda286209de340fc3857233c0540484a6c122890f57838539dcf3700fc18cac9e3d26e789e90fb4ac6c6136e335c2", - "0b076693848b988297b804154e319d4489bc530a8404c530631a09e4abcb264f95524716fdab41a79432209c3d20fb91c6a5cc47f39239015a6d9b343fd39f51bc", - "0a056e3e790a86a478520473e350bb217536fb3eed432e457ce0e0e589f3cc1a800cb8d92c1d504b3cf57e352029b376160b0834837238abeb3d82ad448034b7bd", - "0b06a55e8a13471ee08a70c4dea4d7ea312f1f2b1b7b6668b7646637cc67f08174132e049430e3e24eea07d0474e820342b128ed7945cfb6f4bfae9183cc09c230", - "0b030ed58334fb9b7d1996fe1137e4d38ef6dcbed374bd492bb02d65d60b5eec1d3b510d9959c4a1d905a4d62af2a89b73e2e32da33a6fe527250eab6242959e65", - "0a043ec0fdb8ccb0d7f31bd45a1904451854351a17591000c5f04697f318620878fd9ae8299987e4b133daa7eb19563bcba214fbbb754a5f79843c376cded2c11b", - "0a042b70ec144a9a2ba9784ccc0b3031e306447f26f700da6c11d48bf0be572a678794d0cf526c438b1ee1cf6cb349b9520ea7732087b0f99c3f5b5786b8fcb332", - "0b021fc2ed0527054915aaf1072c714731e25185ce01c3b737e3136c598784ccab20840866123f2e9f3943a60332edfad9bd2941339ed28a550b280a1f0183a2bd", - "0b063e12f4faf263fbef007a8ea08d3d7e0522664dc8ea95c2184d46193f86789adeb46dc0b9938ce4493d83fe6b04ee983f1cdc49ddd5fe72c750eb17db386463", - "0b06ec39301e19eacdc2343a6f8a5e1688eb3739a7a50465eae0d1850ad46a82a52d67a11dd7f268896f239e73ac61c682dbdd8129de6404d3aec922c7b85feb11", - "0b04f441c22c5a83ac547239405998e3ee6f5b6ba4bb7d415abbd6b2e928cd26223ba6fbff685780d0e079628c998b4c50ec8e61a060523db757e2279a9a751d12", - "0a032a59dd076fa7ff1599e03536a6d266f8801df7da967eb426501537057804bc53a6754667edbc8e550c250fa541b0a8f9e120e438f46f3a3e509b3ed2b9373b", - "0b01359740ad53307606bb456f8403ab4ff74e78de894ce2ae7d601d3e44ff42e5df3365b3f8e2006cf637be8e79dd3d776ebe6a46151f80e2b07d54809cf5cf91", - "0b0056b8f5176d322089e0f0bda81d4e45a75375166dfa9a7ad90db6664969225a11e214bc5b1e9888a38ffafb43fde4c627b42c001cf5ea2638ee3f0aa28af3f0", - "0b037720d2e2c2e0690a8865b4f2c57bf313ededce5af6d22e2a15b9a0322c7aae72c5b4b132ba056544424c140837abd6ce70bbe86678a6b42f9900ddad8fed2d", - "0a0725a2b3c4a0b3ff3d6a83c86608300312fc8cdfc6f7a6fb2fef19618f3e48973ee3f0c93d055bd79914ee850417bb84c97d619198d5a2cfb818fc3f0b05d009", - "0b0715c5e419ac602c11a6a40225e733cee8a3d832543a089d545d2042c7487a0203d3598900c383864190424274662db8ec1bdbba1e6d1b8a6e6ad8a2d9912fa0", - "0a0299c3233d003556419f0ab94a8ee049c75d7b4932664fba40705f6afb1c231c8a48042b033dd334ae9116a4836f935913655bf9d83d41501f72c0192a0e6b2a", - "0b05e16e1e3daf59220c69ce0af1bf0111172e882e661ea369e5991f9868fddf2c23d77bec19177069400318ed46a74e536ab80b7e828a3884c202acc62e89e10f", - "0a07e2c2133fcee2cea5e3251323d2a0028bbdce368c64d5f4d6b02f385e04e79e82782771da4332715808772725a5f0b5365c8c48960e17f1b779ed06d9c9a123", - "0a0641d3f72f60d6ed5027c19270d230ba7f29fe88569a2044e0f0d137748f634cc73b47c3798bf03f969764d87d58a63fdd1c3bd2d3c86ec52b96627049001143", - "0b0039e8c783776e8af44d92f4999ea43ebcd0e119019222d03c437afff610692f34e2364f0c494a8f51ca43a407edb9de921241a9d7fc335cf5e1937bacb48622", - "0a08362ee58378452a3aaaaa14cca536be20100322639044dc2188ffdfc5dc9a76ab209001031fbfa99138f1823cf2d47e7c55c56ac8ca7c761a304ec2848e603d", - "0a054998b6373161e30afc9bfc081cf97541ed12f8202de063e456959100469189a4273cfaabeb748df758e3e502bfe3d6f7ba8e7f66772bbd44fbb9b82d4a012c", - "0a02417cbf7203d5a0925f28fa469020d0b6a5dcb7007b03edd8f9a1f27369c464984b1022df5e6474596f10c7364371ab418acb3db64ab99efd883efccd66792b", - "0b04e286a23c86a1659178258e09ba449754e02bd5980d5c30ab1555202b568a30310b561ee4e83093fef061aaffc98935f3cef40a606ee5977b023752a9cc72c7", - "0a06a1510908c087b3e73acb634a5b123d29b38ade0820878910ed6c760cf98a28d39354f2d7fd5ebcbc723f80737295b750dba5f2baa1ae27e20bbcf0d2065e8e", - "0a0827b5f165c5f18ddbd8a5f84a0db6b497980d003669f28cc197bde76fdcf96ed743a4e2793fadc28b2970465c7792669e41db76c5bd0c27c3258c060cea6085", - "0a0667e0f0b959325be812277226cbaa278011fd9bd193661a35914827e336681f69b0b9994a2d84804da79e184e794a9128a5cbde4aa9e24c4ca95a5dcb94f66f", - "0a042547025a53e5c504e0d3d3c89adec8ec5a5355f601807db37d313bc1802ad03d74e1b6047779b745faf5df04f36bad2cce3f8d3ad7fb3cc7f195aac2d55ebf", - "0b06543bc5b0ce476ffd7d57889099a0aee279510fa20fbaad5e314e8ff485fcdf6434e7a8a85b54602fac4c9616da2166058e70da43c3b933af282b28ba790bdf", - "0b0145594448558ee8f3d752e88d661f1ffb7202b213d28e855240d6c907651bcff2a2ca02e4d10c1b382d0af4ecf96bf592c48e7fabee2ee5f4be11e84572da0e", - "0a063ed6a8bfd20efb541a56a71004293549f63a34104add8206c013245be7057143be9e0efde61ba7a34d1da11883d5631cbd1f816edae630c7781c84a1fc6b2b", - "0a017ceeec6ec03d7794082bf71677de11337783d4711ae6fa9065d054abd66bd94f8d853cc90514c1c06b1fe760b5cf35ee7cd243380d88b4bb90cfcb0a27a40a", - "0b08cea37711ee717ffd2fb8bc8626fff31d693cbae9bfdd5314cf8f49195d2d7b24726445a3866429f863693e4ed0913159317af5b917d494ac63e5d82d52f3b0", - "0a04d0da3d537c57841caf62f6ac7f61e0d33e71d55d5f793659af11375d74c84ea33f86e884d388ce254ffcbd4d9df130f97676517be5dfbda91e38d9d5df8e21", - "0a08436e01d6bda3c4f7b9706f13b1051724d6e5f5b69b97a2b2cb928b3a3d1f1ee08ef39fce9bf2b852e4b22246ee91d781517cd503a3c56e4c87e1b0ed6223d4", - "0b05041df758d2fb279891de32c2acd0c72eec04ad250e139ef8868186edcb9031112298233d2845b5af426bd51efe8b3632fea004e241beccb73f66eae4fcc32e", - "0b07a0ed849048b6cab333d6ed2b5f7849457dc54b9cb73e2a5b97cc9694ba6d47348a3624cadbfbe0f94512a6fa0306ed6cf18a03cc794ab0b7fd6dd9b0187f7a", - "0b00b42e8d8bd8d5e84616c2074b909da2b0842c7ad4925f99523bfd7a914572571bb45b7091085db10630043c4995be8a2a0149346268270135c5e7c1459810b4", - "0b06e37022b43e9270999a94cc3ec7c765c5f51ca34da5957b2b4dc25d7dd14fff2d4f080b457e87b00deb70c46bc0acdf5c600192afbf3ba3e2939e991dd51fd2", - "0a0207f705b30bc8cefd18cf3033319859f05b4befd3a3f6d0ede620fd83f57d01fa0806be1b3a798e13307885e1dec699e12c7201dda66a4cd0bccbc9126d24ed", - "0b072ec1b0dfc73231c9a16fe5c058bceb72f96a6856f658f5a55345288e2f5ce79bcb456b0752d56a1448a6db08701815cb08315c37f52431a2c5d88a9e5b0f0a", - "0a03777438ebdba77cdf433a7bdd55ceb4f1176f2654c93640226963e08d47cda9aa44da3c98d2dd9f4ed30d40e8b8e71ddffd8a906d518eef19f51b43e6a34478", - "0b070c56a7efae4d3386fef1d920bc08187db016368e24980c7ca21e10c53b791cef324bf0ea76a585d966c75cc0be584af2a09152d293cb0824b86f13ddd0d111", - "0a00b56e1214cc142a8a7cb2b0ba8762d6f931f3d1fc782e679ac76ab4cc63052e7bcd5da9b06581862520745b3385fbea16847775f8aeaa319684838c8569a5bf", - "0a066aeb6f255e584ddfd16c18421b05201552146d5244bb033c0eaab7ef8a9df1dfc9d8b299d0e82eaa75bea5747a3767581a1df226279cfac56a9c64dfefd729", - "0a037fbaedcd2666a910e319bb651ed5d1603759eda84aa3792ec1d98861fcc3c93b7df9a38f967c86eefa68d0d0582ec6977ae838246c88367a08ffcb0b8a21a9", - "0b00e81fb31b6b6a088537c13203819d6b945d9ba2427881f384fad406401b925a32d27836b8ae0852ce87c9d447da49fac23864b27f3993261c3c57741d994f2b", - "0b081c7df774817fa54713ac78d4971385e1dcd65eefbeefeca00e11ddfac45f9b3c856a15ca1940fbda90768816a1b545e613c3cf6f53fe945b90c2e735e4cd83", - "0a00f8c386deab875ec65e166ad5af8cbf950e71ace27f2f4a3e1a3ca6fd8e67f08b5dd6a1b19fd8ad89414524de9d0a86d15e9a49aec8539ea52fb3ceeed9c290", - "0b021d55c881114f6b8e1ee632d8f6c7c6311297291e23a0cac968f952ded268e9a1ccaa6ea8061f194f2a90f3e0049db6d12de9d88228288ffc9a8e5dab2644fa", - "0a07eed2b4956a86d45cdf25ed9a532e5937b9aea57f4e60e2b32796dfb88fb91b5dd640f94ff6de5801d81bf326856f80a91a71cb4b5041b1325021e27d8aefca", - "0b01a55f692f1c5b2b6b7d4ee086ba19bdaf36940fe10d918b27bb321febbfa603a0da9e2d0f6515ba2aa8940a8098117fbc319900333f9e38b9a5364395d915ca", - "0b02dc2449476dcdce400065107e5cac7fd9457a617fda980d0902e95cf3639aac0ed5de497843c191ee7afcb7eafec70302bbc21248aafc6e144216e906aa4673", - "0a069c53e3a5baa5188995cec957a8d143cd18de03d1a2d3c4cb1143250d7b903e23b26a884a20ab6c12bde9a38e9af59e3f1d772079add9cb326e837e9da51dc8", - "0a01e0cadf6803fa959d24b4f74122c124f937672dea7f5815a7cdc33c15d9080425892500815d97ff2341e0778a841457108aa3ead9a12e3283b6d6d9aa791a59", - "0a00018def3c4610085b9afe850b19cf24d79557aba90e8232069bfd2596f02a1ab56739544254d33fff294dea1f10518f3ae0bf6cdb4c54ecdf6cd1823341f030", - "0a060635d3a5e601bee98013fbdde0b1324553011b34b5b032c5aca519166b05d3fc552aec5bc0126601953053c4a3fbe29e5fb74a0ec4a7f4ae42c11dfe84d12f", - "0b0255351d9214492da51c66b6fa81fe847eb7b6363c34c0e1d8691926371495f558afeaae21f29a290410e1cf296eb02d2eb50a84cf7217c4b0257cc02734047b", - "0b022b20ffa4923c067973f6f14efb53d508fcfcb07e0771dba639fbb4e782f74680eddf031d5e86e4ae93ca8ca2d80cec573423423e39644ced46c388a3d7d63b", - "0a0447184caeed1d98cba746ce42aa4e4cffbd7dfc8e1792972210f9650dd663938ebc8892728009a43d8979c0929686ad1c0a0f2b677e9096efa08086fe569af4", - "0a086d84139f5c9b244c7ab6839a718d96f9e4943123a145ad43e2efdddb6aa1865ed4ae2b6aeb97b2db8085cc5fe1d5bc7fce1fe501373e3208156a839c1ab6dd", - "0a068488a9ff886df744d72f8babf4b0f29d8c9c58014a77344f2db768e6f68c0fad1d23e036c2e43f57f6a6ee64589827c6879c06bf62faafbfd92ed8d7397e25", - "0a035a6f7da8466c228243ec3b01aee346006ff09b7d39c5f629b086cb4a7a4db740d736002db0fba3280d590f0188f6ad69d769ccd747c02047668f2d3644b220", - "0b08059a254af3b164ed3ccc0a9e4251e4026e3148201db314834599bd42a7b17a433d1f2fd743aab59be949a5aeecac09192cea083a142aeaea1bcf89465e6aee", - "0a0320836a0e2d5ca5125d97ddebac1559eabc690fcfdadd24b5b7b24ff771ca56e4e672c7ab4199fbbd336e618b177f23c2ee8f5848525366d7ca71a50fff17d7", - "0a077a21d6c62ee5d6e14d2e773c23831e6c1db3d19aae9d70fc2849198867ebe67cc9766c471ae93c367a3ffd4ff4a06e73f575f3285def39eacfcc5976336143", - "0b0143c6bec2430fdd05baf82e6886cc4ab4d898bdc88955322c030660710e8c696b60d447997326f6f327d9187f9d86905dfb7522b4b324c181de9cbb66f7d9f7", - "0b01a100596bda99cb93f14a4e08f4f2738d7c2dae52acfcab2641ab7c3bb4de32371df794f108bdd278370f3c5aba74d76d5875b02288582487e58806be39c863", - "0b040e562f9ce23080d0ba761fe2966eb805de3973559b8a48b531c3e7522321285550e005be9b3ae9ef058f2b39e8c45fcedbdf296ae2dc71cd781b5da1573d92", - "0b077b79408f803497d9288ca5848a7fac85fb2b90d7456e46a5f86eeeaf460b1eea6c8e346ce5bf3bb3978fda22a3bee892821125d11d8dcd5c695e0a9abe88be", - "0a065c0457ea5b3843b7b9e0956b1bac7a24d2acd1fabde2ebed4170338f04513ce0a45902a8f8cca913b0e54d39ab72635627adccfd1d880ba20230e9170ac3d9", - "0b0825d83a8cc8357893558f959b1eef3918dd2e7d38dcdfa17575a52c707faf40a10ef1f87a0b47d08d429c3fb40f2467ccdf8747f4d35325c587dda27fe9b7db", - "0b003a718c426cf8487feb4a49fcd59d2a5b173d7199be7d1a9dff5eed1c5e3347aa2a7b68f1917d7261bf7b3b3ceeb6dd60cfbd419530eec65e8d1e6406209423", - "0a07cfe37c0dbc6cab0d0f799e24cba87a40c3b5c93e2a77a59e4011691053703a9e8db70f74efb618770c9e7626d50889b6ffb0e657f51bf949f19e6b25e9ee6c", - "0a072a9409315f37805bb8684d8bd51f26b0982eb3608ac891b9b87bdf13bd57db6b0ceaf8b52159d6133c7030cd95cc16b6788c74272b63aa2b8aa6cb181c2c6f", - "0b081ede95d1ca9b17c03294ebbdb2d4645ad477dfa34c3d8ad689f92ba59bf34267a0f8c9e2e067dd6c493488bdee84dfacda1adb52045f8938ce802e8e2ea084", - "0b00776a0abd8996db9100ad32c8862b82be56990c08c3f6f181972dc29b155ff7c5832c12d5b0ffb63ca67c617bed2bd67d5f59e47f9236b7bbeef40d8e926d1e", - "0a01555397fb4b495661121910bb7949d6de6b2f85550aa180d118f199094d7a2a6fecd1fe81eb5c48da4e2ec9d9c50857d1875da59e1d6f6d4dfe057db1a7a640", - "0b01e17196d39342d3987604b3f853370e4aad814f2dcd85a036fbe14ba1dd17b4b453d0955728a568f85d7c441d25e31ffce23b6c17c62c85201a6873d9a17690", - "0a03e8faa92a72d0d8fe3d2984ecde9c6e40d8fef4df417a566a0e0e0437ec049b1326cfd1075951fa782043a160bdfcea24b2f249bc22dca33db39637127e8064", - "0a0333dd1d2f838969976b1741674a5f90479aadbdb73c46a8e83f9f2820e6de2391e68f06f7705abf12d30c6673c1389dc8eff290d4d25023e888f77fb642fb97", - "0b0365930110bb709861df2b4bd5b2c790156a0d366144b6f3a28d8a8a5489226db8796562211417841d431480304683707c7fd65296e83b2e6aecabedd3dfb251", - "0a06088b16dfda343510d7bf7ce01e017e0a3fc3255e96425b07357a93433cca3ebe3fb2fc89367a198bb98da1a2eaa3399f3b03f229b49e6e660464d20eb134cc", - "0b02b1309ac214b61bb476d0e93060d23868adceb995c1629700f09ac6273c29ffe71b37650581503711d0f25d7c88d21f8de396eb090aac3222760dc1a07815a4", - "0b03ab9c5293c57cfeeec6015d9300604a7931f09216093ec70e80761f15ded86f2c59d3f0d617a8b694eaf8aa9f432edfa9a6c4f998fe2643fde93d5cabec8258", - "0a019ab97ec956f11c8b82ffd50ca0a80d740406656a6822cb356a37abaed913c5b4fe80dda4f0ac33f02933f92764c08f6ae0dedbe6986c0b0d13480c4e432134", - "0a031901898b8e02c34555105290a03a1b5cc6b1a9cbfc660621452d3b7d5c4deddbf158ade3b1e7b2dac027090882a66705dcb4940a49960f06fe12874e165d1e", - "0a00d2b0df9bba6c9636a19105e5270dda87409cb37c06e6ceef0db6753170ed649b02fe2836756153b2ab1640f16a145d9ec7beed606ee6db7ff57f0c0d406fcc", - "0b0855787c7e1005b8bc01892875d60ba5d412b0df3c7255d5b27a332a07a3bb9564936bc8f420c226953b63f815eba0ee62d86e9b03adb898dd4731520657945f", - "0a019a60da3fee9ca8701b0cb050681184cf5d802045a499d959d639c763989526f3d358e89000b76dabd93ec3cd465fb3c387c143dcd9fe7116eecebbbd175396", - "0b0209c0d2ac6dfdfd6d46e578618660d8adcddcdc2046f01a9e0832dea31e49f6aa4ebca18943920dcc7d7240db7de6a09c2fd1748732994e7e0c360890f9d426", - "0b0252be0f2ad67f492b3aee524f7c58b2ab7093edc870b4670d5024b2768759f7e2b6d4a6c053815235c2838e79363b9d01769132627abf30395886ca73e685e2", - "0b055c1265c4f2624fe42ccf05b77c0fbe493ba94d45070e8574574446539885f6972992d29cc72346d472a502b04d25e84f23cc26086f709d52e198f9cbd9f1a8", - "0a079670f73ec5917c52c77529f96b65f5611622b3e2d636d3b988e7c8b74467a02cf71d7e32da33b1bf761b7155456ff5534fda23812c1efd19d3541516ddf31e", - "0a091c1814eb5c79ea006765a5e0b78324037c744c4e801911404623f5b3b394dbf0537530590df91f0de69d2b6aebc64bb5014e58d6f471b683081c9c13f217d6", - "0b05e636ccc0ed8454008d997c37072d9463816a7c950838d0315841a0cf17f7cbb8302f22590a2ca4895a46763deec6f5a0622fd1d75da2af737e79cfe27b7355", - "0b00d33ed51e8271c911f9159a0100f6a7e849141e5e4eaa88152f297838acd6650e9abf3ab6a3da1c4bb2ca12be936976de671e86db1ce06b8f5accefc4f9fd73", - "0b05e879e48030da76d170d8023079a9e3cea5e70f47e5608772b67b08657bd6316d5fd409fa83aa57454b85347f73e289ec15bed85a8222ae56b65e438ceeabb0", - "0a01a3a39bdbe8d25f8e9fdae57fd19e995bbb5d6a116c54c408253325f8a428ba31f08857c99890a761e844a9067d685e2dd18c9ae3f110a2cb96f219357a3438", - "0b031918ccf6ac2fc15b37c83d1f1c04877a1c65a53b095566d5be4a3179c6e9cd0d4741192f78d28c89443b259d6d86e3b37b19e7f56dbdb7138b015f45e6e8d4", - "0a043ee2bbb1d098840490d95e5b5f6b25e8ca7b4dd106f902a00a51dcc269d741361080721e0b62a25cfe2f4037f99df88e5ee8fcfb81183856dfbd1b7ed2ab00", - "0a06f0280dcd43c66062a2eafeacad5a9f4b098de734c261f28469e563dc1afd65c9f7fe32b1b915f5b6163581433b11db5a79f87b768ff1d1d2c40801cf12fb32", - "0a02715570757d1668e9be45c676f50593d0621fc9ac7545ac34fdfec2b15a498a6f1e3069918349b625eac3310373d148091791d20e4172a686e7cf3579ee4e3f", - "0a04b89380863d55445ac4399f4abe3f29dcc181e8df8f4a19f75730f31491d925c34251b1005ef34df013733c56892db94a98835ca487caaa5f5d2bbdf8135e88", - "0b07d14030b35ef9026609456ec8c0f1a9ed71962e70c074d0447c11477093284845a885a043a4be77fc0107dad3548a33bafedb6def6183a538901697895f5e28", - "0b025fd88e7682c3f5e24b035941a8c6e21e37b4b5b99b434789dc3b0d2e82bd27b2e277e18103d20bd1da695a308d4c204e20b8a6050267d27265a1f9fce30a8f", - "0a081248d14168789f6d08e41c404186dd53b35c6390c5a338a0f08b8cfcef0dddf9776979a593efd7b49c1f2165f5b0b73862a0113acf7d9aca4a2cdeaf00a28f", - "0b01d6051962fa1878ac56d834fc48c776837ee0bfc39c5a670dbb9bafea5f3e84b85d7576608e3d5d2581e068170d8e66ad4ad166dbd6102ebc355ed688cc4a87", - "0b04224773541526a147e201b1097a265544937b8d275d470f857367484a3d851b599fd02b95971083625ba175e81ff69b39181179c0f2eabdd3716c84b3a8bd34", - "0a04569aa33acc3c1adf0ae856818e240bad3d31fcb4a4dfb6c6e8d9045f7cabf402015bae614ff823ab9e70ed4b6f61d7291083aac50e36b3ddbb2562cc58144d", - "0a01479f84f74fbdc4ccc00c9eb53750894cbfb08b358c8baad5e7b6668b0b81ba72d35f273224534462e3abc546c2e8eca52f4de6516c2a5a5869b06c20e6a00a", - "0a0260a93681ac79cc273eafdca7806af669e90bd420f827e4fcaa46f245fd86086d4f06fcb7d0641bd5a743bf281bdaaa99a0d81691c55ec9a86b6d78870b4f01", - "0b0090642ade605d1e1b844886962c19715e57eeab6df51c37d550530de2e3b56a39812700c805314429099cbcc6522d0ac0af434e6e2e816093e2575a4d17dd89", - "0b07612697f6e1b22700dbf3c9eeec0322847b20004ac46a54e8445fbf4eefb1cea736598b8b6354a330c2dc47c9d89e255c975fdeb33379794de005453a9edf98", - "0b075dc6bf146b398ae7fe499c5a2f6d55722aa970851edf4ef99113e6bb53de2ec8b804dd6ff40a9a86ea8d56154e448b73b9e0620f7a8ab70b0b315d30f2d29b", - "0b0225320bb520dbd0660a785cfeca4a4b80e2637e83f0ce884875f5e365f873df74d94f156dcba089dee7e0384fd6de2eaef6875064751953e4f7e985f063f323", - "0a017269644bc5652cce4b48fef11a794b6446cd6641616812fe93243167e702aa33f5df213125bb9ff9cf811f6c3501a814342024879309a6e8932b62560360ba", - "0a039b4f05014cf4ac0648102217579328ddeb9b24955965b69a329980e1c588c7ef00427afeb4b314ef410fc219a17353d42d705481bdb0d007254c717e9a99f0", - "0a010d62962111639f8cb7add912846a7a0665bea1c3d4602e909bbe6771f6ba20f9f6351c7e76de5104fade31f8d8f64175e498db14fd453171c64533fdc9b19f", - "0a00eb66ff92f1566fa4e2d77b7b7c65148313f6d1d6eacdad57c3deacdb85ae18cd7dbaabcf8f1a860b5abafc9928d861f1ad27e2ad566cfa1fcb359867331d0c", - "0a05f0687d5e2e5713fa1512f11b916a52a7c66211a682a86eb34acd966e47e3b0fe7414cf03d139616919cd6497286351900c4a88f5b54bca944aceb024a2dea9", - "0a07b46726837cd264e106ca0085defe76df614af26f3da4e2c895d22ace0f48a2a7c25bf055ac2987e384ff9307100df762359c55a8ad4b85f4d5c112c9125e4d", - "0b04cf5ffe09914e8a5d6a7392603f831dcf44d28c65207572349d3a43495d83d4d2c9c44280c4e0425a54e0730bb963d23d0fae969dc2bf998ea7efbe9160cd7d", - "0a02ea90d3949da44d6afbd3c4d59b1ead0481269de1e317583595598f1969db0a2d343dda6e6302f6a2fa0b266be8221825b4044a8efa520b23e8d377485e9aa6", - "0b0228bb2b5b096074ee671117045d8b10204e48a07b14c79d78a03dffaa806e0b0a2bce34d54c722be83f700e8f13051708d894d00a3aac9bf329fabeb6cde7e9", - "0a0316ea4c58b19dab6b31a5a5efa049a674d652e05ef0e744ba9cb69978856a817c3c7be29a96593f2686d4d84f1afbd3ba59ddeb30f13d94949233f6cafa2aeb", - "0a0080d03f4de61eb28570f1c0891fb04090c77f445fe19251e53eb26299c11433faa089af548de4bce345f312d534600107406b13c38b954387bab059c37e74e1", - "0b0166804238ec3569faf294b1d2fae90bcc27449b0c4a1a0e4e5c9f761b2a04a868ee8229fa12953cbd58002590790c1d44d4d41fc32724136fbe6cab0b6008ba", - "0a06d35305bcd69d7aebc67218ebfbfb4f21b25628335d332be2494c5dad6ac86fdc8d38937823541d9d246916c6a36194d3f48dad888a092822ce7c98d3b3e89d", - "0a090a295c1ebb47275c8aab93ea695fc0178d0d2ad8d71a0a4f5b8069f56c09810a7200cb320d5f117fe8676437133309f9cef84fc8627d185fc873234c4d5d20", - "0b03908d514f10c7f5b0546615f51bcc2aec1297d8fc7acb7e48494b5d0788e702dd7cd4bd76589d989e714217dcce054f26c71bcb7eca8a93a3ba6df6ad3188ef", - "0b0120f05f363c01113634f16c4585fd153e580c9decb9f70e036e8558ed883a8db7dc2564d268e0f83d9c62a13ad80aebefe9eb46121bbfeb610fe98fa8ca95e1", - "0a05a6b2334a26e8ac51e04fd88131fe4b68fa4b5274713306463224aa482fccef601f42159619113c9c8771fd6d564f98340ff7bdf32ab5c5371f661b4882d1d8", - "0b07e3628c5270ce8f48de003a8d522e8acb7434cadcc15e9da256ab5e4837d6f142002ee008957789e25226b202f2e79703df8398dbd02b7d392479a6311998cf", - "0b04cf1010769666b39beca2e0b16b388d6d1998654cc62fad3a7953829189f0d87c5699b46624da956ea65f38eb46c5a88a5a6bb1b9b9a0be3d2c99ed556e1604", - "0a0278f349f0a5da7d685ccef501aada9bb3eec80f901573520b635cc73f104683e51c3807341ee7b89c11f1abfb932f8fb87fa27af928c20e1e642ac943ef64e9", - "0b00af54e0699de521aaf63ab219be6aff436f2bf8f4ce9940b016d774f6bf9dbc895d4a9ba1822c67ba7688b3eda76f2712bddd116c1882f00aa3fa9cccfb9f4b", - "0a04b4ba0112015b51245c0a20c601bacc914feecba7d2760359ade2807166be955f8881eda2bcbf269da3a74c1ef4f9d3d6c51be4c6452d53844108672a283c35", - "0a0835f5d7a4d13965bf044d5a6ee711ab31df81d310482018a12a5d667dbcfba24dd2a0210eeca8d5799a9c0f3fb19bda023675c1bdcb53ea0f47fef9d52757b7", - "0a069f1279c6e22e6fb7774bec4a5e7ae1cdf4db20acc168a304a4553ccc46b62364f6c069c2582eadd5f588cce7f0d5b7981a5d11f8b444b9bef6b65496e22782", - "0a06e906110a0f1de1ab55da46e72d7465bd0a14d2f829b63ec0c1ff4bc21275b1fb4c4cbae62cf6c216470ef2d3d368588b24ab765bfd8cb343479f6754e62c0f", - "0b016383f66db0506935edbf4f8e5b91b7ee67ec6dc248657a0e56f26e397a904de0deb0511e83d01355f0acf85a572742e5283873188e8faf48358886a64e89c8", - "0b0527f14160f1e63ff9e7f40b18107f94c4a75e711e6d8fa14abdf5d9b3aa0494b83e77571ad2c16a998b622b4447b57fa4c0b5a7ab68139ae99673e935f8e698", - "0b02e5e982df2ecc86a460fdf4948a611bd12bf9cbe8f3c943427ffb71cbd6a01cfe91adc8c72481000b7bfc4ed4fd35568d32aa508c6dfe3ff49071a7f123c942", - "0a05bf5c7d55149bb049af9c95209a468e4d7525b78609e234997794c31e4c6c5e8b4e744842174eaeb97edaa3c2b12f817010e5ba0eddb90ac0592004ff1b98bf", - "0a034c9c4f524e5c9201ca60f06b4d28331cb6981b318bcdc039ba5a382fdc834a2229dd87e169cbe9cc7032c86a24183f0243d08eed696f63217005b560c395ed", - "0b07f7cdf5fd845c84f71cb53965365fab44278c22f33234e0cd5414d4b82648d5e4686c278fcd6e50b3aabb26927967b4781b728eff3b40c32c083d074af119ac", - "0a00dfde855cdd104ec50f8cc2b78b6b73b43adcd1777ffb9937a50e45f92e657a865e385b918c4778cfa18fa07729527df696c90ba35a6a4cdea61703d06bb990", - "0a02cc65d347d7d89ce6a411fa4502ee754ccae95ab8b9920ab137ce01eac248142ea7851231fa14ddfbc2e545bc1c05412d0f62721def317256f71fea1e04e7aa", - "0a0736b040c66a68bf92380e6a538ec4024a16c3295b0862b2c4a753f325bfd132b68bf5798304abd8879e21422fa56e1f079982a6ad0e7fa490b1bc12c71dafab", - "0b0823eac6586370acd488a54f2362124bfb1e4e9eaa0f39aa6cb4fcdfbb1e4c2166f36cd50e70629fb60fe88939d8ca747e7d384537ecf28c46338a2e1357a877", - "0b074be584c347e82a81814411e5695455cbab0b05b8790e4ed5e9b61e7db039016df5a727864772b7ffdcbee7db391394109e99abccbbca70a210c7003ff6b983", - "0b0059ac31ea7f82eaa99d4c9001406fada1d877325709f6db5da8751dc99790cedc04a62e948d77f594e610496001394ab317851e150815a61fd90893263e2dd3", - "0b04c91781c72c351a25c6f6fccff0079f3bccd84e12d8b51a5ed5c39a4d19e7adc73de2677e4d35ebda6dd950a61795c9af397b51c1f98d4e249db4500ffa1501", - "0b062629c4ecb8bb34d35b2f1da86c0c53d55029c25281fff961f625f8228d0352754f68b62e1e932e7ee9d361db342d798a357346476e1984528c1f35ecc36c46", - "0a039c1ed60c8f610f7bf006513eb6c10014ded4e2a4d38714d25c771c2408f73db1333ca76c1e8f9c063a9c1225230da03f7ee6d0b9879f99150ab7208db9b5b9", - "0a02f069b0b50d28a7f6dc4b8e0e66afbb7d6bef000c68242c5bbac78d6e25c187ae1705b58b53e342b63656f7ffb56563522737a6ff733e7d06dd90ba9eb43fd3", - "0b08f1b65f4600d52b3b4d41c4d5c5e6346a99851b757866e82e8226bc0076c634a2b6d223362eba45796040f423555c3a6dcf786c12124fd0b2c9adda7da2ca8d", - "0a0457e731f3decb048da945b2d11f3a3e2a468c474c0d3f5332ee7dcae38a76c31a5704f67dbe03573b4b970c6759f23af5ec1b3e03e8067ad45ec0e1f9b29870", - "0b011bfdd0c2c407b1f9fec58be123d910a6caea238ae9e25b6073320f12ac18f1543f46cd9442a1ec950861e794a755f800fb0d90db6be5f73ce84c07b2c4d8f1", - "0b04ed3655b9f456ae3d633c6185e3bea784ba4437c65e9f7e9590b4148ea82b1558198f7835fcca2abd17f51cd773fd3cbf6231e9ec9deb4216f670c99a404723", - "0b04dcf067c57325f3fc72c3e92b2920f6124d92eb35ea0f9a19ce7690e37d9680aca372ab1971f75a02154e604b8a7d6ff0ea8d8f847c0ad5357a38be69072f5f", - "0a08132d463506834b97b577b6478ad96bb51d9c8fab1021d0b0162c73fa21a91a2aa874005d273ff36303cba7968883876df01a70fddd73434f354392b010c835", - "0a08d947a85ed63be2cb4c124645856d33e2cc8c887710db31adbb72d08d8e4c57e9ef84f1f75fac092b2b2bcb07ae2b7b79698e35f1274af7b5a32f48d772b08b", - "0b0098911bed4ace2a1e8b1fdf78e9eb50c174525f4ff91705efef5a32d1ddddf60d15b10e6497f08cdee294c9731cd8952ef5844e6f1f490c760af83b26e9900c", - "0a06bddb8ac31089d4e8d11b9615ee21cfd89304cab6a171c85ee98fdb86f5d13f0726389083ee1a4acb60bb12a592fe8d9c160c7c631ecf6a7b559171fcbcbb9a", - "0a06f7ca6131a43a213447fdf6edaf0dc51f7174fcaff9bf660817f265854d6574d219c6526439ba033fc89b6d25fdb7d7998c9915e6777f22df54ed92bf3fc05a", - "0b01798274c9de6602ac0bbb47fc8389b158b358a750190179d65948a3e65b4a9710246f69ca1ad5a4575494cda7bd6c2b4d25a759fc636a68a6d8a3b76ec85125", - "0a02c8352b04802855c1b1a8317fcc6302b9fc730fc39497caff6de5115833b669888661f09d28a00ec9664c31fc3a8108e9c4569c51bbb330a45aab5c0ae0c622", - "0a00d458da73cb29c39bc6ea0a9006c87ebc3d1ad09c9484b3d6d33fd3e92c534620dbccd0f6b4f21c1d0af2d6b28b76ac8b2d82b13269ad3ed23dbf921eb042fe", - "0a00e9acfb09dff7dc90c2045f7dacfb9bd2cea9efad42bb839f15887c69603fc36243b81695e0527f817655a149529f26faf5795444ed40967bcc58f86aebf792", - "0b06a3d6fcaa67edde78d235fb07454e4d387ba6706b37a6fca06c907b15e4be0754eeea66ad753f3a27df935bc858c1c416d326398cbf6762f227dc2ebec57f31", - "0a0102c79891819147a9cae6d5359808c7c8d13bad1bf49748f6f69fa913e82067a3ea6a5de665164a2db81b5e1e5ed8bba31fb195ddf6612a9eab63a8253ea0d0", - "0b0367881762e5d938f070596d074ebf2c7b8e8619f2f1988f1ac5c56bd8034750a38edb5e665de7028e95f72be1af6a36418e289310247b2e2b18b24b452b690e", - "0b01e30334eaa04916485cbc4673ec52fa3818bda0eeb2a723990951fd226751ad701601262e789e380e405587a947e66b472d7dd19fb26e72c1ca90dc50ac63b0", - "0b0296695f5124d2912151b4484842bede45a2f0af5a4331f72954863f6035695e318f013babf0e691f9b4beeb8640b41739dd3c6945a0f6130cb3c875c576193d", - "0a0880bf231988bf5b43957b6bf089d3230aaa5bb1e7e3ad6a33e02cc0ecbedfdde6e6412794628f1ec1b92f933b2ecc75edbc2c418d9fcd40ffd1822186942241", - "0a024879b561f9e6e281dda7f1277dcb0abb50ee7892cce2fac2d0ead1bf57e570da4906119560bcb202349272d10712e68cbf57cc760caf1bdcb0d46629e11558", - "0b007d7b93fb4812bebd95df6229a94e0a0cddf612901c253f78b44e28c9689164ca548e13a449085399d87eb72752869214dc43834478a4aebecf7b2fa5bbb44b", - "0b06dc1513a8b7d45a201de237f691b2bd0aab7dc6a58773026b5ab9cac4ff9ddd433418c4767977e5363e0e3f111d7f40b5a434f43cdaa301e2b737593de1373f", - "0b03c965a53f32be30766bd55cb8b756d402fe5e91ea08a4dabac58ba407c02fd84872fb98f9af94ab06b83f8ef427077f27810c96dba6f46f373c6f0a9131c70c", - "0a044c6193bf430a7f702628ee6bd78fb3e9a020696a850f13b329a54cecc0f490f805d66704fa1b93aae14b1f48f319c9203558821ef63244e4e5dc4d0189e239", - "0a01bbf5da39ba45d9a4ef364d9da5f8be38215ed2856e69e4636196473018ea7fb83e7aae69f3af6acd3a396b61a898120c7250c151ee9745c36e86cefdd35cae", - "0a072f80988960952293a5bf127bde9cfe07e50c2337f5a13e5fea670c68e95f73ad62ac404055d405337a84bbcefec8a62e977096739db06d81870a7e5df1b494", - "0a01b113b61c94621ae24e79a5ec410c12a0e95d9ca46ae55bac9ae7e26c9c22dda2942c6336ea8b60e5150a6a72e9743511434250def5d3273e7fa019ccb805e6", - "0b07865554fb312f85d82dc0d1e83e8cd0db714e763f79ad19b1912707678fa416faf06eda7d11eb84554668960cedaf3967ea9a2f88dcb5b48117275111674cba", - "0a05a6888092947eca07bddcf0e8d6d806a1bbb555987257a6a393ed2487fb9ccb5ae5ed555bc7f6ea13629d38b64acef410f5a45c4b207cc0a7492c67c18509d6", - "0a06ad61b16152948653d1b76f83d4d3270e3c2effc11ebdeed4abb8fcbf41c2b2fef2dc4c885be39506867c56cb6277301762040aa99f62605984f0cd63b2ae60", - "0b0579a5288c6dfdb5603d166100c365ccb7f118878f1bfa9a7ed6d3cd5ca416814857c4c7e998393d67a12d5c5f5228ab2beab8858576a663af988ab60c313fdf", - "0b013cdd7c990bfefde8c1d39f518dbaa42f4d5bbed0493321912ee52cfd7d34598dcdbe002f7d6e452f5bab018600372ff439186122bfdeba0dd12a7a159b3193", - "0a003bef775096ea796c551f43d806c356943b27416dc79857dba7b52c030c346347d7af839f07dd3069db0ed7fe0da7c137efa4cdf52764c4ef53c6149f81c2d0", - "0b006842afa2bfda4189535136094c177a1c1a37bd31b5b475c9a6fd4afec49a43ee7b4e8f5d6cab4ebe291fc0e2f160018d3cfa96666cb1507705ecb66838b26a", - "0b025d008ab9896543482aa2776c04d1c91c483287123e779ba1756f492ed16899c6df4a4046c44f5c93f42caa5d0974f41599158c95165a269409d94bed19e6a1", - "0a087b8d56f85dd4ea1840e6a59ae91283dc74265704d88bd53cba7e6925f940a820e71eb73c922682dce99c92661f8541f35322f8d66e860753b15b09c54d0382", - "0a08cc7951ae9eb348361a12d78d30e07146211f5f040b5eea619c3af38631094842ef3432312cffcf5c5fd7b4d2b55445df2f8fb2ea2c3469c148ba9f41a00bb7", - "0a046aa179c01dc71903a655621e7eb31ee1db3fa3e1ecf3c40fb436d1981d84dae8ffa398451cc75ddd7b72c1adad4a2291819886a11c31d3e6bb5ec397b51500", - "0b05e03072d70cd36c69288bc950911def3d31e1e404edb1c577863f1e2a11141fc6a42c4d4c9f8e6368e0ba69d6b97d285aa9fa0172a4d3ea37ccdae173cac915", - "0a063516d8c16e45e720be606c00c55969aa9eab71d630eecaf6b7e1dd5c7a0a5833f5abb59d250a89778f65aee8ed82fdf2e26373736e384588b675b2a761a89b", - "0b0899ce3d0582cc0df863222bd8b3721376d82cccc36185bea2f9b196e4dfd80681e60ba02208fdc0df24a4bbf07228acb0930ce40f748cdc92ebe34406a62958", - "0a0040bd25c7a8ebf24bd22bd1e352b7623fffcb30f0d58df7237674975efb43b72a6a2be486b962a04d3a814702b0974201debb2ae510972cd714ce40277a6fa5", - "0a0699801a35fa3e0edb30d75deb7fbe841974a72a747b099eab181b876f376b3c60937fdd3a120e47e8f26fe8c62e4f8a3517aab04acf210c1d07ae8c084d820b", - "0b04ec5457d16ab12d503121e158633408ba0175ecec2d9091a589e446b751c74a7ba2d5c78932af411816831c4ec32af6aaa26ae48ea15a88af7ddac1d9c21b47", - "0b0916b92f71871038db2843d559a7e39bda8f9e361ee9d4adf2764e770d035c1449ce5c65a0c2222b835732977e48c0ff322a379344ce1938e02d274ff820c40e", - "0a01776ae7d36fc6d414197ea6e7c20c815a81279b27b684cdcdda04ce881aaae9e6ff6099ae78ec9d9d3e6b74af2616b6e412667505aab2faca04b76a3295db52", - "0a038c187ffda35b306d9f81f2c3f4927099c1722cff24a1ee6f3f5b732c89dcc18eb38df7250bbd1db345e9e34ad0cac666941f652d05d2bc83438b6010cd2a65", - "0b0628f6cb0f9ef9ad95d2a3a31bda3f901b80baeb64647a04f3dd0d06857e8162359a39ae71fab2e9877e06849b425032c82dab125badb4a75d58819d93323ae3", - "0b087d8019f4840a5a78fc0f7da224a753f845c46f7ed4bdcb58361d8571414e386b34b48cbe55c9711d8f8ecbb78717d7e6ffd83a73b5a0936d9d2020a4ccbe23", - "0a073af2c618fb0f9c1266a321a735752e39bac2ba56de5aab214dc76f680a4c8bc28112b3ce1f7f93ebea7186ae4b0040df9e964f7b752cc9754ae4c2bed78c1d", - "0a05feb90d41da2e1063a7dc432b98c817241ffe71adf2eece6a9618f11b7bedd90c41b134df1503a6d318fb7c75cdf73aa3d9f6d1a2f2e83c167afd231ca5056a", - "0b018bf67a893aeacac033b2c6f3cb8d396e59f7db7a1229445cc3d63de019ba1f8b9fd86b9b44ac110d33ae1033eead37b454b2b93a80253e3cd69797a5d8b7ac", - "0b06779c7eba221fa4da6cc2839baccc7f691e029f5cacf09a7fdc6bd38d0f80fa8f6df0c8c6c69132afb4e4a350e394fb681e9c55b0d1a41ddb9982ae3b66bbb0", - "0b06ebd7305ca2c320e52db437726f9a46c8c948d0c008047859398045eb718493c3b8df2318f9e9684a3bb61ec11e545dfd3a3ab139513641c94360d0474d73c2", - "0b034502d2c8777d1cbb16963ef568cf9927ac00a7ef79b9179f0f539bef036f568fd5f49c5c1d284cc6b7135c9c50af9464add42e812f9f90293e4f3524f5fee8", - "0b0547ea9f28e22de31cfb05ce7e5c304f75475806184a6bcc0fa6aaab8c6e29296858814fa8b1907a92ed5f4741e8cc01e44324926a4bb655889fb4737b5269e1", - "0a020cf3bc33878dbb73f47ae6e7cecc53923b9ef54073be20b603bc70c78875c5b4ca4c79d49d7967f8fc0f8d0b174f18ed4c6522a7a354eed616f17a909a0ccb", - "0a07872c5fe08ffd5e5c29c058f1d291ebf9d0de57ca1fcfd533da96ecb9228531a43d202bc68d025d82186a39cad9ca1db2ed57fc9b33ec77aeb565c52fafe1c0", - "0b0530e93ef4ae1291dca76d6f416df7879a89ded8896a5ea0ed8eee57ba9c519ce38a16b79204fc69aa29b54a77bb1a0a3ff7f2f2e146477d8f4516aa5e12ab35", - "0a08ec8dbad2405597cc5a9ec76f767fb26a385deeb1ebe653f89af757211c10f99e32c6e27351e6dbb5fd67744ee09ca1bef1c177e0cca36e4461349a0ab34393", - "0a0450f95b392d3fb8521617f448e7fc48182a619310d45028a4207375687f2fdce996fe93787cc3be196154c1a52576b72241a47013302b127a8f390ea901e628", - "0a033c3df05acece0a0466bed351305c4bc79e39ce8ed85d8e9952bd863fbe706a38aade4dad5e93c7cd9101b982597ace0639e98b3b2608b6c240c2a5deba3bb7", - "0b0498188cc6916137c7662a6530ee4650ed2d479357cb6bce24b4ea706352d1631efc2085af0bfdfa25403e5cfca7b8e51f28c80b6620e09d777f54ca13ea4cd5", - "0b04f31a13d63b75ec96582548b3eab21456df8ff4c349b99f752105178700f8e72d90f3b921f29162705ccde46792a92ba3ec2c4cd4c9ee4591498c5557c0de26", - "0a0741636f036af43a1a3a145883723231cf09a7d7efe65ffc4a68a8956471631ca5679f1a3e3d05eaf78dd72c51ab94dc74f8c5222949634f6f902122335a32e4", - "0a0834512a2892ef77c40eec18249510f3a117e393697f5387b5a5737c7df79966bf51725b75d4c3fcd3db358b68466fa03eb4e593157b59605df066c0eb7fa9de", - "0b056b8d5e83c25e377a0431238bb74905e1991f7769e468a55c55426232eb1e734b09721900d38d9c85675db82681bab3bc8cd2b87af97cbfbc79c3e7d74c3e37", - "0a0059c9c62a228f5571c7f3cc6dbf65bca27d4eaf13055096a565cffdb25966dfd5af43d218876929d16650b38d12717f71b44ccd447082c4cb757b7fad6bebe4", - "0a059d6d33ba405773a9b1f7646501edb6555def428ce725f4cb3440f725370586b4f577008d675c395489b78e3b12e7de8928033ed310c462152aa9faddc01fb3", - "0b084ff7f2f7166b4b735a7bdbbd82c35b63a6aa7adc0d75009f8c404318fab5b2167898196d92e1a8d31be80ccd5402c9679ada52ce09a93faaf207a21090f547", - "0b079b93134825b6f3e55435212bcb3812918f592782a8aa6ab2a642b303b7c821c426ba52149ce7af6dd53ab9676accecbe2a5946c73d27b2abfb8b48982da196", - "0b002b7c1de669a4453893c5b0258a1a5764139b3141aa36f830ef5f08a5528d1ddef5f0e18e3e790d86f976359ba87b1a42d9f22470d863e51ac0fe2f4196d875", - "0b0476d44fd932f92df2945dd5b1e9a5da3b33d7fcfc128d6f932bbd150fb0470be734767c51260fe57415bd3bab566361be3517a4ba37c9dfeb53782bb5cdd4d6", - "0a01c2870ecc329a6f397ac7dacb7bd8bfb0780cf3707b1923e822d0635718b8fde36d532308ce4e2523434f4093048c82acedb9cc449e1310bc45c64467496c01", - "0a01a27eda1f0ac88f19d5db6fea8157b707bddf5bad85b91b57e56e19a15a2d1e2ee199d9512ff8723372fe70baeb71904818bc156ef5f88726f462685809a432", - "0b005341ce5e8737796fcd4c7fc4d8af5c1821ba14d17b8c575640a68478460fabd47524e30cf7f30a7d8625302956458bcd7561335c9c60221c7ec937de9d43f2", - "0a04eaa94302f77f9f7e508d8b1ea4c3afa3a24e24942ddc3d7d003ba912db8fa759f64a097c423e0d1e66dcaf8021bb91f9398447f2921e741b54042fb21c2f6e", - "0b003eb8e4cf0dd894213048830a9d665d5ac0e092b68c761230ff8b54d13e83e0dd4cea4d308c2da024baf3fabeb1e1f23d1ff9b754f1cd64b43595ffd4fe0d3d", - "0a049e0f9c49c3b7bb179533f033d7f4762622c9efc30efea701178ee4b70091bb66bddf2c23e2ee647d26c4b1f5d2788e49fce16c4300586fd648bf2e20caceb1", - "0a061f210d2df63d0d7d05090763ad62da66b576c6252efd0154b0b3205bbeee4f28d5bbef9beccbd1a692550fd28c7ac42ea6f474d53d33d9a29aa56df409a1db", - "0a02075e9cce8e2dde2ab03c30e23404423daaae36a5bc1aec2a7301fe7f529169375ca2e9e11293d0a4bfa00e09bdf72a7b9bdb98237abe5bc6a9a961ceacfc83", - "0b0869f156b9dbc4e6fa175df0ef2d1515706fad6c9fc985ac8ba7d1f55ba257703b52a386b45997fb2db965501fed6bcc77299e9b6e8c0e29957915f22434f702", - "0b07b3f238a237203a27e4e002b55f1b15eeef1a29689f1a9b887d9ab48f4c3bc8e3265f775c02ad483cac3a2a915b981fa65a6c77073c492b1ce02f20fa6465e7", - "0a082daeaf20d7a92e296ed62a71e998df344154cf6f50c149feb5f4ff752a6dc528af81c64c65a5c23f3db8b3c6316ac3b19f7475d326e912854d7445d23706a9", - "0a09131fb089d755915174eaffcf433f536b491a3811457010710c2623528549f4852b16519c7f0d2a0b492798f997932aae4119bf2b9bc3b7859f36e4bdfe9cd6", - "0a00e7b3484bcd4b5c405cc948d50caf029edd7ef4f9e89539432874776ac66cb847cba5d4dd25199cbbe5fa9a3fd3ae727c6f8b633759ecd6dc68a8ea5dfe6376", - "0b087caf28e9cb6091b8438883fabea80cb128eda885e88659bd2d2515a2cb264e2786fd63aab355a0d738eba844f4cdceaa643d20bd60cb035162dc2d2f788c63", - "0a06a2bddbb4ac6eaffa53fea8e6549d5bf99dbefee0779df841e76d29a83f2fd9fdca01711d0446fa427ea95224fb60fc57ab3df6dec8d3a53aadd3ecdd06bf50", - "0a044f12fb66de72754f7c2cb91dd2472f52133668f7f90fb5011b7cb05e4fa882e9d1e2c57e7af31768db5c7f9cd987673000773cf1b967ccca1b00f129055a76", - "0a02805963607ae39f942cfd3a7e5fd3184568aed393107b2e3b5f510fcd16a24ac697ad44f20283427066cf8c8a0fcfd32b1f1f245ce678d7a5826c7b98bd8f0c", - "0a08c254b325c6d1f8c8a5f402cfe45c5ceb7f85db52bb267559ba3671a29a2590e61eebf8b2e87d25092f49ed97b70a955d775c521988260914522b2792b130f6", - "0b05c1d6a7da43b3f95f33a9da709237390e8694ccb8ba4cc71accf0e117eb680bdf13cd8e444af1ba0bb1cf24de4810fcfab03b1a7c3ebbe8b361e3ef41dbb676", - "0b038aeca29b00ba5656ea2c8003e674bfb718532b8e979b2400719f2d0c110afd2eb25b80e4da511453939ce207ada16d41410cf35d78612851c2b47cc6901dcb", - "0b082db56ebb50888ee5278579e999b72cccce2b61f4ccf888a5b8884b32c811ac969fe6dd56372d710d046e9860d5c83a81e77dc37fc5e7c0b25db22766039b05", - "0a01c1cf0a2d62b9c7212129c7949d73935a45b644f7eaaf986bc6b858f9f093ebe2dca486398032f5f9e819b723f2af68735fec6ccdf0023435b89471df5370f1", - "0b04d45e3ae80ed26087dd149a369b950f34d7a1dc5960a7370d2a4e2545226140ed17347fa0f5799e8893692eff5e40c163fb5492fac45625dc2be4e4a7a04672", - "0a01ae84141aaa27a2690d3483e65c8ddd0e84c3415ab555756ba3494e49761c030e522d7e9e6632b411695b6c29a23cd5bc5e26853fab2c6f189d61c37ed49f82", - "0b0243898483a2ca1f430f9f6ff417b88638fc3b8bea5fc9d8e68b35ec5bf8cfd175b0cf04e059e0ebee5c6ecaec6efb9d412da6c341f783af92d0e63e43ec4c29", - "0a0752cc4742594629918cb657dec316cb41e3c231e013a789177a238219f076ce48bb5da803726978a04098314e584f6d2fb1fad09e5d12afa7ca24de91be6cf8", - "0a051a8cb406465f9e45aea246a55034ea0eeb7b5c79cf0cb7f7a21287cbdbf81db74073d1ac2d8e7090ee86eb14484df2344108684f8f958ce5c712e2e63b5780", - "0a07ecbd3d3ea2195f3b9c90355a411d01768bf43ab52e72ad1735a1c90982c31d189c683a73a168ef6af7ba3abebb9e2064a0c144bcb5ab7a43ceee95922cc164", - "0b0361c354b993af79ff44ceb07ec458ce46bbdd2c33ad139b69c9d2aeb5e9ce9e68e7011e163f477bdf353059733f2634e6955c35ed10237bad68d83dce042ade", - "0b038db0c04ea4599a75afa4011ef2cb18a9078e88301dc7ca2d660c4a35ddaf09e3713ceaee162ed38d3f20092e87eaad79778adf62c9dc142d1b5bb2db1ffea1", - "0a0081e8680c347bcb5b1f7daea0fb3c3aa0f155312910764d95bad1b454d9f7902a3e5217da5d5317fa46341136f1df048f465f8f6013a5871835646c7378c7c2", - "0b00b806df043480d4b19a2de62ddae23005b5ce91ff5116989602618398126ca6b4e0218565d41bfa007cec94deb2d9e17de5e329ab81f7c321f221ba3c5afff7", - "0b007297815bebc9eb69daa72a2431247a09622cf576167a70a4941acac66ff89e111597e1d0bb7f7394923ab082874eac8b7026b00068f98a19bb23a3e07799ff", - "0a088687ecf0694b5667cc9a0aaef3a1e6279aca9ce56401219a1f4d9b148f53546add335997d42be7494e71de56ef73810a26737697fe6a61136353cd1994fb3f", - "0b04438cee154d8ef920b7ddfc2c71dda925e7dfe8045504e2a97d9bf03f646e021c17c87d75d2bdec66e3d34b00d0d3e2039e5ac7c39a2ce1a3bdae788e0d9025", - "0a02e4c037f46ab8b5c4b4c29e2243f8ff0ea4b00a84ee28d7b2a242ed6e310fd61c5a218b369192d6d57a81fc33d56b282fc4472cae6fccad3be5e394eb341720", - "0b0311d83eb7223860d0bc4431d6ed677e38e094c58a453573e4befb13233bc075609c90fe595023a56d5376a38b4775a6af37674afa1e2b45b019d65321bbfa1e", - "0b01227e6c668f59a710ea752091e41df8be36157bacf4af5656906c98089a09547c267c01f191cced1dc4a470779a90beb8c679311385ee432d46b63a7f839904", - "0a0764d575757ac186a1f92de32720dbc698c29d0ca4861f17cae2d7262c5a81fdca61b99e6cd1b36d9b473637728df96997ecdf79385219d71c1d11733076705b", - "0a00aaebb09555dc538a9c93177a97580cd8b5ef708eaae0edab2309e8d4fcaebc35ff230994bdd9ded7308fce9487bf6c6d0804e2b850c227bce7cb9d227c67d0", - "0b01cb617a7a2367cf80d22ebe00beac2553d97cb77a324d4b657c67cb03768a1e278ac78017df474962a0983c6605156dbbb20f0bfd8c85cc3579765236c824ae", - "0a040858781e953daf08987456d4ed4bfa67e7e4cae3d8becd3c87251ecaf932c3c93f51c552ca2da7c38ad391fdc16a87e67d187c85d1c36b571a9acb04092700", - "0b028fb713c3aa3e9936f3229ca8bc8632806232b39ec8d9cab5830818c514f40a5d39d431d4278bca764838c0d2eb1d52e8228ecdc1fcc7b823ccb6f7d5c1548a", - "0a07866a9e4d9d83b26ce24e285dfb7f16dc69a243494d7116e1d5be116597ad96d0cb586cb80c745551aa6d424df5a7048e793abf19eeeef25ea2f843c7e6f963", - "0b03af8181e2f8a99071f29e8c297a400fedad423618e91f8a99fd1745afc6240b18ef8b29db9e6913b7f4038319749bab63a0fa320ea1f7bb0e2afa2900557ec6", - "0b0551d768e207ad2c9d272b63e802a25b5cb9060c8feb89a8f2c9417a2e6b3247bb3cd4ce851dbe778500703a5129bc993fbf4bf953b2a4b9546a502934788658", - "0a07d44c26647d46945094c7680b4c244bef6c4394d85d2ee6c38c38f0e69726ae952715236795afaf245be627e8a7f0a3d3528d842b434f9d8a80ed424701a97a", - "0b089ab3f9bbaaffca8887a547a1667aa52d1d1f03af35d6132c5391a34a8c20c24071f81a36b7c33c78eb0736cf7f26b7962d574ec69783814e8b884fe20b688d", - "0a08fb6a4f28617b43f47924255edf44278c3387922856477b981c5ecd8c41be7402cbd435b34fd7f539dc3748046912897a66221ed5e9351a07ca082dd5565be2", - "0b02dd2f09fe9a2547dbaf53e9cb503d7c67ccde8c888c004248c706abd644ef697fe371bb54f0b74dd558803a771a62f1cdea0f70c1a6dc044f6276e5b2dd045e", - "0a065f11275fc83a462097399671c66184a1c82bd3ae234b8eece10e0918e08f13042581cc03568627be6c842ca2f29909114e7b41f248ab8d3439cc08f59748f9", - "0a05a581e5a1bb583f379c4b3137f88e1595454ee285e510ed89b80031bc3f7d7a76162ca28efb3454733eba1254428ec075df947bb7dc269f4e01c4dc385e956f", - "0b07fc3dbf523127a95ea4cafa9cd4e491f13b0081b6fc72198e0725b15d5c6315a9369faf3781faf268cd67ede6f704abeafcaee6377b778e9666d926f54b1f3e", - "0b051429aeb94e8135237e0ec8f5c915f757383b45243cf55248c8e26bd8b31c8b91fc5055e2bbe542cda0bd36e2ca03910301c341655efb5700125dbd6b167566", - "0b087e22333862f2c8059f24cba09c1e527dea9aaa224435cb49eb4ccabec9a0f5ae8f317d0f05bc64ef84e016a8de45cf532d4fb77eed5213e48efe5b5ab4e374", - "0a06e9720083db09d0519c44d4447081bf47a59a52a769371ab52e730c6fb06ba05a91b53b0070936ecb349484b36d458aa357f72cf3417dd09b9282898c94113f", - "0a06653f75d74b4465344d52dfed58a5d9516939a2526a47df0f439269a07bae87ef9e8a720f9af0ddacaa9c969b19f64d3efaea1b064c36f9d5b186d6874c9234", - "0b038da11b716ca55facde788a02dea120cc43d6846085b4148ca02615ca6888beade4294452e09889f0c0cc4e1cd5a79ffe7e39dc84fae3187cdd1af55c6b67cd", - "0b0573b3116356f0097d6fb259acbd503196085ed9dddf1e2af67848c940168d8abb6ba7c5ead46a88eca988673645c72172ee48b944b078d5a77b22c36ac109c2", - "0b009664080f3abef1a22e092561398259cb6b744e68618cf727d871e4e8afe84667d2c89a1e7f37182e79c29c6704ed09deae20c44534fd5fe849655ecb9b94fa", - "0b046ae4dc5d5f81a9e72414f2cc7758f19f98449f2134904042673b6fbab6c1374b5d09702587e712ae5b69149a931973128ba636e8f1fd7f46bc3c84a8db0bce", - "0a083f6643c2082807fac00182bf2d03e9a10bf21ac48185a53577bb1bb804f3339c952e1bde2aa02e73edf4a9e5d72a0f206fecf730c54d8db291c5275c16491c", - "0b0513de9916bd05c6baf2892739ba9ebb72c2c35525e61f7ca100e55595339942ce17ddf3a3a8dee8e1ba758d5cc5643a1e996bde0d00e45b225cd92696a86fed", - "0a08a4a6045c3a32090e4450ac3000aa7cb5888296f87f54fbd4b758942c5c4216e04331e23d2df7ced1583cf33f958f5dd38525adde858300ed99af93701dbc53", - "0b06b954d9f74f544f0655f292ff9adba07c15c3f683deeb8a55220b6af43e8d3895859d560c8a3fbc733992d63affc3074ff1b70b4e8af3502b6fa4c5ad02afe9", - "0a0916bb7b3fef69ed7518c476a39edb06358921d9427b7619c9ad3f1b865e1f39eed26488d54eaba9e5e5723a98592595e0793efee4af58f01fa574b8ebcc21a7", - "0a081725e0095ed120097bafe745b4dae74c2b8517f183b0960d87d16995542c1855fd177ebcc0bba19e7eed42864ac131efb652cbe741c52d6dcd8a1cacdee24d", - "0b0605d6e59f3387be0854cecab6ac5a2f26407715f2b77e4fbc4055725fb7c1ebf23ec880b80e76827b51395f17ef9f17646bdbcfbf55abb062f73487f699f379", - "0a02c0400f6c7163e0c4d3fd3a6ee108d96f523b44c8f0ac67326de3c33a1d47979ff336aebfa4dde00688329da889d2e0d4755c6ad41afbd707f7f72949ac57f1", - "0a03ee25e52c693470901f43a053f28c99fa4e5a80a85e1e8b1d01ebfd73304f4ab54b3eec94a3197d856c04e1936c8ee7545bb06a9257bb5cbc9097ac5368b49f", - "0b060033e8c5353e0d58cc148241284b349d9711caea52e68c7a26eb9ca92c8896d309fb5bf7c955232ba0910e7643632c7e7e1f2b7276bccfa5b8ad3de4bb3274", - "0a041ffa3e2f3282984e780f502286c9996474100564b624a888d78282ef3b751a2ab52ecde5ebefa53aa861eae3e981bce437218816e52687a1c73ecab4fb3c59", - "0b00d47981996b8fd45893c1b45605a107a5e3fc17529c8da79324b173d928d2e345bb270e1e6256f055b122957a06bce7c9a88d4ee9152096e5cc272384c02539", - "0a08d954f689554537ea32c96a580617c064072049ae26bcf1d548a8baf08f0ba7b3de17b52967bb9c854e76267a77f0c888350344677ff19c984cc8099dcf4918", - "0a00ae20db52d65c9f45cbd9ecee9fe9486cd10448b62692bbbd2b5cd5e58862b8a922a4b564700b632362265aa27e927b895fa0be210ba006ad16b14fad2a25e7", - "0a01debcaa9b0234af73585143fb5e9b8b72f35b46ed0fff15c3293fd3fb81f23c877f3fa09ca0ac083428ed0f91a0e314bd70b0003933cf6d2b344125551c5766", - "0b0652af638ee5e685c18733cef44d8c040b2979e7bf3380762fcf24869734ee1233a9e333cee537c89a80e2f276101ad6911546a90d396f00eaf19e1bb0e75646", - "0b07d1ec80f62a3d7f5a8910879b4276afb0eb458e9659a88e08dc5930c02264eb8af00248a711e8749f7ea434a683e361bae1fccda26bc5e0999dbe5ca3bcfe0f", - "0a03d91859d76ba99e5b41dd7121567dca502540961ba52d9b61c029f816e63f5804544595738b0aa978a61e03ed1320e52598a533ca5b113f773c54825ff91a8b", - "0a0282b93166521a5d9b54bf7590b664b91e2ba8750830af01f7fc42ab2b9d80b7674636697c512b47b2142f0e0ff62004502a19f63c24203d4e3c1a05383999db", - "0a04d4dd9c11cc6d2393724f942c31c143e2bd00f0f8f9d106d828ab901942b3459288dcebdfb028e758cc8562575b760e2ce7ccea7d21b6dad49b02a8da1da7b3", - "0a05881e8257e342ac5a7442039019668b6ca6252a929cdfe1071fc574c737e8c1f1e3c5825abf951af25c3f2d95f3ba4bbdbd77a85e1579aaf9fd93190d83e5d4", - "0b0716649b3f86ba999accaeca25b8b43e7e6d23a7951a809861f0a115ab65f5ecbe7f1e7685ca32892b7479f0b6aa3859f6c1cf79337753584ed71918662f0745", - "0a00901b759b4b9639c3f028769ce0eac157496999d7bf1d31b0429c1de34862e25dcb791e4c403cc2ea25f45519156a8229fc873d6a9a7683a0d16d56d0a72329", - "0a03b9fbb6b54195cdeea218ea974d4883fb515b8278850c529e914a20cf5e26a2b214e1bd00fe6dc2b663b38682a25ee7d5c3daa9f15b5b17ee7fee545a1e9eba", - "0b02a5d8d266f8a3bdedf51f15f6abe7b1fe9c0dfde97d65d7dc58a92007e31452d597b613f00bbbbd9915ebb816168b7b8bf1bc25e38184fe72fc13dfd3677123", - "0b03ddf8b19c47ecc69dbbaa1254db72dc98e181c4a6f9a75501a56b5ce2a1a5982fbbf251800af3323b9fcaf3cdbfc521b232417099719c0978b0496d26441289", - "0b071b382b52acce3870948129cdba440c35b0f65a59916cc1004335e0cda2ee1366e489eb835383fea6e41387ba8cca3636ba2ad2fb548412f1b942a4a01b5bd0", - "0a02d11d20a77b2e41730e7430302542963d34b35ed12bfa6321c43ec0f6c03a5fbdad7c856af6f6dbc8bb78e57e13d928e715396637818fe7cb5c9fd1da62d04b", - "0b03706d6c2637e7df61e8ce3b3ba6bf314ce33f1e8f42c561eacbaee6afc4268f20ea7b32f93010e8ba2b96052115b95339aec9a60f1a0fcf64530e1a4726527a", - "0b01560a4178513baa02e4eb1eb7282546698330b9373758fa85a405a04ea87088a90537c400b2890dbc913d096eddcfddf7bfafac9a9edee7738813d225fefb9d", - "0b02c3163cded6818cae1feda5a273803e13d9bb767feeb913f0414466d5034d696ffd6df2ca9b3d15e5058ebee57f61f9cf4392aa0fc7ab431090ab210a871e95", - "0b02cc2265a2661d8fb081ae3ce5661348d15e0e4067d8d6b8d812a39e92926208f0b77c5121d7808e6a6d98097d158cd46d249c809bf2cbef53e4625d993e1525", - "0b01ca382e053878ee59a32f53c311393f253fc8b7f54282ded795891127f43f10ccc5fce78353af186402e5a5d105a62db83c485cd1afe9f13682ba52eb37863b", - "0b00a79fb859f82b4f4593de4f9ec30b7feded83cba6f913f44f3fb441c4834d307bcf02dad4b05fbf8f4657755fb4b58ab739bc76037bbe509b86406b6ee66019", - "0b03c2d875dfe948d57cb535ef91c78afc8bbe5b1586988fa6f7626d57dac941a99ccb660e3332d9671f125b9aca73d6274d198d44e54f792cd985bce91f36beef", - "0a0668971b840e4b4e58ee9f20409f2771113e25595cc491ca17f997141dfd0c4fdce7bb9181553ce7247d88cca9e121c810be78d4b35d145b247b74c3af12874e", - "0b0002a3f5f2df63bc5bddc9d2ab82a442fecf7b981f3997fc5eece1fa4620873baa87a25849226863b5c4d2c142764c704ef2ad9d90160592578ec33133987cbb", - "0a0703909793863cf6978b03c5c5e3859640d00c7613aa77237f437a90b4c4462df380eabfc1071c8e3a5c1654ef67c25c43bd3760e01289dc24e07199447b8dab", - "0b020b393df5eb77179a656faf55f426818808279ac1910680d86eab6f98916e8bf4d8d81aa06f66affe6eabd03198229c32af050636689add3af1ec9a9be1923f", - "0a022d319d62df03a7a6cddb154af4fc5b6910fff55ca67060994219debd3ac68b739b183d4205d6338797218975df2f783ae3b0cfc6792bd39f5dd248e400afb9", - "0a08c283b1a42b2b8d0f932927826dac104af68d03dbf315b17e618b37aacf266f13d9848f21b5497ae7256a02f6ebf683203636ee969d3a182fa3cb150dea2c36", - "0a006f9b7fc96b0ee75a08c8d4b113d2363ea280ae16fc1c92752e43bb4bb8815f81f8a68833715016d1ba772df98e71d178f1af67d084079f861effdd751b8004", - "0a0530f05b304867498ed0f1ed4967a53b5791c1dca5cb53fcef69efa59ba367744d05c7038eb45b216366583235c118e7b8629183bc44827de35ab69e1ff2fed5", - "0b062449a6956c6c2b671c72de22865892d34b1b96f34aada8b1947dd946621a64b684161cd28c65cd8f6adff7ea2a863adcd8967fcb27aa4dbf16e2cfba636056", - "0a06b84fad869ca035e97242b6b8ef17bd714e75ea5c606925bd8bfc52b57feba2acb7f088d94c6d44a8fd2cc52459b89812b12c34db51e57fa9753e8db5e5192c", - "0a0751a3f288b3f96717a94ce91d07ed4b4acc1ff90ce87d1da70ee3a44d2e01afa3b8d6292527b20ef0a1bc65312581a71371889148cd0ccc92b882113ba6cdfe", - "0b064bd7a2fb30484079404c66bf23661b4a1a955d74f2679d9f58a4a273513d0a4aff4e83ec92ac9156f80753b442f15aae920a388dc1ac43bd302e0b704505cf", - "0b027baa57dd2582aed372d65000eea033329665496ce3ccb770fa93b3da235675ae2a37f27e35dadcf4a1c77f10eee25bde6b8f17d85864a76ddf66fc3c30ff63", - "0a06478cd66a3390090e79936a64c3d2cd6ad9a6cb836944563b515aa54d7b92727fab397e17a20b7a878022f2536130eef13660d4a016285eb5643c797615f7b1", - "0b014b4fff75f2a59893f5578a7831b1223e4c1b9034fac52815904e65835ce939beeada5770a6817c6b86b9b3c87766e544fc69c700ac93d991484679ae37ba42", - "0b0167b30df220f8d8e8f91f7f9e4fd7094e826efbf89d3d3b8bd6a580e18d2d5dcc4d9170ebacc2bff819eaaf5948a5cc0c42c365fa4f3018ddf6902f0dfe4b2b", - "0a04d1fd8b5b7a931a2756907ac523a79a31664c879cb7460fa285fc4dea5f2b5e261175d098058180f0643cd641bdd037635f8ca4a22f94c3d2db0109ac87b801", - "0a00d5c2798104f555d80e24befb7779b3182cfd5e9c4ab4ec559fcd91a47f382410674030a951d915d1ad2509c37767cfc044db4033c55ab576d93b839140c641", - "0b07ab88ec29102e75908c098aa332b2fa8392cbf2ab12938e0175f7c089724de4b428a04e394fba8294ca904403ddb37786e7c5c9726c58c62e0c46338e3e79fa", - "0b06376da3c163fb9d81bdd3ce5146e299c98388eee6f19f54c9d173b3f823043b848d1bbdba5596e41085824dfc91fc98a420e8e53da0f0458762c1f5ceb4e737", - "0b03bd7c5b3eebf1bd42671bc5be19a94da07b3e7d5121c91101a05663007bad9ffada667b505b5c192078d40daa6aa89626f817227cf21cbaa537b3251e3e161c", - "0b0120c87fef94a50fe47ff8d567370b709d63eaaf57870581e3e5c247e2572c324a2582ae135b0d66d2575d944822af5718d98cb8da580d82acf0f1db48f94346", - "0a074e3affffd1f7a6c2a7b2d2656422e7a896fde141a15d3cc330e7810cbde523ea5bcc75c90d2f21f23b2ccc7da95f79dea114e4084abc18dacdbd85131e31c2", - "0a051c7699f767468501c245cb90a96fc8d6f0f1dc08ec81bada4f6bc75b87ef694f425bd30096eba47050541ef90ec6afc3c14a937a228bcaa517bda7cd25fb20", - "0a03cfd963c01f35b8f54e262df95a5fe593e7b6d7dae84df5b0244996e1b7e691c3a2f98afaa63aab49765db8c01d69111cca1e558f7a8d61761936f18146e324", - "0a030fcae24f76b001c6c929c74d46b59fe12d03e7107f4d6d1847f14b766672c5fdf69427eff1aba6f07c5701ef3cb127142eaaebea02846cf16cb856bd907dd5", - "0b06433cff78e8f0b83796e5c611328369f4f9dc765dab6c8b3ef7acaf43e224f3adf7375b565fbfd7f58d78a152543042d1b7f0459476c34464930765ddec53b6", - "0b07a57741881575e89d742e54056ec244bdd65e5c97faf44098c5ce5a8735e294f6c86e90ee11968d46d6ae65a6b52b33afd7afdfe6c6988e3da0adf7d21416c4", - "0a08bc6e3b69a656db92584f3178fc2e5dfabcbcba6aaf72633b8c75a609e3158cf99653b16126b8230a3f6d00374bd93fdbb410b3e9bea6f5197274136dea23c7", - "0a062fb4d71fb6d85264089e3c95adf9905b0bce1ee409934f16498c365b1c658ca1bbe0ddf25f26430f282fd3f1a79f060dfee5b426f2433548f37746f139b83e", - "0b00ee17fbed0c2e6064817b17b879ea1d1d8ba52de57989224baee33e3cb849b7e2248fb2e94c864d31b20db177f64a9ab400f6e5ca7b4e05dcfae3a056248e60", - "0b07c7179616c7083e561c8c4c6f6b73bf2e1d423dadaa69d5555ad55986418eb94b0d930e5b8a0e7fe5abaa738199a3704988a1e6fc207ae3575ae6a9b5b2e728", - "0a090e11b3714c490d423c3464c747dfcf72f57efde93415f67a623614211d86d13cbe3c8020d091c732cb58adb781c16cdbdf838ca2fd186da155ffc5cb03535a", - "0b06b08af8dc806b1cd149ed07e00935c1d50f9ab4df21fd414004dd07b3938bff240f1d9cbf17f694aa579955e915334755876c0ae2ca17a2d7ea74a153d0f130", - "0b01489ddff5d57a4e3b0f5860aa4d7d717b405d77f8f0ace510ed055d3b6b6957b301f14d9b5deeb98e89a113b48d2b1031f9c7d940784d882dacc6e889bf738e", - "0b01f7ae9ee6834c221f346677a4680b64b9863897f2007375381fde9ecdd691980bb9e995ec56d7146c89150f09434739b0bc832c1e5140beb90138ef8bdb5752", - "0a06b07878aa45190df0590f39905c8a447972654603c9c83ec98190234344496374dd221fbaea42e86a6535830008cef0e20ee8cb99922fd552f715c3cdd11a3c", - "0a058a13a0d2115beb29b20e52be92185103e4fd7c3d1d65c7ea7b3dbbb386b77533329dd669a2c2505bbaf05d63663ef5257e247058d235d0b8e3bf83cb74b26a", - "0a0750d4f666fb0990663c51dfae512327aacf460514eb32110c805e6930c564f3e6c2254ce9a8c701e26d1d86aa94a6d9bf8c682e212fc2d23edb476a4eb005ae", - "0b02418a64419ba856e4437adc62a7a3926e775c2122a986d2df0ca0e92ffcf3410dcb6f63de3f68b8641660cebc3a7fcae9192ea62530f360a04b50eeebee1345", - "0a083816e81c1015fa1c786831e090a4df5f3053cdb8b9c115d2a21c6ce61911bdf5a51ea7d2f257b7cda35834796304ff347254d3b58b4b3f44b9662a1c65863f", - "0a089a6959145efaefab5edcf66c77a6a7649cdc94a9db433ec0d963c93a7aaad69c99af00b05ea8e7a6606a3fe257d53ae851eb2fdcc70a373e010f10551d4c86", - "0a08633f7f741a084119fb96d50c5e9bbed2284fbc186f01a0f7de63e5ce43647d8ac1969a589c179fa13484445274641883bd9a10b683fb15d3d3ea8b2adc87db", - "0b07918532513ca7dffc20ba390fe784e20f6b7af964d83d3fd61e4f0419a338c5c7f023cbc39d3758bd90ef7462d20f43969d7e8ace9844a48d64c0ecdfd6498f", - "0b00102a92e1c9ac3fba8ebc03289d9fb187f92020bb96b8a09eda3c0c2859ea6d532be2329c31a3446955921e564bad05a82342b46bfba72fef01ff1d8325afd0", - "0a04ed2bccb3492a5407712fabf1505eaaadd06e8cbc2ab69ba01b39bfa4e82354b3b56b80eefe4390256cda4b804a18f308f0d81032e5689a25f64aaf74ea7cff", - "0a04d5e1f79f9d853ccefbad6d2ae657425574519ad27521b713f733d11b85014d775711bd783cb26ff8499ddc26b9cd7a72a67437ba3d578a26184e417101ed4b", - "0a082bf20cb9afe56d0b80bd78e5eb99bacbf5d8b641fb9a28cdd73a94fe47cba1d3308f1641da6e0cbe40523fda070081129483f945ee9979f25f5b9588226d5e", - "0b024be97bf10ceaaf2c72d7c305a3973b262bfd995e64da6b7c16d8f742703ec17110925212449fc201df064df43def981787513e35885333919bc18256fcddbf", - "0a0701e8b7458e7fd27bd114bc964c23b4fb3e82cba6f9222014dc865cfc6f669a8f33e91b8ac9ddc53fc47cc139f67beff5d96b0cb156f011e4ab28f4dff84f2c", - "0a055bd4f0bde4ebdd61550ed6c759ff33e8f5cd4fe81963fd98fa6fa696f075591b65f91963e20e5e83912f2004970cc7e315982768bc2b9f7e85e46cddf9d67d", - "0b03da1c3a380aef50555018cbebf26ec6b447d446770464032b29fc4659f5c33266fd9ca8da039ddb8ebbc6e72ef724fe18a6adfc2abb355562d71f9f415ac78b", - "0a0675634ac617cfa4ed4c7100c4a3c2e2df9325f3f75a688e89c80245b7cf19156cc34ea46d039d067901b51193c49a276eca002aa34b7695c4b8e7f4a8d88ee2", - "0b01ebc8c11cd0a408bd0dc2d75de30834cf278a04e158f890ba6c74c539e9d65204fa47da5fa0fba7208c2d1524078bc5dbedb4d5dc4b2d1d0e8465c62ac0c5e4", - "0a00db9559c1f2217f272bc3ec15131b1c788cd0b1520f2a126ca564830422109d3b52496d9b4fcbb3ab85f4a71dc59dae429164876f41797d769dad2e8dc5117c", - "0a03673efc8a07146e38d7621f60c184a78658b10c76b8dfb2a98e18794306d4a78d9b2cf1a5bb2027a06baa88c101413c6d450ede85a5c4453229f6963d379904", - "0b03ac4012ddb4539360a6718b71873cd39bcc6f7951e636617cbc946e96734a5556dd6075eaa267747ba96416af252f5ea16287156c032d600f1e4fd11e588c16", - "0a01a9056070a2dad9bc7b9a7655d378aa68d84d6363d41c1ac5ebc302dda5081e2f2dfe710677fe31d0c2f84f8f2fda045db855a772d730db47e6a45043f22e44", - "0a010ecee5898b5381ee9b05fb99c00d4b77a3cda28135ce32bf7fe1ac96ff506c63031873bd7306715f114cab5057839d9ed68fab4b9aaf4758b794dee183c202", - "0b0053f54d0770420bae325ebd046bf5fdb54885290672a4ee1d4baea5e7b1569f8b47b0b93213271b8f7aeeccc09a5eda47b232330e7beb13217fd9a6fa35e284", - "0a06b8c5c4b5f71dfeeed7f450d6560a2707a8e3d372666d9a391e0fbdcb8fb540cbcba3f6bcf7f43dbf1d7771b87118a377180aeb962fef7fdf47b2d8b7f41a9c", - "0b00e048ca50adc6fd70f41bca24250691e680351b89bc830d4977fbb220132e8565edefb86f8435768aad078cb7032e42c542af2990e5de477548400abcf1b7f6", - "0b08aa0121e618dd3ab870e77c296852af6b890c22762beb96013dc7908583e3b6703b5f111e4e7db96574262c7616ae66fc2a9240faa5f6b619f01c8b5d0cb63f", - "0a07797f7b57d1406fcb5ff31e35821ae5891730ab2b7a2c96341f514fdee203f7e9239f6f9f82491bc0a38ec964751d6c2793f0591515c308787c5c5ac527f4c7", - "0a00b2dc52405c7ec17207e6aca2498d408cb99d16e8dcf543819b1ed3774954a1e4918ad920cb972426cf689d106d88c2d347633ef4a8ab1e4be0e22b918d484c", - "0a0417fe7ff5493ad3a792f6667488833dfbca62326798aad8c8c055229d680295fff809f38424fa3e7efca5e94a911eda3c4e60cad9dd82d0d1aa031dbf7ba610", - "0b059596a76f7c52eed456def6baac82dbded5ddc62ea91c1f97d89d57387eb3784f4cc39952eecc7f3f6980b1e33ba9cd7525c7663f14d7e37a2b7d2ce701d2f9", - "0b0093a0a3963148c445fb688e595ce7e3c89b0059d096f5aa253fbdad4433dd8790cf1dc686c79bdb4357fb0eb5330fac267a1b343e5a180b9e9a85d005b3f3d9", - "0a0021fecdbb971af32fce8daf3de41fd9b7e50ddf11b2e299072e35d5888e4351320587af6525ac7aade13b37e4eeec0ebb07c53ec4d7a7a8123d7d1334b63465", - "0b018d4d4667fe19c3cdc5a8b7d3e98db224d8753194eb957192b9eebae70e7ddcf6eb7f53921f9c2b0368c9070c470112b09a3476e868a29cc5e9f64c43038232", - "0b03bd01fd008fc6dcf52bb4b429d585e5996c5e9bc3d4f1fbbc8879791f730af05e4cc8c69b87bac1891b656332e53e3274e4a693d110f133c92b20c9b5081164", - "0b0791cab0fb531948e1d9375285fa1d41f855aa6eed486566af119735e9105a25659bc9f8a2366b9dfaf33d1cea8c15543eb5dc933b8909be40c757c45115cdf6", - "0a08cadc223c065238d8063533f5338e08342079f4ad1bb4f345b073cb3a59c6f96f602f065093cfe377b91527f7a8f19ce7dce2d29b27e37684b8521b25ad1722", - "0a016747e0ede2b90b6dae3b2a09cd2b07742120aa79a5c749e76a5a036fa576f436eab2757ffa5f063c83a73bc47566f092a1ef2b58eff183fd08948fbb7fd03f", - "0b05e7bef00247bcc0920563982dd3daecc155da293176582ffe9621ec3059d3164ad72cc79d160cfd9e67a0f10b9e48417c269d2633a2d16847ce76ad109557e5", - "0a01b47075fb8d8f9eba2a99622db9f8a726bb365de2770016b83fb4044a7c09874210e1dbc2af6340c8f3e50ef6b5fe58eb62723ec4a09b553fa36c1a5c8b1628", - "0a034170b7b8d87ba09f33bc90230a39b7e79158fc2434246d9f5a0e38f2b43b38c1d576abcf5fbc4e2028aa2b88016aafb101fb8e5616c17787d42ecbe8860ff8", - "0b059b510f5ef33d95149fea0a6bdd8cb5345588423675accaf705e91e03729a42b4a7c2f5d2e6f2a02a557d50d0f1714d94226a27d3c055e27760aabccc0efb27", - "0b0676b142d4a22d395c6edc0ac34abb437bfa24888711d122cfd89272be43d390c6c1720dbfd97f3c7829f557018b97799098d6b4c95619d75d3b3cda36aefd35", - "0a05382adc16828bfafa458d6f5ae21a10e1198c482cc50bbb84132a9c7c5e33e9eab4838c06934f936cded12d4057061ea9a941d026f1772bcc6b25873520d6f3", - "0b04100af84471add5db9a853f07783598ec970f6b5e95575de897cd1fe41770069bf8015b568428e0a6194e767f6c105f4e5c5b3d8af105088d1a8283b096b715", - "0b013b11f4910d233e72bc86b01cf67b522be2b6a0421e09f35c8a196766da951241c546e3f280f1f7d36e45df04ec3fc4d469b2309d41a3b830c6e4aa1ee47691", - "0b083057d78c17e5548032f6dab1359f0ad1fcb312f4fec289e7418f07d2d84967a9c1cb92dd43b2a287cd7c38ad3806cb684250ceeede56d0b301e45b3b7ee22b", - "0a07cb51b288b47339009b7bf7e8576a894602c7e17a945f9f12238669ab86ab545ac863239fabc44394bf33eba43c61dc8bec35f26b3d36d87d9454827adcae5d", - "0b04c2c94c9433b1a7886974497f38687425b8065f614a1735b3e0c7a7c777dd8dc71fa00c0e36c5f83930cf2954795ee13ee8d35162d8901003487e2127e739ed", - "0a08de03eab1cae3ef699214785231f016169baff652d71065195c28d782f9b0fd338b4f10bc582b2a9da3425ac1a2d4570b7e078db14d0b63f834d36f7e996d5e", - "0b002c151e67f6e4cb120deac7302e32bdae50cdac7b6b2657fdbba45751f6adfec14f734c5f720d3111601aa9f21667a352b9a19aee6bb7fae489fa1d8a1eac52", - "0b08ed877f71ef0b2074e38f20ad608932fa50e03e80ca7aa9939c90b2d4cd758e3099220c5480e59baa9d9a40862597657abdc26a0cb3c73bdab33ab488fcc91f", - "0b01e4e9128e6a5848b2fafd507d969bf3f79a2eafdd629da07602509b35c28aac187e7c39be9be128ab504a6ced6878e9b2d191f83cd04a7eb8461c4073a1a23a", - "0b01d6d23297813fa5c2f3e46d0239821985323dd6c5cb7533a86ae6f5b15d264d3a25952fbe2419d748e6d34df1beca3753c0444575fb046c01f9f127bafec242", - "0b035f677e949917d95fbbce9d58ce271ccd855780ff64b1c4751cbfff6452a7d0707c7a111f414df511fa2fcc3d3e048a48439d4ddf7cc9433ba7e4e483a19f42", - "0b01d93f672e63d7f4632beafbe03fed6a2b9d8020c1193f2edfa3f0b38bf76b2fc9488393bf2e7cdd5eefe65a7d4f3ad918ed3b8a42606cf93fd05ed7fa766413", - "0b017fe0732c938da948c4b0619ba2d121749ca499f1eb416e109a81741f18dba78e63699be1c736373705aae363719a0f5684b7b198f19fd7e317d0aa9d854e71", - "0a039b7ff4bc6ffe1d87f0bd4a767a259c12536286edb777860d757ff70e0ae2db6a7c8bb5d26998a7075128bcf46b14ad7f6af0e5807302fc3527b7f96dfaa330", - "0b088bfd052a19d06041e0b49f94c020bec55e2727ae87f7d8bd4add5c1525d1655467487b7eb1aaf8fae3fdfc77495b0f2daad5457a0812a6b9180d99208a33fc", - "0b0826df267c4f6c317a123d085ee3d74eaed75da64f6799db3d201941cdbb1ca24276f5fdb24eceada3a1076560f43bd480349de58fa7e840a0240ad36a91cc68", - "0b005dc2747cd84286da298a354d3b0d8717855300773c6a3f007dd86aa57e617ed8c4e2f3f7292b9ee4b976355ccaa919d1de5de3edf6cd84739670111a844d45", - "0a05669d550a22ef48a72940c6c64829690714446a6980a323c37fc1d565db1e474798084c9f58ee30bea091375ea2d13f503174c35780c20383a9946958040d26", - "0b048100bd58ed70330d8d5cd8df27515efe4cf6d7af10b1afcbd0d00687e8990d5ce1f0f924cd47c5d3c909caa79f617b9da0c4991c49233973252d0777c063ed", - "0b04aaa3d1255f2ca624ca435b2c41fa43a231f927c372fa20812ab3f180b7dad2652ee390aa31d06112b3723afe2e04b23c5fce1d05490c8a7bd38e877e0d1b38", - "0a07f8b75450657a666019521d41b8315735d88327a80d1761a1901465ed72195731605934a719694211f315238e12a99663bdce29e09b4e8922e16ec6487ed69c", - "0a04f741b31d224c92670c1431ced2631ff7754d9b26580c8aa62f315d7f85d8edabd7afefb69ae459ca400b9d810eaf39f3de7a877b87635ba99582a8ab691e38", - "0a0769431ba5ddbe6001137ae3ddfcfb787cf802720edd8ad6540d609dc96f5ffb1e76987c590007610dc9503e645666fd246c876c99c0bfec933df9f59e603af6", - "0a017f2bd2f7c781c41b0352fdffa91b5ba0fd767ebc103781793c15612ca7f7e88a566dbf82b1d3a374084d1e80dc227ed2f7182ad7790b8ddcbf89647d0c6fef", - "0a034f21895dcd07e9bb8deb59549b210042675591a5e0555dbce4630416acc43b19e5c72034ac57e1ae2b67c8ad36fa4882c27af8ad0608a0655c37d183759f06", - "0a063cb8931fa85b51ae0c16f89cb546f7025aab4277cdc11dd936ef113f8c53fc175585f602ff8adff9c03067d25dc0ebba73d1e50628b76226b6dc6bc045c00c", - "0a008415eff3effcb04d9fb136c426e5ba0db519702892d839a5e43bb8b81239c9db33e19ba6dc6c06a2034e8af8fd2603ba8a8742bee135b288eb0d6e53155d21", - "0a0915825535e6d32abc3514abf245256626d8ca136d7daf9cb6014d5f28a921f18eed0c00e2a09e188ce4cccffa686464cdd7e09604994efa49c72f456fee5cca", - "0a08083b216158ae41a96c4a7846ecfc4ef597f95a3717c04f808d2fb2bbc6f77739a76705b972a34913cfab65e325671e819dacc4a497b00df184a939e8f78896", - "0a0756608a002b207e40d90e2aa6e2972a0783d9c8ad0fbe963d7b3fee24c549d53be4555b0a38ad803aad031d20aba063a014ef4657ab6d99b77eb74dc6bf5e30", - "0b01cf16556f9821e22bdbcf52e3a5ebe9c3cb3fe13749700ec06f6e75120256f910bb86bf08ac3e41f7bb4607e7c1c8bb3a5a81221df3b321c72caf45f4cd90a0", - "0b085408b8260cf8625be0bfea395e3b848acd24f45aef1cf6ab951c820473f8a339385cbc123bba8cd681c84eb62f66ca9cdce07351c6b94140e83da33283e898", - "0a0415d7fed2f214400bacdfe028f4f3160b53f3ce7209811675b85b26896d8faa3aad368cf71d7158fd171f2831d4095b83a251141e9f5eabc9f01d91c9b92a3b", - "0b05d17159825b9a42f0e2a430c79ed9fb08c5fd57a630411e27d4a7fc4cad91eae92df2299c4a8c2ae98ae80e0f0bc27efafee309855e71ddbee963a684bd7005", - "0a00c91f97000398beb12a4a48185143ae61ca474af501567d3e4d77f9bc5b4414f74cc9662607617d61eb623831d70a21bc9567f0e93ff4e03e55e937bb48d825", - "0a04d5ddf41d476023d172e8c2c9194d754f66ff10658b26c3ab82342bdfbb7bf695bc013083a9601016d32ed4aa7cf75ad4ad3e51334bd2448448a8d49220f680", - "0a07c5c17ba6500167c60e17e55e95c54b656122ea2f1a6bc996c4d01db8210b668306a29b5b115498218e28d1f540a0bd596b4c21fb43f777fe1699e9cbe1df57", - "0a024d8c56415c091eda991834fd281d73d2f7c673a1d0e888d38c4475eae2f47356f11a0d21694da9799c5a09c5279d92dfdcd37f73a8cd22286a76e60f02b46a", - "0b015f866692502ac9d8d04d528de74747fcdb5e1f375d70a63b73286b28aa03a2ba1d09c0e3890c784186b352f33ead913f1cbedda569830a9f455134fd45fda8", - "0a00ce3199218c5e5b4b0572217cc52b4726cc90d2dde743a866f9dc00d35494269ed72af17ed27d7f695ccbe5360775d286ade45b94eeccc2ecfa7f1a40834720", - "0a05ce757336660a1b12c4f05159c8f52780e7bebd82a1783135552e6690b916ff1e12e94d0fcb9373b4e8e79f67d2c98b4b32bc64f1252a6a3a4a131fffee2b43", - "0b0194c7254d4ba87677a75e65ae474fa4daf18abe7af146d2ddc2a880c8f2d66d3e28b3b2216a9732fe8de7d274e98e0f902ba32b9459bffeabc38d9cdf23a187", - "0a061b03a7b1cb0043067ba239850ef83b28c84c237f96ad20f82871e282b03e92b27efde35b71fd80ab0845cbf1c99fd45401322973a9c64ebdf50108e40f63e6", - "0b06d7f157b36d83e96f21d47419afaa620409bed3c4504789eca38a9840b895a3814c906d792e2faad64fdf5f416ed46f44ecc5407aecf1a4a45d4c47678844b8", - "0b0229f059a37ac44a699da5bb4049dfe3cd2f97903e2cf818231786fdd8fac772a359df0595d820bfe3836116d45e8a8e314ede68a7408fb663bd37f4397eb47b", - "0a0827fc6de52d198b797f053bedd2aa92669e2fc8b5f7bcb95f4f25fe5e6c53cfc1764ddbd3d14ff09f352488a7ddab50260da2be0eecc66af67655ab335f207d", - "0b0734270b3da3e458e05715ea5c0afc1458116109285f5e0611377651b61825b24618c7234cdbb96ac7468a199e2f43a99acb8dcd95a167d919d5f8b54ea12395", - "0b01b46ea99ab3f75eb3435a92f68d07f0d1437adc9e613ed66ebba3635fd5a2fb265b68b4c5c0ba12ced2ba86e67272d5fb15b36edc920fd31a6bd05129e80188", - "0b00a52f86537086e39e1b41060d366887409686ff386b9411b33ada9db9b7e6c1ca4499af3eb14dd0e7923f0e9c491e7de5bfa3976d8b72841afd4918082058c7", - "0a05ff6defab004b25557e7d01e93fdbaa70f9d945da7779cdf9aa8aaee0c3cf275772d86ac5b637238301b9ebb6d84ab155560582f05d527146834ce910054b05", - "0a03e4e883d3e7c929b01e2c1d49c194e7e5476804f67d7e08c564355135f62c51699e4eafbf44e8f5b7fdcc209f06d59f0502d406b7b862e8c5fc162c8e183742", - "0b06d929905ed68021aa837ffbddaff30dbff40580672174b9f735e8679c8f5b6427d75b41b41aae010f9fe7333ac75abc591081d8f1101184f7d81b2525e3c74a", - "0b0547f2cb6d04f46a70a4c5f11078f368a31df46c707d26129bbd4834eb5ef76688e69216b8eec3edab846e0a7c57766be11b53370e9b2d29a1c3646fb56b5b2e", - "0a0371d4a75a1299a060adebf3db75faa647f02db43a53a82f3fc9be9fbb699d2bd968ae49f0db2d665c4d563c5f9f44074db8676e59ea6b287b4bdcd48617bbdb", - "0b08bece29f8a9bf9722dae96cc5b938c4da8c704a88cb43c40c6bb793cdbed43aae9eb3c4bed439f9960799e55709830f8715ae2f3b475669b3fd8e43e3143b46", - "0a06b5deab346bb5441603bf45e871ceff7fb6e0f77fa83515e707943588b511a7b7aacfe9a30bc1e7d7de8e170a0950a394a7b5b2419273246dcc1ac38d0ce520", - "0a06089e8f486457f928aa6fee9adc4f5a2d2bbba861218a74b3155c7db6142f2aa911b316ab74d976574ba95229509262b6cf54cb2db8ee244fb462dedac38f68", - "0b0537053261072bd42417fc1f0e91b7e0d9754aa88df2c04b52db13698790f427746095f666b04bd372dea403a683a835177a109321fb9532195d46f5098a7b7d", - "0b073575350a95a86bfeca80d514af3317b77f7104c57e76a5b2c692018071ecb78bb0c435d9705ce0ee73eaa48985e23ca722742000f72fcfa20bc7424a43e54c", - "0b08d7902497b5b1a2fd645f8b725a529c36426fbc9225695857eea2aa50b924464d7cc4645ae60f2f0615725e642ebde041a41367cc61dd3860d8c55bcb55b4b2", - "0b041a4c4fa69a0c12316aee05de57ee50a47e205d3368f4cd24a17504907ed2c9e23ac950c734cf814e3c2cea94cf7206446f5034ef18a279859f62c814ae13e7", - "0a083dcc1d7abf39832ff7d76c4ea8f30c1b6f71f1be2d1e8c9ec7b6fcd26a24c2214611951959946dcb1220aff58f50fef94bd2d57cbadd5287df45865d87b0b3", - "0a010dcabe2b186a369eb2e608d01055ba20909545540d374693964d5849b98dabdfee20566b77e9abff8ba3ed8cbd7ad75f92c35574c1abb5de44eddb67940753", - "0b059f68772572ed63702d6051ba48083ae6f3b624908d5d64f296481b1b91397338810b3c12314dfe12971d265dc1d85c72cd135aae8560bfb8f2487607cce418", - "0a0288c268e91405cd4ad2a10e5ed514d84dbe497bb289315745466355c1da112cd99bab0410ccb5628631f71b3d8d0e491d8cb8db57b51005e40316ff53f3bc5c", - "0b0756cc90eecab95e11edfd6c416487a9a4bd7763454d4dd50c26bf45873745f86a392481151d85b60c87baeeed578cdef835031f36779acb30386349fefa5cfb", - "0a047e3d07e9f5d582df60e57b77d026185a59029be4d30a7106c06a61d27dfb0ac021208858fa7e9afde3f0bf7598ede0993ee157b9f009356b4fe91ef6ba56f3", - "0a000f57d970251f190c5970031ea72a40841e75691938818b16e373d88511b20b24c495090816ebc140e881f918e8a952e9f697fec26d659498dfe9c8e8071744", - "0a00c4256fbde5beb5349a0c29d06769000171c08e3ac33c0e45c8b213211b713ba7d88c1ca9d508c6f34355d4f4ecbffcfa33516720162ac85a44152d96cb0f45", - "0a01dd9eb5bf5f6a330263f7742862af69d061f3dbea36b8fe42203ee66b9791575d900e95e1f8df6be96029309cdb359b3a800a21947093c01f1acf138a438a11", - "0b08e87448eb7319736c08d168ed6874aca0844d5df30994a3b3d3754b234c0bda9af2c7bc04979d255294772c950cab2f06c9e826a3bcd528e3473254c14c7175", - "0b003c6ae9001f0100ace3d002cdbe62718dc2e319157f8247487e6e093bb4162e52406798eabbeb776795ca9ce49cf8ebe4394d0c5b462ee21cf75567a28dd52d", - "0a0606e2312d7d556c7b123875c084ae85f96a300cad2096df4c61f2d1f424692e979153e01780fb9b80d3429467d10de6e9a82270e3706da3ad431f3e4e6e310f", - "0b06cf8ea581b6229ef06fc4c4746531769d3bf2c77495c6982f72890b2679d1e44afd6c6a580ce05111ac6b0bd440b59734685bfa746bca4768dc3d0228da686e", - "0a0436341d9a3fbde48a415f3ff9a99a7a6510803cb918a2d15bed310716c5773f8ccc30b108eae20d0aec4649d8b562fcc8569540579c6f286e024661a6c5555d", - "0b07c3d009cb4a13bd94d97edd69dcf2a6e4849e795214492dabfd5ab0c5f0d06df8481a39dea7d9ed0ff845f5f862f69387a831e25583e559bfaf561f3b47b6c3", - "0b04996afba4d27ff289b13c8f78b9634fe8b492b8c62b7383b5f97905a9e7cb58cf30a994d42594d4e3a86bb269e6df523fbf4cbdc40691e5cbe4179de1bc1bc8", - "0a019cbd9b997cc7e2f69440e8b1ea7e91543490071b9c564554935e75422968e0dcc7b4cd09f2353380e89d063ee54d96ac3dcbea7e0e2b71f64a8a4ad243938a", - "0b00651269cdab4593127e21254bb8a1f3e8c950b82393d3c53715eced79d6d9377039d05bd7bcf7122822bcfdf8a50e91da26f909d9c2df0487e438fc0c7ad2a1", - "0b082122867573194258a1877dfdd96b1e9905203ae37ab2246f6990921b9825f41d59d9492c217e2aca095b4db8269cd4e76e516a18b2cb27fd5a273823e89bae", - "0b03bdb2880898f5d68754fcf73f9c22d5b1d283940a89026daa00be6141d6b44fd8d6139c6f91f33a53c5e924e7358accd71ef3070e28872cedf49f77ba7e857f", - "0a05abc79a862f02aae2b34e6d31bb501da4e10488e3340bd97c12c3cbb1fbae6d358f6ab04578aecd0fbe1ad3dac8a1af691bd009cde941de03da460777652774", - "0b003b04335b0239468709516f79992bedff552a6b3a938b743828b0d626e37d745c5b50bf1ec0d97a27d603a73a6c1d09f3161dcf49103a4ff856d1a584951358", - "0b062e03a4231745b9cf9570716ab796cf337c1abd8f1eedf912bdbc664621ff9f2adda418a4d343319e8c8947da2361a4697bb1bede8e2b556dc18d5a08b43985", - "0b0143ebf435e69c3698d5e10d93d306fa8e27b4ba2ea88d50ab4d866a81dcb5abf017e3335dbe59acbd4d12296398709e62386bc3225db0b03809dd95d6b169c3", - "0a030803c3b3f546ca8f3fa3b57df8c9c33cf76b4ccf883e82fb63a438d83438b570465d1a00e47b60034f79e6792cfcf9b5273ac6db5f28a3acccc27096603c6d", - "0b006bac27c304f6666e57c76ca2df4ae4be93536fe6960e6620bcbede805f7cfda584aee7b0b5f39feff55f59ca636741be872eca746efee790400ab8d00d3ef4", - "0a04aba575f6b2a4428ab88defb59e7d69d465456331b9ba0c47bc610ec5706ee476e6a510fc73c2cbeaf1df6ce67f4364bdf4edf42fe109d90a32d273017160f1", - "0b090e78b2c8a4b13ffdb027e8746725d807bd7c7ef80a89412deaa14b18c4df141513ff4a7e4732259191c759ed4d41c50bb37fdb9d383faee7f63d3b47ead578", - "0b05b0a7d6d55b764028925b5ea4677567c07e9834d366550b64faef29ce638b12171333daf3a0f48726a17e4b50fb24f67e6ad7b60d6d02494ff22d00f73e1995", - "0a03090c7a8bc55846e1ddef6ee624f6fc069684cb87d6e295671a502e3abf5696189885f8b9122dddd45e6632efc1ba380064b336b5ccc729d60314f1a2171546", - "0a0359d168c13eeb9431bb7d1e63ad8c8c6cbce0793e6189497e4abb8dc39c417d5f4f610148633eba171b9b16d2b2722f339ad4818ee7ac54890834991b4d3f65", - "0a016e66175d8ec891ccaab4ac68484b7460921950f97e9b188f61020607116f3a1a4a06641bb6e0686dd339e38c9ff68f65e9e07ab1f6b9ef72a22d15ae8a592a", - "0a07f30ca2945525a0b6772c9ace7bd8b6c1362ccd4d646b5c5fe42f4040bcff881ac9767c6b2e6f628644147677908b761996bbebe697d92b478e5c9829269481", - "0b04cc6b1783182b9db09fb9adee0dcfe57078172c39db6760e4a682a5884868a2e6dd4dd5c26f6a52b06345b306e5e16463acac1d82a66fc132f7bee9890e8acb", - "0a019627ccb8df6017a644cc1f3da2ef7da88c3b7e53e47cda9c7247d448cb4d48d9b0c358f22aef8c632cfe78114b4a4310438125eca5557365acd20455a2c463", - "0a03d8e88eacd591eada0180bc6f9bf06cb7ecb462467399f9a1808af98992811a9f6125e579822bb7bbb5bb364b40c5c95349c2426b5fb1d8a69b2ee8391cdc8c", - "0a06c580e50e1fab36e29cb663daae187646e6a09157d070312bd23af7211f30cb10436e8faa1f035f2e877f1b7dae57a34346bfef14c6d1e3e575bf348fb2475c", - "0b0523d52850c05e4db6d083998b48bb67852e2d2d6e0b09d7f779ea051f37fd5404e2b3905a0c799b48525d2dc70632a7f67178867b8cddccbe9c360189aa8804", - "0b06a0a6dfbb0325f7ed4909684f3aff939268fefa542f32d33bbd9f99afaaf4edd4448905e0587776fe40f053c3d32d49a103491f018f120cf49c029e6dd09e6f", - "0b03ded21261165a9c58f8eeaab1df2f3aa503a35c9c9a6f8d163b5e25bac03086f1606b38461e196b475a8b5266f76db0c35435ce98b118700c7a31cab49a56bc", - "0b031a71820ea6838367577a88ff38e7ac2ddb1c3a8e3861360b54b5b3906ee0b4d348101ccca978a07bb33d0807ff996f726afd57a421e71347b8c56df5eef28d", - "0a05e7b5cf6cca6ee03ba21c8829ca99ffc2707b983e114904f6197c3dd95c5ed99e8221e8ac27cd2a12cd39f98c37ad3666b09329ac974cade06e0f972778a762", - "0b06c7155efac2951c70ca4912e5794e5d40d0e2bf8c606751644f3ac7f4f9fbe662a746164ae711e9bcb7d52d07f5e5e558dc05d8c72c9c4ae7df5ae0860ac436", - "0a08ae7b0e6fa433163e895b788ba766f6ca9e5cfa2f623b2c829466754bba48a14b25e86bfa00ce05ad101988df56f8d316bbf4c608c9deefea69ffbb87e4d5e8", - "0a05406fd2cbe84d97437657bdb58a6b118cdfbe9d5e30fa6b8ef4ec721d5b7ba847543f9c28a0502686bd2b5240fbf6cede1bae7bafc8b33c13658003db3ec6ad", - "0a06f51380568c2e4ccba4b6d5b026b9efef3c8f67c2379bc403e902ee7f5a636f99c052d11efccc2ac969092d51e988f01490ea2eebcb1bc21df9223464fdec51", - "0a0708f25e55840734f80b17b3e26efd6602e896142b7456b5f0d77d03538ee056d0ebb77f6fbaa821696cc3fc8d05396ce3fc381def4c4a7d9d269aaa319dd1a6", - "0a017fa2e692c7ccc8835f750b80e4e8635eeedafca37f1c5147417197d2d98fce89d0d525485a073ab9743bb206492d61b3293e9aad4c0a3f701a708538fe733d", - "0a01bc51b55d334eaabd025bf297c224021217e55079c6adb5a096815482279aa51a55a098d0dad95bac07f171e6d8aa5abae26d3a95e1b665527ffc74fbc1309e", - "0a01afcd6b1a84e0c0e51f0bd083bfab22c3af3475df154416d6735f4c7943bd4bc51885e9545b30544165cae14c2b7875e76c30fd839cf9087e357260e2023ad3", - "0a0157e2636e260b1c12cbbe707ae3a80af2e93e1919b0f529dc523ea57f0426c17515da1a9dfb512ba071fe2d3538e9bc376bd909374d0f156152da086305a510", - "0b045c0c1871b41049ffa8f4509392bf5fbe60e7bf10110d4a7efa757f8b2750ca57e2cd8a581b2b3e0cd5ac0ab1503422f52d78a723e3a046aff320303e915caf", - "0b04b15fbaae972e6f59a68c88c9ae1791aef0ae4c18fec839a445c6f76d0a11d726b85c08bb83bde6f4f1b9a8074e802fa113acb50a573d4faf512384bc10b4a7", - "0a03744d2324782e318535e292fb1b29a3cd82572c03b525ac3ad142265be6bac379a95523a8c4f23298727bea67026872a4e1878710b595fe7d9bea681aba7785", - "0a0857807589a55638b9cc4887f16b215cf8364a1614009bf811d0a723bdd24f4c4cf8c273d74ed5b0c3697040924568c8ddf31ec192a185ea00ccd51d4ba72419", - "0a0144881de13a18f6cfc726faf3bd8a17790d14a8d27cb74d44a58a50f4b5bb6430ac2036bb01c127ec39afcde756dc1ec6e3a51975695bd5162c65efd9eac571", - "0a0215da9cc1dc1293e1657f007aceaee6c552d142f32461f09bba715a48bc564fc95b5eaf812f3015e5ef912ba0dcabc66c7d53821a8a43646e4572fb67dd3e16", - "0b05bed234d94128ff3cd3bead347e6d3aab9a0a65925b9ee72c33e04de28119bd82ae2f1610f316de511217e65b4326cbb6b4aa246c3c620da2ecd44c0bc57000", - "0a0305094a476a8a9d69ccca76cf50bc5f7212828284e3b89d6dc27416649a6d3d75a863af942cd45c49f5b47f732670c3ccf58f68d20ba61b165fca6be63c77f2", - "0b048b1d9c8e00207f777644fc59ea70ba524d4d26eb0e2c8cb922c3a9729db5633f92d3bc980404b080761f73a7d6916402c747729043fec519142a709d59be2d", - "0a0029eef00db8c35617c5efbf35a4e730910e8466971c1c0c01d2ccf8cf9d0881cfc2a285ce8784d34f371b7046d00a5656bd713674943201d1d08828c4d35ccf", - "0b01f5e6f1416b291f5416e7a679087aa7f439cc9e50c0955bbdcc26fe1dd8d4c26091103773f0674eabb86caf1f73d465a1185ccf62596bc892de701df95e53c3", - "0a0470cd68adb0d71e048f6cbc2e38f38bc9336656523fd9f96d955185e1502c65903736491c748f9625a1e41380afd5842a50807c520df1de81706631510718f1", - "0a08a4d6cdfd11ec94d4e7f0280c3acee781e98b25665eaa47d5ca7fc39173c933b879c985c6f0152d9b31f5ef1998707729e68c7abf7ce97fdc5556db8a27412d", - "0b045b0b709597d5a8f0119f6ae609f08e5c7b150c0f2dbc6f91d4e02a69402e75cb03bd2fa4497adb243aba762e57b2718b25ebde845593cb58f54aca08e0f3ff", - "0b0615cf2d96ba0fad7e6e1618af6ff559e258b9f25af414bacc2df311037ab375c6493028bb854da34ab561005cb2c23c6d8fc033999e5df615dcd586d25461ae", - "0a068403ffacac5f11db3b1e0a4eaad98da971296d0556d201b73bc99f94b7623b1a00e48bd27d9ef55e494e7e5cd443fc3594afef774bd63ad41ffef5a22bd2aa", - "0b062b00c62ec1bc6e07ea69d885152e32f411478b3abaf1311a455ff0f7ccbaf076016b0be8dee5a756b6953ea713cb8ff0851faf6e7a4334d8c94b2065fc243f", - "0b0389ae47adbad47ea73cdffdae339e6e7b0aa99faeb8f598637a30941d061b384bc91e99c79a5f2850b7b05a0c7995dcdfa8cb0bbb086ca2985b9a721a3a0dd6", - "0b0491643c45c8de4da992d250e8cad8edbcf5e8f6dc308b4b97f0d1c2ef28f70d1b186bf8abbe7ebc1772ee059215ad7869766bb93ce8b2fa9814c7f3ba1b851f", - "0b071851fcc49583461b475a03b89b76a8e1b2ea126e5ad8ca0a6f9550d43cba53ddf8b06f1ce9e8f42d5d9da94c49d142c1ea1352ad2e88bae87ac458b720558e", - "0a0764b5135a8cd8e4062d40660843887d12582c49472f45f22683664aa16048e426072fd7973b82de56258d4bfbcdddc57e687a1d5e8c3e5f4eb4096b617901c0", - "0b025cec84aa70b293c22ca110bb40047544953405a28cb296149c0c89e61044724509af56812d4df322e3947dcf28744cd9328e4328bbe0e10bd450c92d2d59ab", - "0b052c115a51eda1f15046033c7968ca9ce6ef7e38dccf56425bef1928073b12235369adc3ae77c603bb986b74dad46ceb15561d809fc8bf7efd8a4a0b982d5f43", - "0a02fd06ef99314cc3896e1ad594e1106de2fc75cdb3c8dfce69dcb493b13a1e8c14ebb00e7dcbcb0283710e34747f1172e490b22caf04b35fd57626a4b0c302c6", - "0a07eb018f3e3d42b858d2be4edd3c748da1edc518dc1abebeca208204e702e03524507f69496417f2844e0091b5845a57599badbbf5770fa06d8d6fb4608d6807", - "0b036f37be845ab6ce4610c6b2e6611e2a3245206bd593d0b2275eeac0a5370e412f462280ed7fba90fc32dbe3fa5c1f1c13fe86c839c9a033808dd50a0f17e839", - "0a019422d3f56012d12d8b1fab5c6b02f0a09d975447834a93fc4700190c21c4cd19bb6b3517cfcf854ae90b728f8f3c9da267555fa4c6f3229f69c93ec09e78a9", - "0a065db56976e4095dde3d603bffef4b60051c159086acd76aed17adb651ad084a45d63d0589cdb575b0d5f1888166565f4b26af8f567dfff83c1026777758917d", - "0b03031b852a8ff08e9fd47dcd4aed4f611289379c2054c8abf4bb1e4c51aa51150089d6ea96a1b2a90ddc17e792ac28f10af18c8ebc1cbae9a9187dcc6f186d4e", - "0a035c414c0086b2bbd239af68173ced18c69f9ed3c3e5334dde5ffa3f129d08fec336b14f7b6cfeabe746ea8009d63696f78c90d3a87659a3adf5a91bfce6d606", - "0b02488259f9bcc01f4514eb7bdc29c18eb8a0628785def1147cda83c07653b62305813d16535a25308bc9eb9b64052ba969ebc5f1bce744d7ff6c113e6f3e65f9", - "0b00359335b402674e039fc500e5fdd50e2009f76af200af332a1a9455d291239b48cd2d7b125d214f2e1c861e939f7d9209ef16baf2986384ab90e4dd6100fd1f", - "0b05a6ba5607e2e89e9a2724fb8c274300ee95d44fb62b11f037512febed7074c964f34b903a3846790fbd9337a5e54e554c7dfbbc13d3917849363b9f3409832f", - "0b02db526babb2e6f7868916eb90e1d7da501c8c8504c63f10cf4f9ff909e461b5031866cd5ac041fcb16881621afc3a590ae902175c130b6f812d13f83a80fee0", - "0b02691ff7b584cf61eec10c1f9d5356043e1249fd02e6151858e7db75f51152a65ac32e463546ddc21c3410edace4632f3549e10ff95fe70532bbc97f4dce9eb6", - "0a0241f2564dc0d9f056f6f3ca87aa50ca5b8e85169a48f493f69c4b804117a438fc40977c89efa4466fc3e2485108df671c95830d35fea2c077b504d83aa13038", - "0b08c1d1d3a4b89b0cb7f1e5cef9148ff3ae8231648c2239a4f544bb720ea83ffb4634503da0345acebd883d15f0de732583b1a56bf3fe757f53c7b0bf4938ab5a", - "0b00188f74ce9872d02a92717638b1d319b41793ad7aa5770b42319c6df6e00fb4239b51e020de12e721842abcfde807ae97079bcb1324a8928f7a9f87548182b1", - "0a021a0a7f69c5288eda48dc65ef76106fdaf5f56ce68575fd84f303396792e9165fa55ac9e926286c57e86510b2e19d1272bcba968b39883c4371fd3bb9c4a60d", - "0a00dbb1c3e7bfaec56e08a6f2696a834472fbd678ca00f761bd5685b7ede8984478d75f5ddc4d69a81a03082d44cbfd598ce08352c8a78837764bf7b869589172", - "0b072ad3bd9951dfa236e22ddbcd4c6c96a4ecbe7d8835f8e2fdd4f1ab0ddd60a4ac9dff0f333a6032b8ab49776a37e2420190189830771c3b97c1b3954c021929", - "0b07915bd67e26dd67e6c826f34a8d7608034c4431000524bac0731fb2458de834fcccb11b52b81007a68ed85e0640ece7a219dd56f2f4cb7c280af30d5f22fd2e", - "0a03a89d4d3a4ca1b456a99792631f0f075643f893de09b925e74d27adf4336dc3d7531dc343ec4f97b97558835a2dd1e47553f7923d2bdbe0f7b4fce28db9c909", - "0a08675d8f8d76378066feffb312b01b9766a5ef3dcd4163ff566a65aac3313dec0886f4c24526891e38a249088d88b52d92beb02628fdabaa3e4d58a64f443ecd", - "0b053bd204b35f466a86d5a4c5d89eeadbecfb64a0fb8ef13278cb06cf9bb6ccc6569f7ca6cf5b3d0077ddc4330f9c4fd69114bc6cc772622f91e94722c52ee626", - "0a0154e1f819b67c649b198fa8518ac1d1470a391fd6bf346afe4a1faab6c1668f40f95a1934de2c9d4f2126bf719a79e8e800d6c6a971480dbf69b9de31622acc", - "0b04e8fb3373bafcacbc5dd0bafffaa1fe888bc466961592dc07c51c4c2e9d217b1f380cca1b85c822561d8bf0274dcf1238ba44e232db3035b148e8c8f96d78a9", - "0a04827fd01b879dc2a80bdad7a344da400bf941ec56dca4a7628d3abd591cb5c1277a641bd24460f491f156d5f8dd5d28559929e9ea44457c3da6eec46d48b22b", - "0a01ea594d9391dbb357de28ba098a62af1cfd981df3f9922084800917e7bc713dc3f508008e4a9b8c9f93e179edd59c696fe5f36864fc17166e58f6645f8adebd", - "0b0910042d50b2b12a90d8253ce43f068b19b5d5d734729e11cf9305d2261e85598a389a78f7966c09ef64c1d4bb8c50ca58a4e0c3022ff4eb9d457fc453ed1c92", - "0b067a925c2373e72498aadec8f1efb10a32514fc46b1ecac2f12ed68497434112fe6adb502592113c4703e6b527a3d2a17aa941bd30db7fb633cbf7bbcc0aa778", - "0b032bfd1b644edd086998ec22e1d4e9b04bd64725a49f43e69791f8bbd3b227a9fab60e632286cb829dd6d4f778615f09b3db1fdfed8bad48ca55a016206b2b81", - "0a08584d6899077677f276b24475ec23db78be9de2bb9eac80ba87a5ef888bb0f32dfa835f1cf888e71e0542863f1d91152596370eecda1bad37f64bc61d7490fb", - "0b088f87077f9f3b5ed7d0af99592a1fd189bd08e770d4db2ba70ad2bcdcbe2aec6b4faa5c8e91d286f93b3fc8687bed1263373d9c1b06f5ee7aa78fcbad3e1ef9", - "0a04af3bf44a33721249b31118bd7da8aeed742eea9fa391c82ac457f0e1b0a6c32e29f1457ab7eeaff012ef84d9f58cc92f0c6ed184049cb2d5beef9cc1822cce", - "0b045c192462cffdd2d6c25bc84085e333766bbcac65b17d6aae82a11dcaf8c84e62a05567b38c8c394f793741f8f1364d8a8b00d240e4d58d3af29f0a1e75f9b6", - "0b0465cb99740fdcb3434a2e7920de0e74a3eaea512111810c2180b375cbe0f6053c5f5c405336db9a9438277a8ae2ff7a233a010c978a3ea9b1f98dbdf0ccdfe6", - "0b01c5710328e4a382b0d3643927458c2cfc2d74468adf0480d1e7b7fd0b0c4e3265f6ecea0443bc653c362835a75dcfca5a5bff6232072f0dff7b9287d7cf4f3a", - "0a0225b09d1b65e15d0015f3026830cfd2bc5c41f54c3d5332e300f0b67004b85cd42d6e403076c423bcbae1c252c612dc507e3f21023b58c12290a68ba785835f", - "0a06d7f02cc4f4f2a084f70e68e98c8e2d7f4a06a5ea99a65b485f5740f3cf23d9a83722ba44bd17eb065fc00570ce8268b1fbfc1217f3cc745cd1ed6807a85e13", - "0b018f19b60e8517bbed6318b8456e933098df14851508590018119779583f70dc7e66b3e1b60c923d414e82b8bc0a5f189aac92c5b7eef5b98b4bdd4afeadcf2e", - "0b015c1639c0b0ea9362ca596e84a58dfe83191ff62e691df9d2e2d42de775df29f4f9566619e4693a91d44321de789c5d57ae3fdd90feffa90e6aae7afccdf558", - "0a05d3db06da7232af0604b27a89b00acfcccce63ee66c8d54e6fda10459cf71c098c1c9cbc2ba3f08a995259b958fdf64bc200bd85c9b6869ce36c8d8e993ac66", - "0b0007850847cc57ebae87899cabc250a1ce031a56aba2f81a52525a4b86b8355dcf3d2f872d0959e95eb3a9d2add333107f6db14f7a0b0fb33a9355872a1b8573", - "0b0394fcee234a321228bbee0166b243a57baa79198b6a19fb9c5c8d9ee1a9801cbe5d837090d692f9d48b4da418a41c954e64a69e1d1db8a5787b3092557eabf7", - "0a04f3d2345af60b493fc4a5813dbf7502f0083b50fb91258a47003d73e8c67a9660577c578e02e2fc71e0d644181fdc70a9cf3f439b11c9585444a0175354469f", - "0b034b08fee02d4e52760f584f185da04fc414e465fd1cdb1864036f2d32fc3a826425a32427f67b6072791cc8ac95de2ce018410e21e76bf80057379e6edbf73f", - "0a0648ed205f5bb28bd24adfdcb5535163d16d762b244ef2789b5d24e0ce0a4edac7ba7d094a13e085e65be208ef6824bc4f0ff978ee8653fd9cba3a8f65f33dea", - "0b00e97d6fde9a39a0d9b79aad9722277670dfdb96a68596def09f86e63813d58799a54c783198d9fb743aa92f5796229c656ae8ce07f7fec19ba186556f2f1186", - "0b022df87486c775dc33e790b21853367950c4d4367fb1fcc29e57ab0fcb7c0e83f9eb0e489c38fca048633362692860cdfdd53960842b6732dd2e579852b1edf8", - "0a090bdc53babaf8a1f4175a5b94de68ff95b28b775aa4b8172c47f56e1122ddbbc027a6af59dfd7a12913e955308191e95a31de2ae60293150432d71eba73e709", - "0a061b8c76979bc8abc0be2ed48f92e476de8469e23f8fa9490db4dbb6011f55d039f1ed2e3bcd29f83c96521ebf477e8abfd0ad30eb2a1694c6f9742cc1cea98e", - "0b0186f95b323493cf044cfee45e0ccd8cedd440a67df5d0df346ccf5796acb9d85d929fb8d8ae774843f770f23a328f233603950cd43b9b8783725a5f1aeec34e", - "0b025356af9d01610a0b568017a0907d54f5ebce1d2b7fb15f3b7f7b3439f637fd03ff846f6065aaf5ec7e7cb753cceacddb622e2cc057661e0cec2a8508282e78", - "0b0301b0ef2df72b4dbbd0835e8a5b349b6863a6b1ac54b772ffd2b8598b8c48c8a10f2fd654eaca043af967f0aea65ce8f6613ac6578a36943f55519cb6b601af", - "0b03486045ba44caef7bcbdf6e2f96ad27f83185c600da465d345d0955cf705f66d99be956338c5318230cf6e14823c3a5b0dbe4020c814104453992e3b8dd49e6", - "0a021f83ebf794b287479702186e92986e82164f9b5e584acd4943f65a656e3b2ba6c51028336995bb105d2e0d67cf4741673d725332d466e79a2b54153d26dd0e", - "0a0595c1cb404fe0f081dc4e1fe0d231ede425a4a23353723102ee8c62f2e7637bf77f815c3067f4e4a86cf6a1ff97f79374bc58080fd2dcaab29f7472ed2a997c", - "0a04417f70d582240a609f045cb00f9584225f1e18f5ae3c33465283d456b2dde7ba4460b872d1c72c49559aadc37b7da416ba278104d1e65b145b871a5c9eee5f", - "0a051af0c2beed2fc14e5736258dbd9ae244d668b178b8c861086dbf21685c504f3b719175d659e5f0ff08165d848921cdfea0049bd9df2de591358dbbeb797082", - "0b0180fd43bad889cfea18dbbe1d31d155fde3f0a2f3228b04ff55bff3e76c9c7a51fee85e20acd00841144b0f968910f0b3f78167a5416a7c6588b134a16e7d7e", - "0a05733c35bcacf3b658656f821e1240c82606dfab12e0e22742152126a9f7292d656111bf7a3bd06037b641c85051c9b95d818bf5e2d497f70742d1f41fadb5f4", - "0b00b398e33f6a6b501718af44aa8c41ee1d4a7aa93f3bc8fcba9e21c32f31603c8d830b657fb16f291412c9864ebe3e56f722cd781132cf77c071605a3e9311b3", - "0a04a6b151c3c17295a337d2062de4b757410a898f4a6a58384c9ceba42bf225247534e121871f6a5451ab3787e88866c1a926be67ee011cdcf4aed51442a7a941", - "0b07ae5d86ad3e8bc8ad75eae2a814386183c0baab42186486f2f005b3705b3037e5a9c531a5cfbe1dd19f7954832cd1dcabbb4fc3086cb61417ff77c93d8e129b", - "0a0807596c98d7ed4eac5f8240f27db7f532d84c7ae10948a9f777f2cfbee6bb2a3cab40548b3b7793a485082b6f8540e12b678073d2b0bb568c27b434332637f2", - "0a0651c9cf5b4cd5584ff52f6413060466a2d235068044ced30748095d24f092edc336efaef60f754fa9cf3adab78fa6cd0d5d919223e82e340f14520d2a3da92f", - "0b04b9896a2f80bc50d66f2dc33641688027ec4ed40c1567738b4173613c5151bd24406da4a2c23a27124496f97178bd7fbab5733e2e675002d227ac9a9bcf2535", - "0b009861f406777521f2279ca13edf06d969918ec7b22ff4d0564425e12c61c1ebbd534345df88fda2320cf9027761c086e5f8362a17696bf8a64bfa2f44f58a16", - "0a00cd7690ff9d9ac6b230a55b70112ed0bc2a3f8d6ad9dd63d86cebda75e7552013ea9e4d61285a2e87e4f045243712d59b4de1a2761267070f6d52065fdb098a", - "0a090dfb0011beafe4e4b7599d4fcf2dd203ac2cb2cbee4aca2fe69a7abd29876a8e6e8826798c4a09360b0ffba4bdef70ab18d50609c68d5dac8ee9ef387b217a", - "0b04eb0e2fdf5a12af72cb5cbee007c9a3891cfdd868fc30053178e247ddd502af21376b40498a9a91a53d49fb34cd557ded2faa966ad9322f2e24cd9e9b1d7290", - "0b06cc0a75761d25fd69b3af1df7dccb4ae1d0e7be388e22e3e225682cde5e4b22802fce3ef46edfd11cc7b25f79604ec25a93f4348e79d2244177532ebac1bfa2", - "0a08e52b46c139ff035b3e1328421772a7117f5a0917a07d225420cbe0833d2b3de5629ea6fdaed9f6fefa1007142d2454afaa9203006bffeba27e2adb903661e1", - "0a01759dd7e0bbedd6b964f14040b838438d3d1015a842bf3ff46f3db805dfd94d51a9b78f541919c53d97528e9f421ddbd2157cf7cd2e6ef70c7f5b763a2b841e", - "0b0323b5677e033a9bc0caeacf94101e6fa8955d901472a4f8787cdd910c458cff468d5b845ce33ffebe82a83c24a19927a1c9a821d90a46b1595ddaf702d6d2d4", - "0b08bc6bd4774e3cbf58a47a9cd960e54741e33115532b9b4ea8c51b021a5a08e077d3b00e2b779bca8e32b0b9478ad535e2ed859bc8706eb073e3e56772f6f8d9", - "0b010a99dedb9a6fcf3945dcf2fa114c1350084d7f04cc03445b479acb755f3d958a2d340a8621bf3fa921a25e453ddae18b3c2aebab588051bd763202f42b8f29", - "0b052dff68ef6f3dc35a29201b4488c65d75e856ab53b5a330496dcde536a263970cad9907ba0f3cd6e11073ad4b22d9e775a90e5624f3d732bb86360900ae88ed", - "0a058b5ff9120aeb0e603c03bb23ce68ec597c76bd9b30007fa5f8cc4482365e73e98e366832953fe05b92943a4b3c93521e7f3528c8078f666e5c0cc5d8124aab", - "0b0525f36261c64aa7c58ad998d574c063212077b51f18f23cb426686f6a1901fc52c0a0fac49ab071f04cc2f8c6a3525470a4ad814004cfff4cbf875a5edfd2b8", - "0a0300414f4adb414b649989e4bce95ac6e56e476610c992f6a61fc5660b4dafb610e8329af8e79f49c822d2f32dd24fb59fbef61de11536c28dba730f565286b1", - "0a07a3c1f100a0f8c568da02a05e0df3062cd0e3a0ab200c346f1cdb8b83fd57aaeae22a426eb76a351eb24a6fc43261b2ecdb4a0d0c8b5afee899377bccc240ba", - "0b004b3d068023302bc980b79a715d09f3656d064db96592d9630fc8031e002209e268aef4253c78c85f32a7c0527cc053831a3d3bc59b85181871ef06b19ce27a", - "0b0653bd20e2cbea999f9c8383f83d3a8900c7c634742e8419502d8063e244260e9e374d44f5c2238e5e6f499223a875319e51a52553962deb20a245d8ffd72c20", - "0b085f593c291db1861deaaa213678dc82bbaac122bff50d8eff999766ba94292e9575d1e0969847d955f2e5ae646012c63e41cb8dccdea587c780393f7d2c399a", - "0b045f84b0adb262aeffa863a78ff0b8d10f2314dbf8d35d02d2cab087898e42adbeb9d7c12d31b820de7b71260b13be35e1257cfc5894cdfc17a1d26deab8eab1", - "0a03720fb35241984967143a8e117c8d0ea9e02b0e2bb91dee67b94af2975e4526851698d65a0ab34525aed4ef34f1145dd95bbd169236f8d409e71a3423c5b348", - "0b02665ac818e1fa4da538a910c08f8030dbdf6c1bc6aebc46c2063699943f945a48173e300d7f0cffa4d7885d281ba49d289e3a13f22a4c089656c1302e6127f2", - "0b04cbde9bee2acf4e706cd47696d1804a9fa420739000cc6f0e3ea2b005895d34d2cbef2cb28ef4f737a0c93f8e7c598431fc758cdbfe3a6a0a8ec9acaf1f103f", - "0a07b67d64e22d4aad47d993b58309348a03f6111707c0dfc21401c16069cf6664924d2fa4496d25290070f18fb21d5a1454051e863394260f5a561911f5b8a7ba", - "0a02c980e9a3f2d17e2a109d5c1a0c262bd38926ffc908143265a949fe81b36efd25ef3318ddedea0d96e0f938717fe3da910c07d58ce4b7a1c635597622b7c4dd", - "0b010a203dfc98b6b72367bc31a2dfe64f9e66074c0fc116ecc58b72c276f7d68188e4cf57ad9d0d82a2223ccc6807fcbf084346c97a0997ec4ab88609fdb17de8", - "0a0789ff995a682b7b1d6909b47465d002fdf13b1ef740503b5f1a717c3957973fe6c60456c9a48470b9f8c4fc513a1062c691bb2ee74f7bb5715710174cbb3d8e", - "0a06794522d6cfdbbf8c03782e7dd797a2d09988d9499f330690439b34a8d0c08d0579eedefa7ad47e32b45fe8f35344c5eb255286ca1edbdb2bf61c78c6fc4708", - "0a06d154f0bbe38a881b8554499fa86224dc94cf8e9c1916c378519f329e593a58238df0cf889f371d24704eb8129eb58883219e406bd6eee8217302816f716c09", - "0a02f0244546fd4d23e17cec762e437f17f29633abf1d5e985726d6ab4aabd2eab7594d241f70f3620322da68f3a8292672a1aa842793cb8ae10675afe9b700b64", - "0b0372c52f5d18537d3ce2ee2ac66362f3e2a40ba6742541b4428bb6f44e35ce85116e5d6595352426c53c6f9e1c07ee1dd70a87e5768e28fd9ab83a3adcb87ba7", - "0b04c3a1d3fe6bc3251d250516df32498d215dd4f8b3a64928b198f804da8d1ef93dab611dc1d1fceebe0bacc62abbbda1403361e04e74530e779d8f6f460c72b6", - "0b00ea702a0e4e52b0b2ae3c4afaba4d05b6b29f68c63eabdce315c2d1a7205d6be1bb8e1df19fa596f06ea05d8fbf144a5dbed40e580199912daf0bf5ee50c820", - "0b080cff0d9e55c56eb3f634071ad4c107b1c4fc135989cf7c9b233eb6599369f294e53875d9bea6d0b1b699403b9ee269fc670ad4d3d4009a7935072841ddda92", - "0a072898afa30d1d500c9fde4a869cda042d4cf2d472259223b150d588784aefeea7fb89650397ad794574ed948a56d2591b5b2b075552e9ea8ca09f66eccc8000", - "0b0659a21e0237bef548268d332e39c9b138f23d574798a3c3d2257470d541ef91fe2142ce919111c90b166453ecaf6fae149a8d7f167bd60112c6e03f33fd5bf6", - "0b02304e9a8cf71c28a1a877bde4af945804fec7413ec9b945e3230c6440f15065c71b1d24fa72458c2efac65d9dd6e512662199d485f86ba8a55d24e4eb1ea24f", - "0b028e1e16f450f5ab1a19a1b3ba666e51fc1d5e1ed7cc94990aded6aa2346870d03196a2b39cb816b6442239fc8247cbe514476ee7aeded47e339114cbd87889d", - "0b05234d4b14bb727ba845cbe83b8a23e5eba202e52729c7b4faa2044fa45218ce3afa0fbec334bd10bc879bdbd999cd4d9d8379bd719a3d948049804a09631b52", - "0b018e7cfe2783b2f5640dbce278d4eafbc665f612fc99bd3061b19f38b582275ab550d3ad5a68ae503c1ed4695fcfa576201e6081b892d160e5a5aa470b2626db", - "0b06ed387210a2ed3996123de2a0165da2244b7a7a82ae1d75b45f91297a1996c002308c6b44e45204febff729a464358fadfecf61dce4d3b999fd6cb4d94008bb", - "0a05888f154dc67bf4a18262a48213981d9ded899375aaf0e8207401a275125038343e3dabb6e1a417aae2e7085ca248a73c7f8b18c68aa9f31878b0a912fc205f", - "0b08a57061e5ccce8b6564da475a6c28140a30fec52de98f3b05c5c4f3bd553f27f916644b62e2494c4e6e5f10b7af54e1a94ee8bd70eefd1fb343602619e6d438", - "0a01d7cc5d32c1b60f381711aee7c3dccd72f891a1c802061567007fc578c62b2faf2c96217ddc9a11c926e225b50232384cb0b5828bee95514809bf6988c1a8ad", - "0a06e2c5fdd399f77f92f0fee7b7313e85d23797c70f8575b8e3278427291b3d52afcb0b2dab009668056a6e6696436c59becf7fd7c237a9263f2577aa0bc26aae", - "0b07b7b3ae40613b7de053f80e29ffd6d302562fd2c02025b6a1753c4934f9458a3a2572aa54e179eebb352600c6b2a9edfe58f6efa7292522bd8bc8302af53a12", - "0b060f45330ac9fabeab5cf9e574068c817f2ff440cd008a60f4cf6b60f07988a1dbab8e64457e2e453072bccc47dcd0c320067670478fc927697657ab77aca679", - "0b06935a18da26b1a5ae39bb1bdb6435e337fcac3f9d62516e3fe8a3a7398235575da99c3c660867fb8a83f6096e0fcb050528ae22bc838070f4a5006c2a4ae118", - "0b039d9ee6f9fd743fbe759bfd8f687d673e940a35aadd01462a8cb81dca1d2438345a53df01f071cba9c731600e02e60aa2472a5aa893de039e611ab1c19b532d", - "0a036255534781bd9755793a3e895b52dc8f00ec40d425abc733b516f35a39ed100db8aad19ef93e33e54c925690adbe5f7eb398210f2be16aaa47896458c1576a", - "0b00724a2f4959900001a5df13d8e879b8e9bbb5ec5e43e9697a31ea0cd5758b5b80e1d6b4241e9d27d165ca58ae10b42beb920d3d46479ed70df11df3961cc1be", - "0a06fbc18ec5d480323ad86e68e327c2839bb6076686edd56eafd0fe17f086f3ee42741309ae174371b2e5efef0f2935377cf47c1c1f230b7e9d63ef756e137320", - "0b003439978d2fe9f0f1607bc2ebee4e8f8e52a1c24fb1859916793d67d1108e8d8c3d73e7def15f6dffccbe7ad396ceca74f82a248a3e214403aef51492221b77", - "0a069a4a43754d5c12f7e2b5fb8e9ee3e6898e05af78c1076cb7f57bcf8a5590724b28f4695639be453de0a2a80520332ced8fbb8f494e08571e559794b097f7fd", - "0a02c925682e3e4d56a7c4af8e5e7f5881a2dd7d69f3d49842f72f4393f3cf87cc626e90fe60452dcb9a39ca7e84165f7e604c766debeb1780f61881e78017f8c8", - "0a05b737a49d9e73ff7bed91036aff6fc9856f2df9c75935db56981468c8ffbed546cc0fa0dbe82146168a534f56f1f308ca845d6a17b46d2750e0e3ac2ea71771", - "0a0074f0f688b3e6d1097cb0871f99d9358e75870ec74670233d4344f573f51cd3650bd061a1629a05c562de24c09274eb02fed0197fe2e3524f92b22a128e6138", - "0a05a846da99bfa2c03158b3681de6fb308c2a8bf95ea81cd1b46306314fa1af077ea766ce5374c075adefb632b5b9584e3daf75e90893029138376ecb24fcf0cf", - "0b030588ee6a3d43a87aef46ffa72c5bc1b3c015bfce7b00fd2e293a941adc12ce28b5e4576a005d4d5c1639fe79c157c2f64edadcf1099eda9604eca00fc63ed2", - "0a0892b038d074bb80ee634bece5a77bf0248d60fbac082e1b6d4c48a7be704c37fe454de2a2f516148a09ea684c781cbd0986276dcc9df76f88dc11660ddc2f94", - "0b04e80eac5e5619245df5bfea67a8cc5d3a9c83f1f20c52e227fd51f1835a9e3ebda1276c2913076c4da02eb685153389222423d00ef4d5fd43b7fa3b971834a6", - "0a06e636a35d530fc357ae08428a496b30ecd3444e5e428674f3300883105ec3cffadfc79052ff7a5f06f5960439e5ef331acd1d5b96adec388b1436fed4a96432", - "0b088e034dcc8252bb52dd940a4913dc3cc38242cf02bc906f3081463014ca953bc6ece91302378a39c188803c1b69423dc2b6046b7e1cff3ff03466c6900c3c6d", - "0a035cf6fe6fc8401f2777a86de46177a7bc7fc023e7f548ddc235fc66a5b7da7f9d5fc4e2695a7a29121f6629906d7046bd62546c5da42f2ba184c19879c99ace", - "0a04a5d0cf1df4cac9535f79f39510c7fc5f5cac1c03ae8fa9e7601759589fa613eee65bd6150a45d59f4bfef24eb03b075fb0a4d3855252fb153674b440c8b205", - "0a05e82291bde8bc4aa57943704f40767d229892c49383d21dc40d0f7bbbb2500a5d7772484bafa2faaa937983e7aeed91fec5bfa7203bfdc24467f7d03e929896", - "0b005db3f952caec3c9913c878ca6ff5fbe63ca203d5a34c5f0ed5e806ffdcce157e0f4b280b9437fee2da7e473186908fdfd281d46832ddf60151fa94da723bf2", - "0a07a8c4a188ba2d1b6a56217678c6b95d2f862912c61b6df89128242a09d250522123789016164af2b015be9db97ccd3218ffbe8926d8934f4e6ec0c67a7a8a9a", - "0a07253ca6fcf3a0e2acbb4dd5d61f5e5b21b8c9fc32eaed56a3b1ce319f9796b8c1df447d1656deb24a00f61accd17387938b59e91405db6485b022d30cab0906", - "0b041f3bd9f86492c3be0785cd0b8028c0857f0e6dad38fec55dfaba2e297a5bcbd1aa9f90f4329373cb65daccc92b1d1f0f971dc03ea80e60af7aeadc7fa81bf4", - "0a052b728e8d31353bd2c0e6746136b9f640fa011fdbfc5fb1b90f1102ccfd307c1ecc1c25c149711dce9afef56eb0c7062b14c17d84dc9b6685f430319776e87c", - "0b08de23d4b3e121d98df84adb108051ed66da2eddd30c9cccdd6ae40d8da949e22260e793fab72a91f61ac89bb01328c2d75aca97e8960d5015a563f2ee39af0f", - "0a01d63475f2739172eebaf5e071dbcd54c26d60f550bdf83047db8fa0947e9281a145f0141c206d5af441d9b1cc09f3119722bfebddbb8542b0fa30f8c1abfb54", - "0a02ecff1e95e50d3cc5249a932d20d6234d08a9d2394a7afb59f48c61bef3a4ece8b5832a321805f0d8cfeec54e3bec4f3b947e11e1b2a8041dbbb6effb3217f2", - "0a06d369651acd4bb9bf020289f772dfcf95ae124971740795e69d55f363a41aeb29acc71693e24a027a392548e2f4153db6356f25f52c46d4c419170c18c11efb", - "0a033d1764d86f4c2316cdfcd32ee956fbceafdbc4d4f0d56b894e76fdb4b2d5cc6207ebe9d1f9d904b8380e284b1892ff48c5b04d1e0943831f973a3438a04aa3", - "0b0076b169fec292335a883dc5f89db5ed41b4b89a89610e2287df81e71ff9bb90ea639e7e0591f29f8d2e6b87eb3d6fa281f0303c8895021dcfe17f5ff504054c", - "0b038db0937b0c741626c209ee0a63b3f84e508835ef9a61b19b656d526c760083e2f2e9612d84a9da0e3673674abcb622c34de7289fdb681649aa376b8883e90e", - "0a0766f3cc031e8abb99d0b964628b99a07ca823b1589adbb4dd1f6f441874f392649013c07778b52909b3679b3a9ede21f2b9fc85c242ed0a252cb35c57a4e60f", - "0a03ff04ff06b48d2e6a7e7c62c8cbbeead942fcc4c70d4fa6a89286380a27a6b8ad9849107074c7351f2cc4c9d5d920d9d179da049723dfe16c902a0e0fcdbd3b", - "0b024a3825e92edc580178d2e77666667ae87818a98ebb20b5845604c626b0b4e0869b645a0734a4e0867b7f8ca53cf5cdbb4e6addcc6a52e936736ea19aa98e69", - "0b00a93a5aed9262f2e42e534f151bf8dac9832d68525a1b01106a1e15106349fc9e0e955211ad390e1a7090a7a8a71fb3f0635548361a2dfc179601ea3e8bca50", - "0b02deb33e27cef18977a1d7394ab3c7ea10534ef6a0b4f63af9ff6570c4b3005457dc4eb364708a9a4a04e2c6fba6c39340da7bac5b5966a944b01c60ea186a88", - "0b08c5cec375bc259e489ea2aff83f875e9054e145ce344ba280f35da35a071bf61e0b027ada5d3136179c90b6adf4e5b26fd7a8e7e8f94aa0e756d59dd9359eac", - "0b08fcecdadfab0b5c937e071007e966e9c9da03575dc5033b1aede9c42a41dd932c9bd477872d287cc4c7c1712685bcdbb465ac559fb2a32c9b5919ebd5329901", - "0b08db7a570250ee909706c24620ea4379e1508b3ac41d19058c3768abc441d29acda17a1ac69ffbca01636130cc46d8664a967d8b07486b92e45564924e2aaf58", - "0a05afec95c2771e9450520c439f3fb2f925cbec0839a1bc287f455aa2a464a3856d81302363174c28b5ca059b2d4d8f339d72cd916638e8e488b9e90ea38eb2d9", - "0a0491b2e0082e153120ac4d71d0030310ad829e32bc93421fbf9cc65a0a3d771e199769402f58fdf64c0a1a4df5c3a31655cff19677bc561c3e69c1f0ef31fc00", - "0a05a5817b2307b029eec303c5c38f95b9a28895dea4432491d41b23e0d2f5f486331cc1394b5fe31ff3d93ced03bafcb1336c5ef46553683f9a396b68d96532e0", - "0a0482bbaa38fb945e95ed1c0903a688519ab7a5918ad3f56911634f071d02b08d4cf21e91cd4a73e2042fe7e972eae488bd8ba1e357f4f0b26d897d58911dae6f", - "0b02cf78f14b8de83bdb7b621b4b1f200b14ae8ec0bb00289c31a0ad151c14cba736a8ae0c55c4ceaf401519e0b8e9754cff3d68d3cf42cb5efbaf3aa684d63037", - "0a0646b31446ab3cea2fd84258038f6ad5be84eb73472fe88ffad0de04fe61668848c455d6780e20d3c70c5cebac4095722a14fae25b03638d21ce7723493d4afc", - "0a03d365bbbf001883e43aba7a5a2bed3374b6fcb6ddf664c69521ef44a432e97ce348a69b45a0b8d9a75c292d20261e2a34cd2546bb2921a245c83a3eae7d8ace", - "0b048180df5e7042c2e072263befe6c083993b1cc4f0eb3ef06e0488a3497d4f34a87274d87860dea5c014f4fbf922dbb6da347f37fc8066960e7d384b40c6ab0c", - "0b0326cdcfa386ff67ed9879f312a21d729b3213dcfb5656720f40e0c8ee82dbd36b227e31c07ca73e66ab179d70bd8dea2b1cbcfc14288bf00b85905ec7413c4e", - "0b00a7133e685512381203ec7f0911f94f347e06bc8615004b82ac2e976e152cdbf4bef199656097468ded46653cd523968e33f849617cd49038a581e99768ce13", - "0b0920e9839cd48abe98c9c321bae769f68af4aa6730a5696db1068c6dbbb76c4bc5dcf538797d456dfc8657d6a2f5091eb0787b31844afb8069aff3a7ae5c4fe6", - "0b03051dd7e588addf2837d84a52b99bbd9c7b0a14e7f5cf9e731a216c358b312b28cbf7ae8e428d750a1dd9a3bb2b8e92e661eb4d4d4f849e789baa93b495c848", - "0b02644b55f3311087858dd080ab77b15898ad3205bdbee768820c2fe69879151cc215c30cdc7eeb3d97081913de478f0b13e4cc33f12a1d853f54cce73ec9f19c", - "0a084b0c8b21ec2f11d80165d63cb2dbed632b2f3ad108444d1bb269a6f374ed750c1c925b5e9726beb0f7cba54f4ea17a068390d98f70779c4902ed294d4f03b5", - "0a05304d9d8bc0277f09fa072740f876efe978e422f5a77516d7585ea1782f99b92ed73aed0ef2816fa7ecea7ef6c801efc1ef6cc375dbe1a778609f870fec5525", - "0a0129329fb0ae20f068295808b201d67e3154b464fe534634a9c7cfce62b0193789e63fdb636b72a760cc3ab6fe9adb9684ad93b15873bc344eb161bc6f0955d7", - "0a03a104870c5d8d9e457bf42065054b305ff8944d4c8d75fc77c549f05bd93cc0d7a6155f6d4da4c0e851ebd391130b56f4c4d579ca8c5b0a22f561b345216996", - "0b02e7797e768cba302985ce7cef916279b8adc314f35f5976587411f03545a53c028a859ce3c888f8a51560e92af5602c4b5989ebd1640c3ab89559619391b9e1", - "0a041e9e67f800044b70d8222af2e2b6998006be6d0d8a123406fec088cb2d4ca6b5999c2513c26cff1249f5a9f56fa133697bd042ed40cee1312e3925590d8efb", - "0a075b50023addb09050d1c13a3647b3533de7b325f7abc7e6ea3cf1f1e778a6f8bc6a72a185a581bdfa10bba4ad7be2c5b2bdf19328ef26d8a2ea917c8be61187", - "0a064ad77a18f8388df91bf1e596cdcfd0b10d717d129f89c6c629a0bf1d865015fdbd10ed3363889bdbec2920a84c0fe52682b251e9d1033eb6de092b32ae11e9", - "0b07053712e4afb61f64bb8bbb9ff44aceb11365524b365080a50f4ce473042e1dbc3a1f050f17f9a42e139cddd4b6cba1de758535e6370c92bfe2a1fd36b82770", - "0b029fbdcf8557935cb8c2d577f1519cb8922dcc7d087d8bdcf13dc4d41e9f667c2b8b2a9cb8150d4d4927238ab171688ccbb68f7df89b31d7a00ed833951285dd", - "0b06ca98433329ff95f01ceecc05b64d644166220f772e5afa50af0209a376aa632294c1dc917bce251d1e48cdf1af1610fa6ab73f833e747d598f28b962961132", - "0a05ec09acb0f13273050f1b64fbb7e14602dfafd6c0183ff2c10cbc99f2eb510b56f838e7d6baa3e1ad998788ed84f3fa3c783c9dd72bb4b600b402ed3af3dfc8", - "0a06d191d0501c63d388330a172006125ce7875e8ffd50fcc9ff418a4f4a7210bb6b864c2ea4964843e4d65a71a3ca677ba0a33920be7c2e7d0a8db0e8bccb99fa", - "0b0084f748ad7311cd1c76577f28b74068ae1cbc5b0810386d58570438de990a44fc91bc82f5efde692509c410b7119c0f2f8870b0ba40dd42672b1751cdbcfec1", - "0a087262569c2415eb47caa1fa0ff29b8feb480dc14fbd533842965f747ad041a40b7a153285dc4380c6161f0840a4ea08dbf40553401c7beedd2da59089012845", - "0b02d38888bcc507a5f1f5339d65529e560f75dcef02ae3bce6aa743b3863ed536549e402af920cad6fe24cd278d2bb469fbaf40ae2d4bdde3ffaff80ed24c404c", - "0a00ec7cf141093587f28201bbe08a77df51ef9c10bfd71f71a5ccc88d707a2a86a4bd5d5f1661ac8244accf9815ba7a17253f883929e94f7a66e9d212667604e3", - "0b01d8affaed7e5d66c37c4e9753a223909687c9030735c61bec6be9de283c06a5185a90df11eb70e98b0a422326d9b439fef67831cfbb26af41e988245b42c6df", - "0b01b2c70cb2db49f720bfa90de7d78aee351aa77a5d82dbf352235286228b47d3524d0a2e2235505a0ff76a9c8bdeceac0f80e9ee62f2cdf9347ff849bba7acec", - "0b0662a1f85828f8c01243cc7d241ab3167aef43bdeaf1c4c2853d756ebde427302457e9657725ad03f5c37207ff074dea447d1c2c1d35dbe68a73f7a60da8f1e4", - "0a0742dd819e3af317b73e177e94d2a00e920fe175ac759105403463a140a72f578accf2c6fe191f41dfcbdc85c50fc2bfedcafc0ea8d990b4793899b592c43103", - "0a08f6cccae868dd8684e5e0de6dab29dfe2d158c1cab83a4d6fed1005e85fd95f59e990c6b3fd235aa65a61d503a8fa0528e60b51f3c6a0a46a36ec1288a33a08", - "0b04778ad73f3f338fb818093e6f42c515b49ed3d13b95f275cb9694accc32e0c2df98dd4b6a816c1c9d3f32c4d50cf9ae50aec4e3197cbef66786e16e617fb0bd", - "0b08d26bab97399d0405af7da83f067773d0db9b1593e37c8aadcf57b9a2cf862ff22ea75c525d0b198e58db8227e9019d466f6f8ccb31fba08974d55bd22db123", - "0a050475045b5851e3cb80eed59c47a1fb05684c871bfaf40fec70b1d1f03d4ec55f353628e26ecaca4d041e0b3e446711cb69c02809a09fd4387ec015ce6c70c9", - "0b0087f0e2bd65b8c5e4f2f0886e92827420dca85eb00572a8cbae778212014e2e2d4ae2ca00ca563b91f4b59a8bf19a055ac2ec78cbe39d5c416cde35bc6f64a3", - "0a088f24dd0f0ab877f72657e85188fb966cf551ff5f5e92685626e0f75f05d8896b646113b0f9c3644ff70a97cd3c33c3ac898bc20529109b3095a23fa5db9c50", - "0b060f6f4c0102384db65348f419f481e860aa007e0ef416a6b447825e7a1df337e290eac284a1ab3de0535108212e97f246bf7d96dcacb1ae35fd44fc82f1dfd5", - "0b056a0cba0f581bce39d10fe42d6cfc6cf2b7d043287219cf96b6ac878e7ea51120710b70ed235c711923b2a958966b0fee2d5078a242dd20e87008ca58380daa", - "0a0663c3e39979b5dd429ee3a490dff686c2aa1ada3cacb56fc82ac40cf168914c7bb381661899de4fd027a7e7dd5a1f70a4ed679f8549d6b8930b35e1c9b24cf4", - "0a005a62c81e02185d8904882244f1fe054e8bb3b4f41a9198f3288bb9a89a0528fa35867962febdd48c435c380f5dae2a5dd9d061e531596279515062353da90a", - "0b018b2b7f4a6dbf39d201347ace03e5abce4f8f25f11855f5c24a8ee48ba0f015d26a4617b82beb7c7344a132eb2127c0569b5f47f40345f32ee97cd6e75c98a4", - "0a059227adb134f5f5389f7a44dd606c0f81b0e07052d3208c4583d5a09d8f8adf13e45c2737b6677bddbe32c3018a70ae6611b7101975224f25d1d9e6be3f2791", - "0b028fc579c28229842efa3ddf9ae2d510dba44da531d47cbea5b0d6d0a86442c1f0ac265dda3e0df7b3390d6c7cf4355b8d9628aa2d60388ab390670199695db1", - "0a006c811053b2a4584e204116ab26f0056d363094cfa2d7bb53c647455e5018f1a0553bf8240a1b0f41d410e3230c038d82cf77cf300030a8ddd49c7a098aacf4", - "0b01b2a0bbfc4fa888ddc28aa5d218a32b06826b05ee20d192fef25771cb697f5f674f5f7593348c3fbf0026dd83d37c3433bb237c155374e0c967fa85b8df8801", - "0b062c8842fb7e52fa3de7a69989ec0703e7e4d82aad785abc71a2e78a984c850b2a6380c5c4a77af086dc0686d791310cf3405a8562b308a51077400b291b6249", - "0a044f085b5dbce0538dc3331470c5388d65704e155fb3f68df1566f20c0dd26d9b5fc2761c65daee855a66e95a9773f33b2c90cf244094f0cd5257f2d6c89b687", - "0a0193c4f28f41512e758c3e32d836d1323ca7ff27d25f15ff8b0f09744a6aaba120c0f40b582ecf8d147bccbe3658690aee4ed9ed6e96325c4950b20d31e0025e", - "0b0181d41770cb7c33dc13ae3570cae65e58b4d15028fd4461c289944be70764992873d25c9f5e35e44f139646c450f5d46736d7f244f292b7dfc258c0f1e0c33f", - "0b03a8eaa8f6f8a496a21bf0d698d3dcd93620b45116ca00f8239c5fcca70995f69106a9a546fc38ec9bf7777265f922187bcc5a421fb5c493081cb05db4c450d2", - "0a00728c4a9fd1a0751a79c9521fcfdf9ce7765716416a260ffb0d2364c49c52c1fa3ba9e1c1b3fa6ccccd9c3c4e0befe89d02d3baa9e640467f6071add67950ee", - "0a012ebf7710d7629e430853d356fd13114f997fad7f69676d629c8bb8067c98736540a908469a4d3e0f1b6a897017bc32f1ad8f6d61509e842ef2ac8b83f6fd57", - "0b062a591a3a9e0942177826d34958b4faab610975e551bcc9b562020c42d010ebc9b8d1cb497316662864a53c3501f7d86b76059088f02062e01daece3da47aa7", - "0b028854ccd3dc26fe40436a32f05a7de05174ab46aa14c3e0cd6afe2541a7b7a64184f39016ac01d6dfe77d48c35c74be5812ac59f1071f097f1c537c3168b897", - "0a01c11a40d7f677ca5b50b4f59ea86db4c366be59ea5e346ec40358341a47e79ef3ee27ba52e31afac6bef11634875168cf1995d436980314a6c876fa58ce8be5", - "0a00f1ec9a012b9f76ef7fb0cef7252940f148a1d10b97f1b623471ce888a58bd6a29ca3dd75a4628d302c7f6416970db2a9a3bba452d679673bbdbb8bf8c876ed", - "0a077c53fe3437f990e7b2a0fad3019a135c987acd491ffd05789dc75f235b6a195152dd869bbba4609a2fab2314262b51a82c06553f26686adf17cd565000d305", - "0a0883e4ba628e9e8ef3b9063cf6a1126526386d1a7d666b640531ec3f2aefc01bcc9481f05402d20374ded128a6974af7bccf662e61ed382f81a935e9a14a6142", - "0b073b96ab171f203230f91fe8f9914f985a2a8bc3811ac955da4cb79b723443f3e813d5d36df903eaa3b7bf935f0d8424661cad083ff0af0a86e139e235545602", - "0b01bd9fc6826c97daedcc592c2d822a58a290bff3cd1c58fe86a006f8c380620518af8f355db4fe61ec34331580300414fb540c24ef870111a5a26a3518c9287b", - "0b005473c177b81f57106c8948836515ba80f6fff4e5549ec8be0af2c6ed099a9bba255b49fdd17f644de68d3f410017f952e798a18ecab8212ed5d7cbdf212180", - "0b01c70fa98cb6ee71f300a337cf2878786c6b849126560c50c22246d428f49d56e82028f6a54f6977d01349c45533c4a917c1f58bc0dfe7b29dfd86b057afb5ff", - "0a064b808b2b0300838930157ce9b8da814f99f9a9583c8c71348589b3b753f147eda351694d627033f947c5e965f91e19f900252d3a7805d8ed367093ecb3797a", - "0a027f155fcd04a12ded6cb09bd18ebdc9b9f88d2c05a5befea8ed1229163479593030e596908324a3a2ad5218b83e7fd5afc6858d0d4ba742e8f96fb8a0fb2855", - "0a02dcbfbeddc856d0b76354a899400a6e8597cc52766e363466d59d544f33b2aac84b040ad3099a477f12f42858e1a9e8d4f05a31b4119d6a9c935ff1ba3315d1", - "0b00cfd998ad2dfad952089bf984d5fe3eb42b6e1acc009e83bcf3e365eb894e56188da7ef80c425dc74178ca6eae6f762a7e50659a1cb068b4d29370404421aaf", - "0b00caf55539719585bff4414e25997373c46cadf0443425182dcd12a490d8cbfb51d226d4f0dd890529dd8291ff2059405671825210f87e2b834eda5e9614e056", - "0b089c1e29747aa8a3e358559da747838bdac1e4397d33046c643fb1c0e5fce45ed9075a97ce75aaecfb1eecd3eaebfdd58adbaaf97da0936a826c52ca25c87228", - "0b00bf7ee8e207961628504e4cf3715bedf3292ad62b9b2d285037f6f2e7723091a1051b090b70a9fa7a20b4534f8ff07e80ec685abcd63cbd904d5e2c825b7675", - "0a032eb00e465680685a9298976b80237837822fe48312c154471bc37b14c2e6f05c172e93bb4118292610c8bd6aaa19d59c84ba2e6137df7090371cb80fc055ac", - "0a078f6e2cb335296f181441a0445a8325dadec50b7ad14898c561e295e6c1af75a107c02bc2b3fb7e455af46a1610c48ef9cd1cedcff858bbe42153699d9b647a", - "0b07024a188da84b34c7e7f49fbe7e48145acec1312ed5d59b1ee826d75289a4fce25d0327efb7a3a7ce50dc990a94e3956c3d2da62755dbf9a98d9cbe1e497d9f", - "0b035c6fa84b746b71b09fe33049137a2885062dbbc25ec58bd5cf489db643d486ec514bf11a7323b091dc69f758e8dbc37ee92de49713a90c1f5b55ce2dfe7285", - "0b07e6dd165cab4c5a7258486b5396f5a27987f62936cced85c25619337a53f3031caf45672f9ad2882b9cc8769e74b3f5a484194dd064d5cfe16ac7ed690f0ff3", - "0b069a7216f850b957169e7c7f8da3ffd00f6bb80a13148057cd66cd28d2beda4d2da829f6ead0c0de5dd0b37132095215a0b0ab89dd10faf8293a25c143bf69b6", - "0a008aa47594c5cd7abf2d7c667f9cacbdf2061484e86bf570767e4db9b7bea191cd168bf696c3a4c629e63e21026ad0dde909c8607ed0659970cd3865d8944c6d", - "0a03c73ca461a22c547fdee35dd2c0844cb100d2714391db35b7db96fcf245b6bdf2fc090adc67037853c5cc96382e40b43ea9dca4d2c871f2135084802929da61", - "0a085e9507048be0b6d7799bd39d01699bc7fe99bcd8f038d07db9804bd87477e928ba3b59fe3e30011b8e8db7f8ba4b97b5e3d1b1a104c91d9e8be48931d16208", - "0b085f015784090095962485f95806eacbfd7f69c103457adb1b33f756d69535e69145abd38ada68743feecfc2f72adf5b68bba5b016b11d7f887f2bf1ceaa5edd", - "0a05254d0274469333d83ccd21961cc2610df7377a0328f75285c358fe030009a6dcb17a18f3f071a0f62cd896791ec2614a47d02cb075b9c60ab563113891bbdb", - "0a01b3da3431fade1ee7385ade259cd8cfadc9a26ec45120f65d4004842217c507fda201888f07640a0470f82850a9f8516eba2ffd61dd9993da03cc55923096f9", - "0b035dc396b176ed86942284b7667eeb8db82d36d400c6da944d256698a941de2fc0e36e81b983073e190d0360ece41beff70c41f6ad2a6a720f7daf03d1d05161", - "0b0487ec8907a10ba42bb7cb26b0f894867aa9554a8c1bc2675bdd5f25d753671eca48fb9eca98fdeca71dec6c1d4d6102b6191c146b717a958874e13ae2d29801", - "0a04a2fb05cd0c4a0bb2cbbcc76c743294825bdbfeab1f3eafe5c60ca3086c83b09b405e0cf07ef8fb97c154d3af960c0f2d7a65a9cedff23f0bbffd0c4260a15a", - "0a004494538ae9c32575e254716e52f54c12e1589b06cccc78ed5ae3a9f5e9064143348c2f1bdc95576553143d0a65f03092b6ae7997974de9ba3a1c467ae3ba37", - "0a07215beb8499fcbd91fd7a824e9634584dffa38f62b6399aa70b63fc6704eb0ae140dbb69f2177f756a59b23ec8577d8422966a6ebb4d6221d47341bbb4c097c", - "0b03a19bfad7795328da6b2059f48f0a47bad9e4257054141639201a8e23ed1538d5b7c6fc2b12f11194bad1aa75839e83ceb7d72bf62f0cfd949e071de3fa79be", - "0b07cb1258b3923e80d88da0448b338bcc691472570e16319ec3a1d3f41ad76d698cac3938c4134e698ed2773b9b036b4b38319afe9725d70247c121fb5303130b", - "0b02ed42ea27d48d0462a2dbe72f78303ea7f12aa5dc73172d349aa6add4962de569a0c41856a97e7ac80036c9a06c83dffa4d0c6218a2494a46669367aa6dd5b2", - "0b08cf11cd4b8f39ba6e95ba104ae276b9ca534dad49e1df3ac49be2f72d862c1d375bfb217fd854b48759118444cef7731a21587f96cf6ef02a5f843f65aa3a06", - "0a075c90013c8750224008066be2f30e1d19dd5e33ce4805d692bd6b462d2e0c52695f0ae90deced6f34e284ab9b2bf03c947e8082272b9a8eeb033785f359b01a", - "0a03b9ec6be7a7a0046693008231ec19a187c58d7f8bbe383243da1b99a6482a87903bb12fd518687742709295eeffd4d14247205e674a92f980a757f6a43b2b85", - "0a05d18ff64c4d1ad90e83ad4eb4720f30219db7ca35953774c6bd941a24b3c62a9754d309b849e1cff7aa9f431510558e9227ad0f700049b7258e03276e821fa5", - "0b06350cd63f2a50137b32282e8fe8484a43582211275d5e1d0f509069a8c29196bd3f07c9af129da57e1995a66b417cfc1a3ad89165d7fdcc5e440187d0bda6ba", - "0b01c74ae21176bf4310b541eb48ba3283261d34fe47db9c397955add9ebf8824ada6d1ce912428a3d17d8adc3cb746a0867aba7192aff1cfdf3193338ba38ef5e", - "0b05b07cd50717797da5fe102f721226ea7409a093eb8b18cf12b433ad302b1d6bbb8d96c684ff06eb31b8210dfa1382805e3900f887d0510ecd04fed83ee767d6", - "0b03b46ad72300654762d0d62a49b999034619a456d0e7cd504ea124058b4c16ef9e189162449dcbe6a079960bd4ebedc703bc0b48d5eb550a9c7451dd0f6c157e", - "0a06933ea5fdc1913ace12b0fcca6726c58a67354a8425eb153dbbf5f417e45a1de188deb5eb311a514b2422d5686e46b47b5ef76896974a1b6ee616b637ca58c8", - "0a06403b7ce50357ab28d91906e4565ba57064ed3149dcc408287c682c8c8d8821996e807badf7a022a02536044aef402e2e37408dcfe436f5ba1b7178a2c8c951", - "0b06ca2291c165710965b7ce73105250503144cad440865b512d114844b4ae67426e4eceafb0f3905a7c473efca2d89a8cf7b6f2b7d4e47e575ee4e986e3e97577", - "0b022933ec5941c23d58d68d345ee9b3438793e189450357eba8bcb71ad7b14fe53af19afffb4244d8e1462cc56441343fb97304ddc2eb8366ce3db5eaf214a7da", - "0a04614ab9cb6dccf2beef9c47eb5181dcaf57fbcc73780ffae4375f434509c2908a62ec566d1ebc33849f54a0d51b5b3f3059b83cad8780c5a46e7ad5e5146d04", - "0b041b76dae90ec15f9e93ef883d40b13a18c9765b206fcc091b639caddfd67775df9e9047a77a757b96e17397897692bc93ef0f66c29655b5f6da09538ff1e074", - "0a04b3ffd8b3f0c844b27e31e6b8b783e2830bf74bfd4424dad4e18e5b791a35d0fc131a4a700719dbbf8b0af253369cff678961fee33a0f5e7717dfb7c3269bd9", - "0a03e2f85840fca9827cab70666cc5a79d8013dea153bd052c094c28bef3b3a99e23a986334fd54b21dc33b86b1ad35fbc954962a95fb960a7e4ac220bdeda37d0", - "0a0165a4f226ac7a6c70755291f1ce3a4ed86181662851b32a7ce1bed5ff39feea7d0810ed4543538c4adac7400ef0e633fc42fe1efaed4eee48576e04b5cc3198", - "0b006750eafabc208395849a61ba0024f07f6518a924df02eb2406e586048b6f73919fb6625c3a6c4ed59b4edb8a29ca43eab25aae3411601e0d3235c78004e201", - "0a0113a04f751566cd3472b163fb55825f0ff0788daab1fc5033714da285cb05779ded76d601bf8db494bcd065d38483cf7f103510f2f52892d947c1ac3738951c", - "0a022ecfaf53db3289cc8aa504d48c20b2c84f68549433faef4941680a6a608aca2227d533f5265a451d49cb0f882863187773a386fbcca155737e0dc3de7ac13f", - "0a055cdd6bebd47124f5d339eb60626a8e8a5506184773d7a0511fe728a0ce2188dc0d76e581b1f069ec8fc06f527268b674e361af5dec1ad90e26f1470ce3ecdb", - "0a00f98d653d3f28d3db137473c00e94aa2541b4ef8997366c3a81724aa06002661817895ec9a702f6a1eb383dbca2057ade7ddd95fcf99de827a815bbf74b76f5", - "0a06c20435e772732d034b101e2abddd27a4ae52d2d4b9b423a2da83c48f863bfeb310b85954e2dd3eb85a1904d74f18fde0d5f9b0d56d337c16d2c637c77f231a", - "0b07910b154b9082173c88cd42dfced855183bb31b9daf0a53248fbde2012dcb9cfbc79e29ae668b49c335c627577d3419e7f9395046027c7308a428ba8b6dcebd", - "0b05340a0fbbb6292c896a772d001cce7350b604e5096f5d33c3e54cf6ebf8dcf265f9e84cf98013b8f7bb67218e046efa4cd34020e9d36c53921ca05bef45e729", - "0a051bddbddcfe9844a16a1652f80e8dc0665d48c11387c144deb12ba8a91c8871da2769159efef2d4c0fb88bf5c948608194d0b331b3a1cde413c5add26ab9291", - "0b08867b63761a956cf1f87b4c06ca424c445929a9121901c61f2fa92f7437555601be80e7831b590c287af5f1816d0720567ad053a628d3318bf33d9ef5f510de", - "0b06e2743be319408f787c55eaca3fc1177674b32b346a4ee7e7861dd99e5f89fd66406818a75a3e2b3c63e87a58d2c52a5c70ea999534b18bfe327feec64cf57f", - "0a0579b68d10b1fa618d4b4d96c0525f5c6ae75747a24251729d3cfe96a9f758b7fd8e5199f3c36064f2476f449906c4495f170d5e0783c974dabb5bea51922ab9", - "0a05572593b6da430c9ce6ef7f4ecec9a9df2feeabe5bd6308668c807e1645fc8f6b3d467ce24ce40442992f7e8f959e408f20abd9300542d37a9ae5e0d7f9e732", - "0a029c16ae1a850e71017c9fd9c778a62129ce206206cc27768f9a2a98c399eb4b473c05a27b61d5209b0d27347dc93074d2aee26e9fd78b614894b7520c2c4bff", - "0b0856453f7c0a5c71fc060085f4a3f7223ce3f3e9faa782db7eec6a804c5cc8ec37a78cab8a5628c6e7db42e742897b5e792c48b7b17994bba64811eb5bafcf36", - "0b07ddd251df5a80b2e55ed9a0e9017f9429690853a893cfed53b25753a83e8cfdd8ec14e14e0bd74dde8505525e037857bdee6a3f5b566f8cf643d843c4fb82b2", - "0a073981721c01cea7f67856b5f8ed67a42e3f93c7fb78a00aabfb31a97622676ca89c828aea0d43717b9318bf32f1527ae23fca874036768a22f2ca58cbec6bc2", - "0b0005d94962fa83dd98d60d266bada0e30e7a41cfe2d3de34b571b212e7e627fb4656b9322ab48b84ac5807d3f1cb8b766efd764dd58421a78ad257ac6b643be7", - "0b022770653c52a4aae527d5de41ba21db0985c5214d32b73f2646ea3a29d37c6ed2e05b043df67f05d5e618ff5241a303ffb158573bcabcf08b6f23529893d391", - "0b00d2888e0e3eb6cc218ddb152d6d76ceaf9992ae3ca2846d1df4837e23609c1689ada42b0a9c5e26ee04a2bdf8256dc93421e3c4ddd25f722c95331991a43e7e", - "0a03fbd109be4a57400e681fc01f108265e8e09d94f5f92a6db2b271f62736a1e250013f428ce6a392fc07aabd8e9d54d0f847440061df234829bd0364fe275af6", - "0a03951eae089b7fff3d5017ba982c31576aecbf8af6aa9fdef23e15bbab9a06594136fa357b4bb6572319a1d9d6887dc541417ca4eff33adf4e4016c6e221a446", - "0a04e25c34707b48722dfc37b568239f16c0f58dac68cbc9d5a8df0f4250b103b92229bfd83efead0695f6d296a5c26379a8cc864274d6efaf5d87fbd2802bf107", - "0b02f9e83297641ef82a8c84cd762cd579f4490317d3a39ae5b49c2bb43a6a0477d3abfc7b660fa366ab3f475f1338a9b86a9622109aa33fb112e5889a01d6fdb2", - "0a08e2c92f8846b233243885dacf5da6cdf463ba2f4eb72db74fe0a5e39509a62fce8de46a8180a53e70361ae8c0db13ccee8da962901ec88e08a6fd7f0b79fc22", - "0b0181437f856b08cd9ff2e0cea1a97dd9daec9da97eec8ecc9aad8c628fb6911cfb676ed8b98d93595fd1c4a2f7af16f7fccc61755bb820983d074dacac0fc1fe", - "0b0374741cf7909d05ace1a66f50f2e149398431c1ac3f9e01f4d71da5caca684ab733bd5977b2618aa0e3e0909a1ec60dfe65e00b4c4d9016ee73881bce956e21", - "0a01f4e3b32440dfabd3873ac9fa5cb9d958b3eaa72046d6885cad6e7a3a6f598be01c2d917eda94de3e083da8fac1e40c94dafb1768aa05b5dc2fb88621d2f213", - "0a05cadf0c2670ca86d14d9d95e843a1c32286edbf25502472c3ecaa5cb39449112384bccf784142a74b8cfd6ef1acdb8e5255d61da7223ef9562b3c373f58b698", - "0a00b8a3d443ecd72636582e9d0d6f9ddd139c9acd7b80f2123af723b64ea57d241e6be7f47b62c0ed405d1d9335222a9b602b53c521a8ae1224fd5f00d25633b8", - "0a00180ea349c169924dadc11b3c0d9d439a5f5ae1ddd9a8f18dc048edfdb1b300f9be678e8bc0f5bc8ed8295558129f0a3bc5a1899b2b1b97247c6b91193ffb4a", - "0b03b313f03f89e45c4cc74d8ac3b75f3d5db86ca2c8478b9b0f7cd330a4fbf35d2ddd282f5ba35a491d22d95e53a658a46ee4f0962cb81f58b08c7784a262445f", - "0b036f5dd9c752e014a8a8d489b1f640bdb860097757c699201593ad417ace66f1c0b55ce19053b574e7eddaf332fb2dc82c0d8059e69b580d4f9dcc08ee97f31a", - "0a0406f0e9e6f894228dd668c66372e4b141e933b07fe95d2d70263dce896c75acd72061a4a5fe6d195422b0bd1f60afefe5ac1333023b9d6f8abed45a28fdcc5d", - "0a05442160264f7b04483eab7f0cc36898ac482b8d1735fdba3b93c810569e5f69fc0bbd9ca4cf6f2655e58fa4edb53b98dadcbed69a626a2c3beb0a5a6e352c8b", - "0a05a400b512051ea50e5ad5657cda9e9ff47569bc664545cdb452a6d1be55fbfd292d3c1ea33dfaebcc4f76301785709890612208a81063b0ae91d4f796227a13", - "0b035e8dc4c2350e6aefb20ead49250c1f94850a1eef3d2a8934c39b5e63eec3e26e9b901faa7c6e9b6f1b2b4329cc16f97c0ec5300e7840919db0cf00d6362fcb", - "0b025b1d915a10550d5808b30f539ce7ac277054797c7beba99a09367a19c54ffbc6be69251a0804b135d8d0dd3ce6a665c9fc58aeb9be030803722176a1352298", - "0b03a672c2339a4b23389dcd935e7f2521a7d19d37d1e2c5a333e12209a6b293fa3e42b3b5a6a48c05ba414009883bd741574c1b97682215fa25c38a76268b1dd7", - "0b04fe65ddb7ee800f5654d75ac4a88ce270d39c407ffcccde86ec8bca7f6f22ee6a6a62a5ad24de9770b0019af700f9e3982d95dbf0e48853bbe7fccb23fdb695", - "0a007d0780d6ea58de4c9f62a6ec37331cb77e49ddcbf658feaf7d4f8a7b0ba47e13a2ba7512d78be592bd3880392270405d08e455c4372dc0591f538ce8534c59", - "0a02fdf126a49e7e43b3eeae30693f7997ff0743d09ab006c87007393fd3cc36275a5d197a2f6e92c857a8477882b728d63e2122e30842017c276c93aec15d754f", - "0a06a57b09dd5bc22c204404d70ff43ee608be72ff7cacf9ef0600dc8796c338808d2511f4d759bb508f9297ac46894f9e3be9c8d72c9b2bf258bfe11701dcd702", - "0a0862255e613365bc3e5e93d1f390fba57e085909cb4681522cb4c8b93058bcf01aa1182f69086c394e3b47eabbb96c6efaffba6150606982a18c0d47449f1b2e", - "0a02905ae218d18ac1e50827d2b61bbe8d376d20c443f5e28ff03b3f119be6696d47bcb8704c9ac0b9ae3435687dbfae7e1fb2f1538afd1734ad929850b282abe9", - "0a00bc703335255a45053b8146136ee24db93c9c6035b9180eb3744e2cf6e4827014b2340f548b17ac7d2335c9cb6735480972dbc91b8b680b4d0679ae22b15b72", - "0b054e339235aea93bcea523005aa888c129efc73b3833e27d0119756af70799ecf077508081b528145820ef83607db1c60969529b98f246a44dd428b76f7f61ea", - "0a02e433c07323c2b54ae12437429c126684abbd386c785c2f5b900d9d3f9c519a8774f26837800ee95b3ee2ee17cde71f1d0917b928e98b5eb4631dd8aac0b37b", - "0a017d6a0d406b4fa0ddb6d6fdcc6e2d5ddb399c5a59ee0fe33872f27fcfa92dd1c172306e6ad23ab653f25f53395bf8a7f44bc01f1da1e948783b54025b38ec9a", - "0a04bbfb0edad8ac0b9da9037aa2fdf01ef39a25d98acaf4ace50563ad77941cd442974cd4a4e878df3aca9280f5637907e47593f031bd988e337e738f72949a57", - "0a00ad8033a02fbc1fdfaed96e8eaeb10e664b20b8bbeeee96926028769acfd1561c023d15bf9b8a923f9851cbfbf79614e31817ee0df8002f258dee5c23c0084d", - "0b02de52debd5f26d1df72b39a310c71dbbfcf00bbe69d70c829a7f1e7346aa0cc9b0cf8f3794cfeb1c418b099d4f47f89e218a878d0eca5908f358263f6284312", - "0b01bfc0e1145cfc145f5bac841cb5f3da411d28a80fe853b115d1668537814c23358caf73968d5366996efe2dfebad0258305a7b1416c72b9a60b613cb2cd629e", - "0b074bf2d1a2369fb7b2ace5d982868ea14cb011b883131ea292cd2b724c1518a46a681780aed44e8a6bc1485bcd6729157b8b468763ed123c11d6f32b059d49d8", - "0a0409d5f6ffd09a24b1af9b59d3010face4ce89a80bf0c3d91fe3500e422415fe095b9d88e896184774390e9aa879fe8db4b35f1330772266e27aac17664ce9e8", - "0b01d40717f40cd81b54975d4e78f481dd18fc9c982098be51f4d3f457ace52c2388af9cae41f793a18fcd7f5fa9376e70368a40534197df61aaaff56bf436b800", - "0a00de570092466eadb0e0bdb78758fbdc789e376a66d3b202d7c259da632833a58cbf8bc68b0c82832eab51dc5c1808c700b89faf1fca3130e7b2aaf7e2b9733e", - "0b00b0bf73f884d4d205baa35a3d7e98eacb91b3f505d42615d5a3f015a4b6beefdecd7f150f42d3b9363da846d06d991af8136d1d090036e8ff38e2e50e32d55c", - "0a0490779c83e8fb74bc45bd4d5bacc9affa419df5befb8c9bc7481dd0125aba7d2b9be5900be1c3d0ba35e3506298125ca41c381836332b4b7966a55ef662921b", - "0a091e9544b3b7b6008fd3b70723299a4e7300dbe4cf10f5251021466d6856abf27395c56ab86307579b40b251fbf6402f79e63633a1902aba0bc2046dad2060c7", - "0b01543f705782ea7b474173a211e2066d64f264244b34a922be057e5b746e8244346f24561aa09eb3be7373ec572bc419862ef78b000e589386971d69c271df1f", - "0b010b793422374928e3323ce76d4c42280f4510e6476f57fa493a5ab2b33741eea510038d793dda40fd39933af1d42676b79006ba8083f2be368a75df3281df67", - "0b00840cdd4086c054f95ed463a4caa92f12f2de99be25c6f4f8d231264a2fe636e24da425bea52bbd49745ac07b8b4547a3b49b9c01f1a4cc4404d6f9888b88eb", - "0a02fe9e94ef56017634f84ea5809ef71c90152b944b963ff4db5c81f88764e528368b4812171b97d3ff0ef319e71d7a15d01919956a60fd6d4dc75ba86dd8905c", - "0a02d42ec5f9302a065adf572d74e59a71a296367eb590ccf441fe8e22673af69c27d5a0164da0d59c6886e1350f903ab5e6f6f6a23cb84ce6c8ec6609c66bcc71", - "0b02902f705b1f009b19df7b3e896db4a5e0e3d67e2360bf488533169a1442468ad17f5e3c2a2c6df5ef5bed9a9280bad799325defb579a05d3f4f2bef92073d12", - "0a05aabd82661a6db44c45a3035da849166cd4536e31347c8e824365c3ead4b1650d65d4ceb94e0787ab4d3cc7a11ed03e14c6b5b626033617c1df597efe8e6398", - "0a05e11fbe51698f1f5b339e65690d42cb5b2b51c6ffc45b38702e32edca52d3f106f8fc237918a6961ef47d50cd9156327d5169ee70cb26b100356ae85c815714", - "0b057debc47bcee924a34152f30acc4496b8604931a58ad4fbb6e548e212c8daffb347bffc8f733e3ec30f04c4c350cbc4b1520e8038a67189d1f9cfc51ec111ca", - "0a005f0f2fff828e36c362aa73813b061e47437e5cc68399731eea64f831da0ffc40745a56bcee4fb3eb0535f1f65dcae2ed389ba1907b76bf1eae7e67fa2a9487", - "0b091924f3504ba0034a7271a9dab30e7054e45ba5a6843da442118d7f784c85e3cdc8b8cd98277401a92f5eb1d2839167cf3be7b938399dbaf6aa389d74569e35", - "0b0687a19ff5febb11f78be4882f6d7a4cb3d08bbaf407a4644fde9cb0f9957263550ec13169a5649758049c0fe4bdcd8a597d40db981636cd555de26d1222e657", - "0b060ef217365970218df35a7cedb16953a975b94831d6f0d4107577b777170b0cef578b04fd48c8009d56929cd200d30b54e16523734887b6867756c4ec062ea0", - "0a00bda2c9665fdcf2a39a8d0c00d0cf4d4d44859f5f6c74c072fb3f9aeea26fc77bbcb2c3c3056f404bea4fb1bbdfab1b646cfdde028ed5875fe1074ec4d99963", - "0a0169930070dca6b8b2657ff329c39b84a13ab8e0e645bed38ac5426685fb500c4a90440155c69aacce357ecc885d863531c88b269ce6e7d1c510d8356c734774", - "0b074dc2edd7cc063334617cebe7e6f8c5a22232b273b5900268ebf8ae5bb3cd8b37f6c8c39bd34cc96591e3b0726d727da9ce1225a3854e6dd5e0f3e66e002d0d", - "0a0631333697fe604b244b4435e0ad61017d9b3d71888c35a46bafdc4b874315c32920e1a6caaedf09de29f94fa63706a483ddea35793aadd267e789ec2860e2bc", - "0b0916fe692fbd8ad5421901a1e588bc3484cdc2cd57051b1c5ed9b2466f6065bbc662f25e7d770e8decb395e164f10d75706cb9dc8c6eaa02a5af4a1e77bde291", - "0b0026d0a9231c18073b64cc343bf5f6db68260b5325f305d41caffb39e3ea16273bb1c1c8756cecad98d38a30d08446a4e39635373adfa39cc4f5f39993358677", - "0b06664db5b029632c4d229a78cb3bcb7a57c4cf9f00fec5037e3be279888333b03999dab25e1fd2caed36a3ca0de2a36a26fab1115693b747ecb27b0e90bfd93a", - "0b05cd369ec7c835a288a2453728ef43e4a9d8403efa60af9bb549d71e9802f4b39b7c5526ae1826c2e316514ce37f743585a5e4570f40779c93ae0666b7fa8050", - "0b04d55b4d9164ee9aca99da28a2ff597113d05785d9156cd6a93e77854883930b7638d4a934310dadc87ad57769327e2ca66a89eb4b147fe8b3a679a41112cac8", - "0a02913103682db52880ee18f4b6fcdf5a2a2fc8c8dadf168c116020458e362a8ea37510aa0e827b1ec905fe147d7b69f3be6882020d1ce9c657b7b9b60c8bd72c", - "0b042d42fff4d0bdeeca3e08ff8c794a3cd443286f31d3231d3201bc189ca6b74cfa4ffdef3770c66d8297bc82e435929e394ed6cbfa9f439f8066813787901014", - "0a04feb14202b08428ec91cd92f3ea6e5d345be178540bca49c69461752be8bcb08581eaae41a9c290acb41db08e86692a16fa9cd509376b49c07194bacdd69aee", - "0b0065971a83775059c31366030828e1247eab4a9cc2992953beeb52fd9fc586d6e6fb799950c68a7657c31d75a4b5041d9f6954e9c8d0f7ba4b738c7f6514c69f", - "0a07c21b5eede3a350b5ae90dac3f066b6c69a9362bd459b643cc783339dee0deb56f721ce684d9ef6f434449a32158d113dbda17986c8c3de852dee1495b20531", - "0a0546e21ca5effd1da5737b9dbf2c8640e3dd8b699238460c605e4869af697e3712878f76e750f1b761011f5e3059832ab396eb55e85d274e103117886a5b7156", - "0b0478f84578ad74a385040d2c0700bda12d73df414e57b2d08e4701a73037a174917d1d6b425b5f18b3918a7943779775516bbebadaec11c584a0580d1709f584", - "0b08bd63160294534dea75f59ccac8d1ee2b6753eef1adbba1ba5b65ce1bdbe21f02538ebea85d9ee52f6c22769f9f5ab223e4f42c76e4dc9fb28b3fdbad70f337", - "0b08a6804606adb6d436c657ab8a11d1ff06e99439688a1397c6b0f9025768b27f53292371c94b1e82379a857fe6ee3c7f2c45facc73d8ea6f9170b117d4e7ffa8", - "0b02f64aed9bda62a5926574226dcc99d4902481b191ea65ebbfd6995d2b04c84cd61d7ff9f2fd1b17ea4b110659db621da8b2fb83890283574172039609aff9ea", - "0a048dc862b43fcab0a88275cc958f51b96fa4c34cfd3f296e0f82668500de35693ec10e760a90fdc458943c252de43b1e0dd435b60a674d057581c50bf4eaadab", - "0b088899069cd19ed140d62611f8a0d9227e88a1a1a649c3e685a7b16b141d6933d25d63a9a428615353f93ceb44149d111f1b554e77aa50340cf9b5b20e5c6381", - "0b05345fc931e09ae19a230c6bc3ffe46b5822e35c36e9c44a9cb94a02c524dabf5175cf6006713fd39be9d75833a6c955f434fa8911d52c71f132efb548d7bbb2", - "0a085f207d8d5692c582cf9d194b905b7c22bf15bb0cfe9a41efda76913a26cf69e6747cb7c4ef59cc775f3ee8f93bed86eb2388ec24598fd0fb23546da92a8f64", - "0a01a2a368a8ab53cdd61fa514fe7e0e409f881c415f6332323fa3116f74849a3eec7e06f89fcb18cbfe23184025ff075dbb6ccd4d641d6ca60447be58aae4fb45", - "0a05655044b01062fdb5904a43016fe54ca3ea63e79c874e8bbabae0ab46293419a2819958c495feffa49ca31809cee03de8c5509fda060ecc9f54f19660e03498", - "0a0273afd02da82fe11a01ab6fe5a102e9d1a6fd4d02bc152fb3efc712ae16d5969cf80caef19eb7b1fad3ebdfbe221c1b163667bd33088f121dd1a44be4714def", - "0a06d63de45b8b4a40a2837aa2cd04e58dc5b065d0e88c434a3f64f061fd982855afcdc0e04528723785c213ef3fc51810d8c2a5745d912d97e4a28865dfbef2b7", - "0a03457126889e5042db0bdcc9ff52abbd980738cfd9ec6112428c20a6cb8bb435f650c2a70b2d1c4f7e4859985c2b111d9db89ec1354a01103d80ae3916800d52", - "0a052a4cd63c0d90b1232f22084d55ff3f9f076a0331af19590c550085b1a30ac3cb261847ff1a2a845b9f4c733e7391df80db29c7f2f67d03a9364881e74340d2", - "0a017a04e81cb61c29332a4ebd7baf359ff34010207b17c2c6a3561a5a2d8fb184d5b0d1f631e51da21e6ae086bae6da07bc81f465166a1e3cfe6915f35a4ea361", - "0b04fc29b5c83301f4386c1a0bdd411aacc320718e46701332002e0ba18b332f2b4e8c99a471c480f242fc322ebd39e88291a941b86ed6dd7dda23a7084269e52b", - "0b0305e75fae1370aee7fae19f2bb89fc92988dd15530ab58698da84c0fff4039ad648dc9bbf37735b41d47902cb16b6d45d1e571e1bd1a5085a5f60a8b6bf3468", - "0a0744ee6c65e98106f01331f619fe98d83fb09ff94429e6dfa5ddde47328bbf378bd7f23a5692c288db859d45e12cc2e952adf4b2dfd266cd21eb76378e0a70d5", - "0a05cc589a24a0bd3e8f95894ab9df8a1df9f60c5d85c8c9c2d73839ad7ef920ff07806eaba42603a2df7b4ccb0788615dd33c6a8fb2e53046e4ecf6c6747e015b", - "0b039137f7379a37659c31201f4d80503bd0936158841efb960c81480b5edc288355a64e9a517741bc12053a3c651d7d5fe7ecc52ea3f5970dd6aa845026676751", - "0a00330202c8be0fd8559ed80ad7438110410167148ff62d5d43ddd29ef19906f96f7cb354a903b41823ffaac0f5adfdcc7f5ef6927f30a077a369ec458f773f81", - "0b087b59ba552c0bf8f0eb4601b20a9d2d212358ff43cf0ae522e0bf02850016d708e91e5ef1321b2b575c80dcbfeaf4bd54df1ea583763c7e90da4a9f1abead27", - "0a04c60d8bd49fe85d6759b6da61e6972c64c1d263d0cf8d0bb09ca47b5226312867e3ab7c2c8ebfc259152dda61b88282a027b321a95c9484daa8d57684bcbeb3", - "0b082fd993d36ee673a6ea29d139d6bfa0dce6c8efcd99c5520fc439b07629936d49c2f0892dbdf3f90797ef221536dbee429d61320759fa3d4563a37215c8acc9", - "0a05a0ecd230eb0bc7febffe4102c50b9905433b208312838d6a8c3113379ec8edfd01d972ae2585e1c8c537fa28f49034cfaab09ce24d3fa1063015c1c8eb24c5", - "0a03b0bbd62654019c6ba45fcccd5116621318120d68f346d8fdda7d76e4f63e2372009d792cecb1096e3d7f19fe5fe435d486ced301cbe12ad56b67a430977cc7", - "0b0375de6fcdaa53c495a027fa63c82328a30d7ec2e34b8197a8e36bbf5ef9c11ae02497a2a4c614284301dd4a44d9e1f44d0f2cd7eccc9eef6ddd9d108d6282d8", - "0a04d5d8f100376cafc77ae3a10d5752f3dde444088ac86ff34144931db69681cd3cb211b7074a2519c8cca12521d1cdec67ef0a8e128019c4bb14f9824eee7de8", - "0a072175eca8a400068d806a6c997c7b65bc29591a5bc8857f404ac953dedc4e23321f922cb48f56f57f23fa119bcd956323215a45cc85fa9ab83e64371ced2f3f", - "0a031ac51d77872d92eeef37ec723be8bea6b1eaeb0b12b358b18cd971e6002f79b90f976b30e0df0a0816a28c3b5e90f4d41a0a28170b0405f13b192083c0da27", - "0a00dc08665bbb80e77625ccf89954c5e61b313fb5f08814823a994ff478b6c3ec943f133e279d17a60c4f19304b0a7c96d2d33411879c8ae8e88981323a958142", - "0a03c9c36f0296dc0483d2ed2cd6f24a4ba0b8d4a1d3dcfef2d4f3a7eddc74a3e4ae86b12a690378df23226b6dd6a216bb70d185e163ca3a6f4f0c78997b21d65e", - "0a09234098c4d37e8bcd273b0e34d05d7ed2a75448269e6c982945d6292aed31a8293fb225b9b1f5c446b6c971b2a5f1406905ab415ad1c7163d11aff8a2c8bff2", - "0a08325d33729361abc759e88f4169e82413a9f3b3fd7bca92c8979dfa535521a5f06e419933c4f03c49c89c2afdd076f4b1c68f1ea6b59487aaf45b302f5e6e7d", - "0a0728debd4864f8ac8b8a30ea3d17c8e123d463612ee637c61c13dbf011bdc2b28bfec9d982b9275634cee1b9dc7a425147a6aa064ce38685a312b6668fcedcbc", - "0b013afb05c645c2028b0a0c0d9949215fc95f033f035b239311efd536f3b222798e486d09940f211281a1c005b47ce336e267331d958a834504ab6a8510a66afc", - "0a04ad191ce6edbc6ae7f5e86d18d8579765e0e5db2b7d13cf78b2310488374946faf9e35068c289cd0b2804d9c6b385bfbae5698cc20421bcc731d6e0928d8f2c", - "0a0225f6654f51242394b49b5443fb5aacdea5e9e310c7643c27f577d7770e7c326abb5f34b52cd189723883a5e085032c05ddafa7c5029ab41a488e6d3395b222", - "0a04ef1bdf2409af86dee39f5d3802e0ffda7a788a2d1ecae225e89cc4f46358db4499f4747b61c6b2769ade099fe249cf656cf249b034f348949b74b9c0db5699", - "0a00ff8d5096d45fbaae350410865a075af54d3f7571a1d1bf3dc41c969fabce67d8de58bdebd97889572d8263f10ca111e6c768791edc52b7f831c4ce2d517e4c", - "0b02569c58730a5c89a31c728c405166b7579a24c04400eb467095626851bf53fed714c010fbce6b1a202282eda62aebc8656c701c46483aa189109a8d4438ecf9", - "0b0470cf8886281e1e659ee8865dea1e64a4406dcf0ae467659da6be1b06edd3c3f565738a91bc1bbd509ae931de28ed8b995185b5a68c226c9af8a54994029f07", - "0a04d79a13611b87a5f4b409ee7ddbd471923a7c57d92e4812b96efe9037431d11973a9998e5b17cf7aaf33a307ce29ea8db51a0c1190f84b5e0fef6164ce431f5", - "0a06d2a9d9c472a468f5c21d0d1cb40283d796440a72a21141d0afaa434a8cdf7dcdf5dc16fb37473115e4a2c69f22fbf2e5b22d8e46b925b8cc6476ef35844407", - "0b078c36a062449633048d6c01f182ce4071325afd337a4957182433a8c87dbac30032916b0ded116b0dba1e0cf8afed3dc1bc04a9c9da6d595dc87653c043f29f", - "0b01be0050edac6df6b089bf4976beaa9f2073173eb7746f581d3c4362325aac694b3eb1fe5d4bc85232eba66f720326f7e4cdc16989376c32bb32aaadcd556e4b", - "0b039819e7a26ad964b1008dcf6a27d9e06ee7b7fe7860fbc9b08347c9fc3cba512ddd8f59efac4d5f1066b19bc14132034d5a050951d787466f2274610aa72bdb", - "0a08db6a38481a15311a1a4faa9a7df2027ae9dafa39577c100deb0f459932ddbf06834cd2c5eace099e9c0f0dfa2784e16f217bd895019ec54c69984398e2c7be", - "0b090398469cdad4edf7621c3e2cc0cfbf3e113bb64bdf8373c03594a3f2e7de21fe9734da39c3c971b529b5784cd96ba033eadde43a3a86082d61e02558249aa9", - "0a06ab714ec8982222e7260fe9e42adbbd9df5d22d4db796734978d778a6376581dd21a9abfa92c1127770d76b7615c9bdc914b22e10c079bb3abc70fea018ff33", - "0b05d520d5031f8a856b0ed79923f4c688877100343022d52f7d277dd7b95076e2873fd9c3676d40041fef76ce7975a2880e0d02056704f225d893594d65ee368b", - "0a0696a3cf742a339e4ac4816f175279a7263e6e142e1b7f419ff11eccd93968ab9c6d68b5cd49ccfe22c09589925e6dc8a969a1f94c0b8e436088bae4a33acf6e", - "0b037481b0263fe9add7bcc52f9868f2b0732058e3466e8eec064c59ddd9a8ca697e17eed291e6f37794eed25484993293f6a053fe9ccdcda5d582d3afb6d9d427", - "0a049c812963acc21acc783341f656deaa2a7ba007747a357dbb982a61e7e0ee0269ce3bd2c4e0554cffb51b6a5a1dba4b5fa4457306718262f721cd5eb2d0553e", - "0a058f84c7ae4ea68aa0e1bdfb6ec9fe42884addbe10b117b7928901307714f33c1422e6aa44708f2408d6a4f375c40318367b59f7124cc1befda72fd4eb67d0a1", - "0b0240b08158e4f6a2172bbc603d17fefa44b5dfc09d1a91b888a882832f99aea083363af1d5a23629913fbfe56419dc1b535592c1e468c0dcc899f5cd6554ec02", - "0b0502a87712c9b85c721a6fb8d9c30af0e57c3a76564147dc8a2f3e19c29d55c2a7f80c7b6e4bdbd8a8b29cdf63355cba7479fdadac66767087d9c8541574193d", - "0a03ad922c1ccedb412c16a4c1703118bc63d8113520fcf2db2789d62f9f65c7d0a8a0cd97efc003b1c1575fc554c08f598d2369c166f3f150fc243dc4a1659445", - "0b0256096845a0cc0d471e5cf745547949ebbf7c7ed8d9d08c8c30752ff024e0e9222b67510522333426a3409c987b76d26dd79a55a20aa88ed787244ce9f59663", - "0b00c740ad1a077fa387e02a9efb37ddbe3b885caae8e3b72ce44438483cb708dc6031be1aa4f33748c34860c96ef641bbd02540ae858c9f5ab4df7bdd402edb30", - "0b0348c4bef18b4c252e4b5371339c165fce47096bd38d1849202eed8c01196b4aa861325d26cdd74ef7773408c59655b97283127fbbe2a82f3e4a8f0b37f31b94", - "0a08d2c1fd2b4ca45bc9a005b73e358dcd4956ecd106b2b7b1d4979b69dba34768c3c1c8e85d6f852e5ba7fd60562ec7c2aa68f516f563f9c30babb597cafe1058", - "0b047dc140c15e7417f12410d0a6d5c8249c33f4ea01caca144cc423f3631917601d0c8c9df9e8a4f4ecb8a641b702cf0c3e8c80884e5955f63aff92da42a28ed1", - "0a08ede645b52e4559e2e5f35acbf026ba23b918531fabdf52110e37a50d4a6cbf942a8bdf273d08f4d167ff7ed2640640aa282e30dbf82d2d72394554d9687a07", - "0a03cc71814650b1474dbcbb860d2b1e3c97b2250ea47859e6983732017a96e1fd8dc269d7458765dfa88842fa89e65e9562356feccd867145dd4a82c49858ea8e", - "0b086433abc8ddb83e707efad168c8542eb6367c55a14f3c206b9e16790652cc5f2b27a91c9ceaf4f1711191d49cedc38b15d0ea13afa1671f2626236157705441", - "0a06b100a2d175524455e85efa2c985b4b31c68fa55c713a2697a82c6067e4af9910680963a1b8942d549484a1486433f1325c9bdea235e8312b96fa06d8b76060", - "0a01fa5cc6239931b050dfda1ca459f5b34fb6f3eca258c423b5a3b6e9abf58e210bbce49a621a308f8373bd1b1648da4be1f3bfa3cd899afce12311a9ebf5bd14", - "0b05455bf980c36d0ccb955db696f77f72e7d4dc47a3128249bb5d2b2bbd67d5473f26d58bc9d5b23a5d70225ad6dd0e19d8d36a20966cd815753187929eb119b8", - "0b05b0199b81a5bd83e452ab3f1b08ba7cd35e23ca9c0d6e53cfe607fd239bc6bd59cccb867b439f431395b51f392a6c7e5fe73eae9f8d580b1c1ac2aeca56d714", - "0b02614c52f8dff998e098021ad139cfaddee135ec26e249eddb0cba9e122fca7c202f648fce7701bf02f2f31dafbde53ee728c759b4d4c23f7466c776a8e42bc7", - "0a0215d11530e09e7eb4cf2212c3bc1743c40bb5bc3e5078108e467c5849b512aef450e1aa2db97716d8f51433e2140927457d3f88aa7f930d6aa6b48716204d05", - "0b04e3fce1379a9176f7b24dfd4392f6ff061e0eb6a433f3d8353887b560cd0791a2d5304ea2ae15aa90f9a917e4eee167d5ea1c415dc9adf2d1426fd979f88da0", - "0b0815ad8eb28dbd1450b45efaa3e4d7d960b71e95c90173572bef45af4e1b7cbac3a591d814d65952c0d75991ee4bb058689de6e523e47a571819faffd7a8740a", - "0a035b19d4478e562ec2ee28ad19825943a8673956ac692797d2902b4d51f50b99f3016d9b0241e3e11997c7a2687eb03efbacef52620455134fbe67d65d669f23", - "0a0126f9fe570f13cd283ff3c58c16a47b7ca97805f8a292fa912e11477466d04c48960405139a32c764ce5499f4b35c63e67225bf1bec6e87eb93f1e0ff481bda", - "0a0585dcf8a0bfe7fe7b9b67e1ad2a2db6a1784a633a85ba38c2be34dfd9f76847b17e090e1655827114c5f7d04a82b430d092bf6149d1e511036d177521fe95ea", - "0a07ba2e1757c9a028de6d63b3f34b8b139fc9400e85cd672b828ac44344f669ff7f0277edf74b8c132bc632d621ccbf957529addec218759559b6e07f4bc9827b", - "0b00456d0806df8ed157d337bfc0c2d55b1e3bdcaf3267320424aaf3791435fbaaf9a52e2b6c23e937b9ecb4630dbb4f929e8fe8d68a949c547e60afcbf8884a57", - "0b05d8f6f53218a03beb68120a00b44b66999b1276095b721a814140e43375b191ce59989312440863f7071f0b8f693312505b9ae3e352e11cf0d08d97d249d233", - "0a031bb5e73d7bedd94595d39eaec70ec4f9f394824fe69a1e48063fcd9cbcf4a86b87c9e41c251c66d1b1b3a6687afa5b2ffac124c031175f479215b55dfa345b", - "0a02cae287af69bf584a1f321b0982fd8de2974c2ac748922c4d16cc93e118c1a076f481a14b16e8d4bf4cdee0ffc1c478bb9d134a8c286be714c882c4100ff1bd", - "0a032fa04b0c6b8cc0d89e25f0b5a9091f5e616ff46389cc61c49d3c5b722bd6d2632375ea610dbb6981b105722f63074ed1e6f3ca8690129df119687d695d731d", - "0a078b5f940d1adafc4a4f0225d4898a4f81dde1b7f89461e4ca747acc2dea218263ff6b49dc2a6dbda097182a2ec56296113df9f110e700c9837dfa0c81b9a054", - "0b003cde82ff28ff30473b1bc8d9b861ad04e612ad44d1f0802d1a3f52a674b71b730229e65f43c1a3146b43f6ffc3f49e6166ad971ebe9ccb7996cefc11f6fd70", - "0b072dfcabe51299668e5fd3ac3dcdf415c27c42409403bdab11a9ed6e615536d8b36d7f2fd3ca235b33ed3fb4a1495679ec81b2de6f7331439e901b0abdf94ddd", - "0b00390804cdce57ee287a40ebe9b591a181cac1954865716430da663b6ff0f63b9fab136a4200468fc56ed31a13402e7b56875a1e155183676b96c12607d2af42", - "0a02cd6ac947074bacb15502782ebd92df976db12035ab53d1b41d4de8e63830562423946cce76b1ba30c01e6a582de0b5146482b592b199372b053fdd14073260", - "0a078881ed927890c5a76486db259c5bd587c1d802b6dc5185bc0d6b9b5e1e0ad77e12e65c48a5ad9368591d59a5505ff649126743546d6f4972ddcea1236e5943", - "0a010a2c2fe76a2b2468fcae5f9f7763b7584e36c4e3d40e73c9445c59830a189ee741fe60c6378c8cecc20e588d35544f01d80c91d69f33b421c424786b2c32c8", - "0b056c7f0aea5e3b14587cb8b1092a5986a67e00c02c43a7dc5562a7bab29e950a9f618286bfd4f37f62fd322e01349d992344f28301af66635bf924ec299653a4", - "0a07004d7c9c5d5e74d103f82d7cfafbdbc5176edd5085387dbfbe5b81e8ac6434e994708b2edf9df495b5cfd8266b468c323a7640483e2eb963dd064a753b0c71", - "0b0198f125cddb7f77d455051dd6b59f77d5c3309f820d7097ed652d51632576bd1d3891d1d56915cd2a4922ec43517569823b8e32e0e0359b82e85a4f578103e7", - "0b03bee14627c0af2e9a3c17e35b983959e56dfdd8b985ee930e9a80bd8ae0e2856c97f917cd6842c9c3b6fb260c5e59252af6c1c2ca0466d23d14425ebfcde2ac", - "0b026632ff53c20a6a8d7ab12940c20fe9ac317fa57b451f868a0bfca23ba28aac2d395de77fe6e860c0e9106317cfb87f57dbf280b270f822e702564a367f5266", - "0b055c98db855b82790d344075093c22a239d5af847eaa7114e8c8e55872eb7e9139fac00a172255763152308a7742ae91c278b635b48b54c8f2708d9d80d50eea", - "0a091acb49eeeae1bff2d360bb8985daaf42c0479c4ad17d6c1ef1f7956cd9ec8a700976cb6087430a5f07b8ee6793934a03b2e04ff52759e39d4b261007fccf80", - "0b0503d29339df2b367a593fc60ebcbf4561a87188de555b423d97629de4342e21c0b04a991051e09c1e7274ecb0544b7145700f0a51bbb32acae475201b7212c2", - "0a03ae143d9ad658a7e765803807f40e9c479083e4a962608b12119b9bc8dde4b3ab56ed15c50996ee2362481ca79e56e2c2d90dc21d038a69e291e7c7a16f7ef8", - "0a017b1f0226b91bca355b4164df8835f15f62e329e03c82ea0bc1a1c109c775113eeaed3b13682c56d97bd92805c64001e17abbd8c44f3730e1c0d8e54064e158", - "0b0891c6c14ae26003333b7c3dface3c9b2e79c16a087e5a439f2b7da684035debd8f72870326e619b221359d424b7632e8a5bc3465ba0a81077f9ae5be1b925fb", - "0a03295bf59379fa96ec597d569617167dbe77e5ceffa61a838bea4a589c8e909955e5168956ab9280f54985d1c0db199c95b74fd94767b28425c4973f8f78bedd", - "0b0388854b9e8936656e42a89b4b8c47753128dd4984e7967382bd3781fcb1a4479da069cdd9a826f118b893cc48ef0576c96f8c6a2c923532c423a197814c82cb", - "0b06a68e228bd9840423fae2a52b0fde14f526656330f18142a8bbb88738482f06311436287e23a36dd64b57d8ae6b53381d64d3c8f192815fad090c1b53216694", - "0a02652ce28cfff32a7a26dd70e6b6d5ead68f7322464918ca71a382273145e7db20f188d9b978d55e956f9496734cc70381fafd04edd7adb1c507fe2bcbb3446c", - "0a04ab6bc21ea81027d35ced1d2d86a6326e798e2269f22dfc1811c8cb224a5800bb7818edc7fd81ab8b3a05e3b5be14148aa582c089852bdc5e346756405b5969", - "0b05b9a3f70b5d01ed1afe09b25959008344fcc137fa9d5e55834efef4802cfc8af902e1b253b8ed615d86ffc6daa1383bc6ff6b3672ff38e44c4f59db74c0cc53", - "0b08cb75746fca98a30f5e69aa6942edf3b2fe86eeb121baa899b6b79b892b8e657ebbcfb8222832be6c1a49d698b0e11284fbca4738f925bd5e3b9ecd83d29932", - "0a07a14beefcb3d97f30989bfd5068782bcfa305314b36d338e768b9e49ed205403f725f6398d517e28fdc80c7c366b4363cbb4747e22aa79b6853e2c3518ba868", - "0b00b6e2b2250f22fcaa76588e6f0bba29f062d227e7647df7261e3791db50df9184c4168cbffda8e561c4678944ffab795a9311c5ebd0d4e75b4268d79c1d714d", - "0b0603d2dd7578dd9e1503a339265102b35bd6d3d747d6ba8124f4693501c7405bb4652a98d440313b262c60fcdc8859ac0601b75bf655603c7d8afde537971634", - "0a0780ba78fa6378fada481b83d777523e8ce3a72c21558a1107340cfb944847fa04f1082dc6bb624e314226dd5bfc7f6389d76ce5390956d244dbf9a317ecb2da", - "0a078d37bfd8e35c907f0aab67b8fc343347188107756d5f69bdd5fa25143372cf2bbe056e8d5afac5f045eeb7dec03fd904a5e2a956c7f4ada138dc75d46a4131", - "0b08e5eaa7346aaf89fdc2f425d7306d68b2cbc2f81e162f252debf27f9ed26128840b44e60169bd2a79366ea5819916936a940d31c16e78abe4c4f14a2bdd862a", - "0a0175f3881a0ef9055c0a94a2367dffa6f0c6023882906889f576cf52faebbf96e502de23bc47d72609dc7e9a5ec6508e47f04906312e9d21e3ba93a80ad2064f", - "0b05583cc7b73674e927b83ca1ff26297c53ca16ea75f4798679365413b29f2f5e85b7de425c1c9a57fac26a67ad44f2e994821c999a94f28d09ee0eeb00506c5b", - "0b06d2dac7246dad4dde52f1b8ca16848d39603dfd7269559604f1211d4a38e1dcd2144b563e514786d44c1e97b062c89b4bf5d7f087588498effe96877b00041b", - "0b02d9246118de4c5fe4767521c880c78ff468b3519d4123ce5c9a23d3f28beecc7bcde0455e297ceb322813cba61f02bb407ca6b7bf38de5fe8b896f5d57051a3", - "0a02a5e344c13176188b992b7bddf59f7aeb51900201ccbd53f8afec96cc502cfd78f8251284add44439e5a792ec330f4d5379b0d310e16fc707b0db861c20c419", - "0b04dfd16a53aa13c4885bd5d391ae9d410ee55dcc5717a59018419d4565013949365109ac45034eee1868d662ea76d2a231c692b692fcbd71e9b1d9a950fe6f95", - "0a035cb3319b1a6dfb7039434a435019c9980f73b4103156d8eecf15347130b467172bb5c84e6b0d093aa6bc312d24f33c5364a2b002f66fe0f58be579309fadc3", - "0b072dad01be9abe38cc339a5e1aa13143d1a1951b554f40a148d1e6506c4774e2a3b602291ad934d57cd565fe1fdb19ed29310fda7b86079d38afb31bbbfaa154", - "0a02f6c566488351b3b2d2328f0c029c007fc2008433bb6f04f0f54869a34ad3ca7a3bab81c89ab6f9bc299a18cc6cd663e95a991d88aa1faca614298c75050a2c", - "0b011462989aaeecd901de663f3ad03c49efb6a47c8ecf3281be8df386e254bb47b37e5333e9eb7c9e9c65f784c78a2a38bf014526bf791c79a50c2068a8c5b204", - "0b0789101c0812af849c7a8e53e242970f8e4b45d1cb7e0951f9d9f8e0d383f7f9edc49ac979935bd77b1652a9d720b25f6857125ad458f901870ddb9bf250f820", - "0b06c056d5a1c04c04fac3bd763d102b453a3a50165a63dea63a844260f8778e43ebb4b2beb0c021799cd39c085a38afd01651cab1c8301e5ac5a29025286736a6", - "0b01f7acc2298673ab19ecbe64a6e6d162cd7222bbb8424aece7b2afe06baf3d6f712ef4822df34d41e0d54a871711494f32d0386f1f5b354c07eb28d81729f99f", - "0b048bdd0667cc453364b491eb8eddbd2e90451f0740b8711506339988e08e85aee84fe8b9b94b3e9ee28b6bd5e4815ce8373dbb1beaef43493519d518c8183933", - "0a003070e223fabfb27cc77b375c8533649ac2ae4d30193b342f98c182771c1252c226f6f12793ee314f5eda2051a8e5758eff817e4f364096672dd01121f5bc13", - "0b068d92fa1842efe2bf034bbe640e74d056bbba0cb5a7aee29e1ae2726ebca4823e8c627a51fd13c90ed0097b2ca2ca38b53af1b27d6a400cf365489c1eb6c880", - "0a04f0d8d541755c6f3640af689aae37c4e49466103583a031c19204063f6429db44f15d47ba2dee0431284a667bb6c30fb665d8bee08920abee623178ce3ccfc9", - "0b0690b099060ed27031b68389ff3d1f3923f454563387b364bcf02e7c5e88a50a14ae06ab2111f38f8a41ebe3ecc1733ca6f378589446bcd9f3c2a82e55452d43", - "0b06a0d3e0e8a673068ede845a961705be0c2e8839bf20da028f1423d57762c7b088915fc175cfcf7645890f3993345d613ef15dfb98451c084ca011d009674582", - "0b03ea3616efd5dda21fce70c608e5a6a3b6d9731f3f640055c3f664df29f6c07a19055083eeefbc080be535996b2ae0ede39a5593c16ff626c426e3e7a8286d64", - "0b001805f8afa62595f669994293cba3404ef763d5b8086ea7d1a1159218df3cf28cc61b7d597940169a8b20d377bf8c9150d56d429bff955e381995b81e01409d", - "0a088372a599092fd9e9f542c9159e66c935d796874a3bd6f12f64111a9250327549312c714c844622ffb8bb7a8dc7f830f781d580c7e8d1d07945634a2f129511", - "0b07c3240e46ebe36965406501b918e7adb0e302d738dd0d1eba025f411cbf057a7edd97a467ba8a85848b2a174cff3dca0d70e99b63f5f6240c1059590b749991", - "0b03ac37cfe0d2b490f8c1ffc0b47260d746047fc7b8bf974818d2c67b5323234d278933ae1fcf49bab50fe8c0ea2d2732aa51778354f80c80134846c59d8fd1f9", - "0b0681e5d3f250a382c5235c3a49e165dd71055118736d7401444227d589cc24e701b5d2c26642ee0730679e16e655f032dd580c00d020ed04011702e66c47e654", - "0a0215ff7931fe44ebaf1a1dd5960ea0932e6c0d77bee19fa3f5ff1d0c42629457f4a3ec1746b3e151586a8096c3479f860af5e5d6d8d6e37e58b2bf8ebb19e65b", - "0b07db725b7395e3e1d773e96071bba53e70e61f6257f3b0646b97315b00b2e3ae69b424fccf2e696f3694fe2ddb0f3de5c12f92593ed3e68d4f96477f4bee4025", - "0b00b4583b4a0d9717804627a43c1369735a5e8283f09ba2251adf5af46543aa9c803751339aba6e6b7952d6d00dd61befa0bcb7282d721f4a14818c74ff2d1a66", - "0a0565910013cbfdfe4ec54fcb2bd1790a7c415b0a112f4e1ce46aa5bdd88729e4f5febe730981e9aa26c0da52fb722f7b76323686ab5f44ab563a605c7c97cbf7", - "0a082fdd96fe940c55787a5c0cf5bf61eb37234a92f67d6ac87be3c3fb537f75c44f3a04a413de0ab1d41378c4638f0b839e994c188ce8cfb17bd2ca94f4f7e13a", - "0a04d310587b3cae9ef839afa12d7388466570b3c41c0c18e2e020c5eb42cfd086fe4c6d2db20602135e933879a9c09b5c1ea874d4d0bb48e0b5708f4cf42a46a3", - "0a0750fc1fb6d40a905076764f272f70989fff3cda07e4b9c51dd0a6f16c0e19305e3d9cf978596d43ad3dfe63dbe7ae7b5dacf01db602c7da65174e75440b343c", - "0b04b23b57707168bd45654202e381cc9129ec2e4604b332c516b8d914d8652c6ad6d781d349be1d5eaab01f595cd2c0971554133c57ba037f878bb4999c69108e", - "0a04987128b6ade9863faa55762e39a829ca9786aa7e6366cca84120c330b22fa38eb498fc56f894676578323b02f612969e01ed1b25710e98ca528a020b85a4a6", - "0b05d457b62170a2c5f73c596795b96f6f10fd229bc280c8df0b5530a80068f04eb4d354b41c08bf0c590a1fb65a9675e2fe07deb8e83ca82e4747475be9828ad3", - "0b02243ac370dd64dd1d829935bc59d75b05d6fb169603625056e17b6d489461eebbc6a1bedc7b457e5eaf5ecc0ab0536a3fbccbc848e532c5834c87b423343250", - "0b06d4d4d22e87f076eb90538b43ea11fb3f48c7cbfdbcf93410e1b86f10577a88471e470e02675be34d64fac6ce6cff985687e5c775ba5abe64f32f35a86009e1", - "0b020c710acb6406b338e6f2a934a361084d07b0651117eb60dd42dc67df6463fc875493ff436df21ef2693130f2b1b7ac9a8e682ca7e8213036baae5da064d322", - "0a01d89cc1d30833db79dcc7820cd9c284c6d639b046c0f8ad31e7a81fc96591968f099d8c0a27acdc841b6d9227e23e810039a7f8f6044609704553f5ba653a72", - "0b02f2d43e6623c265fadc99a10ccdf392cf7bc063e6f622b7ce01e2b13f35381d4dfa81d396eead11fe9b8b30e6147983f4528e268ee7a122ede85ce2ef69ae89", - "0b00301aaf526e5b4bf0ebbef420e9e2cab5efeb73a470c49eaae68faf182115fd2fd5244fe5035bce5a9a063b2222109fcb3ead46d2e1366c434ff472c5bf4c47", - "0b013e7aead137bfaa1a8c2cb041b54ea11ecef3baaae800dcd14575ecdc1c550b7eca8bca6970eefca7f1d90e2ec1e5146bb63244eb70af6591e2282d8b8d1375", - "0a00c99ad48031c7506c0520fb417e6e869e2f80e26e25d13d78496a52b90da6f2274bf4565e47023f64524389a64ae81643548205ab32c1217816ddbbd4315be9", - "0a060c325dc930f8cf91335efecb541dd98b513927201df9bc8d9dff16f034ed7ee8c3030e418c5a7fc7f6a92442344f2caa01f7c1229b5788498743667cf8fb29", - "0b08fa1327ee770dbb99dad83636eeec9acb95b140071a0d960df1271b6749e0fb41d5becc8a42548c6b637702ce5f53f23ac436a8b5a1e55e637810317979ea64", - "0a04aeb72bb80cc674432ac87512b9b0139b98ad453da76a04f12c8f6f1e5458417151b02b9c3f1d139cdd182b52697a49aa9e3861fa68697754a9aa4894982f30", - "0a068931163de1f22166f28172351bfb6b2d184c9b498981b47c8ef9cbc4802ce021abc631c2d5aac8102cdce87ac72e18503b7a94b189268f4d6e88f388c84340", - "0a02c4945845b072ca6ca694f8fc3f7e3e4a79821f070aed50b2b80f58ef11e6abe692c84f1774a3c5ae4d8da7505c87bc4c13d197aa86f93bac18ea2bd6ccc9b3", - "0a04fc8665d8b8d13b2930e66f8117a6a2cac7458cb448a0184a8cd3d3094846ce3e173b3ad4506d6bd4040143c5af9621245a1a9e4eb4bcc4f3132ce5131ee48f", - "0b038dec2c3f027d96936ffaefd2c10fce83bf7067b98803fedd4efe583afc869c63aaadbad4fa4b1f715171c7df2869d7ac3444929f63d8e3dec93a3590695b17", - "0a06d8c6a66e35c036a814c9ebfa3e54359647ea78cf717b80c0cb3fbc2ebb9078a649e11885d9b45ae6113f3b6ee612257662dbf1ebb345e45eece2c841c1a1e2", - "0b0122da53f89c2ef045244166a9f26269af07dbf3e1e320de459bb302dccbc6e2f6fac567a3f6e36a504edfeaa53fee69b30cf189c51b9d2d8707f3e9f3d9f2e3", - "0b087b0657499fe905a846fb2ffdb8e04fe618e4f62315217cc920e20ae8c4101bf0fed1b69bf65bcef9ca4dd08d87647c09799862738b0d94b864c577ca315e02", - "0b013fbc601ab4975f08cf653b4bdf5d1dcd4d731579832a5196459a8072768b1679ec494e9e678d14cc74af10938adcd00db544697434628d838ce85aee5e996b", - "0a09169ea6581c28d6affe854c8e5a25cc8a60f5ee4628543ffcb6d34031f9565b9ee965837fd0e8fc31069f76c6ff8600391376a6cde85a7d7ce5beb76ebea893", - "0b0319c348456d8cda9b04b3b987bb5cd1971f7f5e6416700eafb001eea3d9ecfd938d98174766595234a46a6b8b8977426be416c32bf3ea627d323e1c75ed1cc9", - "0a03888073a76af97b2a900b6ab15083d1ab642be4b7ccc90d47052b5d73e41bbdf868cfc7c1e8b008b1ad62d605479d53c0b46fd3865304ed16879dcd5f76646d", - "0b0452b16e5a4bd699a048418dc902a2c0b214de9ce444fd50d77f366bf6fc21dd3960ce807fb1ae983140dff08eb3cc502f4b09388dd669566b3597ee3f9c7255", - "0a05258c3e218bc178079a8d7d03e8a7ebe25f30b0d2657045a0442f750d62ff2c7c2723a8e04285bc49a306438e6368be0b7cb68c97c2b3f552bf4980b4310749", - "0a0542ed37e2f7e403bd672ae3d34e38b295437d5176ca5d36f9166e25960fddc41730dc5f9fe800ff733cc99b4967b458cc3ad21afc44781446f8636ada867aee", - "0b00107575c4be30470e194ca8b99b5b437d6de3ee0660a9f2170f3c858733f4138af97b7850342517865858cd0aca4ac30e69d345360dd54b67e56fc27bc44d6f", - "0a07be963de795e6680cbb6f132d91537a1f0157f81ba5d199c6f6eba08ef2f6c07348d9b89741cb0881d1f1c7e2a77954549e07c42d9ec2dce9e2feb4e57e76fe", - "0a0597c78219993f26f1c091320c5db91e098ba52f46d3d6c7290047e59b08e048787bb815c69f8159446bf0f3c966394009634188f4fa36f7597a29ab0a60b169", - "0a00d1356938a480c9f687b560a92765ca925bf7d1353f021537ce6f00f6b4baecb2d897a61fc12a98a7f9fe00cd3850b46ed49ba1c68b0cd3682981a584badcd3", - "0b020fc153fa22ab9aa4267682d2319e03f71477f38a9287af8d5d5dd4193f9a452dda669c400f5dc9346b093f71c98e23ea96a05aff4a7fcf90ffb333a69f421a", - "0b01a5dcff8cb9571d98d78f50b764651baf55878d0db9dc00c0773bf5a2bb12de2802b3ff0e18e17e673fb84b4a716a8cea6ad7800d82a4aa71f9b037eed9eea6", - "0a00afe7f35f93d660e1911e805a4b2acf59ef1059996b02b1c787e704ec389cdf78a6a8afd660ef691beb77e62e8aac62a003b6536f812a608a73b791e7751d34", - "0b04199a9b53bf8cf3aabd155ec9fcec436e9f6c305a86ad06e4062eb03b0d27797c79bbe308e6256f3efeee897c850153c31bda9bb689d2106ea076a02170ba8d", - "0b07595e7a43b85126422ef831b134cf0e6ddb6741accfc7fc533b8069f0926e9265074bff78a8785591ad3c773d59d47786c2ec20cc988f68eb266bc85d915fd9", - "0a0646247d473f84baee84a854f976269bbb79dacd6a5588ae975566d765b47da96801d27cf6bb19e3676c3d0dffe7af35f9102729ccf520f34c48564cf6a46874", - "0b012713ec311548d4c0ddcacec36271a47bfa5735ef232f926e9668e5db442f50c548f14ae47cca49f5f3ad8274c9726f27f3e3b936a070a58670327717214b77", - "0a08aa445bc9c2a30c0ac2a066e7111836197cdc982d72c3032116375e89effc2f9ee89d0b8517b58310025857c84ce5e2823e58693bc5520f12e7979ae32ef23e", - "0a033c172e3400b986fa91b56ba89eab500046c04e3676999b26753f89e9d9e67d608f49f1f8af888bb95f3a36b7cc947d6ecdf6070f29abaacbe1f84294013c87", - "0b015fa6c1b1294c8eddc2310678840a261eca3fc5cf7aa948169a35b9ce7239ccb51809c4d0d2c253cee70fa1ce07f77eeb792fa57e8ee9f307869d4c89cb1827", - "0a02bae8b0e1677f646bf144118af17b012add0b65832a304420362b7d37a21381a2f4a2c09c3e51ee197074674730b4b20aa9b6ec2a191ce5b2d319e2570043d3", - "0b06ab79fdd48363f6bc5ed9330ea3974b82889dc8ac1f26eb00ea0bafa97112d098f02d86a63c438de8d36debfbd90502ce0e271fcead4437b603e2cc491ca930", - "0b02b12ba25aba33379a40ae889d7db62f259ca356748afa73d43a88aace25a1f945c7a30a298df9ea29ebc35d38d9e73367073f2997b20a0d1a2e7a027c66b47a", - "0a066cdf0e4350247a03eef9eb28e401e45f380b790100dd51d205a58c9b0f70ed619b995d7374b91b9f36511eda45fc7229c49f068042031446d60627c1f09438", - "0b022101d2c19595982374cc264856ee84e95956db63caff18910d138f1f4ff9a6501a8ccbbcbd73ded760a0c6d9c85d2d363b66ce796335855fefd5e7a28a9ab3", - "0b062f48c14f3c569597c00ae8426fb98f117fc7b76449f7a313b65d23474185558a1b3244f368a2d9925a8794eca2afb17d1fdc05b7f069f87bcbbaa7c56d0157", - "0a0262e4e075d3d74cf4dc7b3dec5aefa761ea33d004fa60e13a59ed0cbe541c8138ffa89fb796707554cbb2a36396419e9a18a0f39b708789cf6da8dde128805a", - "0b07188254d384d5afbae90537cf9a765ab4c0b925f241da515daedced459bbea5f475fb13889d22ddb0cfaa401f247f379defaa2f7efc042c6a6455e636f502a7", - "0b04ef0de267475422c971d14405e65262052a834bcc9658522e236ca36c7b4bbb4a7af00df67287688fa9a0061927d52e12b9a57710def8992ebf4d8c102b7815", - "0b05dcb5b25f77bdc2e5b2acb639fe26c35b4f6ad6546319f8c2979a6770d5a14ebb583a5c0a42f18a147c2ca4c926f8e621d5d9684a21f8b34ab225f60b23bced", - "0a07483d1cf32e8e7dda22ffc20dbf0a568e685acd618f480b927efae5d16a91ece2b7fc00c961a9f241545eb8642f4fe01af06d0bc9c169ff6eae4e1293d86f08", - "0b05e3f458ef3c40e8227ca9ac5d905cc1f8093f79ffa7e7848cf45c54ba1b443ee56727d1499150df69c94c2355da038457768cd9403f7f1cb055700779c0c2ce", - "0a0036ad28b6cb0a417144de5f8521616566142676cc5a19508c427bd06529c4a9503f8975ef7cc9a99719563fd241ad61815edb4a10302e8526ea41e28a38fa0f", - "0b004e46d22dca6906bf08c565b5d0cd7dcc6a2f6130f48c6c14a6fbfd006cb988f0da7b83174a144256441ef898d7351c5c3f2f1b9fbaced368946ebe41161675", - "0b09136ae62ba36c673b441c0d1f92bef6648cbde7b8bbd5af9dec325958d16188ce4f98676e43eb5c06e72fabec3349d086cf4fa43e8fa856106e17238d9fdcc8", - "0b044189ace84818874c8860658ececaaa7ed35090c215f99b9a0ab8c857c2d43303945d4c4c13a02656aeb420e0b62072a7a7039a5dda7850dab87a22f4af8a20", - "0b015533e8fed85ead98fdcdf88f14ac0ac378570f368e7c432ecc6994e09b61a5f0e8d33ecc016cb7d875926b68ec0552205f25c7c518ce492f36f57a84fed734", - "0a051f382db93b60791d9c591cc559362519cdafd870e2e23b1ab0fd0cee79c5002f67f9b11f9cadc5ae5baaf449da52fc9bba24fe3f96eef5b7cbdcadbf754314", - "0a045a402050db0095d71b97060594be291565d2d662a4b6f5c085db7360a586f1847b1ad3937a3fc8e3275662e44b6f3a1c043e3e795097bb274267d4d0c78501", - "0a06e3369f5909f6a90015dc3e808da0d74ab680cf48206a7bcaf84fd4b3f8295801fb195e366b4050c84bc1c134a95ec4e896aafda96728bf799117f0c481d72c", - "0a06cb4dc1efe10c91befda84494e90d14298c6aac5955a4312e0bf0f88c2c82018513fc6feb96da6d0465bcc5f2f119aa45b9c5085ea5b17d6a626c93cfa45cc0", - "0a006a5141fa2ef71a6bd68843ebbd64ca5296f28e3512bade3fce79ea855fef0acdaaa6a5a9517650761a83c253e4f33945b2bb4382a36005bdbe547171ce1e2e", - "0a00337670ff7514bf00f287106a1191c190f0a5de7f46234815237fabb7b981fe061a2dd5dec623dc203809268289624c128d12de221e94263a63b10a00ba1620", - "0a04c445602926f055f73d70fdd3f81ec3498292489f282e3fc7b4e62b98b3f92bc4dfae5a0d441ae22087009b437dd295d94e31aecb846e44f1546f16b6c669d5", - "0a01b35ce307ffee879edf0b11b6c64073ab569baed675bc4456c9ad27ea415b0316c7dcffaa1cd7b3d899e762097888d382db740fd5753d26aee96d696e4b7422", - "0b06aa4e80e2b4b3ae6fb260d4fbee3f79ab1bc5ae754a626aa21ccd09dbaa359d0d76a5f94b6e44da0be90cba622b48acda6018f6cad857352231455c3ee02f6a", - "0a009bacc41323871cd25a362641b3456b5fc5541ec03070b71bf94ea001f1457ced179e86c32f09427138e4cb0de905118f081743e05bb2a357b157ed5c0a6ca7", - "0a026afacb76e5f8612a96da796601d993e1e4d5a6baa072c879ba12c7eef91c64491c1f2262c6b1cc6dc67abc5329db9f1640797b4a31f241ea8fa6e45908dab3", - "0b06fd48965e44a9cc56649aa36f83b998557a1f0e6ed7516dffa712065635b60e68e1037899c97efe7a3527d6bc61a24ad549ff1611b1cab12ea7af39e284638b", - "0a02f8b8f77e09074f08da6e6c8af202bacc66a75e7e86abbf9192cb663fa4cac5ac77c49eb35d281b88e35d8e6b8411672637f0a7d2b8564c852908f00ec0d9a9", - "0b01708155c532204faffaa66827e65011d597a1afa6d9154705bcd4d4d7034cca640f3101393af0d20f96736afd3dd16374eaa514f8920c4ab0f94ec6242624eb", - "0a00d705c2173fae00b321d5374a9a4f334a69c5bbbd72aaf5f853d13f4991861b7333421aa354837f356960569db06f576fd7f823776f043fdc2862fc6a0e4dad", - "0a0332c592f65f1ccce818d12f2e7b8fd846f69ee547991189af9bc4d0eb9568946b4323a937d22e2d30fbdbb3a1661376a584e0e29e6ea55e09e5437e3d589b34", - "0b0228b92e292407f5ced3637df0af9639f66ee433799ede2ca63f4bb3bbaf8f0fc9d76dcf48b0fd39d66f8f3ec6ea840d098d9809a7a2fba8332d6864d88ed74f", - "0a07a5424d82d01b9eb0fcd8bd4f8974a9dbe66140c3f811607ee3f64891dc09438578ef14ccfd8424ad878764317fd2eeb0556f45dc954378577517d05413800a", - "0b064ce96cc72e5e17f4c8b893bbcec630795aba52f910b7355ecca5c8d57c5ebb064c4f009ad42bbad2217a9cb75ced55f367489e8a18c63682c03b8fbd15d10f", - "0a0202b37af6a91bdc2eb64f793649eab92846c74bc04bafcbac6342cff5609818ddae573a163ee2278399fc5f100b7ebe7501ff5763aab3984fefa87cc102774f", - "0b062ce9282affde193a36d203063422c2871adb648f901de52d9933af30ea860e88d0711db0ab7e0918edeeb306890b9f88984d76c55c98ff8a898028cbff34cb", - "0b01e6fbd887d1c0b121efcaea9fc39c5fd743a71d86b82496eb942952760436e1e15229b98a16bc561378589556f76abee2ca2d52b4e78f62cf10ef6219e14d5e", - "0b065655c4cb585def2b1048470bc479cf7c3ec6aef5a68b97aae67fed1bc271410f4272eaed21978896601a73737084e8b42c8c4e1822db93ee2ac020930f43d4", - "0a06f4bec16738141441b3334971d82cb722e4b7db954e8905688188514b6f4b989a12cabc4c4d3165b132c1577a20b7dcb7b0c7177f10d389ea5d9c328e3d4590", - "0a07da70a5dbdc96aa04b5d02178308d0720d8570287536fcb38cce2c7ab40d0a31bfd96861f7bac8b7465e7f9069f312485dce840ee01543f5360c0d37e96e34a", - "0b044337acf7c213dab4be751472d6f1f3908bdca893ed7471a8d5b4862d7e7bd445b566366c71db725f92aef2b170c1214a62cf5de8e4de26cb829136c7970ed1", - "0b03e8a2c1a868948154b92f0e2dff4fad1b6d0a3693003d356d8d0653f799b39c59117d7a4d2755ae1184ec2c0b521184eef77484c7e597de5c9fb2cffc994aed", - "0a080311a86186cf05c858c09b4b19760286bc51ed420c2cd340304fade65185f080ad1faac8c6b9ac14085982e94494ac98e56e7dbf97515e874277338a795379", - "0a02bce4673ed446db39154532adb9c75e956453d07ef114172fdb996ea687f02d0b35580532e56685dbb27e81a516990a0fdaf627cb328a8ccc620f24e5984272", - "0a08c54d19a51ab68a420c2597be6d1971a5b5332e5bc0c0be5b9d11e714709c7618872a3a99238bf5c152f66e1c2b7330a1d76b4f89888cca78f9965ed0a4b032", - "0a019a34c0f8cdc168cf1db2e468b9d08f1d697bdb3687f8f71063259578b78ce2a10958635c8774e99ab545f777b8b197e3c0971886731e9f8c6e8961f7daacd6", - "0a01d6c9550570542f2c117e587859cac038a9afaff4c88dda07962013e3231fd75cb74110e5e79b0956d12c9f3f4d12eaf25e23105f055055fd554966fed3e59a", - "0b08d2a6c21b7ffebfa50d867280369d5b9cb11359d277720331378384f102a15f68f42cd447789435421398f22c006034cefb626f9f3abf813f3d572c8857d7dd", - "0b07e5624d54dda61eadb9684d42fe0b584997c6b79eee64d7c72cdeec5b8c34940253b871a7e382412c9cd9d1dd0482ac43ade257ded65f21985141d909057b65", - "0a02a8dbffcdc46cd1f29fa21a69825a3820a33d5a647dd3b70c339c943bae6b017c5913d1036dad368d857ca00ad6021ea27ba5fe8d1b62351b49850d4d78aa32", - "0b043dc724253b7eb0319256da88b9f26e3223b88497174c0a6c7df7c2fb86b954bc775aa151d03f64dba1d97f39c4623be003b565cd1192b4700d3facad0e594d", - "0b0326f6f464c60b618ca26ac04722f7cf464fe0d8e2645c320c1af4657e819d8668e0a09137788a06d1fac4126ac3bde228047715a89a953b44a847db6402828d", - "0a060fc90d87b08b61df00d034752eeeb5fde7080e872bff6e1a05e97b29b5cf958cfc37f7ef3789a84a2f0e385755f3827a0ff4200308265ea06dcf573085dfec", - "0a057f0a4fddd6cadb9ad89650112ec32e5f0f9a8f2c3cb115b9dc661217baecdb82f38a07b6c1b0b78c1028a5cbcb8b052034723dea52c457889fe34b3483d24a", - "0a06d2845c15a4285bf5d6ad3f51decfb771990113c26b6f8420198309f7a4b9ea77fc8c49b0ba775c6feebd134c46f9206839343007fcf2ced7f7e715e5509f55", - "0b06ead00754e9be48d7e3199223bf91cf6cfb49c5c472fa0d52b4a1fd1b430c0877e3cbba7a640cf6af4069ddfa78918b57bcf673cae508a7c6da69f87daab072", - "0b0305201e98d7961c01746dfdb683b4caed35e74929b7c663b01a3a9ed072d38fb3039b2a9a170cfe821aabc95bb684662f47d7e8810ba9779470d36d5c73cea4", - "0a04e0e8c38ee3e2e91c651ed0b13ede038448ffdee2d33c8c14b76cac4aa258cf12bbf21e3af7d4d3f12c3af489793df238601455ca81614a1458548c8ae7347a", - "0b038c362790abdddb186402f314862821ce223100f887ef876f606ff7cd322cd3057cc56c02e548da246003d24e0ffb962792aa6c86b40de527fd4aa4bbff7d9d", - "0a0741c471e819204dd50b249fcb4d9896841b67bdb85e00b363367ec732394500e2ca2abc980486c3a7f0a482fafd76ee3c383af6d3b60db60d47ceb83250fd00", - "0b086b8d65e34583ac850959003929719f65ec1d8856708df1df37284c34f3958b5d5501019e6397a7d1bf8a7f25478bbea1a7106bbcab4a969b54b88c20b137ae", - "0a0453984505da56b8f966609183c4b514e8f02ad659c42f544ff8935315a566544caa192bc71baf4d640ba495c968719c18299fd56d1a67b5b7208cf3183e6040", - "0a03ec97f952d82845311777f5495f53bbbe9b8c1fee3dcca8957557738a54689e8934fe6b5a790db9b9a028a233d0176df51af2da73f7fa2965ae901979e6ac16", - "0a06e3b3d632f2f29c06433001390c9560553dc1b43e8df61ff323c0ca5714ee9137efb66836558f4e88953d23f6d98ad826ceb3b3e9118e3cc5dbd638ba8b0cea", - "0b011fc902c297c05bf04e1b03a99e517daa5e03317ec0d63828550b50094e07188d65e2cb7b3ff0f5752dff5aac123af7fc16a939dd69a9c34f91c2f9c96e86e2", - "0b07cc6554de12a5f8c423ee571aca898caa8e73e4ffb318d79b8d059d42a84720fff9fe0b24b2781fd1c24d563fb7a770242e76946b536fb46c7c1670cdce406a", - "0a01f43e15457e81488213b56fd8b65a69941f48244367e4d85b3bf641681853938f4601ad805302cd817666cf9ed3d7ea7a6c464e085091969b118026a6dbf6c8", - "0b014958a79a88676e87a23c00c4e80246393c61047f117e2f169500e049f653bce74d6684fbd7be6d1bb71c9342a85cde3dd98e75c70c006799c5afdb960bc932", - "0a01b550ebda9a518cf55e00433b4f60654ee70da2784aed7710ea5cb6ea6f6b1a4f54dd52d487d9d585f39b9ac8a6fe55173c35dea9f6df19ab72185fb05580d8", - "0b02ede326670535e9d5c2a528b43c3ea071667dedf36879a19f7d5dce69e171e90b45c7104d5b9c003d67412b4cc0a8d737865919955c42f414291cc2fc5b9f65", - "0a03fe606b831e2ee76189127be9a6a75545b83984682984363215390123d2b411a4468c7032ad3403c61f5b4bfb34ae0dbfd923e9995590e03c5d8d7496bf6adc", - "0a02c29b184aec64bbfd6c48b1aa84d555f2d508e78e780f8c8eee12364b4b7598d43357d749e0a2e9419baf831058edb9df4d5334b6d5bf9a2f772694594bc4b9", - "0a017188ba148a4208d74548b71d54d6cae1a760fc16f7258c7a872cd5e2e6b3f53f15c48eb929fe34b0bdc147f13ff449bf77dec9fb9ff94bd2ab55313574da91", - "0b045d1957b368dd5934c3d4f8b057d80a39f93d22b4712854061293d7d99199033a50bb522c3a9074aa43879d20032143dbc794a6babdd48dc31f72967f1e40ab", - "0a044f91a7e135ed5ae932e661b876f8ebc0c897402c5af541d38a926a18fddc17c34ecced1623b315ec6df78337403c1db0d9b340e555092e987b534382255279", - "0b01810c2cb8dc8477c53ee5d4586122180fb5cc67b1d8ca7411908af4050266fd9751c82d4cc3da7919057effe656b333cbb24b1a65c776f472abf728cd7ff17e", - "0b06d1473871c4121aedb012468c57110983cf6fb252879cdea670b8be30f5eae5f9e9d2440d288aeca73aec17657a084e4933345444eaef4b618fa5701b4c6550", - "0b05b37c9f3f73414767f89620ee46e74a1d2294e0b47f4cda5caefcccad035523a1da4d9f6c4fd2fdac875e2e53c0b303cfafbf323026f8d2a2f7d5236cb580e7", - "0a06bf44e7527868c0853005ab1da395bf320d86f2f6fab9f90052c3de9d2362ce0ba2fabdcecb5662792f6ffffe6488d74375d8b4cd4fa8d8c4c6f5f7c7776db2", - "0b03025b60f07f21ec5076267634b8f9938cdfd8e5ed7dbbfb5d7ae82fae6423178c5ca1f5c6f4b01a8a2f4cf6542bfb9af09e3d60cb57e7c9760b89e8431f378f", - "0a087f49637b1f19e711eac17356eed09de829e326ebb2a5acfe2f031e969ed098609e20326dec8bdb028e6ae3a390b9a76dfeec57f64eef33ebd6b5d86e7322df", - "0b016736a88b0d4fdecf907b680e26863c1cb9ae53d334d5e877ef5924e0e577f1472ae4f2d652355537daa878a2ab16f93c2d944c6291b60942570c8ca7d5f300", - "0b04e33fb9b0e4de940f5643d72389e663d2c2b6e797e159c9eb87fb4c28d668eae05a87ec68dd904cff82307d1f908122decf60d4819f597540ab8860fdef86e5", - "0a04d277daa430aeccc883353a3f10719add2afacb12d1c4ed022213b7f4ce23641cf1a07135c94cc5dfa28d9c5369a5aa0ea31f6d86ea163499aef373cf5289bc", - "0a0721ac898802eed6b7380c3d12f9a765b037d2cd1341bd8c3f695487fa08d73b112d45e4252d7c8e58b828acc873186e65c72c303a2034c3abdc2d73b3d4051b", - "0a02792a709a481ab29a6a1363a02d6227ffa3122b1ea0dc952d44af34bcf39980af7fc807b0e4d44e98db8653ab9a6cf4a05a20762f54a163146fb630e1d8f28b", - "0a07a419ba1445a2d252ce293c195f38de612b5d301c6da7d077c9db60954c3f55fc1ee5b3094dd3e208151fe911f92f5f2e7df4ee53e32939d54da6627f85fe91", - "0b064d5ca0e6b1e5e1347cfc9f535509fb2d100df164e15cd910f4b15897807d4208bb84858b4d1e0533f6dbb4c97aa53851668951c089531ab0281daa98924367", - "0a069e3b9c9d5114a34d1fc2ea891a23c8c2251cbf5328fa84ca14b06224900422c79aff4fd52c46c081c942cac5b7ad5f47e9f6afb2212b6e718a642830e09c86", - "0a01e2054ccafbfe5d6a06706025c3e3d82d390db508b3de92c917256a969197efd63f6a838125c1e8f965f1db61516cb78bfe5e10bf27e95445f00cd5d99af88c", - "0a000312096b9d7063b39e5c21e284cbe4c915d2b891f262bf1f1c3180a191c1861cc79e808d802a47d396a8c728ff670294e8bb2dcbeebe71a1d80b9de70c4525", - "0b086bcd670e52dcdb583f782581e87635480e84c5910557c7f6359bba4972454703733329b4faf4a6f5c715d9cbade62425c1d7501ce2b54f7a9015e6a9f39686", - "0a013330f0228f301f02675172f5c6e64e1b63d3933390abd16623124cb2c3ee10c4bc126e7f2281e073db89641a5076df736d6447dbcc885faacb514825a20cd8", - "0b02465fc54b52d5156fba894ca34fafc477703c54ffd7fc09ed6bbbe199b28b0b4b297c9ca08ab886098e071bec7b4dfc2150ba7b3702ea069aa0f4387b017364", - "0a063656b860fd15c9afee3253886dbfa8c10613d4bbe51998dfa1a2ee3bbdda9a22ca11c65d74638c961718fa4678bce685a77f8e15b6ee82e2bef13585ac129b", - "0a04d05cfe49a52015b4b45e9d9538fde161015335dc5620989241206e70e8e05d4f35fc9018b79d1e89d1143c804d1e0c8ba265998822c237bc3206a07eb1dd29", - "0b03880c9c6677069484c36bedb84893ebf657653abeb547ae373d51a5e85e646926b947a4679f68bcb8b9669d5c5f6c7b7dc78c4e917e3706699e327b592c2723", - "0b05831f15cb7dab7f9936e59d63f5469c0439d0f8c23add476535831203da9a02c4bc343e9cc29a850310f9406260fd12ea4f02ba9fdeff15d7a7b9cc0d776dfc", - "0b03461073dcef99ef1b22faf5ea02865b8be6dc13fd74a5902baed72250c290cbc6bce00852197216f0b19ce2295ea2a1452ab408c00a8b914887d64c42369efb", - "0a00197025830b82b15300bbbf58ca463a700e894137ebc843e52155a1bfea3a052eed8d8997323c0f5a6b96ea7d05bc2b4db404653b28973d74c9beff3b9cf914", - "0b031359330d55d2cd3724a11ec0ee1ad12e3e531a4ad02de89550e53a63eef012ef197f41a96cc3e3445418324a9f070e2b6817d0eaf68b6a3f20278cfa16053e", - "0b076c737c4501a266869a16370eed098abac518b60404d9019341c78a43b595bf8c9378fcff8b58bf650c1326a0928e70c700ed92559479a35e6f0b8a8bb03cc0", - "0b0166cae352fd004e84ff617864809d62b5d9ed56659973b0e98f3b6f206b15bb924c813de10914a00007fc3f620eceaf6b06cd65dc5342acb471290064079547", - "0b018e32183f6ea983d54f0534b8a59017ece730be2cd40492f161d6173f2a60acf00bc25039c8c22dbc29aa9db2982537c06cf07dc4244fe6ce1154d757557ec6", - "0b02582c5f3c4d1baa950d69c7e971f554257da8170671bfe83e5f855e4ea85d78a7bb68310a505b7bc7d46380b31b486f5fb13efbcbc9051ca6346c4d3a3a834c", - "0b001ec396129e78058d7c962c072e309a9a0b655234f75bbe7a9c5af070212ed31f8751985e1c3410b8a5fdc6188c9f044e8a22141cc838d9a694f055823727a1", - "0b035c323e450f562557be2c61b8255170383fe7434e09de8c082652e27cbf1662f185e2d4d21350e811ee3ceb5f5e5c7add6be551f1ff25d2af1c99402f774d61", - "0b02409c2b000f44a203586e6de76a2284eae01cb4e7f90c548bdf148a468b96cd0b4a217e3f1b5bbf96ca35968fba13872a02f871c443eb8c76b704efab56284a", - "0b02adfa62647902ddcc771ea1ae984a47563bb06fa19cd5e3d11af3e9d0324edd3c70c4b2e249b9d4d9280622fe94fa1e070413bc9d20576a1544fdd38618ce97", - "0b065951d12ce4585d9fbd3bed22af76d6a35c1115429ac42bdeb1ae78fecc10490c9d3e1d95b66d28962d05812f28b36eeceece148cd2d4bb3b795fa9624de909", - "0b004ca946ffa8a5e54704b791929f10346297c5b10206c971bbded96ff543edc3c91a532847eda0a678d5f2bd177dabaa13e59e9ea20453fb425794f504f51808", - "0b02d6fb0ed02e43ce7f49f0b393c989ce673a0955876afb44dc65361892239a7514427afb7988d26d65ecbf165d1a90b800459ee33c9f04479aa9a3a02feb6912", - "0b0691734768d9c9cc38b7c350f62ab8e923d79eae76776077845e375c66c4271d99dd11c570c9d53434031ae0fd59a76bc17b9ffb359339a5dd4ba498d10f183e", - "0b065357bd31a80fcfdbe62996a3d107eb7441a7f1d1590e9139dc57b42f8ea5a9362894d936ea992df065e4674efcf9f53b4c34997137b9a7873b8b800484b038", - "0b038a08efbf0f404c151e55ec43bf1f5600fe1474689cdd41269df413404ece2ae2cd1aa4e665688f795929368b9e9e40d250d03fccbbcdd78ef34be9cd6adfce", - "0a04a850069a0a20af52bac4f5ea411cf8254f5ceef126819a39815900a317164fb163bba889d6db54cb3e94025ee61d0d39082ec281b66623f5f645bc34cb2004", - "0b05dc41226982148f8675f818492110c818d34b4c7be2ba75e9d46548a27aa3daefc8b6ff77d3f38c06c0771cb204fb38ea7eb7809b061e7f425bf741f817ca46", - "0a0580160a2574d5c54ca52606dbe788a96a03bdf96b2c8bb2fc2a16ed8512b741cba193f00fbe2b49158bccc87c9cdf45f497edfc544c1c534041fa51c31bf178", - "0a089fe503cc789ee5f4634e5fb2b3b3a23c723198c161a0d80b37acc37b500306d2a3a7623bbcc371c8ff120003890c7d1b0cfffaaf1c47ffb6a79f1751190e01", - "0a087b87142dc980b05d7249ae9c4fcf973be5ccfb73f836a488eadc28febbb297aa7d0d8d5dbda84f15a5ca3758619f5ee087e7a74f52e7a37f24da8a6663f8df", - "0a006f58f4b21a3d71aa9e496ba97c08d460e03651a9451716240b036ac0efa59ab2ac9450c1a14af988e9565c498b93b62ddeda57a7180fd9a90611045c79f358", - "0a035fe52429d0caa20183949ab2bac967439f0739c91d2f2841ec4bee41322842db7cab1da962a55efdb7002a271611cc4982d82ea19aaccbf3fb2bba29a96cb0", - "0a0135b37daa19987c85044a11d660e0f7e651f32d085414411d113bca659f7174c8dd0701c3c7415ab858c46bd299b88b3448779a3266d58710fb60330d29a2ac", - "0a048df6f3dbe7c67dbbd58ae7a4c50757dad25396132022dfc110b956a6611cfc38d988a980451c72c9d8449a5aea762205dca9bc6c35f4a9ea9122db678b5bc6", - "0a0514a6d2774e66e0e54e5c9bdfce6501aafb7591a7de5cba0733de3a1d1cf6cfdb16694efe6fb47dbb8699c56993c354e2481d943f93685c31f0958f48ec73d9", - "0a040638e6394330eea685dc5dec51bf567071b3df2fbd23426d7751f953c75f629417953888e2fd8d8733adfc4f4bc1b77638ef68133b1b6ca3fede51b4ea6efc", - "0b051bfb295fe434b80f61f4a4688d1c5428c79a0d513d0e25c288cbac4311218f4fe1c0f016a57a108ac832974543e69082d5afa4f7ea437922b5371d26408b11", - "0a037ec89430c4ca971605ca62888576b408181aa9531269b53b2995532fcecd1f42709b5b13676c02b5b0095635c330e96b7e7e34398c8e8d752d31de2323c924", - "0b00fe056fa21ebf96c13f6f80f969ab5ed3b13217187db98a9a975e362f5507c8dd1369acaa2ec22b0785a1fd462944aef6994fd70c61d7a37ed544e28948f607", - "0a009a821aca15d1c649865ca66c39fdb66c77b213d4e4c87f9ba3a6be80286188850f6ec0da170b7422a2c9e23e123d70cd16dadb80084341f0b06e593174002d", - "0a0239e75731d0216afa17687dea5981811a28956fce54b4b712c81a1f51258bb768904f1cd4825104e277cc4d2cd003bf0e9c0d776efd5512d51beabe3cdad8a4", - "0b07e70cbf8fa1877b56f00d7ecefd7d779838dca61dd2ae63874efba1b0fe6951a6dd0e2cd0c1c8ca2bd954da6716d5a5da506378ba3aa7d389d23760128dfc9f", - "0b0173c81a00491933df8314609f6bc5ed4dcfcc694325b16628030a6551e4ba40a11b4077ce5618fe2cf1e2d9b6a1a7ed30fa4c887a135af3b88726a79ff93526", - "0b01a4b3cbd747f57518e67a515cf9b1d58a6d27eb197cb842bb559525f61af829c5fd14a464baab65262116d71a416ba45fef5bcf8439f5307a6c2d6277c353e4", - "0b0592067d7bd926c0ff66fb8c83cbd2170bdc6f45a19bb16c3e174fad9364ce4b23f089b0c8972738bddf23b7e69c016d53f6a723a213b8694a56079b0de2bd17", - "0a03d59e4f5619abeba60dc2df1c63b5e381c5e2ca4174f34b42ab0d1ae2b8c2e6dee711baa4f5ac2c0129e6495f5b94ce6b4b1d214399c326b146de67eebbf92e", - "0a03f468ecbfbcb0e21c4979a7bdeedeb42dc09f6b4a75bb163ff2829c6b6040894d77d8c88902b5005f2865686d6d66ccfc5e217ae9a1b8459b93d10025de0572", - "0b03c82cd5c6386e98b4c6e8e097f40b44d61331e548ece5de267b24e98804f1dbcbce3f0e27ceaff6e994260fac7fc079586228e5688fe5b6ab2fe023d5389199", - "0a0314ed18384d816c4e6a83462bf1bced6a77616d8a00a7098ad9583395744035dda3b52e5333ffd4deee4281d001b3936f957998deac5442221af52a12701edb", - "0a05ebfdc6fe9721c7e89b1f828e28276bed32bc29096d26a59d3c95d2ab18d55420060bc350f07006c14bdb9910e51594d7ef7c47b23ad0bd0c6e6bdaa68ea4c3", - "0b084e324ef3e9dde696103616cb6b2597819ecf7c3efe76c7f49f61205ccf1f4908869eb2b2c9a193c14357dd117512320b5e9abb0d25d13084768bc40387f0f1", - "0b0545edd92af559b12562b458a16dc4b55361948e67d3367387cb87eb05b0f0c9f760140b94d6e02b515b1b7da41ce1f2af11ddcb4e138e8115860271084f85c8", - "0a00ad691dbd9fad2566eb032075239941cf34962e95d0e9ad78d091942acc611d4d897ddbd43d25ee0e0e8fcfc70300552feabac5150ca25c17efe7bbbfc90d14", - "0b05e5b5c99d37f518e66ded2be575e4669f896ed19edf121d4bbf96636d71aaace0ecd397522fe882bdb11af2b18b71539152c6c3e5dea7bfa79b1cb59f7dd41c", - "0a0778b50c407314051c7df187c5db9e39137964f0c9faf9f1871d1dfb3c0ad9e23944e06e5cfe997c0683a8129ba6a4bb4a9caa6b4d1352ea0557b2a19c6c1e0b", - "0a07186a8f511319fa2eb9fc504e9b88cec045cdbcbcd78d0440581ea8afaa4d028b2e10672fc0f8ce4488b122301ff5722b841e2e1f79a0601d45e3952c24be6a", - "0b04f9eb44fc50f95241095f588012b0ba983d9a96051f3a6608016c1088565eed629c48c7c0c9a06c89fb36038e7e7084d0a563c54cc8ad9901fe528c25c28e79", - "0a0689fabfa81ffbe284b1bed7719378a364c0ec63192b42738e1e20c17f5f6597b089aef7ecf5ffb326b6fe3027f1577ee60d2e3dea7ed2cbef8dfd7d820a2f81", - "0a02db9e4d0e07dec90cba33079fe3d2a51ee7c0625bbf24565bd3afdf5944c915c26ff0201f7b697bd752508fad1d70921a85d87ca5fb6e6eea9ce4a5ddec4995", - "0b045b945ae18f71959d778c360772eb76f299cd53942eb580318e1323d0759e7df5e5e29063bc908bd70c334745554a37290c0bc75b51484b0b50496d3037f094", - "0a003a27c0640aba56f18e54aa12590a2170ba90054e9f1e9b5732e0103d914d83f00cfd03c9bf3a2d5dc4e46a3934ae749bb3cc640c82c527409be2315c661bcf", - "0b0721066c411945f1dce1ff0f041c227b27b461cf52a85133beeab223cfaea2c8f57d301ff1e3a584887a241c08ec9c04e243c0b689e39f0470ac41611d7a138f", - "0b016a1122e5022fcc5fc6a238eb4091f5f21bbcd72a3ac21d847a7b2c46e7b9848f5f54dd377a312bb4221d02db98687ed69dc8fcdedee4210fbbaec1e2ebbdba", - "0b024aa39dece37de9b419a6a81c818af6f0637ff239a1a33755d17a09aebf9852da2023f915bd05f8868609481d0c39b6eeca5494f020acd4c751a34a6bdedd8f", - "0b039cedac55bad618083bde27efbca49e0c3c6ecb350fd8eb14ed956689937c9513d3bb044488434393d3c2ca0e9deac477f9c203a7df5e6a9c01547621c4c335", - "0a023cdf150045afd74e504fdca0fd7cdb6844a484c39e1495b3cb0cf17521f8b5e594e4553474490ebf7531cc0be55f04c22d975210a5b70f99191ea18e07c3c4", - "0b0165d3fb3caf9ae4c510c77dd59a657b0d0da17ba450bfe9695b8932c9808a4c957c7e8b7b3b9bc0f75f5af62b5c1e3c6e1371a24764ee46e4e0e9875f57b15a", - "0b04dd674e2c3ab27d794494a78a89f5a6b5e236eca165054b8a20e7a8b4285cdc7d49e0280c414fc75be77399a268e876b2dd121d9cdc6745495d4b32c0145d14", - "0a004c8078c166ef236820cacf9ee6954a0020b760a6b1a3a8f67c8e76ace09ef5dfdd6fa96cd8b04cb9de0dec208959dce7f9f736e01dfefe30374dae962cb7b0", - "0b07978fa7c6616ac8addc0f28056f47308f345b6a02d782fef0d98353d7838c9c53f9e1e69a1fe1e3d4e0a8abb1ba2968b43355ed43e5382628df1c2dabf22ebc", - "0b05d5c65f56bdcb4f5bb5aaa5353502908b5a92583266a2696d409c32f4909e628d15358152895c729b0d4388b463ed1bb9af7c6cc1eda7759e78d6fdb889ac79", - "0a001af580fceefbb8d2c68429eeb362cd5c2f0c3cddd653fe2835cf4cf32c0801e01e0f6ccecd074b2ae557d20c79e4324d1ac9f8ba683dac34e2002d44ef6f12", - "0b01bec690774a8bdafeb447c1301b3a558faeba56c774d054a9bc0c1345794ece99eabad148fed47f922dc13e569f67e4b588aecaf53abce0d692ce08ed6bb6f4", - "0a01fe60170cbd23688e034d99a2f7dce8cf61ef3606d16fd177449931005e3393aa25bf540bdb2e3f808d8f0801b48c4bc29d23df2a1422b99ab5fc96e412f427", - "0a05d03e6f2410b9a265449856d3e52349290afb9770faee0601386751b1037c5e95ced8b3067ed2e444aa276fbcc3cca79faac228f9ed5b2a69fe264fbfe1e357", - "0a067897131a1c5462cf1cdfef013fd9eb558b24b82f78717f22a5763ce762cc2e81e9e4de1632e15f0bae9183bcd10cfbe5bd9c697efb4b226b40feb1138282c4", - "0a01fc4ac21917c5a7c0b791cc56ddabfb382f1068367822e65419d1ffb95814521c723b462af49941364d36d34cbf3991df1b680becd6e06b3b0bacd5784ff408", - "0a065f0ae72db56506f29f6d92f56f9fe8a700b72e6744731803950e6ed2c71bcf80a8f08a93e69e0e1729c6df29f6224b2bab84906c4bf043e5672ac28b1ba7ab", - "0b009045c808d74a1c2857f5c309d59988e2b240600178543b74f95a90af73398f8c6efe9fee02fb082a2a55af28b9154e32ca846ddad0024c02cdb107504f2801", - "0b0324fd3df825b05c18139aaca73cb85fd66891918949d32160bfa549bddcac6a446638a2c8cd10f83f8572f1841999879b950d3a0661c49588b16dc8d8d26c5f", - "0a0703df83f8f37234ddbc75a72d499f0ca45125472bcfbb80cb7121d544cd3fd73229b92049ae8cb2c3c3c3444145bbf624dcda99f22729b2ee954fb2a04607d9", - "0a0779f7a7aa877c614d2dcc94b3c7d84018ba25320589ecb1dc5315b1330859589aa20bd42fb684accb6068a4401610f37b1e87fa0d0aeaf69a7760cc4e180f37", - "0b0326070ad16d6a7b88ad086f17976bb79f16f1f79d40c25c259c973b784adad11764333e75f6b4807ea62d96b4d564f17644adf01951840699d019d17c1ffcb8", - "0b08dba17f478da40ebeb76a84c58ddb030df37f7edb3a81c4e58bbfa1319c3b072271cd191d865da63213d2cb7f1906964838811b92565d07fe17962e8848d216", - "0a082c9c1b507ce29a1ced58f280553fdf2f59e9c6cc14d078397cadbe3896443b80a523f2111d542c38dc0332b60bf59f78c1ce03d4ef29c259c54a4d4a4ffcb3", - "0b003daa5592528212395fb73e671913ff4b8c907f2c5ff372618a4ce81830d8bff36c97f442587faa718d8185e939aaf0d6459b277056e30ad2a40789e80b0945", - "0a02bc2e76b3e1409e763568cc2c87525b457d4e5b072ad7f929530ff685c2a0bb4d6f370d6c8412bba5db9b11dd36f7e475fc34f0557ccb89842f03c8db11acc7", - "0b0740618304eee67af8811641cd5a2ba1df1f18dd54795a352a2d07fefc65a8ec8c9b7e13556938d79d4b73b583a822e54444cf82fb9e29b5835e650f8f17d59b", - "0b069500f6b97385c6a0b95ba43e1053a91fa1bfd674cf41f7c76b59594afd751bffaea7f64791b3dfce7c66d5c95885da420223fdfa7b24e82329b4c913f4fe6c", - "0b054f9dfcccb99860fe299478792a841c5e18e73acfab5d217072a31faaa290584d4d65371990f8a0d540385d097c593b9dd06a18ea6213c5bb006867929c80ee", - "0b0447c6bf879b8b17728d2f9d67a742d8e307bf6c69e0051f282c4e96a482151cd2b97a4525e755b5e50c714e830cc15d4dc0b9564a9cc6967c7556d5acb70bd6", - "0b03ef7b23c6b0543cbedf0fd26a6697914ba1b919491dbb29a9ff4a4472f477a36d352050f015b05a71b5c51d605faac70bc9ee110b9e7caa59acd70e67d77e48", - "0a03888da7c3387fc69380ca3dd3e0f688fd72aa7f9798d612e20ae609557ceaba253f1dd926533038128f84066ff2853fc4f1501ac825b2fb26ac028801bd45ac", - "0b004d6080fcc5d09e4d81be2330acd9ee43531b04ccfa8ef98a6bec1f437113be4d260b5e3b86a2cf32b6ba2dd9cf6c2a284975bf999643b39c2113f4b8de8400", - "0a0636ec66fcaffdb10bedeb35c8f30e453d7fb614c0705eaff9aac9d56a96f7a2215e57bc39417d86eb15e107cb675b2d719dbfaa54694b9d5dd2ee26ce8db8dc", - "0b0750139a5d9061e1908a44bc11b2b5268bc8899202ff17d48e4c34f17d0cb5065c0dbb52fcaf10ab77a21431be17d664c21c6ffd5c6984603ca55c02b86b696f", - "0b01b5c896b843da375ca66d25e8340bcc11e2af1dbbebaaff8af8ac2f1875e93c0e1e837bbaf68680d231fcbf92caf64becb75ab920f017c6da8a5fa049673bee", - "0b021a994d660b0e8923d4a38e9d5ca7c8eef8afece70e5b54faec422f8a3ca706567b91d2effdca2ffd2cbc2bb072e01eb0fde3bc697908f1accf0a33952acef5", - "0a08b0c90d3aeb8217b62ec53aa472618c294663c6c7701d213af5e122f8617a89ef5bf704769b52781038fb957b460095944f8535751877a80bd9e3d222c1c629", - "0b0802cbf765e6445781cc3fcf22e2c8aa3b6231a35013c3a55e8978853583924a414f0771bdd22a63dbef8f9285cbdea31ba8834fb58210479efc317a92c60e2a", - "0b057265c95ba03f3c15d991fb49193a4f1564dca2a8436658090c89fa4317e02c459c33ba5e99746edc6b08e1ac4369746f9140b7a27470615048445edb9bc75a", - "0a020257f29bfb514af19020379e2f5efa040fce33d449b3e85438d3ad312ec6cfc411124db93e8ef4ee7f8b2430cd59ff6ad2d4148763d6655c58694894f7284b", - "0a00876c4ff6f978953dba0e5f9780d6137b57ac53920ac4c21869127dee8fc3fa9c1eba9083dd942f11606c51809b91183b884bf05337eae6c704ee08a9ccf24f", - "0b04f8c03f7a246cf8dd41a513e1a5def8073b92f88599837beaab3d6f928aac9397f71950a2f298e761e078b7dacc94d1f6c137d2a4c6453455310252e0a10b02", - "0a02974d321e67a5648c67d29524b24ad1a1c85b5faf141c4edb36a14ef837ca63df850209f5a3691a212b0b9092cb5df82ad2a6176879304f524288fbb3b71b1b", - "0a055c45fbecc30b27247f4d4a18d44750f39f9f574584b64a3606fe5829eb9c43197545e86e9fbbf240cdee5206e245fe590a2797211be3d583ea31e280cd1b2b", - "0a08539e6207d6c1227af88e393418ffb3693928340d75d79829ed311930bf78f4805d99874ed4c6c64a0c9ba83e245a0f104c6a898bcd997be4f193a20a0ed780", - "0a021567db5af737aaa448a7cd8b22a71c654ca4e3f3f2e8f6c127f92f5e1a723a6645ff5945b5b5c43ffc11fe16676f404a19ced840bc49a645a3892c8474cec3", - "0b08838ce666d89b34156030698cbf1c97093f4df97c9a37c36222cb52a278c60fc58a0d3bf42c312ee9c98e91f8e7ded7dd885b2ac27775792dd07df8b9d51f97", - "0a028d0953b79649d6421170c40b9d280e53d1c31883ad18a6b548153c1781f54905554651468495e87147f868c78d912056be4e54befbb4b5cc89d1b7d2edab27", - "0b042644b36acf3fb808e43dff2428ddaa48f60a8ed2cd1db38aeee5432f496f40b2970c0578235a55b29cc850d7460e19b5c7e3c3255adb986efd4f582c88e59a", - "0b0679d58e04aa5370659fab458f87c2a2342209dd762847299f045a346e81d19b08a433f968fcf23f033ad172eaf2fb6ec1be8cb62004642f7394eb9157e84b00", - "0b08650cd6e8698ee8544e7c38dcdef6cd025b5e65a6f86b340ecbfc236621369667fd2dc1e56b7a5e4ce59a2307fec2e6c315f16907284f4668abb3ca53bc5cf8", - "0b023ee789fab9c4028030b6b8906b9cdc3d0b3a0c1ccea09626874486747ec69f0d2622eb5389ef30a93f7ecc283e6194a12fcea666902f14ef5d238df7556f59", - "0b00e5c1e9fa2a7c6e0503307502530f144bd983ea0e3070a43527dd5c97402eba4f62979cb78fd36c8599ef742594de2e22a939d4fa36f93a1121e81d8790326e", - "0a05f1de3689d6adfb44d51d100dea108a18db50c63fed25c4f8d90f1a00a33b43fb997c3b7b535be08fc0d7beb2823563376501e5f3b001d405d2ef4cbc5cd582", - "0b053635960cbd99b436a48befaf8587a1c1ec73c19a69333668505796ca2d5aea6da49af8c101061c03a37d4ddb0c4152ab23c903829d93167edf9d9f1086d8e3", - "0b06851a646225077590430112460a385b03fa9d3956c6a6fce9fa56b78a54bcdbd11cd20eeaf8abca6ce46ca9431297fda14ef6d8f94d322ddf8a0a6967ff9a44", - "0b02d1e5a7f2cffafb8e5be410a45a59a505b1c2820ed22694eef39fdf4f528dc5c5061e8ac7d4e8f3003891f7f066c52b68d2c44993ee22068d2527fdfaca9f65", - "0a03fb415c8a4051b58c14f74e5f955abd45d70e5772a35422c8016bd524370b140376e792b352247206806367b0d8d51329faa214a9e82364f72abc7160ea0aba", - "0b0816f47f46e9f59342de9f9b9ad34c89dd5f31b1edb8834ec0f7b7ca0ef086554a7b7f9c0668abfa04fbb235c708f56b6df963ad0bdccd4b65c1f7127a59b95a", - "0a05d9765ffa0979f204cd5076ab27635d2d8855ceea88715a075e2fa866c62ff15a65ed4b6453b64cedb9f56b18c9ecc47b7684ec6e010bff56043e100fff458a", - "0b0671d44b4d812eb5552eeb0e3571ed413a2a8df3e440746417201187e5a7a516f3b855d75bc7d5ef3b9c3563e0f180107f94f2d391d6f6f6a26f07ed8328dd63", - "0b06e48992514479869eb3140749852cabf528d3e047c7c2f1efdfa81532d4a36a19efbf87a9a4bbb24950b6af5d5b2a5b2a8040e670c73b3892dcb5ba857e6df9", - "0a03cd4de8f073070890cef7c82c00e233e0d9fd728c7b7b53599267deed76450ae72801ef817f09b76eaa8ebe4905a023929317ff855d775d32c3d50c1d157a95", - "0a0144a32e76679435198421616292f4364918bbd0c0ebb859436b3f246baf215c36e51bbfcc6f5c5b769e2c1701b4e445b7d0f4eb468998f0777cc041615d1e6f", - "0a00238a85d600e825f5aab3715c9f5fffb8ea287fade9202633d13f376ebaf5ea0ad5902e11e59880e56710729b53709c1a78ba6b50f4a1eb537c5d4cc3e03567", - "0a0022cc09cd487e2e321788b3104b42d0f09682b1045771317920f6112363a4bae7d75269606400c7a8cf67c20e86489f05373f773779a899d4c2385abc4be120", - "0a06bd215552040f0b25395ad15c70886c3892915210866088ac3b34d295f57882b0d4f64a42c367a6122f530e25db303deb0bc6a56b4789bde4bbcf7b6482c437", - "0a06b41f572491db22544e263a4d782d53b197aa90fcd3981acad79039d049241efa81ed695f474ad4b43f7bfffcac7b634955a1b407630f2813861c4b4416cff9", - "0a00e0dc106be7e5b5ef8f30fdf061f0e00d02a587c5093b8737c676fb93c1c70ee5835a7c387143023ed8b3ab06d5bac28c06cc33617e21939b231f8039b50255", - "0b08306813b0325d5648c7c6ac81cf8081361983b5151c7153cfcf7b6d4edfed660dbeee1887f9778664d15828065ad55d92765f522cedb8f4aab4f8e46ca6888f", - "0a0587e247acea93be5ec11669f024198ea0c3b4102d0e364bbf9ab2cb8938068e662a75782845921bf1f628724948062ebfb0caa764a3f626ba0ca1b645b16105", - "0b034fb739f8b204a60ff84a72556178666bafe1071d24ceecc0fb580e147708f3b89e0af39b7c644307b210963f8b78a1132c892259d4481b591c8a309645e2b4", - "0a03d8155bf58e1ae6d56ccf031a3d599ca9f8b3bbcb24a71226e05928ac8052182b85191ea6186e7d2f78f4843f241c0c6adae74338a1fcf920e6ff8d75e184e9", - "0a040b754fe2f82bf3f443378912be357f35b6964392cec9965a62eda1f0453f83cf58bec43bdef842597536c08a32cda72df23df46f56787aea3c2aab720904f7", - "0b00566db350d54004963532c170450864cdf812864ae6d8d9e49977ffe87a2f21d5352db4c37f5b41f72085f083929cb8a2da5f465ef1601ab2f13f6881ebbf76", - "0b013f34e0febad475e83dbb395f9a7b5700c02478be588bbc26f6107ee708ebca4ca5543b844eeff872aac14d09723dc1f04df84f3e9211e683d028350b39848e", - "0b0080c84b364a2ffd905c0a076819744206a0e2c6f6a78868824231c6b8672e8357e7067ce988b9b242275d3e7c8203cf69b87fedfd28a2437188c33ec983c1cf", - "0a07da31ddb8e6743e62d84f24e21c67f35a03ac8bbbcd55103281c4f49bb7b528929cc7980c27ae514a60a57ef18f890b6cab828825d3259a2dd338fd08bfb02b", - "0a0027b3571b74e92397c079df68a9f531a56114148ac6389bf3217edd46840248b0ff4123c3e77a005caaee5b5ae69d937d4c171634da66786aa2750c0777c93d", - "0a059cb8143d271a92fa403fb028ba365fe15796b4f4f092ed35d7299bb08420f919c202cd8fd4ed328387cae4752899bd592582855841a2481a2cdcc32db89554", - "0a0849fb10d0bca42088eed59b9315d17fd498a0ea38ac2d69bb5e58f2e590eb27c84d8cd0553eee1a0fb475f799317a64d4ed47c6da41338cd941de72aa56d3f9", - "0b07f7e27e7f62594947900f68c38221ea351f4d67edac59281f0069c27a35c6655749c7d2c9c637f8962a57f903191b7e56ebf88ff1b3834ec6dc5289f79ea24f", - "0b018d9a0b851308feb10f30a916443c563a41b7a07f397ede4df98545975961bfd2472f428620851becd0dd882afcd2e3ea706130c06b8e9fda88247a820f0e1a", - "0a008e984e61b317c2104cc2c704f1b17ab559d88c9538edd84628a29c659cd44c07734fc3b2ac0eb904bbf0c0260268ede44c86726aa8bbac0cbe80b1c6a845b6", - "0b02f50e44589a21430f0900d88bc547fdc83d9a3dbc7ca61d7f28afc82c3036f450b480fa6a285234a312ae6148727a86efcf2c3627a040fb8ae7fc8e8e4a96ca", - "0b07b675a5a78ed17b90724de84aadeb279b363947c48f9c25fff3e2580066a1060858cb92b219f81727d8e99127e80987216b53dbde85aefdf83c6579d72c8184", - "0b06cc95006ca9802211729a3ff6233f695f5f1c4517ec18119c321b35838ae01ab828db76f5d93c2ffee54462a74be8f180c873e8e407cb72816891cf6a476070", - "0b0333f9f029a60d631d18df1cb9a466a479ad0b2df45071d6963bdd2f5e0dc3bf67ed72e65b1f6814919294d8988b2a3424398131a1b5c406255b87a1f7938973", - "0a006eedd2794ad31972a41586bf37722c3915df60ff386e6c8bda4ecfd2a3ad101e517d5876a5abb226f1cac6496cf3849b6f697bdd94f5e509ac863b51a0ec89", - "0a013ca93ebfcf89b7e9fe19f0583f3307f697672f6856afa04b4379b36a16f03be4d43b0ad29d14a9a1da900c154f8d28f08d5f604ed748a51f3672b454ac6b93", - "0a091880ed56ad12bb869202ae7429dbe9963b2f59377cead14bf0ad5c4417e97ae989f5de4da75d1a13d425311269fa21cefe53d804358ffc2befca07db4d1e68", - "0b049b7673ad3029fd585c2f25671fa530aad120f360d26c65faf38a5b358e7ae808b6b9865cf3ac0707186b56d2082872275314d275a6b6f9c018ab687dd62dbf", - "0b0511639ee9b919c8eef4979bf861b03a3c5e430f78402a817e8b6b088ffe9d2f6e7779ab25a023703b251cbc2951a795fe4d14a05e0c3f949d4540dfbb71823e", - "0b051aeb97e8f9d9829794fba106313ca3b810dbad8127520431ecadc54c48002f4298390075219973ccc98d44b96ca5fab430eb9f927eaea0532fc7c97701c523", - "0a0786385c539cd959c406db96a78084d9c38457987dd151220ea9580d888bb3ce0f3a7fd36a908a3d121934e02fcce2ce88cd803ad05f125171a259efd1151652", - "0a044dd00201015b7300b1ba722ffd10ffc7f7a550db4bbb5748ce8d095feaaa482e476981cf8c9e74100b2a0839dff002a5cc903c7461a90eebf3ac2f956aefaf", - "0b002c053d4672b31f3bfcd1b0d2b65d79e89b9269c0488855dab6c52db5766aa18955aebae587c979f95eb6e519c0c39b2033e3d2988ccbf3702dfcdc8ddce712", - "0a0561982f208d966e8f108ac61177689cb19c2e79d15b043e16ce51df0d007e1a236d9bb374479f18fd1680efa180bbc5da5fdcd173d72ae0e765f272df177f56", - "0a00cbd0ebd2b2d8699df2abd5d1bbeb751f790dee630aaff71d453048811aa9772bc51fdedaa72eab658bc649ddc714555a3c19ed7141efb858baaa6da3086539", - "0a04f9649ff0567bc63b8f939edb3e57a046cb1aefd16e76841962e510c08d4106119670b96fcf3dfdeeef79d109fd022662e231fdfcd4de4c4d392834b3ec0914", - "0b002f93ad658cc4ef56908be3e2e6dfe192aaa5b7504d52e80be86ebbffb6c4aa26dc6449e8e338262e61fc3be8d27d5ac368c8871fc962100e5b094f558cd61e", - "0b085d26d6be4538528ee8935a0c621e22d0801d4670e7fadd1f631f1172f68b5031de6d87f7a6d018e234b90751272bb17d4dcfc19a73729b8293f1da390565ec", - "0b007ba065c75444fd04253730e06578cae521a785070d1d9089d65adc8abb3aa237ef45bf15f61fe18b32f4eccee0ddd3e71f7587ad9a718c1e56e5d81cd112d6", - "0a084e0c2866fe9d9e511f2f55e80a6bac95a879a8baec845fa8ad5aad493ae817cd5fa541395e87523acf3d0230268158c7b5bd864d736012888cdb87c8de3656", - "0b0640389041925c86c2397098079f549b4fcceb4675c5a0d202eefa568531d3dff99c9b7b81ab7ffadfeed38b161fb91cf75d1139f22f0dd94836fe15e491d00e", - "0a0830abd3b4225a52c3cb99a18752015b473c2427db9598ca50415a54575576f00e694eaa2dacb00e3471ed67f1f7f658188927290f46fa1b0a868a3c5e113d33", - "0b00a8b598b4bb74b078771cc1f3db72dd063fcc31d4ae9f7517dd6d2927ea7a44e6d3f40cc6d29b789bb8786d6bad967a5bf41201f5471886a5b9a7366687b124", - "0a03b0d8418ff8907a8cdbae86883e562d8e36d34dccdf89e4cae821ae23c51d0487b563db76e8cfcf72a62d1d2807a172167153bc291c7be35cc90f2dee3fef94", - "0b01017e49453d1bcffbfc6d38f8aa11fe05ff79b96feaab08059cd7a3b29318b374b5335107f1b0e19bd92b378c77ae47034127ecd94da32a4c8fc0add15f5bf6", - "0a01c54fd6b69a3e440c54895dcdd893e413f652ce3393434d141e100912c3d88e2ca4b25d1fa9a1f0e0cd010b4a9f3f858e3ae204ef5d28556ba6fff4a6ef27d0", - "0a0801b077a214be3dd0b96851a15cd67c39b9c536a03fdf0784d9b7cf8c658cea96ee68bdb8b62447f6ad0cd029ea8ee1c4dc22a22b63603c69476f59fa6d600d", - "0b05489ac77fb87ffe9ad2bc32333825eb6bd331710efd2dae0cfa2d4287ced8dc0c6bd638e1a03e6c87050f1518620ea59ee311546ee4c7aa2569fec5b2bbcec1", - "0b073e826de4dab1afa09a150d4ea48c1a68d3977d660d7ce5d56e413ed12ea8cbbd1e8499f05b1695895ac97a36233fc2cdb19f3f38fd1ec095b24a63bdb89294", - "0b035966990ded71a6991aa70f3ab919b5c1b4c8f6ceae4f156d07cbfa9f6af64834f79a03c29b34fc1860d12f0bcf3fa704d567042d60141fb9ad398357ef8ae3", - "0b002bea917a0bc56389117e40afbe0d9af1592248ddd3217ff8f48eb9d3506e929cc3e3b7e596e957699a8e258c3e549dafc6f06502e00e9f4dc52be7a31313d0", - "0a003d3068a1989309fe4c236cebf8414ff0a73df965e751fe86cc5d0757084283c4561f33043f5943e04ece1c7dff5d8f5b72c798fb997d799d40a28cd16e1df1", - "0b0589b28dc280f33b0cf8767abb4f89acd4c7a139e127c0523fee2b254c0523d593639212a94bd67ca71e4d4ff82390854676af6f3723315b6b847369c6bde70e", - "0a080309b32f04d00fa6a8bd9126ea6f3c50314d1a54135f99a8773f7f418d97be3d99e077ab4585add4db55f34c8304edb77d13e01fcbc225ec4eccef6d959be6", - "0b040438681d0c82302d8ec481eff419b2c791bd243931ed578c902247337cfb52fe4773ae7552231c14174cb22e893444f8263d4f3af9941075ea1fb5ce880026", - "0b0240f4b4d99e58b9a08005c7dbcfa1152290e21029be41fcd1c57886cca8478dc3f7ba5f6748644f44a1296ce2d848fad0507b30f58291eea167cc94de980d58", - "0b08af9b10f9e139f85e3492876a4c5d9e4252b229f42dd12e4a1f021c0e2accdb0bf52ba08509c95ea4def747c8fedea7744ce9d2657b3c2d9cc2c3867fa664bd", - "0a060dec828caff940c9d73cbdaddeeffbf37c772c4948dd0148789072e653aab2325436ad223bbd130acab4f8b087c61340901668b45aae329995340d07eacc65", - "0a081d9467815cb0b41a4269318784fa7feac02eccf79de47dcfe095687d5b27feb9efa19d663e7eff2ba530974f5821bb373aaf5257096b8b1439918f18d095fd", - "0a08c918f97c9aa159fde2104ad698cdc45044e2bfaf9655351da51a3a0c775a1c45ad0ce0564093e4a946b973715d6c50c94f688a7efdb07b7126d93acb29fd0d", - "0b0514aaebcb8caeacd14c9ef50aa8b022af3894e4b61645314947f7eb5944d69374ee1314f989e6624f1f13018e4cfc9c78ac59a2cf867d1430af6e7c8b0b09e7", - "0b05f77154802df15903e0226fbeacbc9a87673488859cd61400d26366c044ef19cdce9505f4cbae6d458b8f5aaaf476496255d80adbb50be4762d88db2c8e39a2", - "0a03d95b7312c484ecabca4ceccc35b370cd4d1b26a290afa67b0df75f1c876cf721f5951d7b45aded2c70fd69ac92b0b738de007e614ca42d829d548879879fed", - "0b05afb03f269a8f20ec824cf45c3caea300247744e30e60327c129fcff5cf5387c491771119e75163839ac4ed1ca881cd7752660b1b21615dbe1f2c9c842ce875", - "0a06e2ade28e55bb934abd18f40ed96f83e4d07d69427f10f8c97d40579e3c82b1692d15ecb3e929281f8a9b00665b34c46a8e9ec28ad1c5ed658740cbd3886df8", - "0b07ae2061772313465c49826d33e8a539deb38ef2ea82a6ccd81f190d27c989c742326c6490f43b8537bf8368562e79c170e959492c694d4da2f7a04a66b074b9", - "0b06a868b0f0d568dba2785fcbbf7299b715035abcf4ea587c59b8dfda99af484bd72bcbde4ff691fecee68453684ad8be062a328cd33840d3d35e78e18b8e5307", - "0a02a689eda63c6a514d7661f45e6a7ddd00bac2361353ad870a00c3431b1b53c02f35a85af17a10b9e514af3458c0ffa0fe4f85e1e8fda4dd08d13d7b488aaab6", - "0b01f4b66bfbb104617522cb3fdba78283831d017f567a097ded2e3e45fad8b46ec5fb30698710552fbc1d4f157d5d69e14865b27dab1347141a6433e15c40cef0", - "0a0188c2bc219ccf14ddf7431fd9d71ce8a1b47ea863a07a1cdf8706b2d0e3284de915b1634a4a540c661aa93edc46eea77087bdad8de64a00289e417202193e7a", - "0b077546b6d1f6cb07dec7ac05d4e06f4d03fe70a2f1ec6a5dfa071886b4c14bb30a4fb12daaefc34faeffb62947b8c9af2082b27f38580b7597e56982160a0a13", - "0a040504c39d33ab47f51d87aec059be30c838f3373bbde5937ba469ad114d9aa6748c702b6577751efedf6ff26166ed3e66a8957ca5130efbbf65748def9ee17c", - "0a03c815f3978cb3f7807ba8788d2b6fc0e885ac187367c651ed719c72cb9d0cd429384d2e6fd629a571ead8c87c95f01618b377bcd25fb663965b34b287b1ddb4", - "0a01ce2c74080145fb1da340a1e4899a85c8a002a41a4ecf611872d2353962e89963d5493cb2a7b1e3a6079ddfa75d4c133058e42a4cc209e25ac2da9fd9a825cc", - "0b08e7e16247047dc8748f2fa972cc6352ec65c6419c187a3974040316263b0a604dab889b42aaa9609ecbcfb63bb36991bc34a869e71debb23fb7dc5dfd238536", - "0a00a8245d6773fac7317b9d1c32a7afc3793b82cb2c928003a83ab7158e63865a3c5a420f7cb58ebdcf31e2948fe0f744417eeb7bb81c69e97e823c8f22131599", - "0b08ddf8a115bdd7a2b97938cde8abae611b05a83463414f23f2b3c9b9b68c375dad517cd55c472f595f9e93dfef94bfc7cc2cb9bdc29b5ceaecca64d64221fb2d", - "0a028cdad450e65075c19dcdafc4e2201f3c04c2093867696bee697403e40ff7f6771f75fdc64d6717c1998c45741d499ce97337f4b7a36363cb9ed0dfe1bc662b", - "0a03e56069f3dc03b699825207bb368edca230ef9bb6e238f1ba100a90b37084b218a2400239f10272219c0355530780fe8592041eb7dc60b74ebe1e4679311f8f", - "0b0002e632deddc0322681810c3afc76c225aec5908ddfbddc7c42b62d3333af4d4f42da550d5c99799e4a303b43f6eddb4e87acd01bc1e35229977b73da63c947", - "0b02bbe5b6df92a870f33d0f11af855981267eb6b1e08bd18cd6a99a8537208d9ad58fe262f657607ec5ee9234cecd378bd6961f66ebbe59ddcdc0eb22ee3b9b53", - "0a091533f9fa9bd860c102720e55b641e876162a723d5ac53690cbc5b70d1e03e54e2533878aed26a13127ab656825b044a9e2763899fa963b7f16da073e7cdd37", - "0a00a0e227af626047e5f6ac1b4c72ebe9b4c5f165dc6ae29592a744a3e739fce10a1e9fc1732ca209f395768e88dfb63ef00c75e945be4f14afb19a59d5b8f3d4", - "0a0183673db0a5b30b0aa9914b7246352d0d674d9b5389406308c0da352bd1069098a5cd6b970c3094caaef32440d8917c69ff6f9a07575d2dbcd98e8e00b0463c", - "0b041b7f2a33241108e75b84178f1dd34009d4938dcb6273d63773eb1e8488bae7d0782ff5fce488e14bcdf2c775999fdfe80b13e0781cd2d38bbbb6f294419b8a", - "0a058bdbffa8486d1e9b43302a0a8f3a816358750dfab276b0550a5fa50b29dc42ee40204520e7bf8d70f426d912d4cabea635bebfc9e020f27e061619b590dfcf", - "0b0286ba79602c5d55d1e0e0f910b055fa39aac9833c683d88c1de623d0b5bb52ba1fde7ac212e9a485699972d58847af71fdda6ecbd98eb17afe2b5472c48bb16", - "0b022617ca59901ab0de048bf76b65c758c36693376c0b7aa79be89d8afbb5a9fd79da6e9c105538799a3ddafab3fd9c29d1e7e996121c08edf0698a779caa0bd0", - "0b081d5d5837e1a2db9762ac635fb9327228d1567772a7993a5593bdc0c0f7c6b3f16d7c6a5db775f3dcaee7e678edd0232a4e6fd9882e48adefd42cf144023359", - "0a0679829200ab8114e6267d9656d9dc4a448f471da097af089a0070408ba43de6116bd3fbe65974478832582cae990c860c8f926eea8820651fe937f2642bdef3", - "0a0230937345d35fbe302997d17b1a3be0d4c7e577007f7aee5c57e492c98ab6fe525ffb00042ec1f58fd0c3c4e1b8d2a4c5bad5f0f6c06b2f1d4e5f5c97de9dfe", - "0b032400047760914f692d73892adf70d2725161ea809b5dc1a1318784a0fea28039eccff76b02e993c68c44c6c43553483e6be6d6d14f512d0fca00f172acf2cd", - "0a006eb600eff421a2ba563ce3bda261742b66ecab4e82e0912be830fd9bb0168333587d9fdab207084c586cdec84e9de6cc7242a62334c4cfcba6b27544db1c01", - "0a084e6b1942aef53ee9dbe802aeab90aec025df24878bb9b5064527e8ee8f20c7f04ed475f8068471e6f408332aeee86a86d581593c23b780a6bef4d1d46d80dc", - "0b00f9e437d505e12535c86a216765ed865c1a77facd86aa76220ae6e954f226205d41da5e40c18a8f3d06fe64977998627b545ed28e3d0dced7456604936891de", - "0a01e09085d876abdb23eff430ed9b3c222d1ef0683777a4b7b790c4b041d287d757ef12145c4d7d5db097c04622bc6cc3ca40fe4225f9cd3fc4a37f5ffde5f61a", - "0a05fc2903db2c10767944368adb537b82b252704ff3e94b05691dc149a0e3e0efb3447eb0eed1e78e426a4d5b5ea711da36ceebf0c9ee271d9abc8ed5ff7ef28f", - "0b08829908f94529e27b5ac1a4bddcebda1395dde374733ce5062b1314d1ecb6847e1a85fdcfe411bebc59c9b20a49f5d30adb227fc41aa82c5ecdcfd3e8a61df0", - "0b06cfe55594aee893b147e572c0d29f986aff611639ee72cf823b40b9a512ff696d2a06fc7340215f18eb7fff5ae77b05d6725754e21df997ad685c45cf221d66", - "0a0615b826b84f95ef32e9332b164f6300a3103fa1aab6d3caa57e7f34b439634c04bdea92f0fc4e0240f230db93393500d4172a6b22f4e0c891d609964f96c98f", - "0b036c7da5151009224d591baadf5c67700fa2b522e77805cc384c7d9121d2f8d439474dc1f39882c72de05a537937e59385dc26b62fd17df0fa956147164c6887", - "0a06b0d159df0bc3e999b09c18412515c835932857e2b84276b89212d0d985adc4d4561d0a49b76065d2363d645bd101cca695d6b86a4fffc3e3e9eb0d9d1733c4", - "0a06223dd3d196f67beb2dde61784681f7ade506ae00247886764fc76e0b0c16d7ab3363551627e11fec110bed5e420c780b2483d790b93d6e2a76aaccba90d5b2", - "0a047e14f2aab8492027bbe9f1ba9f0e138faa67b91966ade8f39c610dd85ca35bbea2499764022b7b1dcae6d8411af1383a699cbcd668961c73be8db02ad2c25d", - "0b083a972933bbf3b0b6addc0164cf6219f1da4db8c08580b30f63e86d8522aae91043a2c3b196eed17ca8d531476ed860a2ccbbe40bde8fc442c2ba2cba375b3c", - "0a07fd74693af48e8d635ef8f7742c48e7a181c491f00e41786eb760e16b56bae50d36eee155598e7061bcfe0570e7ba29d247eb35f7ac9cdad6ecbafd759756cb", - "0b003c536674cbd62f8ba36e1aa927b1fcc352be532d7c79b411de0d0cbcbcd18be61c09752896037ab10d9c65e2a1bfe682e124ebbba0565ca81b773206e7d545", - "0a01d2088ea7ec6957aa5a4b705e7a628abed82a57349ad499775139112312e5f00f32f4d3372b2574355133b0a0d3ca7d109f3bcf1cf65b24c6e45421c2f642ba", - "0a0025ee68af198802914bc9b4be927d3cafabcaf8bb3b503133f06bf644c2bf98c80379c574a8ab23d5159db2b5bfee55b0fbff4d86a81fce6394722c52246018", - "0a00d924b07c761182d9ede15b0816793fd00d0a7c44651d5a2739f7c47804b8fb76a7a0ef8f02dad4e7721cd8d38a9766792b24277f742596d101b8375fc7ad0e", - "0a06e6499103600b522598cb7fafad8c557a1d27950f4be3f3e0056a5411cc8e3ddd2fc56a2f87705ae82d8927587d8571c4f1674dc514e2cc693adb87df880469", - "0b0592a2f3096cb8eecfc56081e6df68cc711cf812372d44481530dd1c175e5cec1531fc5bb5b2321c1f9a1a94615f96e8e4406847a91d426d426febf5db4f93de", - "0a0452061609e75f423a19ea2576ac7c1d186de859424b029b2919adf60f89c9b02611ea22859f97c21092a8669e76445ce086b668aee0d27f672c0df733556e25", - "0b033c66960d51acbded1e75ce2fc9a7b983c53833a331df4db493ec4132c480d61421b3aedc49df3a16d434bd3aa17c7063b2098ea90f8b3f11b16c07cd6ced65", - "0b055155b214d0e792bee1f8e5f375abf1b2f2307baa00a347948033692db6226c5aaa4bb0e6ffec3918ade1abca302dceb9431deb839e58f4a01f7bbd31e5b46c", - "0b03df721e8e6e9f475e96defd91c78023845753a7a36aacec7bfdba3640e84afd9ad7c975a1e84cb8fbbe74c3a94defef025432ab3fd2d821fe30412b33922c5a", - "0b07ddffb8082355d9d7eacf8500ebab0e85455b730c472ba250b5d5243a548d18cfbb2a6f2e6e21c38aac6d121b536718de0948ad3e868ac27d66a15c2d2431f8", - "0a0777116743ed46a8d2c8e8169fcafb1ff2e393be0583f7889f27bd915463c74658e2500ea32e47bc3c6bf948c9fc3cdf57b666d89d736d5feaf2a53273783dc5", - "0a04513ad2221f66d9a2d16f9a25314c4bef592d1150172c1a46f6537e3acdbccad0605e6697d8c1e5ecea55612fa2f9a3b9193f1af2969f3623f3355ddf7ae511", - "0b0345f5d2840b2a14cbb30ae4a10433534d1978f62baa6b51f4cb0a90fa8874990233dcb746e7dfbbb5d7fd736d32eac0d240e749be823ba1864bc0f8268ac542", - "0a020a26b9d430803afd8a49005b5b092560beab75298e14797b4e0f75204139ec6ddb281011ba3a327e5f98edd6ef1fde5285c28ddce17f981c1f458a823f4a19", - "0a089d1136581ccbd6c31db5eb6354e745e43696d05c52d0dfe41bb2ccfcbe424073bf5290d10877dd539c775109cd7873c4b67ae7504a031ee091d8aafc4eb7f3", - "0b006902a313619564b53b70810473fe8171e0c4f0ebf1dfda95167ec6fb325a45db16673501024b7bc889738447f7164de12117b3a769875a7bab3285f42d3cfb", - "0b0523438f2c69fa378e2edde784f7b9cf12ae8190cbacc049f1ee68441c4225c639476f9505cb14984606e08e5c3d70bbc3d01d9d0a316a47289de471f9a17d12", - "0b021b91c8bd58ff32384a21ecfd092d3c3fe5a82775b8448511d5f3d2dbbb0d2bfcb8531c5be6ff23b804f6dea5662fe6ec95ec139bccd37083561b7e662fd996", - "0a087ee685f9a267554fecadc3567bd57b281a3b60de00f24d5a1d5ed7fa4ebe26b2f1bcda57175c0a2d533b22324d68be3a8c38bd5c621ebf32883f8fb94970e7", - "0b03d4b4491d8b662071e260b37f710901b14705ea67f5c8a527cae09f472b6f818713b1c60e779ad8b769da6975885df6248bd91859cc77a83a446dc78043c16e", - "0a08de1833a060b16ff28841ebdd4ee9388a6b3a037b6863044eef45346c17042bd97e1951c4cdd9fb336a580fa4ab1beacf579804eb2c3cd4b5162176bad348c3", - "0a00844a7ef6209469499b3df0c5116c8938d9a7540ba2b83ea16e50df6e3b409e8e4d44ac48e5505298d7047eb2f29b6b2bae4ac5e80e8eb72595e52ec502b532", - "0b04d225aad582e5579800cc37a46b5c905f035af05ec840d3ac646cf870bbd58d6cda65255db8984011a3d7cb456603cd42b744c0a5310c06baffc9ec2398c915", - "0a00bc446c8f12d0b78abeacab6c86523951062ca61b5aa606372696b36aff62053b260ec371552bbfbea71eb43d5edc272464ded3463d4937bfd009e0cd8a4b71", - "0b015134fddbb1293633f23768b434086611f39d98be5f52b26c94a23b51764ad759e1bd89f39e3dc3da0d7117c6f053317a1151982845d2c9b63af17775625e68", - "0a016ceda84c058dc318589c7a75197ac2d4c0d4c8e31aa9b3b5fac0fdd1387e5dea907aa12a58118bd93ffcabab3e2dcf581d9cc32d65a35c8e645c5f2f90a2e6", - "0b025944332c3aea2af40bcd1d1361126e477ab41a5f8b9dd408fa30da1a6e9d161bd4e2ba002a118e4a4145fb4d593b4a7f3350d696384b89655281c5e56216bd", - "0a080f071ef1bd0c8a0b4af5c6afaa73d381f252cd1fae28ab8f59c58b331c46c1ea112b00a455d5f809ccc4a5fe7a94bae3734232b59dc60e3ddd85f2b0edb50a", - "0a082de1be4ab4ac3adc7945a4fecab428bef5246d866364ff6e8f6076bdd8ac309666d6145aa80f010d747bddd5b117d7435d3be5721d3a0e893de9a47b0e7e61", - "0b066afe3b75abe55e067f96a5895fc72b8654d39e39cbaf814b1f80fbf4b8b8fc0316e80ac1fcfc714b4088dd9a6560bdaa8a3ad90ab77bbc77865e00af594f6d", - "0a05247964dd6c76a4384f06ae61a3e1978e97eb2b830e27dd7e31a9d3b5299d7810f5bffbfd68a699bee4cd24580e242a5ed11b096d262d8098458b9a3bd29814", - "0b061c935921147443fd5c9fcf3c50d01ab70f5e655baf131d47b9e6121a4b67168afe3b26a63b576a07adfcbf93c7494a09b0b5e3b5e62704dcc4382032d218e5", - "0b02e073342def228dc406d1e70aa59fc024e04905371d60f21c1329cd840ce1022703afd8ded11999e88e43c59d78ad61893e81bec2308290ec2c39cc8b738a15", - "0b02ea3187b32afeff006eab3ff8bab3510a05325e3ef68fd65c0e25ceaf559b4afc35dbd5154745388851a4df08cf480288a64ac2d7d0c988a3f177011c108f34", - "0a08e9f2dd9f130b2cf9d440c8af16470d836c9725519187d907c76988da7366373ab1fc1be92c760501a97916d0519f6b96e7396eefbb6956e62260db317e6fd1", - "0b0204318a44ab6b8537fad01416508db4d29659b9aeb8bbc852de5265d38bec32ccf32a852ff35c5eb2afb4ce06d3394af7c266450adbe270b1cf62eaf2a2afcb", - "0a01965697086aa53920d46adfc38c81f25296b277b709a5ae2d427a02319f1b5de8873e1c169c1ea4eab00a2f92f9ec3bd09c1e14b9ce95c4f9d9d4ba72200cbf", - "0b030a4e607bc8f04628c6fe922e0ad5c44c427d71729fea2e10123ad3f52c47ec4c00dd634e616f29d308a4732895e1b6c5c7dc2dbfe8dca2495e198b695a743f", - "0a07ac08ac1c4a5c14fca4e8a2b14d731818fba64841af9d31d69dd3493a8e519e9b5291ccc495d16871a06264a9e0509c314aff11df572c9386f0565d64def072", - "0b065e1bbc02241f67b09f2b4a28d84ffdfbb578d5c30765abd44b052c847ba9db0ccec4252d54f66b99cc56533b2f927a19ac1bb6d9f11bb63d1e258401b627b3", - "0b07e19034d036ee0f581d547240b2981605c142e09151fcb8b604a82536b3152019385c88dccf05930525c182f5535d8edec660d292f9a4aa95a1810d21f6529a", - "0a080cecf77b0908c49396fc17ac8fb48f660be833ab435341a0628b4f83bb1a2dbce13d6f82093a0701f03983c4ab71da222975ac128a2e5ae90160e10f6edfb1", - "0b05e0011bb426520ad4399224461b7ab413affa18e8563ebeb825498c7ffc7b6d40008690b57bed8b100a2f22cb047305d3e6eb92bb80a70f37123100b8a8f021", - "0b0412828f8a938b428ccfa6714258bc1b401373f8e76ab9e1848f42291a180a6c79b8456c45ae4547e4f78520db5cc6ef810bf873f25e4cbdd12e0279f781c9ba", - "0a04c8761e7d8aaafaaefa73d5b9bd7cba5671b051dcfc11664373477d086eb61c5569fd494be92243b77bb6d30063dc2142637669fdb131c6671adb38fc9170af", - "0a034e3a8480d7221d7a269b63d5f5949f6fa5ecbf39e4b51d0f4de884a4158403a7112bf12f765e81ac346a53caf32fa422fecfbe47b452ef4354b0b6e25bc4ca", - "0b02be261212aada8687c4d20a8f4230139f43f2d58115bb45c152c5cdb143c5be7dbe5bc8133f83edfcf406c07b71c9cc0cbc1bf7d768253044368ea34270e02d", - "0a05279e61f105f9dcc3725fb6403583d28086dd40b2c908338747efbed832e50ceaee8b96917c258407516c3e26e8752309772bec95c84e0bb1fa8ab60bd1ff8c", - "0a054fd843a55767c8c9f44f3a0d4072bf31c290290c0d35c7232c6d71b28b7130c989feea4e8c70ec4a5aa5dd06960a5be5cefda66f86845f3b001dd4aacce267", - "0b0477abc5791c8a801d2cf2376b8432c8b80b05289c06200df1aa3d1803a0718e36f661369b56009f85eb91897d09b51f3c0c36e13a62205f5908406f67e24511", - "0a024d4e4fe44907ba17042c05c995e54d1d4c98b468a3a76c8ec6d3c7db8eac12b22c2839bf04c6b162709f0b575a0d986a8213284eee455c23f9656188f8ecf1", - "0a02c5b6041aee47ea68e6874235629f2a0ae13e29c2c365b169316f833491deedc0061d492ca5a426f42871048ee62a7f2a56081dd432fd1386833a5c67e3ef07", - "0a01dac88445da747e53001a37bd5e88b3a6c1444e0011202f85ad8f6de67377d64a955befcece4e2d4469bc10cf011f42d59f67ccae28a28a753b921d098b33ff", - "0a0681567f709c95e06ec9585c9300687eb67de5b5fab740dd80dc0112738d9a42e9f10f076506fba4a51778ca4d9c172ac60115152c9d327486e7801e9725129e", - "0a07e936b16a3964deddefe13fb4b1c616afda4f0e0bb91b00a2a816bec56d4d5a31ccd80e4414734f02a0d9bdf5d64f82ba1e7e7fdb19a782113e844adccfe64f", - "0b036777de878b79b55c46e96db7c562af838c5b39bec20022472cbc141daea71698e6ca2d5d4c497799d6dddd95b0071658f04c1b99a25760818b727301490563", - "0b02a869981db0dff28841a2a105c75739c57f8184ebe94f56ddf568d436cb8cdac6740cfaac05a6e4b6cddfe5f46fe78e6b0aea53a9831159d857aae1084bfab4", - "0a0288e50eba16d0d8010d7969a03e97759ae0a2fd132b0ba810b45d3d3c7f515ec25e047e40e95ff657c62e5790bd07e231017cabd9e8a19b430c98f2dfcc6131", - "0b02547c075c981e8ab0059139418e2a0ffd946242913a80aee871b5598f6a593bc23df1645cf2f829acb53380ebca89ea7737662ef4bf9809b6cbb1d3efbaf76f", - "0a0670bf99613071ff75fc0da485a8fe07dbc890a28035ee55cb6e1d84634e11e7b3b3fe61a2d966d2e1b4bc1bc3a0acafa22c742a2abebcc886a43ae51fa6872b", - "0b0096ee9369d298be8fd20711ba5c2c8f51050dd6d18d51b9fc422d77eb5d00e7316db66f2764c357091d1f13732d955e66bf79029c7cc17ed0a160b6a3296127", - "0a00417fe461050df568be120b0b7eb3fff23deb0dede10b97f8c4023300a4f4561feb1f58cd75c40d5d01f81ae1a68195aac441ed5d0988c82327cac7cf96c80a", - "0b08ab24bed54785a5c27bbdd26db3735fe1efd9e40f4ef905ecebb662797774e76d5f01e48c58705ebec16f74091a2259f0ec946e37a764ccdd24100e35ce1b05", - "0b052f55d215a8e5d1c1f4f0aaf7ee5f36c1d7429136dce6f697c8c0152847edb61df67e6d566690c5bc17eb49d9604331987bb229d2c4cfe7a7119818e55bfdce", - "0a04d2b7999942086cae9c2d9b70058fa2a3cfb0db769c5b907f33d0678dd35d3e6326a3b3ede4588c30a837126d72b957eb6c7196577afe885b6c0bb8653aa7e1", - "0b0067e630b3b65681edd7ff9163b9295c34418b9940144a3223d07cab7dd3435977ab6efaa84fb22cbcdd68703e9dba22bce10df721557fe8d41a1b445a01ee45", - "0a0784ef55739ac90f8a39ec9f19639cba92f00da50aa0abd98050c804da20feb662723d3be87a9bb36f4f35221e14e986abef5b9f86155fc5c2ecc3a20d05d05c", - "0b08fb6fa53c906b02a77d9c471ce9448c9bd825dbf288e0cdbf59100e231182284d086025ccc162b0cc31c7857413c2d86468fb5ace95b60d49c8159482fc6924", - "0b04eb95ec95d494fdf870d2997ba004a0eb5428e8bf309253ded5402c6ad7d73c46de6b1d72bbcd07a84977854aa3ad37ce81382a940803576bfe6a015d26b375", - "0a01cbdce9e16d6447ba3ee3fd5fe4ff10204be53bd932b598e19f04c6f9d5def9623c62fa960bcfc179d2f9579616055d620b1983f5faaeb4cfd81471267bda92", - "0b046d97ec10acb60bfc0ba931ece2e27732f491553efe5d9ab2a9cc93ec6787b4dce52696f77be8094278801975fb7d2cbc8e35dc3fd99a2a63c13dc0fd6d3414", - "0b0165290e89ed1811e92ebff7637477f6c3388525064d74d773bc459ed06fdfa2fbebd3af205e341373fdf7b98daec756317c53dcbf9ea3f23441fd0431cb2467", - "0b01def723211f8558c0654e1547e9ea2c52ed3206921ab0624342e03fb32792c3a72deaf88d4e2d21383b174ae9090acbbd891dd049aae5aaea6214e1b535fee5", - "0b038a53a3007dec08b864218c237fdf5fccfd564ea9ca02058679449e782e8fda2bd5ad16982e0966c40718546cd7d4e6298da7af366d011481a0e2f5d1a5c039", - "0b031f3581e0916e79746f3cea53fdbb2e1d3b91aa3845f68f6dd26f9942dd7582fd436e92da619e114d701854ca521bfd883947fa4ab2076574c18459937806d9", - "0a04aa3642ca97912a08b49c7f6fcc6ad6421327da2ed1bc113ee41945f7ff5f0a20dd5f6085059643517b35c3f8fb0ae61a5522bd2884a4107a597941def8507f", - "0b02e17071bf0eff62720c1b37e29871afc0478b14acdcc1826966a27b62421becef7264e43340ea679920aee7e4f026580fc81f5019e7c8f072354f660b99663d", - "0a045f64612c4011a55eee7f00c17f8a1a1717c9c4f349c92f1c386ca69cd357d49a5f4ac7862fe725f61bbf39b480fc6f119b77aa982004119530c7a4ef783447", - "0b08265f0fe115b77ade6322c76f134ab9c7bceb827a90caa1736d5bba572a0e4b1576f82775342a25caa291bf8a4f4feb0027fbfcbf29c35a99230d86b2a4bb89", - "0a000f6701d4157000acba6f47dfe3971d4776dbbfc74ef297bfb20b5521a8bc25eca05d827c83292af0575f0f133d183ad802cd4fa98fb786708706b406d36320", - "0a05367f6cfdf0c28906e52b3e0579d7e436dba0e69a69816702526fc09efe80017b89b14acd10bbfcf4976bcb0dd061f9d651b98af0856e84b6be9d0d57413ac4", - "0b08d4d837d6783d1c482190d477fbfd07960135a7ee2ffe3d8d36f8c47a7b8579632143139b4c125e79bf1f2818ed916f77276cd5e7ef37025711fb2d300cb2e5", - "0b04d95e8faa00731ff5ef48b1578c1fdd4a36e7c7e75f7c415bf811e532269dcc3da052ab01e84b85aef7a9ee98570f4925cdad71b46e2e27e47937e157674691", - "0b00007b6fdc55049e0079391ebfdcaf88952861ab1a20c3ef382037e15d235b6bcffae64aedba68681762d12ae632d83bdadf589034579ce0041edee3a251ed1a", - "0b0007abb77e51c8fdb2c343414c744dc0f64a12f596025e5549bd6deeac67f427c3fed61caf2fce3091d07149347cd4c9588d49948acece92ebcce8ab79b7931f", - "0b063ad66c2c7b1e31f3a3902a512fc7b630684852da90ae663d704b1cd090843ebbb6153c6d88759268bd7998ee18d30f1d3f22fbaa07b643eaea2aee65cb8dee", - "0a04984a5318f222df7feff0eca321d7e835b7defb313d02765ddb8fe4641b1a89a7aa3f33b0308aa640d6a55268f8efd93087108286dfd236cc39c877c64110ee", - "0b058da2a7706b78ec3dcff9a08db4b0863f1774a6e59a3e5f55a55df37d980424bc28a4a7542110751ea6b432933fe3a58632b5a21f59b738da248cd91e896d33", - "0b01da6144e1820b6433f2dded7a8c6634d5e13890e284bfcd4991083e81e91118f6960567c1d7c7c5bf65b155ff4fc80557028716fb784f571fe6374ae6ff3761", - "0b086a8048bc8af84114fbb1ddbe0fe6300cce9f2f780b41a223b939695eae758b89025af61b609fe36fe145f7fe16af7b1bea893cbe54235996958f7be8483c1e", - "0b06c9bb9fb503ca7a7df1297ee4937572b24b379e49bc5c484990e29dbc629da6b1f6745ba4db2789d056d1eb7564607bd00e9ae3b85a60fe406079a0ebb201be", - "0a024fb7919e2514b0f469247767f778b57b80ef54d57849ee19e7dc0431d4735427cc0c1eaa40070260d75e8358caa5be8eb594f360dc16516775d71b996c5009", - "0a07e5b0614b6c3ae8a13e4d4b58cac425b8ae2fd4a9d08268b96b79304af4008218c3fc4ea9e0fbfa5f58fa36deef93e2a5789f688f89d53b7c40a0b5aff1a114", - "0a0154e268f72c310b1deeb66beeaf4b61bef72674110457587e8a9023fd2f7332bc5e28515b21a0996fa2c66d8c6e68017854f2f52933abd3fe0eba83f313a7e6", - "0b08173ff04d01af8d6deae0727a7c68fa7e8ce47256ff147169de8d1a2e0045fd62e6b700a1b06f82382d8fde23d74b263b914ab3eebf6a94dc4b66df93aa4c07", - "0a0264ac03b16401839af88aaa12a795c73e4b4bd540356ad6b002ba5bb438da91b9d16872ca8d79c6ff872f15c41683d3a57e99bb43cc1842eef8a185c3c1a9c3", - "0a05209a34752deb1f42c26c6ce5fb3a54dd2ddc47d4b1f5f3bf1482ac462fc8ea16b57ac8fea6cd11500d229c18022cb60057ce11a7d6b048580f61b92ea2536d", - "0a0263f97f411449287e6776b63d7213073d5f717fdcc1897028f9e5fdea9d1782178df1dc237f13c63366524d269f7b56aa0bbb69c37602b0eeb825c470ac1ac5", - "0b07bb41b9a38dc9f5d618848431995f82d248270961d9f18cf29990398df6ffb7540473c63cbe61c3a3caafa16b76255a3676ec54f4b6aaca8cf9aa21a6c43759", - "0a03bf070b099372e803547d7610e4ec7c1fc3d6077983452517c1a61326e485917fca3d41a29657d45632b22865915612232fec82796ac87a56d4c00e08a5f273", - "0b09088b374341464d7a9f8a90c3ad8e0a36347cab6cfce07da366375e6194b3fc89298bedccb1d72d47ddc0b0d88af291618cc208031e5a1d5c1ddb655b48e1b8", - "0a02088aacd78f08c8b8864ed7b6bad0ff5d769e09daf4fd55cbaefa01b9505b3835937ea2361273945c27a9d7c9ec1957d93db2a63f8e0d90bc66eeb8d9b8de20", - "0a0331356b8f7e79af19293a0021e72420d090439603098e42ca9ee2f46109f5e3b81b344d3644710650b52f7dfe41cd618059a761683318933fbdfea0be9eec2d", - "0b050da6bc4fba38bfdd0049a9b8e5d95f7f2e4b89966c4964c37e3a4e457032c75fcc45ead484e9294c29b87d5df5981946bc8061ffb7c217e2aa01e39f6fc4c6", - "0a0658ce570382ded3832d93fa4d2a41ea9009e6481928727c66d2ee4b0a652c4b63bbb3f99bb996fc321333b92db8c3a42d40ca72c53564c78000786a5958a81d", - "0b033c7f6c75b56944b513334088ec7f2cfc432e347b54f5bcaf2f4409583824ee905c5f227287b10a049a94bbcd3f06b845c8879f5394cddada9d1ad2ca54f97e", - "0a085a287dc107ec468a257e3cde26925d4f826d74a08f15b201757923024908180831b3f724e70a70b42fbc93a7d7e98c5d325f0293f0f46a0c75d574469e5656", - "0b0653e93090fcc59aa1aea1402ea1d6d16b0741265679fd3614c49f30e53830a0b37addfeb18ae37e0c3e918cf938244a14c4dec8658780e993768049b8417a3b", - "0b01a17b3c5bf8f15b44bae3f19e47ed1e309e405ff6a1bfa41ccad44feb2eb719b44b71c8977254e1cb0c5e72c4666cb2cd88c36f0a90782f9c51eb4ae4a8dfc5", - "0b08ae41c2a0e2c08351b6baed9513cbf07d328db5fa6993dcc6c7212091928aab4aac3a06d94121e722480ff55f377e7126de0b0f68be004a5e9a18b65b36593b", - "0b03533a4b014afce3b14f2b38d27f019c6e3817b199378776e15b6f232c8e5bde766e373338c99089a120b28018833f316395ee62809cf553b7804109fe2cbbbf", - "0b06138227a8befbbcfc9099f86f7ef9bf8450b7f50e69d2b3b5547326965b6280245cf28aff800dbaa1b65eccf741a9353506ba381c1f9ebbec8a502dca9a6c65", - "0b016e212f840bfacaa883584b09afa6f72ba75c712b5082fb8a3e214e7409fe53b84fad2005d1c825e5bec8e95248c020e157a2c8bac12d2d292dd56894e859e3", - "0a01bc2c4f3e3b2368b10e60adc1d39ccaf19230a4328126b92fcd0b422d147016fc8489be3f241a87a2636613840afbf720dd0962ed439f778a7e3bfba8ac5dc0", - "0b088bef7c3fa6955e42cbe507741bd62d17ca89571659dec5fa0354370fc914b184820bd16e6c108e9d23134a49cc90f4173e23b739f5e121fe30a2359eac7f61", - "0a055d057d4aa260a8b6232e0354dbbad5270d5d3476e22bb3c5b867039c4d2e425ff2713800e586c7300965257527f7e05558437ff980c33d495fb3da17c5467b", - "0a06e1fc03d23d2540ea8610cdc63a8b234ffc47ba1a5743168cddd0690e1cb507ddad028ccb50e5cb136e3a3d305e66a324cc553c113d138bd9c54e6135a416f2", - "0a0349bcfcc620192dd4f33d7781a6e8df558511f7dc3bc212dc1b7df100f3e85f76154fd3bac382ef40192ba0f99da8746491d1834890abe391822253ade769ec", - "0a03cb1572f2a178604b0116d7667fe7bd3e73f15939ae60bc58447907ead398b9162fc46824d7e4bc4dcc057c32f598ddc96fe7aeb76a1d1ce0057cc4a3d9df43", - "0a086845f1ae536b127f7aed546151249f6cf29bd6a612990396456cf59513287ce907c22991ed592c3d27efbac8cfd558e54768e03e2521b1187bba7610ba80a9", - "0a007a82339e83e9a34ff290fa2b83ee31d07c9021b39a69526cbe1a1564d027c63cb3ce35fcf0e17350da25d0767ee028a8c57b3402eaee1a99107c81daddc29d", - "0a03f487e3d6a14607178f4061f2bb8da5852219dadd8cc1b20ecda8dc4c24371356208a082a78030faa9ee353c0582dde624acae666af317929dd7c49ec0456dd", - "0b08619d40da171bc9f029c268ea1d031e89318822da63fc25b07a3302d56352a82cccbf8b454b1bcb7432f6a6eac642e9a95822d77ba2a3f3bd490d95ca306627", - "0a0256bd57b6503ebebb86c25ba780d28674e4e283de0431424a9a670561834ad1a02dc532cdba429642cc74771c534742ba0d8a9623841db4dde604a1476f5c13", - "0b005bf21205b4a367020b28a971ffc6f3c03ec1d82b1ff9fc44c013ff8c926b06efc4418c295f410acc5f20562c0ab47c3c6ed6424ad82994cacec399ea77152b", - "0b057cfd1463e09461fb97b437822360eda8483b50712a71eacd077519183b5d300c145f5c1da960d85b6bdd255668f4f305321741a75f60986b988a620e135067", - "0b01084e8f7c5ba7d6431242bcd7077a53413c7436f70d32e2209c238b0c11f27288a914f7565558c6a37dfc621101cdac43475891f820bda0485279dd3996dc3e", - "0a04e30ad60f6a87d4f00d3fc6bb9dc1f33c15f4a2e47a33dd00b796de9fb602be83543dec64fc58772c505a37909200d284fbbb81c05381d53dfc795777cd5bc4", - "0a034136c5700b36038f1d26bf70fbd67f82766a868e3d1c1d0f4b749cc99b2427b818ffae69eafd78044f4df4780b738cbc3aaeb25616258f8dc8a830915cb6aa", - "0b04a9b1237d4a81d7d987209b18c0e8ec5576be23bc095181cecaa73be27c41ca691189e857b40066d964e20a15b7b82b420723fdb6fbd4a7b4f53dc1ff70ed8c", - "0a046b2b3d440ad0716e3d3a6c8fb5cca37ce1477d92745fefafdce57ed94e78254e938c4693bc3f139534638988944c457491fd8a74bf1db25484befc34b446c5", - "0a03817860648e0f02129c5dadd1ce4a0c4011ae474c1e0a68e2e6cd93474110e859ff6d2883dd02f9b797687534b3bb68e7bfb224316bdc8556f8d41490ba5325", - "0a001994fac20e7533d19d4faa70975a1316d47febf7ceb6f6a356893cdef3ab440a1886793ce8d49aa523ea7eba73f7558b1547138903ff4462636c8489a4095d", - "0a056bea26c6da086084793cb126145a8b22d318aecfcaa52103f0df4feb902e0e076e7cb29af146e43921a6c30dcf95a3d8baf49c9a3888ae8576db9d203de21e", - "0b03033aac4cfb422b7d2d769a946c6ae71ff9a46eac0696ff8a128bfcf35d378fd7c4b363228af1377349cae8251957a530ff2064a0a9c014ec7212cce9beaefc", - "0a029d2fd269a4009a8c3c8e34f0500075718b6a13b1d1ce170cc5f708fe3433b7de9cf86716f9931c1d6ad8944397c9475e0f4c16877854c2aebe0c58c0730abe", - "0b07fcf7e7df078aaf610e23697652895ade6997da6bbf1c2878ecc8bb2e215ffbaa38d6552d7ae51f04fe12374fd5a66742c7fb4929f28b91a1f046ba4f3b03e9", - "0a04c44af1986d5e006da6f74092ace14619336ff6faef269b77a1dee1993a551d6606717bc0a4d580fab731989ce2d7f72c25244509a3cea81736c67e0533926d", - "0b086506fe309454475fdcb7ee7c9046a74800e82c645bb5030bae6ce77d9d4724935fb18b04d341695ef3cec4a701eaf467e09226337870d08a85aa85b0472ac1", - "0a03e5908bf740bb2ab5ce9e555a80ec966e4902f5c3be3ba2196e0b7ed338e8697d33f5e70ce4ded4bad13d0af7876bebcd25fa0e99233f0e85786b0fa5fb7693", - "0b0880a097b7488d7e9f5a53242255d260afb701286c365787a5f6b8ea368b3f77e03d7259321355383f750fdf313401d636cd0d4e9e992e8544d03de8ba0c759c", - "0b064650595696f3614ba57e1dd7de512d2e0f407bdb879d87cd5d32bb009c339a236eb6f1bed66c203c7e96ef820ddb7e18a5381c9dca7ef01771689c36616dc9", - "0b05cee194202af5a8a789d08b9989cfaba813b03d4f697543d0cde5d063ff89cd072b32a37c91fb824f75639f6da49622cb326b30a0c990ff1fa7f1c101af3868", - "0a077d60866c31d5099551e951859393d0ee0a7a640456a33dac437189a9e42c780e3b1fd553af52aa2ae30e79a06d402a639bd74528dbf2725175068f0b61f87e", - "0a06be4f3a3ecf9024a308088b209ddf29d601e9c90fc0fe8f7a14c5464a302fe0a1c79a67a265d27f90301e8ee2566476ec5709e7daebf6aa443bfc4d38ff412b", - "0a08ed9353467ba1d0aa2d9590a31adedb8321133c77c67191688c70f3b19da0344bdc22162e4a9a87a705c7b71c98d1d006f9329e239212375cbfcfbc60caf06b", - "0b0358287ed82af7ab40ad0229c742b0598864a7f3a8994c606c925b8d5964e740bcb2bb8a1f2655746607cb85ff35ccb988f860d80ea4c95f7d71efa463456d24", - "0b055baa101adff2c38c5f6c3d9cc42b5f3bf34517a286dc9d980adfaccdfd190d4effa8f342b321795c73ae8806ab1a3497fd7a7c19923a419f87b3293b38bc20", - "0b03d21ff4b13dd9dafec9cd60041689f79a4939139664ac0aff4feb47f4a296b4931595f4c90a4333277f42b00118c3329057e10c180efdaf8a0da6633874201d", - "0a04b991efae3571276434ae9e33274983a2c2603856f3add99f42d9f2d07064ff8a180be68d17d08daa4ad021efe4bed64a910af5cbd7d34fb56293a559a83f6e", - "0a07bbc6a906cae28729fa9cea9fb7a8e971dd27d80f2cde5a2b07684b7bc99e42f105afa147a868a61519bc75448275996e7a52a6f258fda0b126becc03b4594f", - "0b07ee10e91f3bfd30ded587df237d9bf4dd04a61c645c38e4388248170512d063cee302599584eeeed1175df9a7f4d81379ae3f08b477751db02551a09722cc96", - "0b02c8ed32e02595564a331b0c177cefc3f5e7f6ec96b3badd6dca8a6cf3650f5817192b5db20604c7a99fd02aaaaf13d4a6b41854be8ebacf89e608b473a7d1e8", - "0b01350dd1d0f29264fcd24d5d4123f9470ef2a233f1b9ccad084d1f23f41dc6dd4d3963dadd7f9a7f821db5a540c04ccc1256564733895be2061a068e15b015c3", - "0a05ae76ca0adcfa82df3079de5c67be4f436fd5e9b93682e02b0a82d6c64fe9a1db1d35158ac60534ab64e6efc5cda3b350d441b999d446c023b2e3fc21ece068", - "0b08a38d49e318b3d1a8230003a0d55ff081585fa88e64142ddd408cee17e7dbca188a86d529e390947b4215ccefaaea991e87ae2e278060b69801414c7b45c49b", - "0b0747e7ead579528eaf0bb8b1c80d8450806e407d36c23e2d92df4058751a26f84f6484859a45a6c001eda04ce33bf4cdc78ecc0af077ecc711b3239a0dcebd3f", - "0a0443c6039a7f2a7fdda2eabce48d4b884b8e8b95a8f94ea0bdb64386318aa7e386c80509a372053ed84ff40de29b9ad7ee854f7c45de892ef0b7abb3024ff21d", - "0b08c89126d78d2f6e89399015d46d758865eb3cd0b0aa2b368e6241cfa2bf37499a4f11a5c4fdab772a9025c92b97c61dbeb221b41b879bf763e63c48b2fd04f0", - "0b02d511eb7be527255aa0a26dd9b84d1f26385c06fe9ce8ad6cbddac599ec2e27d8c955b74ba83c92c7bb9ebd5255b7b75f797b4ffe50590615c555b181dfeecc", - "0a02a0c507b44a6d1d8e8760bb16911e297d761a4558f0968a34d64fc7646c8a57bf38768d4af875ef5e1f1b919c7420ccd97195022556fbb0d49452170fb9151e", - "0b03c1b8292b5c01b31e83d19fc76f77d2a2a5601b1217e21b4fc9eae911b8641f29725086898f794efabd569698bf3d6298d74b4616d8095c284803fadbfb7b1c", - "0a025fca703222b92860a6f0a514e85975cedd5fabdc04e14ca5b49a52f86ea6ee3c5d6dd053fc768affd88eea597a1e3f6c31128690f634890121e245866d5263", - "0a04ad28858d18f65284623ab8701fe688285d483eaab120da0ec47b90fb6fc1138df601b24d0fe12dc5f596f91406ee31b82fa29b84441f54b63dce9e2252e3a3", - "0a074f45d9e8e9edea20cf69e3376b936ed9683cfbfc21183a5ff0b7849a50b5fce7f92f0ca16caceee5a5835973139eb78f7d3e249f30b7a1ae21bc748e0b49a7", - "0b0436657c255769dde21e39d2e26e29bcec447b98b0d8c8baf8450a3b88cd67f4f419dba54eb6ac3c94d51d6dac567b3530563108a9b8aedc9acacb01d1684f38", - "0b008b912e76094df6ae645ffb1e7fde7408832ad1ebce7c720b6a5aa87344c37d99f066222a8d20f8f2be4ec5ab81dc7446a01af2172bf049abeaa4307e6f3be7", - "0a02a32769ea291bf187aaeef3dca2bd57d2e95637ed7df6df84435c826258a5dbd8c2ab6854ca1fe3d8eb170f300ac35efde7d6f41cd5921c9408e6a3fad86089", - "0a00a55e2ec1809fa174c9ed483b6d2fbfe18bf0835cdc4f0188bf3fec284ec756ea6194893145996076d09a17e35f5c705eeaebe6e9c68fca68e03a6a58c8b627", - "0b01802bd175e61b5ce0e1cbd3333a4bb57c9e10c325cb297d1290638931c5c5108fccc35ac799d98d8f1346e86f2d70c98a4f9a94ac00ad282e8281b5c51b6843", - "0b005f59355bebacb075bb450665d3b2004e31756c06e1d5dc5c52dfcfb70d046ba62171e4f0326261bbf2c33bf65488a58bfbade6f7e02105edfa093ec6f73cfb", - "0a00a90dac1cc3e46fe8cd0b911f62cf345e92057db5579191d25ef2741b25b8cad8da606ae0f4d394d79a36066836ccc256172b221f2939248f1bcf7743851b50", - "0b071dd112f55d70bdbf3fb6377f23c0c8c6a93a595f7d797cbd15b0e60e563cba36483f83e95dcbd9246b7a6f1a6d26d500de65e8c881987ea392547bb26753e0", - "0a02bdd60a4b7f258bda4c8d6910afbb7889f9ab417e7d228a7293f4d43d74c6b34a2962f45bbea754f8cfd6aa4ec875a55cbb41dce777e95165d9efd752cc693f", - "0a016ee262ffdca006fac1e5e728ebae8b15479c8c8dfcd9c7c2e440d4ff9ad59e91e89c3e082de442b4423e9ac087b7f6caf187bc2ee937957db9bdc9f4b9229a", - "0a02587996bd99c16baaea6fce547d166d1baa41c689c5b3422c829d3c90bbcc1df5c245d50230e3ebba30ec0ec06856deb66936cbd600928fcae8e56a13d89049", - "0b085c9f6baadb726f08de75e7c77550580650743d0ea366b76f8fc7943dc99c9a70a001645a598405becc745a1de6f81d07bcd3e50076cb7a32f22d295d35f3a4", - "0b02bbe04609b2512c17a82df4d6139e388efd6e4f31756e37f34daf90b39464cc970f3474a12d4e6874fcb758858244bdb4c8afd3674f5cc4373541dcaa474425", - "0a05a9212174dc89bf20ba671743a81383b8916d273c92a00204c28311bb2f425a8aaaa1c3ef4b059eccb7bc7d01e956af93a7a9b1f160b337626a676d843d22c9", - "0b0702520bff23166eea0606ae4cc288bffef08f34b5263ab86d0846a6b7352fb08a952c4500b33eb8bc1543c370c0a9a1cc00f525c19e8d5be8aaba1b8bf15dbc", - "0a05cd1ed6053459c9ee28aff95cfcd6a7e24234af14f5ac2644bc8363fd1e81e164fcbc8a042c12c8b2bb3f97996c313fb9f144b0457cea4dfa900ec7411ee724", - "0a05ab08619c417580da18b6ce7219746517024adda0db3384bd7cc4ea527a6ea31dee8eec931b138c9ef18ca008c13180f991107a0422db97ab32a63e7e169e60", - "0a002733a45783e780f87c9828a5f2cfadf7e47718e04bd9a39dcdac25718671c00cca5887287faa60c9c57b4b48192d2370a79759d0b376193b7922752f119da1", - "0a0101fc35e74e2dc3d5bf26e36a8b07b9ef7d5cd6b8786b8f91e7c19d20e2083d67db33f020c48f5cdc9bb7b23ae028ceb9709425e7637e19133968755339d47f", - "0b079bbcdfbbe4d5f195797e7ea64c9e3b95881457d5b84ea3578fcbdae17dd17d0c2efa4297b2117bf1a3476961a8e35e1f1a0b7c942f0589e79e9c6e30404773", - "0b05f031a8f8a89983dc92432c2c760037f713c4900101c3ac21a97d49e7523cfae8d8ec10fa07f1a8018db6a24c0fd4940d112d46b850e1c3af84679a0dd03e9e", - "0a02a8572471162943e33b8bbd64babdf96e151435ffbb82c18bc8f296e27c7773245c62b4a2439da16570612767cb31dbfc0038194535a499aa0021e4a00723a8", - "0b002b0d4ff89961d4961d79c44d9694476a5c8748c0470b1d8616d950abd6d86d36aa639ee1e245c4f567fce299690b1edf07afa9f6f9c593df2753bf49762172", - "0b0133bd4f0d79b085eec6c1495cc4e2186a8e087f74553cdf4940ac9e4a619039b3f406d26d0f145c5d392a051816990ed67a86784a44fa4b67d550d4bfb16b0d", - "0a0077e393a11f5749741c5c8ef6d5d345e7ebad74051f57d7ac191de46ec7f8ca6cf64940627382ccbdd36ca3e7e744beba1679ee264a0f42ca781089ff201c2d", - "0b06f9a30896326de8d3c77435bc7060a5f0b189095a670a460dafa92af668a7d515de39e47d93a018a05a448aedf4e849fde2324469653e305797ad5dccc4d03b", - "0b02b7ba3264c8ad15e1d6e13b2ccbd1b75412135b3b1ceff71af7058f242725febdfee943fff37decedc94924c1cf26789b77655f738f9dd9b17866472431bb06", - "0b0242d8d731ab3feff17517982801cf6ff94b1c1cd1dca0486273dd1dce103f207ac0df28b0a3e2d527926cb49c9299876f994f87512f2628251cd5ba8ddcb59d", - "0b027f2f7deb29d546112d64171bcc5dcb4c96996b700e03b14f773ae456b755cd691211fcc6aeb886d7cb28f37a05ed13bf91b12f6b0916657ee4a8eafb2e3bad", - "0b02754fd567361ed30caba88268a9ae7e43fc0dcb35e709feb3dd7800592fada8d5622757f09dfb023010c299dc75f85ae4b6661a5bc16a177a6354a48035901e", - "0b04ccca3ce03cebbda1ef4a55bca876cddd4e9ed96dd0f3890efe86aea193cdebc50f8158ac5022ebebcc2d58667a61f0a1c81d3ca23ea3c01a819de11d0c3473", - "0b0056844ba62d654ccc5140d35ccc18eb4d81c7792342832b97c17751d189f28f0ae8906916fd5ac08c42b6e09495dd8623bfa3c9c4a8406c5b8417d0d3f3ce21", - "0b03c5a4daf9ed17b9f20250e953e65bff37368fd87a6cf6a3a255e8b4f0de978e8e53c90c5d657bf2491e95ed54044fce64926c63345eeb78c14753bac94ee844", - "0a06a0ae8c224c96d404b716bf39ec1f056e2f30eb5b474da7b5a5d08e1f04251ddb37a6ba33c4c03a6a3770eefb39009683d73cae5f321c277b3fcc3d64391539", - "0b07e6e83a71bdfa3ead7f49bf82e2c571974911ac656bd4738fc9c9f73ec7708174e7f3953d8d57629e0bf1ee76ed6553c3189622dff07c54b6a8bb75ffec367d", - "0a064b39377177e83bc1111442ef2b51561c2cc75bc4095e9a1455ff191fc5d552a4290b67cf57f49de7e3a82e808dd7b80d57af389d2841afe5baaba261a95493", - "0a044b2eef9237c41dd410591b91eb1cd98143edae2b863cd72bc11635db46d06a5a5cf75458b64e33cbd45b2b22569b0e94a8dc7c33d5a87d0357045efd8d52db", - "0a007e71874cb24c7665c64a6968274d36b3357fede4d56ce248bd41d3cfce441db3373f18d9d2ef39a17f3968d2eb5fc7998a45640ea4daf5a02127811da84faa", - "0a079b1b23c4e82d0a07ced1f72c8341cd30c63dfd5dcb5330cfabc9fbd369c8cf4c5938303c7d9bbd9f06a1cfa8ee9abd1c9784a772f016ed547e960c95a3c71a", - "0a02dcca735e6d26965b4731fb8df36fb9e981b53d3b8a1515b4edacd2ac94cd77f00e58bdaaf1866726241b892fb8c80d6a693df627b88739f79cc042f3bf032a", - "0b0395eeffa38ab8b43af5e2e83313551313dad5b318aba6d5784a88978d88c81269e93f8e797da72faabb50c57c4ea65186f60505492eb824e6780a4f0f5d0d1d", - "0a071b73845802062d4fbdc24d5378faa57982d8652fc0e2f64985a0c08c1bec3dc91479dfe7eb42a45e6470e7a845fc1d6d2a767ab834c1703dfe2dc9b1b7b7fb", - "0a01b2ab04e00dd8ec78f5f168a661a65141036495712b245de7c5d1e5158bd2e7b18a3dcfcc8eec003f1499767f3b88a92b14d9a077360370bc5b579f6ed8690f", - "0b02abde2e7942886ae1f6e1ee9f7bef0006ea48f0a287e4c0f42c137120c4463db5f68f81f7ad4d6fc9820a8b869cd768c5b4aa05ff1bfd8c0c0abc69dd66e9ea", - "0b08bad3f005798550044c258c7b0453727bf7b8f40baaf4e9dd1cd247a99fc950aa32022c994c64bd709786eb23cb5da3c8e7b02cf0fcef004a52983ea6c028ae", - "0b0641d002136a3ebcd811b07d32a57a27ed1f980097e9dcb78eb80d5108651918455c7c0c8e91869c83b75b31b63348d139ae03ae9a52629fee5dacf89be8857e", - "0b0430a29a2e271742987441bb1d52467588ffad2ca4737cf5f24e01a90d3d6ee82ea3a126b0c6acb7532568725aafac795da6f2dc080530db50142cfa76c85646", - "0b0126a10e996701f53c8c4725573b72bb1035df7f8f67785d7d598b6669bfb0c06528517b76fc5efc4e789262639b056984227ac4db7c5a309529b2ff4aab2871", - "0a02e9274da29120f137351b2c40e81d71c3ee31e3c638982c44411bc5f1897e21f074bdb694180fb8d9ab4d3a87241ae843568d168c3c4f110228e3503b48dfc5", - "0a0012ad52831641de03363da187e876a2130da95e8e3e07337311d4f1e91f9f5f055c7093ef66a30cc943a9232286fe2b219f43b3770a4af02d7d835713f11b17", - "0a068a47e8c322bf549aa3a0d425b350f3ccd6d0951f01064c3ae5e8a7b798f572d175d3206e413f9bcf889397499461ac31bee8ad18754c734b3955e168422dea", - "0b078cb634f5365c6f2ef94b510d6d26daaef0194ac25698f43e07ea565c1974606365a386284cfb50feb60ef2aa01f0db20d5b4d7b6232606e6047196fa71f20d", - "0a05dd12b99324db706afb55a2657f9b82e79a700a2942de9acf4c831847c98f5392f302f98fcbe96a49e7e73fc89eed9b7331e30854868ed507d61b162fe336d4", - "0a091308c0da6121fe313ebb15858ba7744b4f6a62cf57caad9c22b81c54d85679822bfb0cabaf19ac7285fad582e1ca43a3982e438646ff707d1603e4a6488ed7", - "0a01dd791f4bae9c2356cd7bb962fd943318a4ef06dc838f6694dc22fa8fec2d84c5c391db791056e9f49677357f1737d5d5f7f4bee4647b9c542daff800ef95bc", - "0b02a45312c6eb8b518db285b20275c9c74ac3af3a8d00839db4a17e82cc919e18852372865945e3f720c7a34314b89233d35e4081f71c872ad8e52f166715f104", - "0b005eb10d28a89aad0339fd9d6516b305644b376e46e2c23e0f6491ff28a20e38d99248dfc16dc7bea3afb4c1e264ed2879f804dd5ec9cdd7d28aeb40c1ab4d4d", - "0b0604d6cc5d906d77f784b79e9fdc0750fd17b14b2e16510f5f9f6bdfbd2bb35330bf94e2de223274b04c1474a8938abae3f2cd6d3acd850f95ec9d74ea0384e9", - "0b02986ef5305d473a3c029bd86c8259e81c73223078c792863e2c70b961cee3ef467c3724f3110fb92bb40131f6bf5964c624fce8ed665968b973501593c439e4", - "0a08aceab64e90205906971d3745e6bf2f1d2331b2291d458e6c801b5fe015fe693a125549c6a404010c2c1a8ed72fa244857f03fc49b67fcd98dee4d9a87e0eae", - "0b05fefc79ad5b9dd9179ba8b29902a68f81d2d3fa9de15c03935873ab4ad2016c0c0c83156f1251963fa086e48cba29b32591e0fcd077946866b98e87ab4a86a0", - "0a061e889710966df9537bd4338aa92d2634ceace9d58bbbfc130f9700f690f7058202872ec4d4af552ee3c12288d37fe41e2bc20d91c47727135ba66f99675f29", - "0a02b69cb6fa0bd2c3562c06cb1e547d8c9ba88b5873822ed532f0aef56b52d30417b3bba6cef1f46bcdbe73b06b43d36bc285d3307ae660e532dc31a7473ebb70", - "0b026b6302104d2eb39bcf17f90c513d14c0a0103aa3fca124898d71d4be11812a5651a79608d062dd65eeb9f8f8af448e48b5ca353b92ef5ff70c67356226586a", - "0a00bffd4fa9080ab615be16e0effc8eb8bcf9c9c36d3215c752971ff83c8f2f69aa149f2e6f269de70b277bdda10aab61af9a21c772e86a5fba1a2ab7fa933a1a", - "0a05fb502f97f57c26e193cf2cbc88375d4506b4f6e5530457c0b5e568926931b29270fc4391dde4e3488b0389b5fa26f01323a7da8f5cde3dd9cc34dd53404479", - "0b07796887618d2906e0fa269720689deac7ef0a162710a59bbebe34f1340d82a3642088826f0ebe708fa15f984a4f1b3c1e1e05a2974908799940297ca8d4d21e", - "0a04974cc3da09502d422d84e70d16c588cfcc2bfd5c6757ed650f75dd60acad0c4101d11d574f737c007543374b7810be2fee3cbd16ed60a409c4bc5d1cdd301b", - "0a004cee930c48a8476c96ab8bae84b3451b51f791afb54e8b1f00cc43a8ae19909088d1c1a419f79bfa3ba7ea501b211c3acfe8f255e08d505a21713a011313dc", - "0a01274c487aba341b6c0d6757ee6ef2c9b8c50f66a459ba2675b3b1af17ce5e45c1b35aaa0b321037cb19e3d961a9c189a9ffb8dee6b66621f725285c1856745b", - "0b02b3c28f6c5fc9a1059e1b66f460ac2df7e2d5eca6903fc17de93a561368a28ea2b5ce2d99b547caf7958b1c9245e2d5f93ef92872f1e1663005ee1642f43693", - "0a014e9ac7115d7ff2a8059974d21538daa0936beb4a8dbe6e7b48cc7b08b7a0ee228339c53e62f110fb9d747c9aa4bbab115aa1db21253d611030b7c631763127", - "0a0774a427fa204245e0f8d1b6ff97683da34c1ae9e6a66479b5a525bea755380c17b52e2f9e53936fac0d08536f549fe129468e432d3e49e16ba608c1b40a3b7e", - "0b002349b1e4ef60dfdfb4a2cf0e26f98cb437ac2819f15ecc92fd44753cbeaabe1a92a1ed789f7d81fd5ea34140b777088f8a12735d4e50de18d77574aad321cd", - "0a01567e08ca88344384c1179bf73844c1c5fe2994734d84ab8613e1c5c022618b89ddeda2cba0ec4455d3ba603db9246b0e7617e12095d4d294dc7806d1038777", - "0a0134d26e36dda93a7a9ba8f0f03eea9a50c8e6fecdfc00277ba83c51ef88fc0c384176306717ccba028f6ef0d4d84a26bdf81d474e7adf7235b9108e07e635f0", - "0b083ae3d40e8edde44df7f27760349992ac76f34d8ba5d33da0f4981b580bf29f2754d7a426816153136bc5de2c7205e4478da956305bb13e3a84d63ae9a6de0a", - "0a067356026126579d71493c0b8abf25706dea5f9877981e39ccb540977dde7342ee0e48a1a55ff60664913730d58ea02b5f1c7d57cb1dad099b1092d566fe4e0c", - "0a0150999c91cc6c7c853691c4aec11d4f814c6edb8e4661fc439e4de8376ad63c23051fc773d92c9fc4842391c1184991278f5c5f8faab4b6ae9a51d0e1d0e904", - "0b03376450163ef38167790a9fd1205ebe18665f3deb843e412c92a7c1e16cf9ae87957ea38236cffa6d5c804505d36974c1cfbfa047f7e613775eb08387a1dd55", - "0b079703a16b0b18d204a4f90c262036331dff266a01e2ad24bcf707406ed1db3a74e6ac410f221b1fa9009e4e7e2c864973cb35d17b978a95a46e8d57cca56887", - "0a03bd32bc62b414d16cfd455f373c017618bf5684f98b281075fc6b1cc474623fbbd657e32fe4afbca724fb620977493efab56e4a7d06801eb45143a820c8fe31", - "0b04edb781507514c1c725379350f9c03abed5895b14df45a775529e3870554f405498c7e15a4011b0dbb0fd438e106ead4dcfe6151fce4a7c250e48f5cc3ac0d1", - "0a08e835351c2e5e213efadcb959b0c11304388570e69d7ec775b473d101b0946ba6d76babf88459ec81cb674e9d54aba72ad8abecad5d338deec363e03e9271d0", - "0a026fe84e5cd4b990dff80e5d7b8c776ab465b4262b5f4eb03df34902ed3d1460f958dd700721e6f13781b317d9f82442e9ca3dc8236744568740551c2d7f21f6", - "0a088c9b521d0193b0e970c78dfb17df2e8f0d849f970c4145c4d79e640905956ab2ce68bf83d0e7e204cc6af6ee2a7fa9f0ebf0519bc4761978b9722f11ea6d7d", - "0b033ddf0dff2187af2109b84a984078efc8664a124240bcdad9a218ebbb4f2954f9293d2ce56ea2f5608b9b0854fed1c6ab78918bec97b3239f41e9db4d04ef94", - "0b009f83e5d18167985430d99e2f77256fec1ea563111d8f6e52c662d8f94fa5e9a85430dcd906748ba4670f69a5903fda8dd767cdf9fb5e567745277810c6129d", - "0a011991abe9a0de17cfaab6edf2e02bcdc5519db6d3fc877de715fce127e784289fba9d16b59d7443fb6783f4b43f0ca76a89265792d53cab9e882c1e4d4c16d5", - "0b0332fab501dc41f42fd9c4d3fd1db17dba80556eb6d285434576a57d1ad7fe7761f8c8efe31dae1225896abefe831368260abca76673cc75f1c3a69f3926ce4b", - "0a02bb4048da7e94ed483fa6bd195b5655bfdbf73a0c41e0582a8d2a729670cb63fddafb49352f1157251ae015219d239de193c94576a0be9183cbb5385dbbad11", - "0b04b207e14428d298bb9d0339655ee58ce618977cec03d29dd8da3c5971ca134a7760e4bf60cff919dd2748cb27bc97f4bf433b66b22f92862c84f8e0f4b93f11", - "0a030cbc9c920402785eabe2618056a36ce3f94ece69b1db1ba0bdd0900a81f40c22f9ef6dc0626f3d3284486fe2a2f2b70e61b986d9c032af90a70669b423f05b", - "0b008d876ec45e7340367ccf8483f37d3c6cb430311943546097d7edf153305e88a6cd3ce1621e2d627dc10faa414c78ce4a7886ebd2bd35d668efd98b65cbeb60", - "0a00b500199bee9d0a2ff2c3aba8d25c50e4c6f32694172cb656155838d2634cf73d7109749a72751c8df699deb812cf1cc5886d25b08dcc225729c1989674ae8f", - "0a04f07663fb73b4b3d8c706595c837f91cd0041853ed88163987d4c2be0d504224d2708de7db907db5625d816b34014f8cefdd54792d92733aabb35da509c243e", - "0b0492bf0fc4e9fd187396d3d5b0c55ea83bd61b62d8910e863008e7acef3aa22dcdfcc6b66a12b7b3e15d56e7bc187a390bcbb2710f0bacd3fdc2b386d0f412cb", - "0b048e67980c0cb20efb8205f7af89d017b3dd43e2287b98cc440a0c31a633a5b4b7bf9ded7aa7b602c8d382687094299ae3f750d43f66bab5ccb6db449e7f3217", - "0a04c0bbf8071741ff6153c90a61bb024b471f367d1f55a427595213f86ee828e64cf232e85ca5df3e9a6fa429d9fbab44f5b2c1470bb37ddef431068532c1939c", - "0a07867ccc88bc3d25df8996c099cbdc4a9a0d301504fc8b5d043becfcc4719a4a39723e66d66e1fac5de245d1da957060631f0396cd756f11b743432b38a027e9", - "0a069f8b65ef828fc412e942297822cd40e53d42a00cff435d26979b26e432b10e20d40bb60dbecb78c1a39022eb2707aead8bf4145e6a7f693d221491f1f898db", - "0b02972ef8516f299ec874936d7b0d46d72cd26db3b8494ebced6dfbeac5af29f9b39535dbbfdea8e1f0716303daf12a4e52f7b91a62966211785e6f9fb0257e75", - "0b0187fdd9eb5d3083faa627a1de12b1be21b2eb8dbb8fdd5886737b4691332dce0dff2072a4519b580763f1ac6d53071f789c214efb7a979e503d05e256ea61be", - "0a01d9a6025058e484be3a5b5ad3eaa2ad115b166b016e0e2c9ce566a615f3a0c578ef03565080db8cb65630d15c4705b04d3b51d6ccebecd9b435ae54efd6fc3b", - "0b04fb244958eed32e0636073aed771854abff42ce49b2f486af95db46e4f6d4941feca8e62acac2f41be4c8bd01746250651031f05a889c78e23df7b617b7f2a3", - "0b02f2f1759821e1f2f360c5856c362d0ad1178f8b8462d21dcc076eeb2c9f5dd824282415b4f5d00e2f5e62618d567741cb5b6755328bf0f0e5738bf2da0392e2", - "0b02eb6dd0f3759c057979090595b491b26dfb1df9fa9b02a02e2fae5fb7459a0e7650adba629fc31a35a6ad8dcf8a6aceaddecc67b8bed018d5f902449cd72597", - "0a0347059cbbfb873a1e636cb475ce1b2c65aa72e8c44f85d9af28e8ce3ae514497e57f12260ded109304652c5736472337603932dd9ae95374d74d24be02544dc", - "0a03776b7d03a237f8108695466b94e519502510512cbfbe67eea72eb45caf7be4fcb96b56892e28c0d68607d227a1d24cd6e848a8b448b13b5aee7cc80892cac1", - "0a0691acb3d89c91635aa121f8d7114b9f91ec823adfde2dc7f19f7404a68e362d4b410b026f714b05c2d835c40459ac7791b02061106b346a47dc2cab3e42654e", - "0b006156404df0426ba8f18120bcb256b6d209398996175daf2c3214a1235ae338b3bf6be32172db2873d884dec86ec4ab6693369a03b753c826ad60970346b925", - "0b08c392e4ddfec0bc40a23c37edbd844c3391d9b10206d5c756442c5b793d0630cd72130e4bffba9e34299bce43f1f84aca27436cea4b3ebdd62bf7e70fd29f58", - "0a001e7c7411c2a28625d64d7e525cae6c68328f7c99eb5a861cc5e67ceccc0ec4a28ea132003c89bc9707f0108943dd4e3cf41cd89ecb98dacc62fafcb3164e82", - "0b0279996a2ced4c539ea3aae7beffd11a0aa417a9b89cbd60d0e424d1854053f05856f7625e16b92d1ba9e8fd9a44304f7141653b30b6dae50638a6ae884f8be6", - "0b043af0bdff2c892da12521aaab76013ebda355c823bb5fd4316ee17688fcfe580c1a538946a09a7b616735149c64824cfe8e0659cb04aaad3c8f1267121bab6a", - "0b05f3d7e426602d157c0bfe6abb23eb5a7875fce90b1857ba5e99449b5285ea1e010a86a5d4ffc482dbfeb1d591161e81c058e962605274070f3ebfad4fd0293c", - "0a06b6544c0cd948b00d7368fc34d13bee7f5c1910c8d5ccf2adc28314f62166f9aab5e700050c8b457da9f5ecf89f95511e42c88b4a4d349b94aa4f1e08706f53", - "0b035ea8bfa91669e23019c49f8f99c47a9091cf977cd48db0adec2f74215a2361862103b778e8d146c96c6bceb233113703960341a2a4fbd4d9d230bd34e26957", - "0a044d3996660c5e573ef19b419147ac7300f47b8709c9c52824235c5181724de537635e3cb57942a74fb88546e93bf6594cdb26aa3bddd43f65031486f8fb14c9", - "0a026e2299daa955bc0343b9884da36c6e7d94583131c3e3952a92a551233f9e769240930b3703c529aac97a9d7af9cfc5b603afc0ac1acd12885677756383ae2c", - "0a007d12c0fa3152e1d5fb6668436012f5a9a5ac8a5158aa87ff9d003ee455cb95bfbc34063ec22edc7c7ae1b67f5b5f139c0c6780c65aac2421b55338caa0bf22", - "0a065c63ca907f93723ab9862473e5a413c289197c79387ce4fdafca65cd9ad3c19f6291dad081b6f57dc1ae22955f67bd3f0dda7c5f628b2a2733af42c77973bc", - "0b03c8af0c02644968c0de00a34abbc25acab757b718588eece191b9f24210d6f2c2e8f60d89a4921123d79bf423713bfe661c1dacf768dad30bc3e6703512be81", - "0a01807cad3c43ea1c5f3b0b9b8714289cf7fea115ad3bb42b60ae7249f281ff45df8dcdcb83f4a4d3d241cb81e2d9c51e3b95d35940a7bd541f380dde92000722", - "0b02bce65f964cb56d5f806643a7afe833a8774bf75e8198e9f1a18a010afca01fbf411659e8964145777e251139c5a8db574cd8d3d4441ffdd75863560096c99c", - "0a07ac7c4de066c10b8a10fe660153f832801cd6c6a5b4f3795ff1b69ccd7349da21c46e961a6874ba309fa5680fa80fc57a595bcca16572d6ad6a29d15c0ff7f3", - "0b03e092cc53a8ea1e852def7735c98d1dc8da92322ccb958d111cabd11b10f27980d127aff9fd63cbb74d29ddfe086d201ec857f2b68d0caac25ab7c08f4da292", - "0b012c9eab55411787d9cd57dfaf30ecd75c1f2247784c3e896922f5cad14b6551fdc17026e72d82c88dd335f50d86eadab19638ce33a55a9154080320cd9afe7f", - "0b04cf48439f0ed3597733ff2a4eea81d837cc4d756018a21368f4c23e22ff95460985b693786a1595f36d63c2d011f1719b8981ec128baccc60519a97207c3da6", - "0b0610cce0df080765219ba80f67d6dc9919f900999d794c99d767ae6773fb42639ae94eabac947a990de4cb8f03bd602a049592340fadc4e69c0d701636b41b24", - "0b02a6ce6b98d9252d407b6515972e15677abb8ec27bb75a6050a4797b06eb10cc67076b660565f3d5be535654eb46e3f14de058120206b7589236bcd2f03dc601", - "0b0818c77e31ca73d3c43c6aaeacf22770d3060072ec820b8081559b5aafe4cb767dc21fa850741a9d692492b655fd575752c9fe5dcfe2c32da0cfa5f2a58227a7", - "0b02c9321bf18d578b43d02daabc6e98f0a56ac4fcf24ea757dcee0628881e1edcc179387889ea7b88d1fbbe0de40bc06b80c4018f32abbbd8ba5a6bf19e7b3b0c", - "0a00388e4a4076102b1d39f3977fc9239c2772206042c66880c0c0d86259db15d838d4e2d5fad5a69dfb0035f1805e744edc3bf9a91e06c26f3f5120ce2b9a3fd4", - "0b00043228cbf5be88ad10595a1c64e65fa2cfc509ab99c3de20338ab7759e70db09804eb9cb9123eb60b8f7d6f539895a179ed241b24dcd9419bd08616f0b268c", - "0a041f5c7a308ca5d3308da86c3cf1d6b7fb8da0b88ede17fb8f3f986a85c00e318f5c357eb46c11d58d75d6938d074dac054371eabbdae29622d30005f22d7b01", - "0a04ab04e1537d18f067a55f20885c39a0acabc6927f4c07512374ea7b4ca2d4ea544b298ac8b700adc67ca43ac65b0e9b262cb95d2138b0394cad0754f63e8826", - "0b058be30d97e8652d0e3047f10364e6ad1aa0e4c7904c91e60811444730828a8010b11a67331874eeb0f8f6003143b363461300631c61ddef794663750e018308", - "0b055a8f45d236623130102b7eb4421c43d56e6533ca2c94ecfb30bc03821eb82467bee4388e89d456aea58c45a49c3f06954068c499269e4b5c1df8bdf10971b4", - "0b07a701d363c3d325090b161cda36190e082f5d8484416dfcd2d4f96f97e761be55d6a4a9ea815263e5a77d68807eaca5eb70c5a2538708e52a1855819e270173", - "0a03d3a1c2e762ea0e38378c6d5ab709355ef975735b63ad0c332690e3b1e6f70bdd504f466b9130fe690c164928dc3c8ba596663ba0fb403dbde30d1389354a84", - "0b01e7257dd5eb985ce5f704212ff2c2b2c58ca923ff6aedead461e11180cea46e8e3b08469192e3c52df3d188bc138dac3ceb2ddbbbd81a63a29d99f8e900639c", - "0a0171f6c76c4d5297620c8f8d381bc68bc0abbb3899f602221a6aac7987022d3f88c6f429d98347fcb98ef08a25d546a0064f3eeca1ed42aaf86f8aa203a95b28", - "0b04091d209b17179701f59f69e20ed0445c962f0c301f86075358c32c062f2eeec3d3e73b887cdebd0b0ead99538eadb8eb6cd04fa3333e041911ae54c9a4ee90", - "0a033543139d2d90c590a0d735bafb8072eab0edf3be45057e4ca939a753ae5f61bf0b8711b8cd057526b3decbb64ee19667ca9e451845962101ca0dcf3613c68f", - "0a03994f3e614e7e4b5157f81c83b6bb7592e1c6d0591e62bdb911553dd94f38b018cd4aa8f9cbd5a47d615ffdb81ae48bd7b1c5e64703a25baa38c3b1db8ea3ba", - "0b078e50d139bfe263eb217a6d604eb78b27c23bcc0785a5299e211b74b8cfe9b3668801ac9346bfbb4ee06e6dd2fb2340e01cce28f8114a6fea7ccff4af603bd6", - "0a01b3f99e142ff44e249289d4ae306230b6a1d111166e34fd58e5c1622fcb5f5c419dcb8e02fd074e598ff27506c4be5de167d22d1028b70cb6a3be0008058aa1", - "0a050e442a84e96416ff8079d7a84416e5f9f794b6ede2fccdda443d9f48cfd2588cdab1757c9900c0d84598e6aa469882af5cdcd8e667f222473fe7986b4dd23d", - "0b01ff6fd88f40fee324a5540421644d670abbb27734e858b66b25918da86428b27b2dc713b1bb1b4e08c3e541cb39a9bbc1982c3e898db7cb2cfd5679fffafd26", - "0b0426adb2c1f286013324b54e9656e79b82697eafa4c5602493ef32f3ecab33437ebbc7d24d080237bbf56985c660dde449fc7823e2b38095b41a6cc17f75bd58", - "0a08a7738517302c63c1dc472bd472f0a0e3b72b5a97a9ada01f2ea5325817dccbfb64727053ea3e17af6fd477575a90c5e11f5f68deb46e833e03ff9a8e266eff", - "0b028c550ea625a82088abff2b8f0020f68b32ac9fdd6fea0c927dde948c4fa64e01f133dfdad29a72323035854c8c3c0d6e741a242c5df1e7ae7016e5341363af", - "0b021d2f00542c6d8256891acbf92db7c937ac2b67865a57c78c6f07c349463f5287c61e8a25b445a56e0fa59363eea82e6bcbb2e8b9bb51f55db42327144e949c", - "0a06f566cf1da4518fc34817d5d8db1c453903d7472651d06f55011907eb6223426cad3c6841c644b8672c7de86bd60f8697bab745b8a463175b6e3936ec620d10", - "0b084f86e5d6843053d2e22bc0ebb4eb39352812c738185b88dbd1a7c1041e48311d1d9f1f0b9a4e0f6401fcb1680f1a59b96a66b7a4707709ed9c528929219f7c", - "0a01a2607b7fbfbff6167b3f7cf3272347a13b2969a4fc370778f0d4d26a2ffb5dd68993fb6def59804bc8856003d5f7d41a30873192bc68a28cecd956c9d217aa", - "0a03bba212603d04708850db71ab98e9a54fcf31a3e9acdb42a394fc2f138f9879310a02efa4ea343b341256e1cc1e3d07c514c7a2583f04fc10bcde9279df53b5", - "0a05fb64be9a30f45c255f0516881ffbb77dc4738ed513b14bb0d718b47a50a0ae4950068ea4a2a91cac65e24fcfd749d4f317be67700875c433298e8162ec91c1", - "0a0081f3bf6df6dcb586e21ebc58c21bc6257c91431623a3eed0c980c53ade238ceaaf24ed8e9f08973c1057475bdd9ad93acf695a84eef227733bcfbfc63f3304", - "0a041f68fae80a5897ef88ac57345f9bb14e79e26bb32ee8c16ee80a3f8f3ac73f8e899d57445e237091bbdd373e4b378558ff81f6141a5ed7e152c34362996633", - "0b08665c202dd78de5571ebc1b696e72aba18aca6e773fe10e9688993646e7fe7effb60aab60a8be30caa824758f0e41420f956cd6763993e2c8449f27008b81fa", - "0a091405ef7ca453ed51014370bae76027aff5f0ec19239ff868bf68035d67d208912a1b526c70f6c6251a96fb222d22332a604f611c300372affb2cfe523768da", - "0b026e0ac1076be650e5d42ee74a7fbfc08d7fa2ddb4e65604588eb479e9e8f78638ce3e415dfc66a4b34f3e2fce2a7955f1c34e1ae794af9ae6f04cfbd8c0e9de", - "0b06695c85a8e49b11068a87207e45286e3afbe6118aa2810610a1a7cf92907bd18971030ebc28e0a0cc8b3f22ce06be82d5c7c9493fd6bd5bafff523268e6d0c2", - "0a0015184dfb6393f61b28f3fec7e9b2773a69cb2435ae0d38872cd04e595f12c8aacbd5d0530a513deededdda72f56842ee045fd8c199df1f1330efe4016b9337", - "0a00ee94e2907734c943369d15b31c8a654d1048947ea32859a4a98cf54b4d45bab11b33f27ef552a57f56916cfd4a0b0ca15c788fa581e2fb9c350be498d29758", - "0a004e75aa04667dcd6556021766b2f0f95c95b482f51ee7ecff925d489bbc7a8bd53fff3625798d36879b56a8a439caa41cd31d77f031c10009e88281dc66c8ee", - "0a01879b9b5afb9b85a9df03a3f9926bb238df16c46719b90992cd3130f751156e0208fb10120f944e7e436c0ac04b49aea86efb45402d1695de2d5bb3ed922e11", - "0a03aa646d7d0d67a5d883a7d3c87c634586774a231cc04359e5df209aef547b6a8fe3dbb5e02b6d06bfc97ddd477efc323579c7ceb0d04d14a0d5d8e556af3281", - "0b04faac894f5f45c94d608dc079c6da9d814306fe0ed600ca7a1f37305ac1ad3a9bbed7a4f07d08685595e01007c61321d36080f62f895cd26fc3f1a75b73ff79", - "0a0701e32f0fea71d6ce279c1bf4eaf41d1fe6c796a89ff8922f59b13791cfef9234548366c25751386109892095eba220f29f7edf7bf55f73a80c7b24187d34ed", - "0b07a09b074b5da96af317035e736ea81390378b1204b24671b7565fa3ed70935ce626edb4fea6dc3e652d771d40752593b3f12ce8693fc815cf3cbbed6640d2d0", - "0a06eb60eede0f9b3f17cbf5d2c6bb75e17192cf9fa102ac8870d1b7f5f781df48e1083354ee0bbac0faa7924ad7a8f926043990d988b1ea8a6c2d30d614a1f08e", - "0a072f09ac88e69b5e7b550d597e2a8065e3e4c2e51dad71a5ff1d9a00ed722e314d439bd761696864745e4ad0ce4dc96dda39cba43663ea3c34d5dc4e49776262", - "0a072cf159ea914d4e4fda2b5a57d8168461cb57d74c5b8ecd0bf8b3605d9cb63edf0d91c2cdbff1c2b565a92bc706429a8d582759a4f6b92c06f41b5d7a7b4c7a", - "0b0681dcca0258e7bbcf2914f7fb5ea6c53c32c48550caf444ebd47b963cb81bf2a5fe197d35d403634250de5156ef71498830b77ac95ff7702f23b9fec8fc12c0", - "0a02418ec9b9081775ad10ccc30a64f76af1a5d4659a27e00a77e74069cd7ad8880bf8fb0c31f9143e1b414bb3d46332c97f13a1bb5f6159385ef803ca470d2777", - "0a03183ee001e2de7e02b4f9964741383a59a3af62830b625292341a71fa2060c4555e6ef41d7b0f9de88a5bf0e2f7ac444f50ebde3652e1174abc697b88e06e9d", - "0b060c23b3d7e9a1f3f381b1c950045e62b9fc105743eff1336b9c24e1751896879bd6efdcd23182c25916fac695fad875ff1736b627554697393413c446092848", - "0b01d62e2322c55008f2717ecc1f00580c66fce1519554a2adcab11632705ac1314bd6083e46c1c1d9dff65e03e35a389a8dd1b76a9e977d10ad6e1544571e68f0", - "0b022662f7915958fba42523b456374bbb25dd8652157a3af2e076064a9b027cfc9c6805f1340c504890e194852660346ce7de9b2377ec85ead152c155f1b9d3f0", - "0b01b726680e8dff69b0ab13e77b808b04f19199cdb3c175b4ac7f5021a4c62d3debe3b79ecb2e3c934596432ad9d65ce568e4ae56124ab83f19b58bbbaa2137b6", - "0b08842023af8efacf651b0aa7e28c43d9f26ec7284b7d4edd1dfd0e6bca759da04723e2a8850030958d3f54b904e2bc3a9942049cbfc3fd4ae8918262e7a9736b", - "0a06f6ddb634f6d775d1f1cef8bce5e4e393ec20b1a6a2ffc23d89f14cd395b9c9c483ddef566fdb04f62dbbaf27979d94fbcbff1c167b33e905dfa179e25c0d99", - "0b012ced5d4e13f45ac6f73cd6fb12aa455ae1af702e7921add2704f1d89abdf9fdb768e12a8b03c33c0621663eb8693fed0ae0b3be7eea01528b12b13f1588299", - "0b065dc84c44c107dd87829d28bc6048a71b4342517c3312355d8085883bf3e146b8896b0643f908feb56d9116c4498b0424027d77f6f5d0a737cc32f453fe5640", - "0a07a1e8d56e6d66d6e57d65f546c455f04948aecb2b8a6faeaa4036263627424c099fe69e834fffe8a9f6460be4860ea3d704f2eaea300e83727f90828a318af8", - "0b02cd75f7b406f1de976fd18aa842e30b8760124c7d3f4750f2e289732df2ac67b40039067dd4883d14cccaf14d182a85d0886ba24b1154202294c6f26391d136", - "0a01c5837aeda420b0d8f7c60f992be1a7998272c0760eaeea23fb04cb8728ec1f35774ebb64bd863c58b4cbc277052cca16d0dcd9695b0dd9c18b235f9dda8b33", - "0a0080955d093fca2a29de52e33169284ea92d0c6ad03aa91f50a529ba9fab8e11346444fd8ae757d2b733d35d0caf230106510a156e41e70c98fe9a7a4f09ac04", - "0b0173b628ca1bc9038730a615d9309234bec551b25f06dbd938b53592f49ff9f4bb2ca9b8cf2f9372a7dd9edb3d75ee8d93c92d83f3b84ca46a6903bbb7f2c5be", - "0b0210e7c3f3ef3b7cb2bb4fb10b5252d6d2afda754f93f8c8276faef9307d0609219bb2f3cae01bfc3104d2840850e5ffebc0a0778796869aff808e0de5b3a48e", - "0a043dac8b5f530b96f8d78222cf424260c2141f068b0d9a30e31a6bc3a2e2a5f9c7561a8699ee0bd5a94968fdd29d535fd8b1d7560caa49fb1ba63d4db2daea1a", - "0b053a5fc0cbd366f6459388a92a7d961dace670aca7308c2ba5fab4e037e9325734378877608bd0cbec25dd7f01c66bc801619159126de64ef9117e192cd31f9e", - "0b014206ec5aace0887a483065079b77b35ad8c381cdba16b896634bcab03eb878e83679391b43dc12980e5fb99417b35891aec9341d2f1549463543d603437017", - "0a05f02f74fb0c6903a0380e0d339885df8535da09c9668e6aceee59760e54272a192861070a7d67996c25a2cf6a0cd7495fe646f29fd1027e505348aca188131d", - "0a0227fe60865fe3981837ff65b2e730c149cbd2881f68f8aea52a9bad2cdc3484f2e42d1fe43251f1e94c5a4cb814612fbe08c4f96f3466f329c2360d832676cd", - "0a06a36cdb265e50185cdc07e5cc3574f71a42eac457b8b362046c74ef0cfa85f3886386ea4aee8d1d2f2937727047714e620ea3f4a68ab527e20fd08e5ba5378c", - "0a0312a2ca344b6c7a07ad1a05137c1d9724b37c54af5e2c91300d33c70b5434be4d44c922d39c580affb835a62cedea5662d2e593b745a4dbf7b1fa8a80e77b40", - "0a031ae899d55f0db5500e0fdab98c55800301de735b4dcd27a346db33f8228b8ba56943f4195ed575855a4ebc79f58e5cfcd9245ed3f067b603eaecfd8cc596aa", - "0b044f238333af7bac1144d21732fa65f971dca0a8fe7cc6e3ce9d4ca03ef2c28b188c68bbaa6234303c4b52e77eb7703eacbe98f97c0decb1aa8ddee2f26ec731", - "0b03a702f35f6d7fb429da960e80406e986a7ed51f0c3f06f969994541886ae38b1b25d9b455db868e8debf78514445dc86efed7818fe603da7a2cae63c4a6ce6a", - "0b07e8cc913d6008265a4ecfb8c4f5302db4d054f711c351d2c6fd066c9f75317b22332e11ee20acf1fd24534cb8118b58cd9bd603fe895dba4d99e39ae5f0fd87", - "0b069241563d342d5cec1f8564dd2c0ec5e150dc5c353206e192e5ff4830ced03643c6950c58eb688aa5d49e3cb7751fe3c1cebd0b8dff92fcaedbfd4b88ace884", - "0b04d22630bb514b0718351cb376a377562822f9702de98da640dd0a98ac00fdcbd657f934a428d4276b6b6bada51d7ec682e1a9a0dcd5f3474353e9c4b1b47e10", - "0b035f2864d90e6c295260b1763d6553c760aa1b7b2e96a4e085c51925dd2f374cf4d2204e9d26478b624dacaeb3536678e9b8470595467f1f09eb6756c2e5b3cc", - "0b002e2ef029fee15ac62d039c55f6a2c949d71001b857e43b7271fa5aa717dfde7d2ac4cfbd7c45a87f858b8de0b38a306017265054ef1f30681ff0140f8f4522", - "0a0727bbbec9a5422e516bf08ff0ebe769bb05355868522658c9c8584f6b8ab9f6efd0f2938ce0427c7f8bb14b6ecc37e12d2ac9005daa2e0d844ec2a27802f0e0", - "0b04411d08b309d452f0115fc77140b78ff363df8de699d4a837237d18af0a56038fda38970cc3b36f3e5e21a715cb99c5477fa9917f07933d28b139e69ab8322b", - "0a032f45572c39ce47b479f4c45b58ccc8dca711eb8fe99125bcb3767c2c612d86f4ee233ac2c72ca74578c54225743e76c6a91f8326ef7bcec7133945951e45d4", - "0a0591853545c320e50d2debbed5e649f4394262872214d1f6796bd1b04715c7f78c48ab3b433f2c3066aa831a8d3f983c2982b1c16a4be7f05b098b0784f0b1a0", - "0a002fdfc51d4808a85d490983b3b1489cff2360018dc6307432e5a9c39626f84be4e84e91726d517f827e88dcceeafeae4be274fc7b611356b2315ba4c043588a", - "0b061d8061070544cd9d7608115ef8b8b178f00d78825b4ad343d96f8ce6e923b90f22a5fb9aa18d735291b427e435e3348e4797e3f868bc9092342279fb830bc9", - "0b0538bdbe30fc7a5ad48963b51999604029861a0825f35f8621ff6106fdc747bb25cc4678299ad7eaf4f514444e1ae7d65f171cf4ca84634c9f92efca251b7258", - "0a06bd31cbd3f762f88f2d3cd07086812ccda890191229e4dbb09b3a9df76ca58488c43b7f14faa0f7ddd1e7e28734dfe92c7372122b481df35ad34240c5ff6a72", - "0a04662120eed571bcac57e40b8873289cbbcd7a0a2bec847ca83604244d74b8a6f666efee517031bf0f4562b2b1d37abcb92e05a0308e03a8addeea0c64a5c088", - "0b072583589add2a9bc8855987bf7dbe42038a47d2bacdd152424285997fdd8401af89272a5ac718450101bca163815fcc95cfd4c6b344a1cec64f67a9e03b1992", - "0b05d61a9bcea5a1dd32e79420225f496036f0e752bad023cde5726a984627070f89abf02436ff9f548190ae082e6342c8ffd0398e63ff8027cc69cc7d946ac76d", - "0a0491e94b4f51afdee86ad3508626896bab94a551b234199a0fd37e53ac9d925541c319b5f098fe2fbd6778e8e160c113edfaa79bfc44482f2d9042dc1f2805b4", - "0b057fd3aeb3f6b6e2051e81e66013f75041b02cf91c26e8aee9b0444c026f83b16243b9548ce290ce3e8835eeedda036f1a5581ac15e9211a4d2bb2a088f3ab43", - "0a082cd2dbe9f78961aedf46c970b68b2840877c4cff8c6ffb82f5732450cc45378ef391e3d244cc29223c922a9022dfc921e4c35a004fe6f220d9a8cbcbe12d98", - "0b034cfefdeae0daebd6d9ea2ca7326a6a432083912108d9267d0f1ef0c3f827029daef5b5d50b6356c3c83a436e200ae4237c68b5821014c42a6b9b1059135182", - "0b046f6c11607b53ffa34b9a49fde28e7540f4cf00fa0a95c88d1c776ddcac531ee057e3fdcbb9995fe623c53b37e062062b7904e4706051316a522a6468a6f150", - "0b03e46a4511b711e1ae5d6545b00cd76ead628cc06171eb6ecdc54de3954a0af4f70b814e8b9dd55a9cf5ea8524de663a7d0132d499e8a49305929514b327a963", - "0a0373f0970dbfe2f0da3d6124cdb61da114bf475d2781e77facee45e87e2116ac7daf5ea0926ea5bbf10677833fd3c33c7f1016d9acd1b7c0903b6a97912da827", - "0b053fa86b788d20b3947c35822ba848846e7b54a96f14e4f585ef27c5aeb1f6c81d34cd17b1170de564fafd427ad293229edab6782f196fc03ca75286e8bd623a", - "0a04332b03e9fe4863711454229f2511078e57028f57a22b01e6ca05a5467c6aa6e13a5f78519cb3336389ee15800cdc2c1ae775dda27fda616b453da3e3d0af51", - "0a05aa299f765659e6cf37ff4ca108bded85d05a8d0f4d7295cb82a90f3418e53d39a35e096d98a4c11654eb02049caaf4bf3d6ff43dcbf292583aa0952d0ebd40", - "0a017ee2f4d481ec2692f8c90abaab7a33f7d373013f34ffcad39bf897710695287887044aae6917b420b87659c4ebc5693621a06058303a2976b650e23d27098e", - "0b029e56f4c3a79d4c4bc8e99f51a4930079fca5ae6bcb296cca1f3a8886631750a63cb4da8c251d377bf78d19b627a9e80739edaf26379e6d71eb48eee19c75f9", - "0a06a7936df445e39166684b45e0f09011cffd6b90448db7abba1348d2c4a81e47f24f0e7c36db08c32ccd0680819eae2c00d6ac936a7f943a49a136d343645db3", - "0a040053ed979dd9ccd0e299420c4ec9e7fc7b9b7760a681e450bfe19562a20950cf9fb0f71f382ce2db65fdf4af859dc04b9ce667cc62dfc88634849ba8605268", - "0b04b2c9898d012b9111334028a3987e1fedf0f00cc07b557fb28fdbec0352e124048ea62bb259ed85b5858a27b9c3d1d2bc14a17b9689a59972735d75763af362", - "0a064edcb87b22fc2f5507fa9105615d50ba7e97cc7e57f42dab02f916f5368f8e9fb14e22cc3f82f66e728e1c4f54da6b03cac03421a18bdeb96fbdd899f5f7a6", - "0a02abc15d36ae5fcfe2b96927ffda6a5a10b31c831605c6be2969442e78efeaa46edac5f43e8c2614413e05a849a8d63b41146794dc3135314ef87782cf8564d2", - "0b05385c89b80509e633b5691c1dd4bd3aa72af48d2720357354028971c87bed76c46ada340aa548d0be431b003b1d4f18e2de27ef75ebc60857b6e0078b7d9f35", - "0b03e6ac44ba4d16a2d461198d6a2ce60359d1e60e33c02d7681edd29cda08257ccb0ea58061ba1fe4d23f8a4aa28216c8c1fdc9bb992c0712e7965ede4658124d", - "0a0251b106f66cfbc2764bb34b2e83253d1ca4c7f198a55fbdba8c06e9f2ba09d11233660328396abdbee2ada20de576fd31c8277eed5d4ce54345717d2ee49458", - "0a0391adbda7cf80e4b0fe809f66a61f77d7a148db131f6095797c3b7bea44dc4addefeaea86bc11e4b43c6bd1a8f35eac3f6c076ff4fb05155e9aa7a0cc36b9ae", - "0b016488a2951ed73aa157afc9f4b6381be40a3ab87bb17439c946e311f62327748a047d2a45252c78f145b2484002e6e9ed25b6fb968d90d6b4d7ddd9ede5283c", - "0a05f8f8a47c0889361e7b34ab0864729396957d42f187da7348cd5a24fff6de6d6d930e06f7d03682ff85dd0761fe4e1155442f2f6e888fecc8218162e99cc50d", - "0a036360501d010db8fd481d256400d4a6b3b4610b27721b536a6b5db83cb7eb2b71bc6272a0b49d34c418579cc35f1a91739108e2eec68a49e960f522f0b5fd1e", - "0a06341eb2448318e5028a5ed337aa9634532ca189a0149e181a050b165956028ac921d210d3ea54a95e066f00f9274e4c3406737a381317634428b01554d15453", - "0a0843b9080ad7d3d169fff4f7db6ea7568fb2c80043910559e99d7c423bcdaff40b9f427c64f90f8d928ecb5da72c22cef55d44675c2918a61cff8fa87230d304", - "0a09056b4ac0d146f7d68987995031993ee6582f006841a01526c8bba248c243667916aaff892a95ad208d9d32e5cb960f3d3440114d9791e1520a0d84c2204479", - "0b0706ff00c02de67aeaaba2d6d1fc7f654f8d7518a2cc7af2386ed3fa7b7fa08cc9045df0041f49ebf4c3012f0b3ec852077b9c31973fe3168d81d8538a6a121f", - "0b048a6e036e839ac97691b8706aacf5137fc01f02c953ee4c54557129f4a0815dd69a97de6333c6dcdae2a63efa264defb27ce2b272ceafc8c6464a63c03604e8", - "0b058bccc6882a394402bcc8691506f9b47702027e8b179e0276048ac623dd9112d663d1fb94ed1c725799298eee293d6f26a0b7f44bbe6bf9aa53cefe806476ff", - "0a0391cf788354d4cf91ce356d94852dc40c148bb5aab82ca3fa30c0f59e12158d23c49e73615a2b1c3f35c870ccc7ffeb00b2e665a321c0785bce5c1f2715d271", - "0b043918be13ece975b3f0f465fe12809e1ee9fd82e6c9e8a55ab985bc41dbd6f911dbaa0d2733cb5dc409ea685ba4d487392bfcb9b206fb09f76510af16ce8dba", - "0b0220268758fcbdf42485dd8395a2c354ee01535fd30e86429103d1f93e58c1d0ff2da9be62f3468e2263569082a7177baf339dc03de955774c22524dc20e1b92", - "0a03e933c7f188ea8333073e916babecad1b5418348190e739158684ebcaf1e0ca7ce09807c67aa93cca4504f6ea35402f19678390c0db81feee3fc38c3607bd39", - "0a048ec8d6b0d0bab17cd68f9b3ca87a7e4d8ae316b0e7ffcf61a90c3b56c64df946dfd12c953270588e490b75ad0a5af870a5a7091f329ed01814b47da844257e", - "0b01ca73fb9ea7565c16a49d071c9c37e285b9ece5e466b2831f2eef36772ac0a71f2b14801d997c9ac1b4eb223c66e5aba24adf075959e17405dba9e48226f990", - "0a0196074bd67874a52b1564174d768af1d4239e45d1750907a29db7d91210bc1eaa365335035678265ef0dcaa6f4d2c2431e51346796451679a0bba72b64cccab", - "0a0490bf5bdbf3f23ea9ded7e68f1e18385f2a37cb5f5691574bec7af9700d358ebf6bda8a7bec3d3820ae20b6f3d5a09db3746e74a92387837424db29458a290f", - "0b02e679c095e7688d6f66b7f160aebcd3b8d4e30c386f8e9b66eab6671b417c9ceade2de073d897d8aef1865086bfadb7ff4e10d7e5251880db05fafcc6113efb", - "0a00f1d5a8844528225d6127024322503f84422978d9541242e7892955ff54a2fe80d52746171f051bd852f47c48ab8d0793f296e534e9b295ad668f9af188821d", - "0a086db828da0c3cd80163450db4ca107d27192c8d2ec8ebe183e14f8a043963a333dbdaff4d8467bd986277822f6a3f173fdf5d1a7ebe4b17f3447569ce7e657b", - "0a063ac5df2d3be0302771c7ae2be9482894dc53292ef6e31e99d46ab71a0cea4894c8095998fafeee72cddd5c9d9667f05528d6cef4ad038d862feddda693a831", - "0b08c3a3bd9e24b2aed0733ce5494a71e68d96599add73f6c1225ed98da0c7f543f0d6255e79c8289078e4d42c19e8bd59425db384e568977f2fd5c65f6b8ffdcd", - "0b0896b779350c7adb2a6955ad4d48530a6948dca953d53bd9cccffd22397834b5cf6d06d068a072aa212918999ea718707a287a3eb595125e8780d37c831d5647", - "0a0598e93c9b059bd6098df6d5d7bad8e2fef8bbd93daa8189441062e499db0fb6567a4ec6f18be68e45e356a954228d0874af9002cd8ed5da89d48f0a8d30c6c2", - "0a05bbe8374f75deaeae34f7ac4f6e5f9a751b0e18a4a5232b7f105485ffa543ab2311ee989590d80418b0d24cf5c8ae895f943c5162a207e280874d2519875145", - "0a08b28bad564bcf22d9fa903a7e79a325d11a50dc280065cd27865a9f44f2082ab957355672516cd4d2ebd3334e48cdde9526a8827e6d708937ac9ce67b72c8a1", - "0b05152503963dea2598103b2c21168f2ab7f056c3af8b0a564ae5ba3b58e67f9105a04740cc2a0d244da5589828bb5b0f78410e7ab397efb17c34c63794fc55f5", - "0b02d147a1be557d1b0afd78d37ad762ca1a657fdd72436f2694317ebdd795d79737d29bae0be9308a1732e75a0372d8cb86b05196507ef2c8edf5051279714ab5", - "0b0535b164c437637a16f010b58b7d6e4d101685051d9dc013b2f45f5b19698ec4cb6e9f641404ae0adafd4cd4764ded81411c0e1b7ccbf2b0cad588f4fd69c56d", - "0a00d45ba41cd7154f08980e73a1d5a6df809d428ff4055f244fb359a774856cc505c6461658f9ba2e64e3506969baae21f1b77833639e47af6c0785bcaf6e92bf", - "0b015e0068028291cc524d84229042c1afbba5f29481b60c27f4047f930f6739ade2a5e429ea7c12160caa82059bc2411e19f05c6cdb09e3e68c8f5ff68ae3caf8", - "0a03d15fa7af8979e37687c30a3700d7bd0c525e04a3575d4a06c2110041b6831b58990ff8a2047f9c171ce58cdf53d968598241b5f4f094a6e3485792ad1488e1", - "0b021cdf4294f019e4b1562559d9459e0eafdd455281317514298ce0812b711e985049d08c12d6f211d729566899be218e25084b525ca9e3d0b0a9774dda2cae55", - "0a08393f54943c8b8af5d45bb0c1596ee3bd30285e660d7fcfbc53bf9d11d6c45ff26415c7e8cfe2aa224b16bdfe5aa4c6609774e62938aff5bd5017b2906bb0e0", - "0b0854c48910845fc5a95339480a8a6513e9b59fb2a82ee1be0eafe86b1c8d20ecd89fc0cc7f972464b586f756e3b993e5f0083a906a0fed5eaa26b42d0be07cd0", - "0a0891dc1fc7d26ae3be2e471b5a63d5c9983c2241f1a3ba9688ae6681a104752f0f96f6a7f3efda054e8e30b930e4e0e5d91f6f7253dae48e0fd90e83fddeb307", - "0b02c117d7ecdbe7953f0f4792f6ffcda70614f37036db7ecd8a23072c512a44e4997aa4cf84a3bfccc5484e41a21223411a4cd4a760e552b3256ab97b1fc83223", - "0a03dc42ed3d28a0f9ddc69bfa3b6a4ca3d8b737ff8e1b559d34fa102b0f995e414113d1e03049aaba7d841c93ed35fcf346745ad91b6adeee63023e56160f5e5f", - "0a02ef5594df340d1f77e93f89fd7b3b1c9e9d8415fc14d5a782e081e5ef55a115f97569b8b2396759de47cc7ece74576ecdf2fa33386d38b1dc42ace72f313bd1", - "0b0313949ff04bf394b88cecead824ded70cce29ba327619e0570698b19c0372de2ee47f4ddd7c1415695c0a07df652b798d800a5bea31b0d657247d8533308608", - "0b004c54d1811464ce3237b035c5ce0e22cdc5acfefa3094d45b7088532a07c293780b338e873101195bea634e4200cb17aac780f3a245d122cee28854f342d26e", - "0b02ed44b9628452115e02be37d9ee63944ee92035ef36688369e8f9203c6fb41c917939dbfb23c2db2d6fa1d63c9185b421706e532840e99421977e3c581675e1", - "0b02bfba115e9586acd853ebdde2bb30283300ee36edd2f4b679b63c4bc1ec74d4d5747508241e66fb3e66342776c48f6d4fb2f5a110065ba4a2891291fab96b78", - "0a081a1edbbed5880e5308f69313d48a216ec4ace7f539bd6d87e83ca0b4f627d980989ed597932fa906f765ada3d851024041ab9613e0aa5d121ce4480ae9effd", - "0b054f103c3bef0ba8da446e4a2169db0d21fa6d05cf8685cfad279ebb12a8486296e4807fd35085669befaee39d0a5db1dbbc8f722013764e0dfeaf086dd2f8de", - "0b08a8a295842f39d703d36fd8c18a61f007974873b10b3c4b1a6a91424f75374f3c20f68c6383859f3bdb522d728311501b601a7eff6cdd4e251e5d86df3e0a6d", - "0b05f0cf3cb05e52e45487dcbf76ea3526d16cdd664fe0ff9f01c9654c0c73d1e147c5068eef25d4b0a69b401622ae514701e69e629e91bd1894a0d2e98964a42b", - "0b07dd4c3567676fb0ad1f89956a5963ad6d83724059de32114802b355133ed0648d79097c4f29f9b6a4111400a476da6e54dc36e89547e5e4cc653f31fb6f9f0c", - "0b04db2cda0deae7166798eabbf2075a5dda872546f9ff633f71d02aa3513a847edafd0c01fb5d1e657f88c7a36a827895be0766b90a177fdd43716eac66018922", - "0a04ea524249f2631c6291882eb7493a7aebe3fc2343ccbf1252a9d26e6f9ddda8c370cbdbe5dc390db5e4a9c2eb784738c401a1ef13d35c7226b8ac3b0a668335", - "0b00b198329572e8ce06743b4fe036dd052da705c25ce9fda7540abb0715193030eaa3d3393421710c4080bff193eccd4d2561a02c5c621e2848de8ec8918394c2", - "0a0095b8ebf5553283209231a1d75b93536643046537353909b426e77cb0baa2ba05995d7053c03fe8f1929cb4ec2a7e21064c3d30b4aa2c35c3a9b349bad6cbf3", - "0a007f34f71683a62bea92a11149d7374be0ee888b72651147d523e2753f20b5156ae1aee38117c125bd97680363d31fcffde983dd14e46773cf2394eab25d7c3d", - "0a03a6897f198fad4f917b079bca79265ff4f411520734600ec1246f8c67d1a77837f464c6f947bd9787b42fd1843945f83c558d5d1cf4dd3e647e608544e12911", - "0b035c2142d11eb82c02cac00bd6aab2ea670d25c208086f74629b6f9e1dc38106d424980c2f77b363fd3a562d880f93f545ae2c10bbddb2fc3f6e6011bdab458e", - "0a08f6447afc6e3d83cc049e5685241db7580b7b7c40fa174de68239360fc826fbe15b43c28501a1d538281f7f13b69118fac92fc0d286fd4c18fd1bdf17a2ffe6", - "0b080818f146e713b268a7bf75d29fb9bda29aee3b26fce1b9121a3fa028ccfd4dab5046370f71cf4ba4bf6176cf700a93fd48de9e1a25a65c23ef321a52c01b3d", - "0b06e10a37a2b76a328926dac5823c474010a42457742b93a5a89162ea52683777a61bca0f1b0c08df401d31d1f3a0454eb295a28425b7aa19cff101d608ed4384", - "0a019f370fa246b8e0175b6ac51f2d01acdacd51cfb81a5c1ab5890bd17eec8aac87e1cd89502a7bc3abe85664a710404ff1ab4b22fc58069777af5ece1de75480", - "0b011928c5f19908cf19559f4f758af2131461d38fc0a1dd054e5175a838f616729963660039ebf661f4eeaabe0f31c8a5801da3b23fa854aaf452a6335966c556", - "0b06cdf76d356c4eb4518b671506b24b4ac308c6774e06f5e4350388ab2e6b94e227203578a2ea7187dd3b59de3a8425a32a9599018bd5e987da34f582facf3ea6", - "0a032c0cd566c43e4b98203ab26f634769bc42bfc748d3d1156a67a83dfa54ccec86993e10ebb730a3a4488ee676dab30c094001fc3ecd7392bf487c89252c6d83", - "0b027c6a5b00382a5e94e3c110ce6f062d3dfc64f822b4066e8247d5838cf2b6ed442ad5fdbfaa4627e3cb166b4187018e5b8fa95a69b725effa0f3402608da1bf", - "0a0107cfd549bee026726ab2aa839ba556a20464fc3c3b784066b4b9c5e138b5110bb84f0c85f40960e19c66732c771795c8aafcdebe06908d0f30f979ae788ca3", - "0a01bf7b7c302d34eb653e29047e3369f46dc2bb4967e79c56bfbb1ab6add0926f844fd52382cf6a4a57cb188e95bda7bfbeca94361847dc7217b1eca3ca047d58", - "0b02183d640f0bbc647aae575a324d3e94b5ca5b979e10e49966b0e366ecfef29899bcd877d5146eb0d513f46a718a87004e393ba20beb44358633d154d222f845", - "0a04422f6daa5171445e4fdc4456c878c3e7d19b1d1bbae8e2f757ed62ec4bf80a2dca5135b70ca2e9e5c396adf0febd93acf555415435c5c00d1042acf0cb16da", - "0a0749db9520685be3c096a6a0e5436cc2653caa678df4fae86d4b6d474fae0c28eff11695b47ea1d280e217624755f81f57886a14351e37d8acd1d16423ddf92e", - "0a07774e8abffe6f37806a55f4433c143dd9d3a4e55382b2f4488f9e186743da1ae34a9cb8e03db23b1a78f38a1edac719f27973b6aac1b9ee61f4436679fb7730", - "0b03790eb61c56d548effd056867874e69b45d171abaca7c6624dac1365a6fa76ce40d868cfb136de321d771fee3c2d26a21639e03630152469e5dff3e44c58a5b", - "0a02d517cd1325bfb241ba67f6d7e946c5ba822c8facf28a4ae6a1e9ba7e78c721999adc92f9dda9e188672f050d20be72c7f33f00f9b5d752a36feb55ee2f846a", - "0a08e7e21724824be7ce09c265785e4250e4cfeb5a96769be23cf7e885c0e5642742e058e6d468e35cd84b1c73aa1754cf6b0e51612fbab240281f89052fc853ef", - "0a05c392acdc9595724348dad3f714a6432b96359f831b7f72a4f07cb8e84a83d878e5c9ab85cc95095a18ce0b7ad5f40c200fe561ff7c8d28c4d4cde217574214", - "0a080e3f3164d8b5d4ea1c6846cc794190533a3e76a0430d7c1f09e54515310f7986734b03aaabbeacefbf3f245929fec684a06942d1ac3d8ddac4b15ad98592f2", - "0b03bdc4e865ef618fb5f1234f7bd9b197ad83fa06abbee46717c59cc1635ecc6ac5ae0788b63170d1d4d95c32dab32de65c7bd44a13d4eee635c4c853865d5d84", - "0b00402df15b55d00df75d5218aa11aafa61cab12cdc3fc3b347c5fd16426e0079b51599e0ae6afcaa608b56f41bc482e79311ad3223c53edaa65289368c08d1b2", - "0b047f52e21561a4e2382f236a0abfeaaa118dcc1def2b9f2491d598bd64bdc9742503cfda0a7288e80b0959b44f2e0288751d758a8c617a9ad28d7fac830f1eb8", - "0b04806d0c1dc269ef5c727845398226401158fe8f2bef2dd1eeac9cf23318771a371a984224b9091c4ed64886175c61d52e24740b71f3182aeae2b394b4a6ca2a", - "0a01253a0b6949fd0e500c52b4f4d4dd3f9608cbcdb4383294003f829caeb8613aba321ca774272b89e155b21a32e623d7de8fdffba51edc87e3a7d2f92dedee2f", - "0a07b262bb299a8a87b382d59fa9817177be5519d4cba928e8ddfd91f352c8134729cb322d8cdffba4f94c969fa7358730032348d2dc90a9bc79631c40d66891b0", - "0b038a03699ba8347b8bcefda821bf236d27e3c3908de7b1a780e73269a622530af95ccc1dffc556f8bb2f90a3d10ae42bb154d1482287d1b2cdc80aba61b85699", - "0a05b744b290b5d46024baf707f9081b3b7386b5b6d44cd88013cb39364a672ad21205eec71c2f9e08bec80d450399a87677567bc348f6db3d7875ad9bba3f7cf6", - "0a07bead674ae166e777947e120fde5b4eca6c2facf03fe4f8e8c60a4f59948897df3fb495770259b1bd0b492c2d247c9978de66180966b0cce66f81549423ebe8", - "0a0045d4c145d57b35ffada2828190b481c9614917c94a8255c4f54d3fca9e4af890b6098ba3a5b0ce4378dac983d26e9b0017694242cca699a8796abfb443a443", - "0a02b3a3d62088726c43408b017ada5b25e278d66409a98efb28078121680dfe7f42fdbc0666bdb0e2427e413ffe174508a38c6d7876330d9edf381533d96c4b11", - "0b06f9e5e5ec9ebcb3911b03adf7e53483bb2c528dce45f7cec1814a2ca5db134a9281eae3fb6fe30d72d92b1cdd2b0fd982cae26df6c136e0e020b7d10efa966d", - "0b04990cafd40bff810a1ab515ff60fd7beda58087570891dc2786758a1c6d3fddac59d245193d58655a83520ce2a70c0f5bf5231ab69e492824fc0e911417c2e1", - "0a00f8e3f5103daf857e04b4079bc31431802ac1237e358a43f52d736e5e3e1c58379ce6a334a9a022ef7d8beb6052a576dbef88c40c184856c1f70a9769713cc6", - "0b02a30e3bd56dc98cdaf1ecfce94fac06c68b53c80d07c6fd2edbcbb1b76a230398eda47642eec72b59453dc90d845db37f7c25477ce714a1f82871b85f62557a", - "0a0413bb48b560bba424d1ea5eef44b08d1853baab4625db0f04d03f1515268386da277b42511f676764ba5e067f7e1b642c50f121594bc6c8ab502dbf11a135df", - "0b0764e8cb3d56b6e5c1cbb26d0741467f627034bbb089e17c4f7c1ac4e9ac9b691603fb99bce8b1f6d724ecdb49e87b448b08ec914103c1aa3accf948a2bcf3db", - "0b006fde366ded0883de3a6816c28883dc858d1fd1fd19ff5f834e6c4169f6a769a76dd51bfe3b86f0b8e838b8e05b4d58bfc2f569fd431f5430f3deaa988da3cb", - "0a08cdd57e0f6c9c99aefb2f5a00952ff84c510355c0e44cff97148ba4fb5610d8f413e61e353042e5fe352168100c39812953b1c71ddb3df730017fc76c5a1ebe", - "0b03bde01a2a6358d1f1c0af082314369a4040fbd3bd7fa079e989d98ebc4bf88721ce46687e29d0bbd08d0f384c4a116642acaf1f9ffbc95036407e5790ae694f", - "0a00ff8ceee68623e6482e9304fa203040ebd171bf5a77f6a626b8daa0fa0225675896d9209d98e7694d97a0a6e0ea23d56799dcfa80de4ae073cc5809c8b18518", - "0b06bf56cf71bf18aeae31467b1db1cf3c39af2fa6694e5412c0aabeab01e1769836ab78e6b8819b92ba345389231a6417e6f50a3b843e74cf6c989546816821c2", - "0b00d932b4e8f0ce3ddf3ea62f1adc7da292aae257bfe40340666327f5f9b08babe401ce52fe93390bdd01df1c40ba768357fab6621ab5951e16bf9a642d02536b", - "0b08c81b8ee6716ba7b919fa72cc9a9a582cb4fe3ee4d84c70d7487997f4b5b60bd0ca11b84801c3ddea851e89031435418a5517b9d5a2940d00474965927eea0a", - "0a029ecddca5f8d67c08a70f0c162c4d5d153336c1d6f3d6d072a57a2d98eb4284ff8fa11b148abcf5f51fd8a104c32b6b6775ab57c65ba60ef6026eebbda4ec73", - "0a031b8e2a728aa3d77ca968113095757f2c561415eaa68a05dd72e94d3c5fd694bbb39e2092ed26cc3d1ec43994bbb7b8e5383526a611b8ee807258c2c37d2af9", - "0a044da0af931a79e33b6f0cf5be31f9c219e2cc3d00e2bc3f7d40902c5129f43d5e5d4214759950d5b9d89f1eefefcb3b0ca0ab47d3a75950b576eb21f9ee2b0c", - "0b0113f48553bb3c2344a0075259b4ba83d9d9290bd67b25db9df6b0614cc75b8598be1bdbdef2d4e9801e7526bc6e5977a1ad6dfffd0f3d11df8e00d890e2efda", - "0a0904c252b65acf30c324872d1f397cdbb08d66a7edf0ee1b5022ea034ba674698bcd9c6f4a7d53b68933ed55392ae822d1b10c33eec940c562096c8cd3a9c5e0", - "0b035a376a55627cd869bbf554b2aba00c728e4ff1c1955a9054a64e301c6dfc0c9d556865c7e429fbf0640a1ed8940608b3cb7c1e6dce196ddb23cb79b8daae37", - "0b06d05cc3063102f3d0ef3df766ba48fef67e1f5112409e7ad8df4623c9644702d7485dd939bfac07ce35fa46c174721d79e51678b4241be04573a0caaa8544b6", - "0a001fb5a9c9ffaad235b754439a889cd5155f16bbc2850b1002ffd29ac5e78b06011c98b1029d6c80fc6b0821718166e8f22df731efff52574baeba6cabd0eeb5", - "0b0034ea63cad10c6408733f13bd6834fab024056cf4f228aa10a14b897f2a429c65ad2ca78115fcf37b0548094420a9fb50a8496d56dd0addcc43dd741c7375a8", - "0b06199c477f9207b38e916002da83fe7b7ffb6f2ddd3898b35613cadc26a4008143658bcc93cb7149e2fb9abb0e0ef69adf1ec377ac9ad2067db3cb80ae297004", - "0b03756fdb553ac1a5f4a9a9258fc83e47ef2207bfd747d144fc1ae107dacbd841388c97ff6b10421533fa2f393af4b0915e9a315fc253e00dc8bfec5a1879a23b", - "0b01bb1d136ef87dbedfe529904bec4da780e0ab99b0653dc70aa9d1ce85e8d3b072ccc6bf9cfb8dadf4f57482069f592721bfc618f8bbf19e9f3f2e1174cafbf9", - "0b01c2f048fd24a80bfc6920de669d3bd06bdf54926099a514b0f2e8a611c3204515f55c392cc995e6c2f1b2529bc0c4c8ed8bedb1bcf3cd7fbcdacef5932859c2", - "0b07382ba227ac4d37da5f9022b6a98e0d03c3bb73b461940db5a34eba7d377a5d21ce28dd8f4d235fccda0c4b8b0046fe08dfcf0f48771cd0427be86329c6fa81", - "0b004550d5982b91f5a59837200d78db1678277e441af03a1bf5745325966f1cb84978d41ae59c706254c7497ca994f4a7c08441f9026f58d43879f38b3e5a1c35", - "0a043c0e231ce5ab8aa908cb34553f66165c7c45ca8451c98096a04fef78e7c60967e87310fdc250fb3649ab676b618b2fb7e4a4a4091e35cf5fbe10ba3abe4b24", - "0a085f97cbdd08b04632c359788a2b59816340d964efdc01aaa18d0bcc573e8d13aaa9a7e07fca297154dfd7685029b40bc500e8239995b492fade2cd6149557e9", - "0b0657878e95595435ffeb7368f084021f47294823ef3cd3c524c481e23405aa3517f58666f3c559916c7bcca462b560ce32335ed8f733793cdb8eeff68bda7192", - "0b0048a47bc63d51e2cf5bf32f3f110f344dd888f7b8e7900529001db374a77d5a9629eae56bc96062ac0c9a1ed09de6aae5bf9a6ad0d6bf2659ec7e0a6a0377d9", - "0b02a1024e8fc97b8a4db8fbff0f78e9c1d650246cb7fc7c7bd510b056fb8262b96593c9e93e0280b1254bf1a0db145f509d3d7f7cc1e7bea0848dc212911f0599", - "0b04a1772a0a8c455ba2d1a9a6f207634b85e290f5cd0e3cf8fd97f7c97a0f16297defc02eff0a260f79e98801c06282cedb45b0e09a365e6fc7b2eeb4c7c55fbb", - "0a013628f6ae57e11d36a250af1c049941c43e28f3e563474f5b75527f3298723486dba12948c1fd13683412fbc107ee1b386a9dff7e8aef6ae0879de96478c587", - "0b0454ec92f61211c449e55791182a590078ad5c202559b2bde32d02dda46eecc617047c016f25bf773e9a34d0ab2d61569ebb5344004964474dcbc30f89a41ee3", - "0b079b06a5063f482f10bfa4c3d6a53bbaf93742f7c4c796542e4519e56aa2d2a5ab113625ed5fe2a1dd5199e0e66065a01c6fe37603e6216d91e6f45fcc106ab7", - "0b055c378972b7d4642f5d456bfa70b8414cdde4768ad8ee78772fd0c626dd8914cdd9dd61263eac94503d640eefb4e7883ab95296870c7b063d800e256ad92d2c", - "0b0284061da91ee2a0d32df3faf6481e4b1a657aef431e5d5d016c0001ecb9c4265c1b2dcfb7d272c8cbfb69b7f4eaf442a86996e9091e32cfe4e6dbeb9d7e2a53", - "0a0453e392e1d7e815f0ecf175bc19e839fe10411084153420c5c91cc83b65d223c3621401d95925657a6a4d2ebf657d49dbf0842405ec4e8dba29f7f7b112161e", - "0b064e32057546f859f574a13c63068e3d4524b88b77a4f2170b7743ea4038d59b76a6d3324975e1c0986a0653eed0afdf7fea5a374f10a48b3af29ced1516f0b7", - "0b05ed499b8378fff78cab9871a5a1cb25fe54d68d9497e90a127b3ef56e34955fe5ba9284fddbcf752a74249679a3799be512e9100f9158f5a84afea706b4193f", - "0b0089c80ee5ea613a1b061778e8c9cc9c7880bbf1e39f6789f4d185d883a28b9d7a4878b5714f2bf1c378f739b43427612c879638c97373af653501400da78d93", - "0a037d46a35ef32a4c51a82ace2861afe23036f6cd527e9ac696180df9167642409ea8947c3cd5d9cde922a402cee9ae75f5aef55fbbf897265dd03d6b8c4a9fbe", - "0a06d0f21298304282578e7d8008b12ee0854d6729fc42713d5737e4f1c9ab4d2c64767e23b02e8bfa6509e3d989dd95deea2bfc8213a96b576d81a4ad07fcbef8", - "0b03bc0eec641eac5cb71bf79c3164536609c8c533bf511b9a0d15a4a28eba5e10facb9ebb8e9d3ce832389085caab6930eb0f42f3b46276bd7bd68f50e0455b25", - "0a06ebd6b686addc532c941d78151f3a5c0efbadbdb84bd6955078f44215a5edb2688226bca4df74c57f3bf774bbf49453afe95f61e7dd3e12b94a8e05f87c6fe8", - "0a01cf054f18ddd3cbd1dc6b5b646354f51be03eeda846f88d07052910abf371f714cf9733acbecfd1897737cc82bde470108ae6e70ea0e905b492521a1813a2c8", - "0a03e20fc71d81b839adda46ef7596fefc57799e05247c66ebc08a680dadc5be66f73af64fc101f784ed37c048a59f996fe2fed876d46b7be02c01c8aa55b5284e", - "0b0811232bdebc57b1f837eacd022893058bcadb4c1bae5c66247ce95f34e58a7189805e1d36280ad0b70da662c6570860757e2db54ddc86fff3b581c8c097dcbb", - "0a00dd602ed54b0883e1a51359b4622180b37b28981973d92fc054f5664f9e170f0627a15691a289363fc852e9c552ae2c1f4dbf67dc1b717b7384f68d91424688", - "0b0471bb6253e31241ca8013fa5fe10ce91faeddfb4cb9d56ab8d46638f851d8a212b4bda56d0445b61deb43bbd9d861ccf2eb2d14b4d4792b8cc1d792ed0df51b", - "0a02d2896d02606d97d4b8f8f0fcf69e2a15b9fc87dce6b87aff5ce4e0a29222d1190c545d4b5c5349943a0f47a2b6f4f2b1e540f8723e192480468faa61e62b75", - "0a06dc0f5ecb5815368a18f4378d08ab8f87dff6210cb0549ee54c10ffe7a2a596e9c2996d804815fdaf971d2418445a6c6f67586012910ae0484571a763d98baf", - "0b003b6858a87d59f482616d3f69b83c4348e39762ee0f11d5ec1a11804aa375260b689751d1dca42bf5bfc5e0d56aa7fc1a77f745f1658b00555366e65343ed91", - "0a0590f9c5ce9bc011abbd9c23222537bf77ab01ddb4ddc343cebea93c4b687efa8f57c050a0cd4069acd0aa91c43243fcac41eb7306c40aa07f833afd43e85976", - "0b05c736455f2a88be6916b7f68fed6a8b9f4b2831791b3bd6ee2f279421a49e54524d3cf500d0ca489350aae3d624a3e229153c2b57e17200280769317e70dbc4", - "0a071695968f1566108810d12b320824217bf9118780c4f69ad1406c45765774c8141b93e31fdb8c660822ca2436979d0123716fdea1dd07b9894036942b922248", - "0a08c4d6d6e0a6958a768c6ff342330657d2ac0134b361b5d31d3564c91e1ac842cc1f2a7dae88b4f3c4ee04b5d422656445743c4ec7c506c4c833d54e77ce3acc", - "0b064ffbdb94c10b5be9255eff9adbd9eecc452e82675ae68de8e313bd67466edcc121d8a57b801e49c397eded3053962da2644075c15700e95a9ef90b0bd22e52", - "0a08afa34bd7cc65d6f25d6208e25bad22c3dc5da2398fa5d8f821970a7d65ca338fe4f5990cfbe9f696519e2484747f83c74529dec80eecda6512b7cf9112e2ab", - "0a0925675c18c5d2a5827640d63aecec5c7e4b5236f4f875021e9b56edcd6b356ff138e6d52a67bcf2fcab2bc1c3156c32961f59e3d81647f32341991c77e4793a", - "0b02b705ad376a013b08988a73a94860ebc3ae70208a339e9eb6749049523a6a64b5474e8f0b6991fe1ac0dd4981a19f9a0e32c1fc6fc1325bc9d94671a90de4ee", - "0b00d9281e803c0abd2b0cb1b78e3410df65da7042c4ec7d40da4e9818a3a826f07d9e8d2a683ccb0e2167a5c71a984d7691a1b9c84ac6cb1ef0e3ef4644bf0cd8", - "0b05991fff5f947647b96e4fbe3a3e24d6539336f931af22a22ada0dc92cadb1b98562fd77dd0abdebbb74767da7af74675f490c629ec4cdcf6aa4b67e675dfc4e", - "0a04e962c022acc6127700c8858fa03fe03392e50f8c9bda6e17bd639bce42e8c849fae2151e79c093656eb3082752924403cac2a1deb610995fbe8d46385e06e7", - "0b04ca466190904ab1d6a09d3da2587c93eddd72ef19172ecdf0e8d08410045f2babdf5998fb9d857ecd2d4c687a006a845a0807cceec565c3e2dc3bcf324fecdf", - "0a0876edb0036575711b1efe22457643f4a5048e773603a26e0cb43b73bc0561a9532a6e8c0de6b4db8ffec170cdeacac85d3c8ab75efc4ab4b48c38a942c9d501", - "0b025d3faf9b0f57bec0b7f43a5176e531136a863ce76aa00c0a09ead52dc2ed813aae9401c9c0d292df43c4a825b055c5001fa518c52e645b07c8573361241f3c", - "0b071628550ce218d263f255a160d7df765b528630ab297324952eb581fbe2b6ae01039c92cf3cd59c2ed0858a9943b87b4d8b53b4925ab43058be8f89300c9507", - "0b02817ee1e48f9167aee31b30368849217e66e384ae8aaee27e454015675bb7c244e9c07220e8c65b0968b6f6093015a3bc6e60f5674fcdad5cc6e08f11c2ddba", - "0a076047a7ffff8d1b2d1e2768dd53a75cf0b1909371d6ab17a041990e3fdadaf893f6c84a0bb32f6f0832a0cbb306c1ac26e88a7930930a038b051c78354ebb0f", - "0b0110ab1a4616880d17b51ea98ce8afba6f0ae3d3292489b60eda61c3229f0e59e372d359dc11e6e5b4b608c33d18e496c6fbd08c58cfa719c12b5a168d0fb614", - "0a06a8f21caf53772d2a6746e0caa25d0925b05ebf495328a675e89e30ba5bbbe51f81bdc9da19c41e750bfa7490eddeb303ddd42b9f9655093f3fcca9e59fbc71", - "0b073e52f5e75f8df2eab5cbeb794dfa44586070dab4e0db5fe13a4ae285fd4ebf93ecef313d673007af409359a5b00e542d4556b3bea213cc9a0afae73b67e65e", - "0b0672448fc7540a77fa89dca332adce3d05c5d5e5843094d890728fcba545c04743ed0759807f29dc23af050962bf524aa8ea7245525c89b3d231774d96d10ca5", - "0b025a4f98bb4df7564970cf3b5c4e70b83ec32c08b2e7e12cbf4c350d7bdfa1bb0ebd209adfa718b56bdf7c21f920b2c2bae50d0b591a980c310c36b04e535701", - "0a040841cdaad01464276aaf30eaeb4b723a2fa117c505e175747f956b8115dc51fb37b4c8b9cb743c061972f536b3906a851e6f7cf6df3b575e326879f7237c6e", - "0a055ecfe7e9b3a364c1650d50c985cec5bf6b88fc38dd6e20ef5a5668c68af5024dc04807a62078dacae7aa706116662074fad256c89240858e505e088958b88a", - "0b08c1c02fc4a4c2dda39868dbcab8da6e07d1570c1d937f866e57fdb042062862678764f3e88ea21791d70bb3e37f47c33f7ae727139c149e4d4bde6492992fb2", - "0b07d87edf49547c5ffebb55195eccec3f87c8cb148e7f9ba2441fb5a417e78425d85aca423646ecce7d5a60edac4d4db8e2b72d87afe58f0e9633a37dddfb451c", - "0b01ce3e07a24f5a03110fc0607083c9e31b0d6853c16659b11c93d6428c5aa66b78a25646b6a224630ae280efbeca8ab637e101730c59beca37eecedb60efb258", - "0a06644d68b74a29c427065e1eb4e1b255111c19423a9005161b0d84d21b5fe9d3066d63ebe0516310e748d9be8e2d54f91f3e46edd25752b54a2949b0190677e6", - "0b05552511f590ee5b5f7a8acc4b11c5614b8f5a8ef47d31f3d839e85f0ab95dea3513a90b98dcbb51507a8cfff8e9c2759cbd2b8c2a6eecde57dc6119bbcdae0b", - "0b06c5fa032ca842f9433f4619bab688e1706c66e1965ab554a014f637ef0143ffb4afefdf446f7b8c687267a5ebd5c718999013edcc0a1e7637fd45a1feffd754", - "0b02f9ea1f6766895bb8408fed24a040d41bcaa78a2c1778422c88388be80998e4a4f70bee370b0f1f28a41a033f6630f22f7babd9c916918586de8c6d5230b968", - "0a00eac90bdba9acd23e3b2bceb3313abfb3279a93bdc002317da36aa839ac56eb9bf4f7ed5e5cfbf98ed6a0ff723a15a84b015b5819b736bf16d48c6df2a9601d", - "0b03408a75dc040774d103d4a807f2d94ee47d43ea3f524d96380d5f08f1952a83fbc60def7e27056a98269bbb0dcf73190c3a6ce4e87fa1d71e20f839dbd5e618", - "0a07cfa101493e343a98fe7a342edc32b5073f2ee176a5f59ff4c6e47c19024ff61c97c4e470351dcd7da8a48132977b669dfc217ab3ea2d312d7bcd76bd65aaf5", - "0b07e1c3fc992dc5ecfe26ce6d6255b57847e6c5be3e8039c3ec939165a5e6e301b788d607cedd8d5c94d223266863c4d719dcc6dd9ade112bca3f452fceb1e61f", - "0b08e9910b1926ecda388e9137b53c033f92fdb582a9fe4d539de97011b7037d63a46de1505721474c5101d9b83cde0aeb058b91eaefed89a222c17b7bcba2afbd", - "0a08e448a73cf4ad4fd45229da7329b721c45af34f8c612caf9ad66b573938b6c2eaee91657522a14fe3e081869e055d5eea62e8cceaa182629bfde5d4a6b036bf", - "0b00ba3864ae027c130b97af9d46ad5f6ac4c76cd4eda0a9d275cf70f86e872d920d9bebe082c060adcfcd668db658da505c40cf72b64840427a53ee8b803c3977", - "0a042e56800984c647de65ea9f194f5531d32094e2cdbb69ba090c552d8ef63cd3f4f8016c8b5e4d2f4addf1e704c6daba0e5d767664ede3eb28bb1d5cf3f2dd0d", - "0b020361495f730b9732b26bcd89770255dc6a2164461555ef562d5f1bf6705debc41ec95dab9c890e248f75558c51d113fa9f5da43ffc931b82afa1c94dcbd5be", - "0a089a49be088472d24b2633331580b96e89e2af14acd72782fa2335cf625afa044ee5e9a10ca00ad70865d11443a76cef0db9f888d987297aef6cec5150298e34", - "0a002ff88d383e5fa23f0797d5d9ba14cced1b369667a025fd5266a368feaee523a4c3c6aac6b6b471721dd457dda4c794fe8e7155d03665f86e1a58bf41b0a81d", - "0a0240c89b7fd3ba89a5bd0eb8cec509b74f945c21c92f9040ab8733aeb44b2a95722d65deca0566029d23325053c69770b5bca4735fd6a9efcd81014884ee3c6a", - "0b07d8b91b71c2328e6a08d90b5af5340e12c6fa0dde298ba946d845f0222b67fefa6eb161361d44b9642fea2a2d9e28c65d7220c54f53fb83f7e4659d996660e4", - "0b06b92bbbd2cbce037d0169563337cbcd06e3be971e7975676c017944b234fb5e1e644c02079f0d692488a7097c4f1c04bdf7e9d7feba8a053e8d6427ab8decec", - "0b06b6fd85842e48af7ad1e5d5433b49a3e182570c5d66220809dc20ba053ec5453b70833db27858eaad05a705be2b184c60e36a47e42ac38e48c3f70f32c915d4", - "0b057eb7660b5a527390d35c76fc1028880c9cec55d699a235fbb8693d8b1766f5769866b6089fcad1a7db1b4d72173033ef7ba1607cd87c2e934c483badbf54cf", - "0b0603076220eb12d791d652697dae4d07dafadced3014bd1f19ffd8475d99c747cfb46f48cb005ef8ee80fa52002808d65c15761105768280eb206e9f5d988fca", - "0b08753e32f0d67664890f675efb8bd9687a321a937e9dc941cb970df26712957cda8c3ee60c6b0d1bbcc13b1ea8dc04a5ff67a945abd50f0c68d8205ed3ead8a4", - "0b0585dc73783859b95287a10a3c15c931194da033066ae8ce65e4415deb9933aaac3f89863162c4c307f1307e818cf783963cc9d715338e302f31e9150a261e4f", - "0b065386ca11ec99cffabfdd8f1f7557d66013596c6356b4e0e9a87906a5993aed7cf83eddb4216ad2ef10af9a3951f5bf1d8b24973e5f4297954e0f87434de9d9", - "0b019c88b88a8d6f8d642ca39563b3c74cf9fb87bfb52f19b858616ce6f9e2d480ccf46ca76cee1a4ebd0cbce6f9b3bb663134e3aa209a078d7aa612103ebaa6fe", - "0b0185a5f25659db87c6e18c163759c7773eb370b833e11e2ba38134e710197c9800807cbde96f1c1c2c0230ce88366932a1b8a682767fbbc7ba046cb31106fcc1", - "0b09054d5117b33e8f7b25683b69ffb42438f389db7a28224a55a3ff46ea0e94d404d938b2a1b52eaf05213c4984fbc2c5f5a0558cfcc90545b36d784e551f436f", - "0a051e33e39745020f8730392f5def0d29a0d8f069027afa408b993f6a91f0da5972f82cd1872a9d4b96a5370af3e7327d5674cdb0edae218ab1862d6cf2759467", - "0b025cc64e07f7b39c939a33c01054b3d03fcd76f2f24e7afbac99e5504f2a6ceef79c90a1c3bc2b136758d1789749e6ddc5957901bf0a6dec84f833232c0348ad", - "0a07b1b6098cfc31bb9f39810446374d53e4ec827af77bc218a89624070e5f2060b45869db9cdfb72ceb087bbed9c315689b3e5757c2b88d7a95b5751796ed303e", - "0b08ba24d610de3f2f38cc07c881b97dfebd0ef4a2d5179391daf614ea1d98d59d282faa08dc305a83d8fe02f732c8b1e6e311f468ae273a956b071b52bbf0191d", - "0b07a8094763aaeff5684735a95561705741c002bf8b0c8bb2c1a2521b9dcb2576b02313d4a37ce3f78fa1d1993ef941670d44bffac0946a100dd52a6d008e30cf", - "0b06eb617d1f3cc2144b1421520d70d0504cc2bd6786c9f60dce90568c92b4f993c6197602649c6c71b694a69a9b2e5e3c6a543244c999a9251e162abc56236cf9", - "0b045bba5f0576a1e71d451f1d103e907b4518dc0bf74266df0675bbc390eab4f55850c08af47f00247b8f59a25d84fb78611513af055a32b63b0bf96b7153e1e1", - "0a04cb2b72be73180757db5031e7ac433d1be2c6ef5409de55ca846bc82150b20dbe9bbff3fabe2a7fc452e28558d096129a7e58e721b8cff6c048d10369489fe9", - "0b06814ab23d7327e396b06cb31067d72e63098871051196a1714037241f85b220ec7b048901c7299364d39c5230876925ca9a8b2e31581d245f329c1d7c6ef919", - "0b065768d7775d71f7217678a1018ac0f225fd5d7acfca51d32c5246ad14dd15d0d83bf3d964bd552072a3299c046c3fb6299835518fc18d10238f57ff1609c180", - "0b019f8635a10b675bf3d6ee5ca9a0da2d058f33d8b2b84c940fc2076a3ff17f5c8d9274d9957fb57e1b60cbdfafebda65de05d083f0b63ad62c8d258d366f45f2", - "0a00ab52efad8a9075e1b1e503757510f28404259cf18484542ac43ae5e804782c1eaf0340cbe8ee8e776edb8fb74dc153ab8bbc98c633e0570f8c5cf0d474b51d", - "0b040512e581b54bcb79dfb08211ffdacad1d7cf73fa807a29cd59b18875e1d456cee9c062f2760daf0b797c76b2958b45c90582cfc8b7c665534bcdf7436b2076", - "0b06774b4081c7916c17766804c239c2ea4bc15175c2fb75a2355c2d666035c859de7dda9dbb8ae1df0f2b4a188d9b9b38b45a5df63a73aeae25c8692607c19eb1", - "0b022b322cfef5d1017bd506573a12c92b48955b9cc0f87728bd6dce94c40982fb569380083d311128f42c199783b96ec5d104d947b501cfb52f00cc324cddab96", - "0a015bc2e95131d7f346bcd1422b0c5ef3b811f8bac742ca1b79b3d4304ef271f57f09e13e7842553de203d85969dc3491ace3caa8e7d4fdb4fb8d6854cdfb7937", - "0a01efedb2cbebf46fd40bbf5db88e70658e9a9c931050b87487cd1416b510f1551d63e06190d273979e63b8480e3c3ccea5caed66133e56aefbdf071fcfd28a93", - "0a01e117831df942ebcd6f609bd8955345bd44abba09244be9842e105a8d51a8f29c7de1394d74cdbb5e544826b7dd6c803c26bca1347c369638376fd43db48e2b", - "0b0751bb3fb7b90fd38439d7c00bab31f1b6919905293fb757450c0d03f365b401d041d6bdd25b2dac1680681202386038d94362841373ad6d27ed4f207d91c879", - "0b05d704d8cd38c4f5c10aac638c4dfe2262531140b8908129f20f8b5be259249c0fa2c74dfc34d2c97bf4d947aa2f2cd53dca335ddf82ecf6e5ceae4b80e706b9", - "0b07d3bdcf4fcabd7d9318f640e13198c71417dca4d121e76749f334a6690b24ec1fcc97af5b20b606ae56d2052010feab699687da349d9aa4d8e09f1a00150cd7", - "0a08104e2d3c38deba3ed0acd635551e292cb2058df1d0667b93d3f8c28454c1fd28df4cd3d5da54631e5f1ebbb1858ebe2a115f47e00229ffd153baf7b79ee618", - "0b08c7f97e12960bce1a80a1e68d1da810774bda098968b2835aafb44abcb7fa5d14d6c1c199eb4c6c371291ef10c2cb425ebcd5662dde4aa5a4d6dcec467c2262", - "0b07f8667b9db3a25bd926a1b46c63e7a34288494829c2dbaa322574caec9483ac8ee5ad853b37c76715a755f750f2834108359caae30ec657b6acc1dd93642b9f", - "0a016d1f942b2ac61b1f0dbc2b8b15347dd87beb201b3a11c9dcc10f50a6ef266c45d5a881ad4883065f98a3a89ba8e280a6b96db93a0c7e1c85ca37e0fa47d4a0", - "0a010850b79eb9fb93db5451bf52e083f6e016cbc2997626c1f3302daf82b228f516958923ab782835faaf0da3095d9f3ae76bff0aa4d06c978694162bbf1bae27", - "0a03be4023eb5df41ac8347e733d3e941e58aff8428753ed0c48a1756f942ef58dab1d4e222426adf7af79b721e8438a20db0c2363e54fe1c024dfe26c84b17ea8", - "0b075a2cb0a8dc63b3e3bf8211eb2797f5b3265a483755e6abdbf0f58258505a8d5f0eda1e939d96701cf5159c2e0cfb9cd83d1874562b5ce7051a46248e0b4ab9", - "0a07f477e161940f3ba328ba4e431326d64e0c9e5627a6012eeb51f2f0bcf416001aef8a510b7fd75346b2cf52e0971b0d111ab4f255416a97d3966e97207a08d0", - "0b0905bfffc5d8ef574b4f753c2a76fd973246a98ddda0942b09f6116e3ad84d93e983256080d2d4840f0a36db7e9dad137f0c67c4d50c06a58d35538b6b2d5c2e", - "0b05f5da8dd118c84e17d35b42359b1d5a6163892dc1e3a2da26f2528c4f5bf808b4b10a98412785f0e169b4aa72c81170c8bb5e8aec9dba7955dd56123fb5ab2f", - "0a0146f3e52281e827785eb5a5d231843639994722c5dbb31b2600ec0bf9d13c6416b36719352071264602dcb10d2311757ea2d6571e94e4617e8e22415277887a", - "0a04f61aa3d106d005d08ef43e20f3f013f705d9b458574f01ead298dd04401f5759f216fd9fb840af12c15813061b8955a0b901cada8160ac0aae9f70bd1a6206", - "0b05b6908b7933352b4f4229893694ffd4f870772e380b43b176831b53e3b8ef7638fd2bce0900067c73433e63821851836b1d2400a3be72f22a18ba4e89a50019", - "0a06c1d4f83a8a4dc1d5d7e2bcd5c094d4017afb2702909fbcf405455feffec3d724417c8acdf6e499be36f9922d00a1b7d122e7623c831f9f83268535ca66f969", - "0a042f61bec2d91fbcfb7fa780a6f275aab25cea659e9e54d8d7daf7cfedbacc5f62a198dfbf2516ac7c633d44b3854e23aff7a57976a03c7a8962f18ff5d49563", - "0b07533fd148bb33f6a906d3aef50a5a3294c7174d887d874f6828f735c8001052f597718458c63cf6e92c843cfaa0614ca876b2ccf278c9e4223f3133ec0bed23", - "0b0753ea2b03010ea899ee299091519a9df4628ea381843212e4f523937d28d0a09a7d0d171300cd255a80c4638761caa6379f4fa6b19e28ff221d24951a35a446", - "0b0428167b4420874b7c1f95004b95a1673077a3d0aa552e221adef2b8a49f29fc79921203b5a0859571a5014fbe73408d4cf291861c27a965085b4c1754fe81b3", - "0b022be9edcb166b1686154443da5e040f0ca6132b34c37b6107f57b734c32c870eb04a8dc99104f0bbd166e03cf87baf9a015d6a4e83a60dc46e69c9ec563f834", - "0a0903ed0728a73407258f7f435cb2bfa615274e851f260f107b3ae127f847bb7c5585095cd8f2eb501bfaee600a9e7a1ce3e6cbd9503cc09898b5a3cbb0ef555e", - "0a03014801a44a72bf6b425ca7a595a2638ba523d0df3b76915dd029bab4fd7ce65c7e57f4b5e5e4a692d980383f905a11354c82f4eb0672bdaceaaee2412755b9", - "0b0032b25eba12a6b4bdf02a8a432ebc166072a14d0c78b2990387bc76b7a23dc417f20144342ea86af4f7280c546f73acaa2a99415552449534ac210784a3f9d8", - "0b02d4169b3b5de5ad1fa627c62bee056871d29d2b33ce9e9ef3c686dc76ca4b4bcffb858f4a3a717781340cb28c874efc27e400e1ce5c7998bb12575a82d3b2b4", - "0b032cd85f753cee19669e414fe70bc8aa583317aa205576ff52cc52448d609fcffbdc91bbf97a8c9018a353315e91c344dc358f9769943d0802af8a18391cf805", - "0b08d7e77e54f353bc1cca4ae2e5e9ece496e227bc2661d832d7cf9fe91db8b83518a52c2483ab80d9d5536f4453e220750486e129fc0b3d686dcb8c8387774667", - "0a03bb79eb53d9bdd2874d7acc93652464a1863c41ee12890f5600f9048f774f4e3e10fb2cf44fad8605b9afbe6cf67acce2e0b9fe26c47e5772d1d18b2b052367", - "0b01b976453c3bab269f940d17e1564f213406152b9b3a39c5d533b7fd6449c644f1e10a1a2345158396d3c5e8b0e5b3d231c6eed15858e9723b54e1f48e1d651e", - "0b047951930773de7588d48813c032b3a131145613a8dc734d88e02e5e39fb258a8be802c18be5c8d0c03545b3d33fb76f25195c4c748d6b2f8ef66095bd8e2bed", - "0a04d3377d9d95e9bb5aeacae96c2abe32884cc49f71e3d77821142bbc7b270aa5b886038194785d40246f62d0ee6bb70337ffba6f6a46b424c214efe67f707ee2", - "0a0246fe020040475452c8d5b46566e38b56b7e6a3e65d7228a47c5ff773a32c94aa664a1059ef5d7f34551741dd2abd1885836335b41f06425895597e54a6722d", - "0a044923ad378fd264a9888f8e436a2fd55c3655dc9f4abea35a97fec68e0fd61ca70bba7835f6586d1717dc03edbc3ad59db87f77d89cb5761883835bd0aa2b6b", - "0a05ef305a42b060f834880887d901e4bdbfcbebb520dad1acae8199d045476cc2b0886e6dd899be89ef6e37863a07d7fff9bc6b32bc09d7fc0a67edc61cc0580e", - "0a082fd6362dd9a3dea1736a10c8c7a9d5b13a66726e8be7f40aaac50d726d72d0e7e606779fe2632a7c7eeef3efe00d7d6a35350007f18e919ec6e9b1c6a193f4", - "0a07b0beb082db673bc691ca7816eb3b33cf643d2b70b96a1c9ebfaad4bb030a623ced517ca3253d6177e460cbd579ba800268cd4b4db7dff90c5ab8db564b3806", - "0b063ebd6ee1bc259d9998c8415d097fff97736f721c1fa4e513ef13c475c1ada34708ff852611e54885ffb4c99320f8480f4e2c58b3efd8de7678a03eb61621b4", - "0a067f5d80621415ed5c8bdf32adc62c0fc62dbd4a6aee6497423294a2d3c64f4cae7d9ca85ca0836663cd4f9e3f5342d3fa2e2dac60c92bc24671ed002a573395", - "0a088466d1cfb9be216a24d0a3370d62d63f24ad3678745b13bd4d36e9c29399c7476195b111790df091e9f6bd6a71a59c934a7ba46b2e6e128613a83543dcd0f1", - "0b0131eeaeeeea9c6e783b4ef69cc7ecbd55327dd4846f8b59e05d165f699b2ce5f80d3650689ab2d35096b3e64ae013bbf3536b2f4c007acf05f4751a59fef456", - "0a009172b42f62d1a21e743a29f70fa74f31a93f3aaa1c2fd903144e8190e2205a4abbe43659351a6a4f2c5dd52c4e067aa1591955506b89a9d54c3b1cff4933cd", - "0b08308d94df1f4847fc42a42db5919daa51489edad86e2996d5d652049f780b8b7a7e510a69240c4bff6aa065d3d9f442403ac85f11ec830e695ad8c9d6cba1a2", - "0a0776f9798b18b827c8b962dbec494952e8abeb7c85aa2cc3aaec41fa61644c4e917c812adb0227e128ee1fdff503cc34d1e60898256b9acb705e3475f2cf92c0", - "0b01f3dce4ceebbf9a0667914fbc308d75b4716d85d082f6a610f2aff3dd5155eb368ef4550bed6bafaf2d5edbc0c123dce191393c3cfbe09b7750155ad6a69a69", - "0b0819ded9a8191798431771661f4a92352d374a00ed228e24349f212ce37df23c67e491dec345ff0db1893dbc5d5bbf625312548676a724801d662cf83858c5b7", - "0a03f54be8e634cc1833949f6d86affcea97f6e4d532686f69e0089a650a703bad606220a9152628898351708487f2d298a7baafca9b4d374f498686f1cb4f0b26", - "0a080f07418a4c174c5be1a2e95c1451d0fccb1ee48f98e7092968c31d21bbbf9ceb2b496f8c704bd3dafd085f8f229dda97aa45b9b1fef8fd86e6d5cdda9b955e", - "0a06fe178535035be35e364e7924e502e9438027c5c47007e58197f86849fb9e96706a333848fbcc4d0998479965efd1ecb79f1ef6d51e54e7e7b2824564bd5dfb", - "0a0415ad6c1c230c11d3f36b12e90dccc0347e2a1d36bc47cc0866ee9c83032d5a8b8e33bc0f5775b66d579dde1297531d4e004c02f66eb878e1295f8a76304a15", - "0b025e19849d09ada7a68b29ddca3944ae6e3fc439eaa380ee3e063e57402f53082b6de9caab9ca1300097ec50b20e1fa0f674aa315afc97a03172f320ff859ffb", - "0b0626af67e75bafb1bd0b3fb64a3f1f469ff20fb3103e528efab836dee1e14007de0a99edd18f8aee259b5bccfb6b4e43ab46a759b9f1eb4d7978d681c9ceeda7", - "0a066a54979e61b6636ed81ec3d0471e276843360c4c5ee85c1a868f9d0fa52ecbe3e8f630a2b417c81bf1740e1376c65aacd0b32cd5f2875989d9af467aa9044c", - "0b05034122bab6143e11bd860cba91884193d23d03913af33e12dc5fa39b3bbf40a7cf66e4fb4d3fc6f40261448b82c1bd4b8cf326bc2c98fd91fbc7c9d37da7c9", - "0b063f07e3e50df0324739ad171488997f8e252627cbba8ee1347e1c3b0221838d54d83065dee30d6d2bd9e9cd740e2fef2dd1d1fc7dadff957665da1a42d8534a", - "0b01b705bb602149cc7ad8785f39807b2939539db1baef2482ebaccdea0b0e4c2747af22bdbed10f499cb8b622b65e12db7ea355d551f59ad6b0ada181be039d1d", - "0a0766e58166f47b975a1af5ebec318c27471bf3ea5c4677d7ae899156fcdd2a5f45c8beb6158b85046b7cc4715b8e4c5b31d8a11c045d9cae6158428190d42927", - "0b090bb2bbc3afc808b1879be2df20e282ba79c6f9f62c65851bcbc4f68659ebbc7b504b4acec6c89907778474508016e312fffba1a7b480e2d398dc77df258cf7", - "0b02f0c2f9cdf5b4e3736dc6ff1eae72211090f26e25b081b3650350695a308236e43faf6c676b97208c500e1a54443e8d46a25565a5924d1a5a0ddd5087e2759f", - "0a04a9b7d04e379f28141dd5d086859347fb938d53802c3e84ca6e3bcde5212928f5ef795e3fac1819bf4c2df454c201188d711d8373c229f95d30d904f554e003", - "0a020806ad32cb3698ee30c1574f89b4c3a0c8facb5a27f9c1917b7cb6b32155b2c337115f1e2519ba704877f84b1b03ccd55be4e508187b9a7661eda643e5a06c", - "0b0523ef60a372ad906d252f8ef3de6041e638105334454d902a2d228d9deed70f34e4b1b58023619f68e0cf60f34bd87096a39e233aeac1773de6011fc54f632d", - "0b01580c44f0bd498eb663340369e9361eae9043591ab66cd217ce25190d70e4af73d843598c3107f0375690cec2ac2fffc03ca16c35e233f4495a60fe9774f472", - "0a044f21aed2254b91e9319160c530596aec0fa1c825aff91d15064b161b2d01f6be295287964de934ba5bb8e2650a96a54eb8d9f3e9eff2826f71560c4da6ce86", - "0b040ae1ae710de58a85537a6dfad81877676320147ee06686153a1e7be8c53aa999dd157f62a0a012ea0a3071789641fd14e8036db04b94dd12bcc52de025cc71", - "0a0433fdf5e4e8f053ea295aff911e03e25e0c91099e47c85a2a3afc91d5c751ffa1c9d8e4a04b42be6e1e58dd86fd9271aeea5bab7b7db8b6f6f43c1227a9d985", - "0a04f212358151272c67702ea3cbc86694856923934fe46f7ec3b87744b456385188f46d9d2a2b15136605f166ee1a3214e5b5d4b95473d180f162859e6bbe1876", - "0a08a767dbcbda3e549591fba83013ce427899b4604368fa86f2d10928dfb77f7c314ce4982c94377b625107830695ace78f716931dc7a7572cb9f90ebdf211262", - "0a02c116996a9f5f25231e4d08c28342e5c27bdd8dd5521881855e11c7da36280c6ad2836e2470d9ac3460a80f15081eb52e9a2867be1a2834ee7801568236bdb5", - "0a00245010845b8446ab5eab8aa7adf2041e40f432c394b00aa337d19d75a8d604419b085205354e37f362035a7036945751526afa722394432f88bfb6177836da", - "0b0210b47ef708c1aad2ab547d6e4c98a48bcdd3cbbbcc7891ad2af1ff2735e282384cf7e97633e80a3f9d5939c05644fb8cf304f77b65821b6a27b6c556b47b71", - "0a00d1727ebb39041c2d4b96d24f4fca99fef64390ccf67d500ce4970d00bc5f4ebae807d2900f70234f07b96eb6a2e5b52f356bb59caf6a3f35aea2f90049cdbc", - "0b017370bf3aca5a3241e96c27881c2840f20fec24673735852892106f8513fb3c0ac69e4c90826280d433791bc15b47cf5a914877f175080b3c6e939cb747e4ba", - "0a0824e3f193d51c58aad5fb8d1aea5ca5ab8bc601e78e588885444862fe43f30c76a184ff19db2f80198da8619711b6f7802bb72f6a8752638231d282fb8a74d3", - "0a040b73a33096a1577262343e3c3901388c0b4aa98098b4fb80667fdbdc6617669553200f099dfe6ae3e5754042c02c5c22b23cf9fea688ea7a0ddcfd7961264c", - "0a073f09e760fa401b9f0292e67298680961433ee210e219cda8ee321501c8391e25837aadc636a17ce7592960425790e39e3435518f128fd84ff028cbd0516bcf", - "0b07a7f343d2f6768186ae3c5203b19713b3627278421d921dd6fb9c7400f30c30415723bbf6f9c7a539806d0abd843e8759bc67830a4a9e2eb0a4197f6d795205", - "0a00ff3d430cd37a306eb7a8e6de3ee5fe6f2879ea712441754e6d45d0fbd485fa4f2fca9c062024d41e467fa587d6098f739e746e51ba2bcece5d87fecd97b13f", - "0a05f79579eea90c1c1e49563a5882ab4ebb34710a9e1bc6721cf75db32ec8331216352e7757cd7700847a910d884d42b8824faeb3a5037efe26b2e050a650c773", - "0a07e82e07d21a598308dce367ef13f34870938a26408ab843409d1722c4af14192048ce5fc4a8d3fbd5d352dd1e03bdf1291b87182bdcd342b3542827869f0533", - "0b01d04fcbacf9470c16bba13e6f25b881cd1b81402e715e2dd948c2134f783154a2643cbf10e9b21f8fdc9ed158e68d3bcc4add4c1030c0b165183f8635fbbaa0", - "0b06b8379248bea1cda2851f910ed7505650d9b07d839277da443518c2cdec870bec6a72dc1b513b1bce405c8408bda73e0ee1049661b0a26be1a1026465c5a49a", - "0b0539122736ffcbe1a4398a599f8e9eee77db8dff8fc338c9b9eb46025278477ed5c8de25021e3183825e3b6793485f9558c05af9e1fe12581bbc78177095505c", - "0a068b6beac14fa49c6ae315e6fa9ed12c20e442eede4ff868da0e8e47d932bc3bdfd3aa4db828cb93cafed9f32eba8a5a9551532dc2bd1b8b2280b915349cf327", - "0b0412f98c683cf38aa11551c9ab718b77cb359837da6d256940cee3d9caf0c07c8675e580f5fc3661599b528cdd26a29caa16a5c9c31e7f1601279dcc316bbb84", - "0b012ee06de1d1c4e8c953072defe3e4635ffa94b7405831288ea3a9b51c82e87c32ac49c050ee48180779f45a962da0f85fda0c0aba878931dea304e69b219b77", - "0b08351df2a70eeb87de84011fac75f84b71ad68860078ca587701e6e110d17f127f763236f20edc8b25e6eaa05bc9e33be3fbe6741f84f71ed7cd5413f35c69f3", - "0b07efdf839c49c45e5f3cc54560a70a2c211df4f74483c36644b239f64b7fad56fa876762e8913e267ac3fc1c2292e71ab94e50fd599348c4f8359754be8ced1f", - "0a06d26ad5626f21680919d44e3a15ea54a0ee97087e780d16efca3f73974cd9b843b2a92e9ab9b1b28ede349ff2ff19edda1f17d7ea31c70e6a8381329a72545d", - "0b025e6900cfbcc52d8678ecdad2de727b85b49833bed72581a141fd06c2a200e71b2f5c7a778c071f196ff7954dff3167f051cd863aa958c5043632cf87b8be89", - "0a010bce7cbd2cab5c533101f6767465ba0aa264b49cd8b4a365708411b2a0e60e058022f211f133c5767cd2b943dcc2d6ce804724f1df81f08f5aa1f7afad98e2", - "0a081903cdc2d1f1474d82114a1262665068969b6316fef6c801235e3b21b0a6b8214d35ec659ffb34cf7ee3035a7c655834da4381f5c9ef58402e3288e31dd570", - "0a0151ea53154129b1cde8e3f6cd39a735ed9ece14dfd3c1a0691221c86ade6a999f302d8b207d6079720f955f9a5f25ab8c554c3762c5d2f7d758f4a5fc362866", - "0a082621120337aa4eeef75dcd38cd846711dbf0da8f4e318ae91b7ef10fe8fcdd1668838719b0ae26a7177ab8cb4a54f85482c681cf5ffe6e861f4b8248b2b0ec", - "0a0673122a634aebd6255f8ff2aa30c1baab0961f6f7feef7c33e334fd0cc494666fd20401607962c5f0520c9726c926f36293a39ffa2acc2210465371ecd3117e", - "0a035ee45cba601ec1ef690f9ee503942790a7ea79de717c74c697cfb367b43b41c249dc54af907ed3ea6b9807a70570b39912c0c03ea6081edfee553cd1a01d87", - "0b02452af7d96584d96ff46c1d67c2fb6eb95fbfac7dc5d0eab21ba04558b778132c436306bf3a84b164e27f999030ae86353e7d6615d1575399eb9c4ceec46b00", - "0a06977051c20d768fb46de5758539cc44eae869a640c718b6a528c934a02817f7b305c230a0091572bd5fe5bb2efb342f18c006458ce7f57008bbbb00f2d5fdfb", - "0b04dd2bb512fe9b1c3ac46cc33518846b8978360c5e75e4fb65462275d40912b9972c2f8d686e1397f5a623d50bae779c17134caec2edff50cfbf39de8dbaba1c", - "0a080962c57b17b700c95810896d30146fb1115b2693da421b73e86f9d8b48575ab8d863031359c7e0a90f8ed564297ade9852fcc68b3a80755c31331cdf95f619", - "0a07d57c3fbd6f067886bfca77822f096f0df241d976c6766a5453f6745084ce457207a6896e00f19c6fde688c9594a7989df079854a390a531db8ebdea30cb1e5", - "0a00b1d9471ebb2fbf14dee267944ad1a0b1518262d88e08bfbd6aa1ef701e3c32567ef980c442c343d9309a59613403ea9dac85c6e8bd2210dd698ea0ad94525d", - "0a00bc445bc7b6a998f1d762afe458b55e41fbd21989029fe3a1b0ae915e8c4830a068e90db4be2f1301dce9a48675720a136d2940c353134e5c0c90973a068ccc", - "0a0047a2b8c539e39355f2b9b7d8fa23a783b095a12cb40ddf14b184b38b4d074b8d1955d58b22ee168ce6ac54f92eb11a1f397511276b3c40f2ee14a704246182", - "0b044e20eb941c0a322fb6ec34bfd07b071cf19f6e089f6ec7b968ce12f599fe6fc3c3a9f9d501dd5f6f454e2f46b2fb405e5449f9cb3faf9be057932286040fb0", - "0a031745c49485c91cc3ca5974fd3f7d520031ef8c08935ba73b834042dc8c4aabfc39a00010bf6666dabf64954ce1b8b64b61affd91cfbd323f07079dc2cb997e", - "0b05c116a901e0968ecc74a7d92b52ba156a20391e944f9e8050809c3f964a7325bd96b64451a060e149f83ab0a537ff134111a2914448e73033eceec08c5a0818", - "0a00b4b19e88a7933b363e2c7d330b005aa92734d10eb314b3a7e5e5170d62538dea2fd171486b02a5c0196d39470674096cedcc46fd64a722b99b0cb71b95734a", - "0b00830336e1cbfdb847d73db5e78b194e62c4759fb59a59f2a85b8a4da86d41930cb01378a00cb6f8c7c299f0b347cb34e2f49488868f5b9584b30c7b5a8080e7", - "0a016777c4f4f4ae239e343ea97f6254cd591e74d3be496b2d71c598c7e8f9915efa68433c2d70b4ccf025ac3bb797671e98711d00c95f62d0d8d71c3646b0b94d", - "0b0881240d74fe54b760a60ee743241f15dc72b99d472c0cbb29ca8dbc5e0fd5f9dbdc28a692df5bc380fd3204bb434635c79fe3a2086aab5f06c64063ecd0d618", - "0a04ecccad50bc5562c66c6b417095f4b5c79acf71278c3a1b865bb11e5b2e8be88fc6c87aa42967cbe1b5e96b43cdfbe88865dc2dc90dbab974bb57307365fc4a", - "0a0063e7f337e41e8bb067c6a42ef1232785e9eec6b12bee884cb5c15b75797b288a7d86f399d6b8ff1194fefd158e5cf3710d67e6bf2c44e6280c5fd8cfe45bab", - "0b06c20eb0082dade14e10faccf1fffb7c068539c723265452c6e62ade6588c7f01126024321299f25bd48c28b0d51e9c56b854dd2e83e8bc5109e0498fe971c1b", - "0b021df36c78b2e72e5eb92a402b61f2bf39f432b1e0e6b01c29c2096267362d2199854d4e7b6e32de80bdce6332c5e54f638fc2ad2201597549d849611dd4940c", - "0b05b93ca4605aa2405147e035087462a60d03013dc86f5925411553e943781472cd3cc6f37817130cc9f2db11afc96496fd781ef5f9678952a365879bf04b2ca0", - "0a07d3218b7d05d1720b418efc0975f9d3c9ce04eb316c8879432af24235a5feb3cb0bb979ae7593e5996cf6e7760a9755c0dc7df5dc0c6409567b38ec07cac2dc", - "0a028aa24fcae7c8a1b22f0260de845002e728244ebb7c0ee0df333e843e7f2e45652af2c4cbc035876f1f23310ca820b6e4ff5898da11853a9233c9b79aa92a60", - "0b0029218d24c9abed34ad71fa6cf7b59fef8ca1f461f30d21f199fb00ef55c91a3824dae6d1c6d99525da19caa05f40d9d622005295b87f5887c14d7897113e20", - "0a007e43ffa2303e7d579b83c42e908112e74b1cc75bd7034eb0bd70c07c4c3f99951c60f6659962f514a17e718c379f6977675cc85622a82d1e0cf58b52d99edb", - "0b077a6692f4a341d6273070308d8635ef586f83513bff385fac3db54202e03d306e1172c49641d6802479b7abae559a68237c92330aa75db08029ac4567d8f8a2", - "0b08f308a83b52d87bffaaa89a89ef5075daca257c9b0fca627b89c84cc098dd4d949679d92bab076627e9689bdfc81acdeb3c6e3940937700f68a5ce72e6e9feb", - "0b0471e4d03f00dfc4b8b65c9e089b4b4337d99a32f87facfd9b3d77f6516ef3a97d1674f6887d6209c86135b07022f7497d57678f948842630480291d5a96a5af", - "0a0772565c0efe1f48beb80d8d86e2bf3129b5f75056485f8004914d9e89d008ff111140fad14c07d3cd6d60ba90f5115cd89df3bfd3fd0553a96f48f931802d6f", - "0b0109bb3b6c8870aecf743729ed26078e54c517e6c2394db234e416292c2f6ba8500e83aaaa5c330042f6579334829b091cd988559c8754d3d4432a631f4a5e25", - "0a052b7727ddca0f133c14be298245b28a23c17ed3adeac5649b3712d2c23852e6013d44cf353007c2ccf95c63c5f3219f8ab1d41ca5c4366e6544aee43103bf12", - "0b03d8603d321929fd8b0803cbef9c40e04a4d7f76ff50ae14495d267d8271188a02cce1b82695eaf9287bf76cea8fd73679b116df8f4dd8089d4ef4166268640d", - "0a05eb823e38ccbde895fc6ec2aab1607f1d62378ad6f39af8ba3955f0a18167d6fb6ace05704c06403fd22f369e7c6cc965cc95dbba388043ec65bf5b64027a83", - "0a037fb7786bad59b75a9d77ecbfff5c7c61051a40dc06e324275922f03f33fce5ba3f5842702e6e301cde7a9d38886478ead2dee879a1e03a95686c7449f55594", - "0b06e92bf93db1160dd1e1e82b598c9fb57434c102ef5c3bb05701cc0764b4278ae274f4e78891627f991323bba8fe33145c313d84446210c91ab183d0e0ab6242", - "0a0260212de55081ce61441084723b64767e4fbafcabc00796d52a93a85120f7b4bd4b0ffe70b211d8a322138efd2dfa58e9bbcd81accaa77f4c359a85b5a6cc4d", - "0b06b081560677d4be3cf8f70fd9eb7553d3421be4d5c55784701ab6641bad286e3d6669b3daadd801a1a64d3b228ccc797de14e159e39ddcb348cc05f770e37da", - "0a00be1802810a91f62780ea948e4949407783bb5d181dfe932368833022561be34cdd365340e21d14a259637158e166d54eec0db50d984021e516fbec20a612aa", - "0a02b42202f318cdca5c58573df3dd5a974390075bebaab6e2fc6b35e9aeaf8ce757a72e94c3d010e88c1a268e5a22c2056b8498254cc317dd1a90f37a4593ea65", - "0b08a87ea159c9055ce5f43a6a68c31548441b3867d2c453dcbdcb63c76c3cf24f8508fb94afd88e4feed4f57a97a314a4c7b56d00922ca090f3deccd6f1ef0929", - "0b017f8ad3a24dbddb10fbaab9d8010c20b28bf5c3be3f75a5bfad2098c4e5adf630679fc304745c7271135d868a111044fe813708a2440c844a4f8808bab4e5dd", - "0a07041f599a8244a06152b9b0b394184e2b88d03b1c3469eeaee4b7372cfa2a11a44ba3d65268d34ab202e25ac51f265c6ae4a09a7efb484ef338207614e61528", - "0b05e8167e0719c21d13550c98cb3d85577c95af603b9af7082444bf0510b2c4e56616df77f8109fd8503f67b3560808dc9ee1daf1c7c9ddd91534c6e301398706", - "0b02ede5669718cf64d771602e8d0e3e18894675d59e33ba4f2632a0ba58ea930a4d3f45b52b22226663d78a0f7b4095f1d7e19481e8d9490de6003bb9ef43b63f", - "0b0311a7c939dcf145cdd4a364648276d5e32174d97ebbb421486840b7b4a94cacb09dbd8e743ed9460764f2e7a0696fd2b583b7eb6c6789ca491584502922e9cb", - "0a0407dd85e0467672c1a0119d417e895f9d7558ac86d13292cdeb50560575c2dacbad9727e5481d535053ed387cd6b0ce0f47218bd26999768ff5d701481f841c", - "0b03b2db8cb75aade3ad369a5b90fc08a9f41f8fbcd32e724edbf8585a8ac620912a0a3276fceb096d562956f80ff5c3df960f54226ab709558e197a5d7f0b3ed5", - "0a043e89f29ed5333b30ed97b6d245b07032d035502c200d7f37dbe52c5df8a0c1cd6cb478b3fbc14cbdd3305166e3fb8f8a0f95ebed4f3ff29dfa74b3542ad4f6", - "0b05878df74feead71c281fe3a69162260723d83000463640d391d0b3abf28b47247149b37b99fe42795f56ffa11a5c04ef191b758b4db621db140ed2661d93c33", - "0a08e7edde8a130b681f40fbce6c94b8d6ce1bc0e65c9bbff6dea68c52659498c3c764b9f11a057672a362b9a5904d095d1f5bcb31fea3e31b35da1d0b9a1b2db6", - "0a0793d1a0ecd5045434b8dace70f1b12d26437e22ba6c646b130a93fc102007575c46c0ac9a612e063a052623fdd63290a07d285e1b4f322b27c0d62c47a451ba", - "0b0071007d6521eb73ac44b1591c7d70d5406e88500694a86421c8e3fef39fa3a6ed712ea5b6ca82430021ae197f15f0e49b2af147e195e6fd7c7867f8adc69e83", - "0b0704ecdfdb0f1213c70e50ae85449e4fa09ed0c5a91c711a11890888f0cdc5cb147e65c5d3b870672b696a505e8064e398d1a44cc9ee53417207bca09f8cf692", - "0a08c296c384c617de9cac6e269d5729969ad6fbc3041fe0abee249db0482006e47f6b992720e113a26cd4d6f8d2f101225bbd6cea34c529ebc14b96bd0ead3115", - "0b046ab5985e52177851b91edfae01618f3f6c148a8b96c1951e070c062bff5c47383ff0d1b1eed207ae0e25e7f207937f7ef62b74d3ed40592095b695d353644a", - "0a01e84c987be37c4def92a78ec56f048b5aab2b9726077331008bf3498baef7ff661728bcdbc9499fa26d486d65924269c7f98778e63b52b7f488e7e5b3735dcc", - "0a0863fbdbab92af64a5130b86605ce757ec98e1e0f7d43df97d34ca5ddd7a737081916c4aae1354f8c9ebd2eef2a9ee2ebfed2441c5643435a9fafcd321ca077b", - "0a077719d610adbcdf3d72b58c6cd2f0b9eaf2be3e85191e0551ef41d8c1d4ee953d0fb82c9d681fa63f4cc9808c00bfee25c6d8cea79d6da95d73ed7b1b1e660c", - "0a025e4a2064478684eca3eebda9cda1690e00b640591584140495252f361e1f906946abd449174fe7ba62af1262d65fccac4890c497bb8aeced7a996e1b6da782", - "0b01e940555a06239083a1866d96fb9cf31aa0285c251361726d8d7ead554f6ad7922d3c423a4c81394fbcf0b3b6c8f5bcd1654b3ce46b8122f26bb5a00b0beeff", - "0a051cf4806e41792d7d7a575eae4460781ab3b374b84754059f48d7474f3cbfed4ab0be1e9102c1c24dddaf864cd953eb7a682c9613a0871518c9d6be71013de8", - "0b060cb315a3bf71a1daaef9b677b0365ca8a81b1c5927c5a101ed09c71c48bc1edbde8774511ef6e56cb64244143019a0eb9f94bd5b196276adfc15e8c5fc7c5f", - "0a055c153a870484bbe1403934ba6c242837431b6b6548fe346ca319c15ba63ac76339b4076d546ff167aace7e44a03ac77533a542485358b68cd88f9cf2be67b2", - "0a05ca267a04793ea4384c142c65ba4d634133ce532ae67df9a09641ddf125ca9df3c7149699335f78f485d5dc919a96430c196a011cd632bd579b642292cffcdc", - "0a051828d2101ac4d856f0c472271b1b68c61fefd85ae10f3948dff0ffd959a43403361aa8d6efedf9a7ea71018cf41e6baa5d64be55efbb8bf3db7463cf4b4eb2", - "0b07715c4c75ff0e94d16f1e92e53401c8afb63022417af187abf921f5e40cfe7337523181da816f8139d3cf466dfc2b47171adbe1ab63fb916f1f0ec693f7d764", - "0a0043c62eb8b24545a0ca973f505753b70e95f4f7b55a133e86c2a4106ee043cd861b80fcbf1809bcf741d003ef4b6c0ebf3eac3c0431a5b5d992926b52a1a311", - "0a05f6ff8fed372e9ca66311104549b56dbaabdda80dbe3fd067f758e1554766fb71b9c9d4d70e6717a30e3758e029422d308fe5af65fa7a210adb3db7595344a5", - "0b00ee11cbe9e513c4b1e99682e2a3617107e0069d5984b491eaa7437b439e496003cd70f48cb9303d980b4d9acdf41a662424a0cebdae0535bebf2831a041209d", - "0b01543f96a8240fece4074b9a6fc2cd7b80d124997342034f6b5250c81099a9e855fd9076b276478c85c356f38d1fed32892bff3ab9190f6bc4ad6a955002805b", - "0a0297bbb2704b9f95fa95456bcea309612be1f21a596201653c894bae4c9838d7c08d44a974674e4bd4fdb9349e1467923530808a4feb1ea3eea15fa3e6337f6a", - "0b029c0b843a27a1533888b7abec1d342a661bfc0ac13d0666f3de69483124eed860e3ff58697b785103efb02d0ae57da46aa0df054a6cf2a2b565770e2d0fd69e", - "0a07ba380e1e732323cad317102fdda30f9fdb482980a88c260881463c7d940c37d9b2de2d058b0c413aebdd3d5f7b25b14fbb3dd091167eaee0bbadbab731133f", - "0b0375f2d48ed9103b6a899525fe8199a6d2cd5046068c58641e95258270150ef13706098828b3caef1ad3b871f5a212fee1f7650ae6f804b2bca5c9b8c3d36b9b", - "0a051a36f8a828cf95b43532643a086010d0eb8b55885a967629cc121c8f24670dd88b04a04e69443debdef837cf80c385fde1caeaf4f82dbce4a857c6378d8d6c", - "0b061f54048c40f17371b7deefdd586d9b10f00010196b866145664fb642741aa324c86e8ffe808104c21ff5a06662a74d29d76f76833b76f5e49fb4c657a865b1", - "0a08ee2a4f63ca524e562b17d9deb1555e4cbb846765587c4e4f77d0fd682f7866e8234dabcb6b4906d2355b49a682df7ae93f8c047573b7fd5fbcd2f7fb756af4", - "0a085ecec7d371308f9c7e6e55a6baaa0d98828f6e587a426daa57befb4faa6343191f68d172e570b252d49ea88e5241852ac09f6bf81bc703ad0d28de96a0866e", - "0a00716fff68a0d8f5c574d985251719ad600c7ba7ef508c3e33f061172f03d7240d6818e20ce1070b695b9ae011daf49d8ae9042971c55ad501a0abbefc74bd49", - "0b03cc159a02973e7c9a2775501fc7245b683c07c5e5e01f675c23f87193eb279cc4507e9d627b80738d99319a6965f800a5beb05cafcba500f16ceb31aeaadc5d", - "0a0095aa6644b83a4cdc26a4d692c238b4440a12f44852fac8f3f94ad252aec1ea9270e87f789c6da5a45db33f5cd6f022ff7c4bb237f8116cd5b47045458ba49c", - "0b035a3357351f9af0fc59094bea057eec5f1d17116d380ebde4cec7bedeb122ab642ab98e609373966d445b9ffcc10802c7949ea09637418969719f305d0f5e59", - "0a044d83990e42309a017326764f3e816441a3006e74f9a5d23de2da0d3d165366d783e56ac0edd0976181548a6cc42af4b3a6dfed55a33489957dda02e61028f9", - "0b052d31a622670684b29c8486216f21766fa480183710d5266ad833f1122785c8d249f4d926f2157f710192e21c1b527c556b927ff4beb3f1f606553def73c6ad", - "0a012fe4379fb0e257b6aeba63ce4ad0f1a3d4adbed2d573c1a680f4ddb155b1f955ff2ffd89fc57f9fc44ea1aca3bb844a5085a32177f2c712c1b857a13bda7ec", - "0b04e39135a8cc846fe57cd9f619bb932430ff821b61238acdf5bbe28cbe4ac359b6c81508678b8ba8eae68a54d0e786880897c3ea1451f4b060bcb582f9f8982f", - "0a017e08176d3c502ea790b8012c446cd0a7dec2df3658e0d9b8a99c76c7cefb7b2ffb515779e1cfee4829b56fc862cea3d5f07088c32dcd520b275a5ed2d7b710", - "0b08b613daf3db65fc60bd48cc3751210bccde311c2d02f628851d86975617153daa81d3209f78edba08ffe611cef308083e673a6cb0b116fd245e2679eac89477", - "0a040f88c62d447b3c1490952ce2b4095f556a41b5bbbd116526a4e3363f81a4edab665abad63cd38d2ad5617f5609f2db385958d07da608e9a078c029cbd50119", - "0b03edf9f4567186627cb47dc6ad2dc9f7453880ef38575396b0866a0d767a72b00996bda6bf4bcd8aac34278ca717699c2c7b86e0d16f3da05f7ea0c0d6dd3fe8", - "0b00f63417c640d9b04578e8e9fe2a554e983a2729db6cec668afc92468e08ebcd8c8f700d317fff2f144bf346334231e775703da9f91c6956083f7433c45f2b52", - "0a052a38ce15ad382b13c0902299374ef8e547e091c22ca17d0225d061e0223f653577ac4f48c3b94ca8aeeb6bd73c9a5e2c4ff6171fb8449e7f354cb764887bc8", - "0b0795c28e0b73b92998219dd97f75cd0ac93067eeb6b63481679bb42da8353708611c028a6088d9cea7f812cfc9177004bd50701cd7adaaadc6f0c63a6f7bce27", - "0b000233c2c5b063a7b0e4b4d0c804984c838c87e2681c04d857c8ca36ce188eecc6da789c2a6aec548ad96bca56bb72c7dcfc888d9186f84b06a20b567fb3d007", - "0a083a77ccafe10cb549879a5ef385bbb381b41ada420305dd3e6a01836d4461d102484f9a904d42fd4cedc06070a2d746db7e343e3bbbec31b3943b5a9f15958d", - "0a05cfa0f1ba76d777b1f38ae5a8626d72c09689e67c639c5a0684d6c528ac6bcb46a075c60ad5e7a37c5f7dfb4f1691c62a4235212a18f680ca5d8e64cff0bea4", - "0a06a0c5faa49702f7e52f36893287e31f940e329842811604c36ff74d7752b7d43d5b8874271202a7bb52181a22744a35f9f5920dba3e7746034d544435f518b4", - "0b08b21ef12b8ed6e117a8397f281a59f9c9f90053763d7dd141afdcc40ac7ea095352e21e489a64010d65f13dc9f53c52304e324a29a5bbda86ae1cf657896bda", - "0a08e6c2a79558d2303bd5d4ec1c39e6244e72d2bb23b1c441775ac0d86fb1aed2cfd943bfb9a728df2857fcf5de72806cf6faf41736b362a5b2d73a3978f5ef49", - "0b070529c0eb20d4d0ebff7bbfc5eed20127f9224f62a887dc4ebb8fe2c115b8b736003f42d4de58bb53ba5db80364e6a7739d96776b0158b917b002bcf6790c3b", - "0a03a213709e42080619e55a0384b4c265bd51d3dcfc8bcbf6a960b2f8282184859e286b6c0d82407eac11e10a06a5765563cceeb4743f220350ffe1c5a3272c0b", - "0a069c48caed3608126f8348da436a8013d1f9dbcae838d42c2dedebe1e103e2fcbd900f1a01cdac7b728956f804eb59fd6ed1daa8ee393e1195924caaa308efc3", - "0a05681ded353593c257191fd9fb0c52d4c08656bac77e53d26be5615e43979dd82409a051e5af70c97a87add6993070da5950e8c94f0e61220f392eec94ba1183", - "0b06b10ccdc4d037b718469a88746a4921942c6d7b3e9b1fa97d3dee38a65bf26e8cd7a1f0e944b48b9291721dea3805557631cf3147419e0236b437b5b43a5805", - "0b0448a53937c46d122ed005bd4790ef797a6a50452d6198ecb3b94899e7291670526903d29bf4e36d47029234d16ba1b5edcd02a61fa7db3b26200610d3fa9f7b", - "0b010f0cd816b9c4fe19255aeb60c13e3fe90a100e35d5f4c02923f792db2c40518dad45377f12e01a7c91213d3d50de0ff18413638c8f208f1cef98f412ee91e5", - "0b04c93b1375c1367542b0eb6fd448b817af5c2f559a1e7e42cdd11cb1a36d5c2521445614bdd667fc88408a13b123759efab167cbadb39ef227e8d57d70b3734f", - "0a07c48f62a01df6df79b9caefc701753f454fde3e0c3d336d91a63e564a734eaba5bf5f7242d7e9d2b36a0e3c4acd91c7d465a17c8e5fc3b56cd761ae21c7bd9a", - "0a0730fd50c4596ffe4d0331feafca6f97bb056b858ed93bdd0ef39a64ce9b3111787157605ebabec252449628745255f4082c523f221d3a3e9efc3e00a7031816", - "0a06d3a63488e0f2665b031f229726568fb89b0e81b98def24edfc9c378aa15e976e072fa2b2c9147b86567295ae388182a09683d4896b6725f1e1bc3543007ef8", - "0b05d2e1a4eadaf729a3dc4d0b5fbf62ce92ba91ad9f59ba6d52ea5d47e65dca1492b9fc43297101cb9fd5d9524ae8bd2c71f9ceb7ebd84ab4d56e9fec0765464b", - "0a0778e0eae5b969217b829a32fd07dd3b39cc371078a684a43391e4190b1c296756882820edeaabd4ec839c8ce91ed81b0f5020527a12b0ce411ffc5a48175bf6", - "0b01c7ad8724ccfb9e440a7bdff9301da1557fd978fe338533665f9285432ad3df58fbab71bfeac2cf5d329c080d253a9a22ab61be9d1cfc9c2c155ee82db2385b", - "0a033799a2ef63436aca8f54e090f5edfe3fe5a8d9344c9bc99799c6eb1537b3ccd75f02c170ae9fcddd73df8cc9587ac4b5ffb9403f1dbb3fb55147341492eeac", - "0a0737e454a69c7c2fe32691a255e6ac519a3e756a1c36a65f035111da9477982f2e7e7984ba1669eecb279a6ec1df0646409192acfa70a8cfdd6b32eac0e2e6d7", - "0a01aa03908793e77d762718168dd98545e52bd89d4d8db934a147f63266b133d83b9f225cf3122a25ad458d1c3d7d6cb093ac126af522f170b72d089dd4d19371", - "0b00c54bc3f6a0d90948d37e6d329a7e87f2144916d5cd71c3fb8555401abd15d73cc05bb0b43b908e4194387f2599b0d249f91210ff83966791423ea7a118caa2", - "0b06966a508e0ab831841c10959cf3d7484146bbf411bce536f130f0f59b6e932490ac28e637e36e40863d9394b3e65b150c0680795fe53a7883ced2ae86712f0b", - "0a0438d3197394705409ae46b8628529b604a039d89345633d55ee35fb7995383744fff7c270f47c9f62bf5fe63c808ed1fb1890d3a2438248609583ead5f20aa4", - "0b059cecada536690e472c8bef5e160aa32aa7b01b54e8bb6eff8ac07f87ddd923109e7bf3c6db2a826414f0f2fbf560af5dd5fcf2bd348d57dbbca83208987fc4", - "0b06f6bfb2c6c6805445f59fd5f0d34338cb50ec0fdedbaf81c232acc148ccd5cf1a654f0289ceeb55fb743f1f27bf356bb934e683b406c84181ad81c59df37ba8", - "0a00f286bddd5c1b46a9c207219d57c52b11fd220b6cd919cc1c49828ba46f22be271c2e4c6eaa6cc0d3889735e684fe05886f70887248fdb7c87d83d51d45a286", - "0a08048d3c4d87bad0381857ae9309d07e3c5704bc8c59d48c066e629ed084e21b0722a407bdcdc2d9fe3826379855949db5951d52a9169a80c1f894940e1b4960", - "0a01c7db0a1eaf7f9bdc1e3335a7d940ca89828e334692c4daa9b4861f74f3c9405054e61d87e9475e1079b1e2f023cc6661c9efee297cf5835e4f55cc90ab2e35", - "0b056679b3b6d008eb78023119b51941fec1e35813b6944192c0b812d31f3041a8fd39173acfe77dc4535aa5da4090f3ee6cb36aa110d2ccff99684e7affc7d427", - "0a049a0117b7bbc7609ff4bae252178fd5729885861c53546959387111949519580943fe7568bae8df3c31d5c6af5cf7bc69af05a2a786da20bfa4a6b360de5c6a", - "0b07c269172db27a4f941418345a75e5061987f08224634a233c365426d076d82a9f7bbfe9e71c2a94b7b01a6ae289ed54a34e8e520e325f12301151fdad33a14a", - "0b07bcbc2a1a1c145aef5e67c8d748c3d92e73dc00a64e325dfe0f48c97f91dbe94542b7a86826ec36d23d472cac0bf4d42fc0d1acabc3463330c428c80f04d2b1", - "0b00ac8ce359df1856be5246f524375d065a945a60ddc832742b19ff39bbb8cb15747ac00ad8254e6453659b16dd2d0357581781f26124e8e9d0e6d8a4391a4980", - "0a05bc4e79e68b5931581bf689c594371263d8046d9c95463531ee853da3d35857aa35c24cdc46882f5141cfeb5db80bd144bab5da64778fd2462a3faf6c7552c2", - "0b0803138ca7e1a3e7d102b105d7b85e885e4d4bf595fa87959cf55241e05532dc563b3bef9773bd313538d5f2d25b4df7750c04d2dc37c9df89094ebca94a830a", - "0b04a5de8ab27853caee4f9feb0ac42137fa30765b8e3d2dc2d05866f09f311a9b3a1d20b0606953a81186c19460670749e22f485ee44c27485f7cfd7ed802ade5", - "0b02db50f3acf31a271b9dde8ba236e2cd34bcc6cf6b79c613ef92001d511c9bd56411452334c8c3202e742651ebdbb1b4b249d57de6dd6bc213787363ab45838d", - "0a049a514a8f31a684c49debe56815366e4bd80d36c163dbff0702137c8f1a6e34ddb3a27e07d0200fd9685c8ec767af68536372b2489c6eb050989b73208e840d", - "0b08e3da8351fb61eb5dec9f161e5b2ca0f44e6ebf54d6b0b7810525eaf6cdeeba564add80d7f63fbaa5bfc940b7dab3252e3cdf576cb67879b382c9130110f024", - "0b07d31f2537ea5b550aabdec5ea8639f1b53726fea157d0ba01d431fe78275d4ccd7e13f43927793436b37e79c7c7d186d4dbe6d58434585ab6a2b017ebf0c513", - "0a01816eb910ef06c924f5013235c92d584a07ded9d2f5d51946e381cb33cb4de8793c6b04ce55759d56148867fb8cfd4c4405ad37f14feb4f2e23e5a4042ca649", - "0a04e066f7ceb380aecba83f53c25a2bdc977b93474d3641b32ed05a2aab737e50cfc40ab9b8333c3818ecb44c7c3eee7cbff31aaee9b9722ced0eebe4b23310e0", - "0b0668d5571d06b1533a8caa9400129afc912e625604e534c18217a4e404313972dd3a3ddb48cb4aaaf89753099dbf7dc2a35e837f303a59267a7682d058e22b63", - "0a03cd1daa9c30cc2e1448e7459839ede2e7bb884ef2e4d86eb4115418a14596dd16f10d5683d7c7229fd3ea7569385a671a890c08a849a7afa77922479804839f", - "0b08c3c9f8eade2091c469a356f2116d3aeb2834a1f8fe8b165e0dfc589dccc71285c9913d6f76325d58efb10dbd5704f790ce82080affd93ffeeb0906ce8a556e", - "0a02022f8019ba4d3c01fb999aedd2ffa8a318569fbc838a01bfc8e0130dace0f5841d0216ac30e71a6289a17a330d86c74651f6c1afd268bd2bc93d69a16e1181", - "0b06ad55ed8dec67502b16bc8101c62961f561ae35c1ebcd587f7d7bdbe5373556a8106d4bbdbd5e3477df6451f9fac4f247903dbba77799d99a29367ae0fea9fb", - "0b0912a191cd180b058f65aa5d4136949b9f7f0fd91d35a75d3a047b90b5af3ae6cbf48d9da874eba21c74ba245cc4f01ac58f0be2f7c5256c8f38533b93ba0e61", - "0b076535740c24be34dc657a3cfeb398e623fdc3438580846669438de0daac92815f086a143a1672210eef4ab73a3035bc432e54664e06fa5fa7a9cae256e7c4ad", - "0a01e8cf8bc249e46cb0982183ee84d0556eeda56f3aa7e60ec0d5e96a00bf5169570b275ba93e0f6d0318d29109a6b4dd89bf25b450ff6a17652f211447d69706", - "0b07d042a69f97fad958a20f36c2693183ad136137f4bd5dfedb74ad76c1d9b2584dc7b3d8ebfcbb3fc08a368704d2bdde394c1bd6b0b1ca89b2de9709c345c70d", - "0a00e72b347bb344fa110fcf50b5f27bd02328c2f5924cb8046cde7b8f1e172edcc5a17f88bbb1ef6e7d35fa592a556cbe3dd63bcdf36524c009cf142d48bc1a02", - "0a06e26aaab13c689bc7f2e600c3ea9e97d484707498c00e2579edbac57bb9c01fdadd637dbbdfd05933b21f79d6e1c80596081dfbd3d38dc54269d6c56c8550af", - "0a08e4a347ebd8344ef9f594dd8a8956f22da57446706f76e7d495fa6360983a278a52b0fafcf63a4ed6deed8875de7bca728d4eca2a8c3045744167d3c4aaa80f", - "0b039e05c5c3e75bca56e2beb52bee58e453744a0cc10e2abfeff254edafacd633e0d5465348e1ccc9544ac8baa4da4b43c67f174b36e12a216336d370c83224a9", - "0b0392d38f7bc59f0b0d11bd766973b5766793e01e8486154fefd00dd65204105609c43e3b0bf6197fb348d2ba6dd9df050ebb5e8a616ded6a365c73aba00c7f33", - "0b04767cd9697e5c6db1620e1afecdc6a7cd9d0682010407cc72b45197de4aa8edf6b7bbe679e45714e2abe0e0ba5f9786931557fdebd6b43dc177bef3119b47ad", - "0a02905b860d111974dc1e1072ca845a89f5dacb889012124cb4d183fc16a9c9cb1a7c12eca77c35fc0a0bd152142ceb8959fcd4f444328c471e45a506d7cf5c7b", - "0a01f938156ce501e960b4c7953c1bffa83e4846d20a70e6328f658700a43cd2861592e5b315e596b534bfb50faeab7bec213e8b541386fedbe6a20c9d276229f8", - "0a035efacaf952f59417ecadfb9a117392ca8cc7f3daa80f97021d2138f88cfab689da3afd893af059084088cf26da1adcbaa84a7b7522642e358ecfa33ab43049", - "0a01d303693bc1f357dd52221a0b0f817e4238b3cec48a0eb210298008c0b807ede7f7afcbcaf6ce1141a3ed2dcf583738cb269e77317717670ea044580bea4b72", - "0b030f1e5f3e659d16fad35c822a873eed27497e027ad6f378cd3952f058eb753967cc88f7de461f69d583b42338b60d8ff4b5b215072518219f7a464a5bde79ba", - "0a08eeda3f87121c9f22dab3a3245e7d6fc142f65bf418ad654c1b50b8ed09a7a7c1bc0620e5974c889d92e3170e0210b980900994b5d7209cbbce4bc4063d979f", - "0b0283291bd64580fd4d46571e5d6e5008845917e2456b064b21e60c400218a038dcc324dc33913daeff28023c547dcf8f77afc4c60e0b7b863d67c5f1c32ed579", - "0a06e45031a9dc27e0030303b8c3badf0ed5beedd885d5ecd41799d2f9c9936d3e9722e6c8d75aad133bb82b4f53f1de5707acb6e80bfd9db0f5f4573b8aa086e8", - "0b01e16012218fbf3cf12a2f077b4c8fe74d60462787c90acd383eb56197abff5b7b20f892dbdbd5ba116c24bf0aaf8834ef80165280dd239b2d2c3bc1d7797a86", - "0a035bea09ba1d8c728fcc2053cd65072647d086497ced2ef08e88cfe159ec2defc377e4d7f022d28e2c9fe27311f3a6a5f42dffd88e05a33c0f2faeb7579d768e", - "0a00a2366ab5a63b9f00623d44bf7d3dc31104100cc4817c345a7f3360c35629fb90f057bb860abe3456e0e746927bc742ee9f83013812da14c296d0bedcf4454f", - "0b07c76e317ab1af072f1aca294de0bbe4c9dbe5d7d94aa6cdfb6cdc8a563f39b171785a6ff240fd035123cb3eabccd8202ee4d9bdc15c3d09e45170483f52236e", - "0a0234a80a937653488a2c324f89ecf04004c713682d0f2b5933e47e805784f59f5a717babf544a6f10e0b2713bf8e97d94d548549c2acf72e9b84268bdfc97407", - "0a062f7a9b212a839e75a62b18db20510f08d55a2ffa7fa95e12893f43e1413cd9082dedb25e2d24b73b2ca6de9aa5f4b694af02311a3495b5ec214196e1f60912", - "0a08466c1029230cd1e8c1b9561446a1b4683a3e958c869b788b17fbb1b45c688106b323ca95db5b547040010442c9ab105734003c54fcffd3cb13e73a643f095e", - "0a013a57c8b90c8074a6ca4fa7fcc51b3805a631a4670956f7feb083a949f82d6efd6b825afcd14e421a8d2f60462199d9532de6ddf46fe931024c563d61c27e59", - "0a032833efd7a62ab777adba529b3a29eb39c537b4d75cfe802ef564ba37e91be2fc760a87d3182a89ea35324cc618a683bc9bc9e31ce09361edfb0e5b03bdc4ae", - "0a0249ab3f5c426ea941bea8de5356990a1a2ed74a622a187e14cf8db6b87a09a67e70b77c91663b1f83a603164b1ac92beb2a55902ea42f389b50a0a0d4ea02b2", - "0b0912ac3c0e681b7836036bae32bb3da1a48acc4b3e4c7b88c54d123f672898db066498f661c5d50170d858a23ee8067c0be4d7113c750d5696dc83a4b87a1626", - "0a03a27b943e5c0f8e5ef4c486f0b83d57b9cebc0b4f92de07c61818cae49fbe668fa2a0436145890b444ec455f9bb952ce4212ad2778830dc163554603065e051", - "0a02484203558cc9e1a45e16535ad24589f10ad58075549324e6809ff08751717fe63312c04f4ad3cd4221620ed4233e1a68b4538003d6f2e07bc35afa638b4850", - "0b068373eaff44b7c0db54d4a16abe452c9414c835081ca664ec57d10abcf440d3945b3c22094f059b5aca86ec71519625a8ee5dacc4c0b1224fa96517e234b926", - "0b08c22abd693e7b40ebd03070c91af76fc4dfe818f9ace2b3ada5657b9d84bff6fffe3b10b56ffeb7e8df66b4f1fc1bff5170d72c1277198331bf1eede589d40a", - "0b0623a914ead8defc94db33a75ee6aaa5d87f6b80989eebd000d7ffd386cb51932467126a178b396898c453dfd9767e9b0cc5ec39fb5c88d099c5706a3f71c84c", - "0a05895859d21a9f2c990eb8395f75ad0093591ab26d6752faeb97c7eca4aa7455a93af247cea952703c43ac4d047e7be5a7c389a0e21a3c92621b8b6821bc29a6", - "0a00d44beb973ee88d03410749aba4d20ed87752e949020e620e5e229413070a6a97745f20d29fc5781ae8ba7931a248fcc04834593476e7d09382e5b92735e153", - "0b02417f49c61f24aec9c8d1b41dcff26c6afba7501291aacd2f0be83d1cb1c6f47b76de8f8a1beb76aadec39d8588b9b8ef43d2c55f255e803a4dc5c6c0327946", - "0b00c9437af4a170f45fa36d9005498a62e0abbcb9d0c3d82381f7e4a92fa3ad7927f104cbb97c26b897055a5cc70afa0c289b21f64073da18d7402702e9b90e8f", - "0b0399ecdea89d89af4ef34f0444abd909d12ada92ce4ed8c4a41eff1ab871f9413513c4cd2b8a47fd85111723e27b65a5b3db54b3efe1d2828ab2c6e8fbe7bd46", - "0a049fd76f66c48f7ea89cd436a88468d4cd90705e193205da15b1e1260bb7f64242592adfe3b04bf979380f65d4f58cbff179c8b5de4e68c43486eb9f813db651", - "0a014aa564b19c4285202cc7875e520c9f28adca63b5ddfe6d4d9b51242238d5b4a5c9a66845600e1d4a622557b806f94a9d66315aa31113b6e33bc24b47ff5ff5", - "0b08d4b507766df825d7421f42dc6eface6d0c2718ebbb2cf3e0b4ada0e9960ffdd0a9eb280d779879285bad5e6a2eac22ff90fc71933c6daa84c26a8ae29a0715", - "0a0848925e24631afb7b4342bcfaba8409077bdce27df16ce8da4bb0c42c9033d164f2942bbfdc4c53bef3d0334e530fdb2fc7806469e23b0fd83286f350138106", - "0b07d8fe68e62627a7707f4936293f22519149cd45341de19dfcb2a35f9ed92edfce300f2d5415b735b92bf455f696ba055310372e50730ce48157cdac4d6aaa16", - "0b05316281b5769d382b82b535f5742540bf938b03f0b141091f36326c1ff88027f5dc3dfc0e81ed9b657cfb4fe480cff2569f9b19ac90d96483a38ebba7f2758f", - "0a073e7c18cd328b2b26de4cd1f73503b1cb301a257cfbc1267f49d747b90a891845b29db882d4cf3f92aedead3b163ff1c8fe5ab63c409450753f17572e2a68b0", - "0b0847780bc26f33741cb054ce27b9a0effc05bc1016927b93e4cb970b570f3a6e313b301fd871f901a3fc6f1035a7a5c27eca44fca702bbca8dfac7bc378c1d8c", - "0a0868c4d85713e59e304534271d45ea6c4150ee032db67431200afd067edd3f2a7c8d4eb6391c758927affa8dab9c317a8bcd1ffb09eed9bec6ef8e58ed126e84", - "0b0860f947d365da2ad46427b5c7b79c478a41ab38fe75deeeb9530adf878067d110ff489a7e6451a9ca93359c5105b167fda831f33932e6e0a4cc02f2e8b18003", - "0a0729e775bc786246581d685aee2b7bc4cbd7bf0d7b98520fdc34eaaaba7f785815eed7ac878a32b3cd5d9438777bf0a62cc467c310a2e6b1b49e33e382b07000", - "0a05efd1afe61ec16f2a650362848ccafa6f989fb95c1e38892dde37fb2562397d699531d7464db0e532a09f66ec52646241c59be63a926287070e015c402f99dd", - "0a03e98c9404ae2a942981f58bcaa344a1c1f23e8ac59fb29f7ea6abbb577172dc7d6167ac9d1c478a00feb70ab9145817156531863105baa4ee00ba5014e9a980", - "0a0716bb43852a42e7519945be0cd78ae1660f41dda0e8c7dc83d8189f14fd91528e3ff01930c82e181326bed4339feb7ddfdde6f633813df1f19222d61623abb6", - "0b041431ae29eb3470d4d61c27e165669fe3c99c96cb6fea3adeaa245713f963c9769cec9dd9c1423ad2dc598b40712ce612ff4d166b4e157651c8213288a3112d", - "0b040140cff65d2015f012a6bfb6071ff9f9dbed2856573f4440ee47d5e867746f49813a62c352e30150491d72660c41d5d013fbe001980935337b9914516b85e2", - "0b0301d6d24938461c36c3fa80faa495864f05e5541eecf89d82734390652eee42163c9d2792cb18254bea77c8b914f681fce7f279772588f0940735522287b12f", - "0a083ebdd2cd342abd8c38c217f97fbb637870786e136c8ffd0786c0d12ab2f89c129d6f2c52c875788dd92672f483f76ba6fb19c0fb64cdd04ef070c7a2fbdea5", - "0a024d6714381457f1853adc34650bbad3d4c0342a407e6a4a11db999f29454138ba0240382fc8c8e7f512602301a67815c20d1198701a593dd78747cbac1439a9", - "0a06392f08544c9bdbcbbcdcefab33392898e7ea58aec3192151247b49eee04afd840ffa29f0954837743cf03452585b21f5df9160549035798be97f651b1d6fe6", - "0a041850d964893c2c90ba44c1fac0e546ed6f19e55fc03c47af3a53d122f425c436ed99a24e227852f97b881ae69d18dcb5b9bfe7a43fb971f5f150e54959632c", - "0a08e238f98997866ee259aa5016dbc5e44653ae9d174fe10bb4c76287cb6dbe2dd2c6bf775c15bb366ce890c6cf3a51d956c7308f4f25a1fb3761d6abafe8f994", - "0a006200bc86a91608b72305009719da3ce5cd97134b4c37aeb48c20746e9369d5673d56e7d5b84fa3c6730277131b053d19d22be20e8e79835997559946712b62", - "0a06208d96c6b4892b70feaea5bed477a59414206e95d83086a13c03d84024ad7f5c2271c20a89753982c1381afdb72059290a2ccbbe2f058641071045f9fbc4e9", - "0a009bcdae5aedbb4704ddb1b731ff153ab71d6468513bbb5b9260623a18da2b9251efef6e021cc4026f71e5cc8baded196a1410166bef3cec718d44e50b412c6e", - "0a015921c5c7b7ff34dc727859b7d5d760401516dd5c3bd20e87392427452eccdb723c2dc97abaa338cefda665a7e973ec4da0e9e5b6fedd222e45d7ecd3a79343", - "0b06e747ecb724dad5551ca2a161e46b526d8e1464c804dfe063f1c33a588ac47e35731cb0502eb05fbf89a9a3283b6f89a2a0eacf9a5eab9e92964c3e53933783", - "0b03031e073a74e10b1a293110ae102d998f80e05159d4bf8ec3ae9af1582800b31f106bf4d13f0cac9a60203865b51f982e00bdd909ff39b82e6e982ee32d147a", - "0b01d982b8f8cc53270444412438327e22038cbd6f63df28abe404624b8bf321844e8f47f294691339e07ce47f48475f72e8dbbc4f0b53c90efd0756488e00c29b", - "0a03dab7fbe791d49a8e38a789e932fa05bdb3424029c9fe41dc9080c4cfc84c6bb804a0097e3b73301eec4419fea85fb66523e58b24147bf1b83b02e1b3c72983", - "0a07945f6b3cc92bd05fbf83791e1a03e3eceb630d55c3ec5b2072fe7698214b8e5a1e94e4cf35ea7eb72f204e6ee5e0d59ca01e4fdfa39cb46131613866aad2c5", - "0a00bbf54fd7a0e0b5e09377c041935137024b3d21a546824c9260350458134f426377ca1bd2e484e3fc58d0d2861a2eab883b299c0b26a438e933a5191993d8c8", - "0b04e0644c10014db6eaef88d77d783c9c523d6a1177efe0066a0daef43d3ea2212e44c0c6e244138f16a661163d1ecbaa4022fbc5983e22919d5057561315df66", - "0b043b4d4b8734eba30d0edc91a55835c4964d8efe80127a316c3a74c59ac7e2a5dd4350ed82ba3e419bc2012450ac82659f3ba24c0665e8ab38f9cb19e3329235", - "0a06402f4e7711bf60a81c39a3bbc6e6f9c29e234b61e4197a6fed49e3d62ba5aa40b692dd7628e6f5c323eca0ee17a81e81400e28f528a73275aebe628f667aa1", - "0a0549657e4a231a52c29af25027a733dddd62e7dcbc8790e7107cecad784c450030290ea5cf8dc4dc61aac6868f4a60316b61597d0fd70a472a27cb148288fe17", - "0b03e90ff42e84470b0e0de385154a7a9c2fe9259330bf94900d4636c18cc8b8ab0094850dc93f4dd22c25596aedf4d133a1f7082bea235d62818490502f919395", - "0b072713b5d17edaa81f0babab2f06496321cad8f29ac039b1f9fc7f2471f5f8ead0b794a512575b53db00297236bcbfa4143182860a6be72f05e63bc573352a92", - "0b04cc7e55d6b463d0a5893489ca367693d3ab49441204e784cfdcdfaa639f3ce40b99035c9821ff0c9aea85b7183e8d6a1ff7e1a5e916679abd9f2996bfe895aa", - "0b036486bf4ffd5888ad769a976311b82ec36cb1989c9307af68d6db9d0c100d4734fc0dfd7ff22644303311690f8af4adddb3bd6eccca3685882053434acf9c0e", - "0b05539033b77594abce6f84e3e87736a3bf9b7cbe08f52e39892210c1c3443ac6639e797b18d11968439f126c0e8a977ea3f01a50a6e68bc7b9a953d32c03de5c", - "0b088f632174fb7d7a978105cf9653f5d7f5c9f787834d60997e091af14e23d3a73298f4d84ac9fc8a58b82c61a867d5a140fda9393e20cd1375bb9f958e1a5f0d", - "0b072ca472723c31fb2ddab477e289dd159fcbc2fd475b09ac8da87539dbbb4ec990216159e20e95ee8612dc43c4b226d0a2af79b748cf970cd9277f1d3eb80c1a", - "0b02930357d0190e0cad59d4e70b29021cc243412f867a2daeefe94a33653ebc61e9d61a904f30ee1bf9f9c52a8422f7c697826363154ab91c091136d7dd6ed4b8", - "0b02d5bfd57ebedf01f0cbb2f1cf22f26b53d18b4da1e831c3b813eb13872798ca021bdf5e9bf43699ccbaf4de91663377796eca620d505794e288e521143a8cb8", - "0b027ffe02ca7fb66337e123d3e701ff2af892a782d1ba7aa4521eed67e107e069e2e49f02228f52a7016cc8a905858841599379681b21b7dd2b95e06d30c76a91", - "0a002314ca60dad2ae3797ebdd5477cdb76ea7f72cbeac73a951119b21aa9b39a87573ca55119d4397d755f0b93ca02a502948e58c9032056e416b5a3ef3576885", - "0b04de0dcc3440fe12f9c3b602ec0c2de865f47e46e9fe21943e921cda8552e3d8438dd48ca6354dac4ea4fcead57a89dad3f872df1b3afe2527acaa26688ab3fa", - "0a027b7beb1493177b83225e7b6a8670dd365dedf33542f191b4ab3c8dbaa46cbe443013835342f34e912ef90fc1f4301fd902f700a53b8401cd01e62b91aa3b51", - "0a0099643fd8947e53686028b363ee773178895dc6d3d23f171eb43a65edf9a2448f83696a7f13e6678dd3eb95313a44f888a5aed288eda535bf7d39e84a37f738", - "0b0214e6cc0d99233f4e8d7383a7890b82bc078213862eadcc4be38ac3cd18fde3bca6a8f6edba1e1c02d01a428e3100327cda9780791dbdfeb7c6e30d64a2a498", - "0a00d955cde22efb377508145c22426ad21dc67fb8efad6b33b209e661b504365501a0cb6963a134a916023f619329477a045f4128b77c039178b3587df7736ca7", - "0b0620d89ffd7e7d327264c4052cb2c8efe1680995116c9966f1f2a408f6b30ef94089851df573bdc1c58c0ead4e78cd562228201f8c08cf9270fdb908e0eb2660", - "0b066178f5f1b66c3d6aa6407668d6eb5f5ca802fa98eea849bf4d79b31fd3cc91f03e62700fd35cd825361717fae4f4cd529b7816450aaec0ba121964f52eb5b7", - "0a05e32b6daf1e543236aba5ed3b4a416d1837525a84d4922c8ba7dda1d50c25fcdff61406acd2d55ac8acdc63969f76b2122f82eb5e8acf950247a8bd0cc7a525", - "0b02e5c3507e0e7169742eb5f4c4556f8c838054433d25976fd307b983d581e2d43a1983f1c577f09010a672aea2d1528d1647ee362a5f1e0e822577977336e1f2", - "0a0870e70f5222abb249885ddef11ac0d0cd0966b6eb28eec0290cd638afd8297b4083a7db2ee9a8e47b3381ce902bde781956e6b93d4235f9c5840c228580933d", - "0a0130bce82de34d76e7d9bc2951880563fb2c1e3ce8fc277bc2c78e4db702d616bd60568ea3daccee132d8faf681574842f2a12ac6b801a3e3526c3a9b98877c5", - "0a03e2edf64aaa533fe3fb2b134a8675056304b4e7e6269dd6b2fd70998818ae09fe9835dcc94756baa483d92e8038be572e945165ef966e22763cd66f5b090946", - "0a04563805fee877fb4e7a2198c5f2415bbd5979918939295983b2951cb7c75a5a0b48304503ed836e05f361e636e3ebc6bd42fa3ac02b8e6721e448726780940a", - "0a072b89d8a292ea3437d36aa391dd63b2c0a2e09543b464a390880b5bc1f2de2c58d650ad34b21079131b01b9dbaa7796956a808fc57ca7bf0e5e4618b4371881", - "0b0339d32554b1944e87a79912c3ec81d36af1cb8af30c57c572565773b5c66b86c14583f2f614e8fd9cd3991004324545c63ad813b79009f31eba282080a6c3ea", - "0b08ee7355b9758600dcd47133f99c60426af857e9bd9766a180bf2c0caec4411f5394ac9187163cb93fcb5680797af12f96113d886456ed1cdcbb257ebc615a30", - "0b04e5530de238596549f4c3ad4453558bdf8afb7f0cdd3a8e986a4225e51f80bbe973258ababf0544cf5acbc85ebea9fd7a73cc4bb51315f2e84af59f49d69602", - "0a012ebc5d97e85f735578aec7f9886101735f28b409c8918f74fbb968834e9df3bfe9d6eba84fcec344e63f9f5e44863f4622e175fceb9ff3afbd69296d7ab1df", - "0a0344690bc51458e63851ec9b51b4b5ed652b31c43a34c12938e4658e734b862113854ff65ff819f1503363d4b445f3e3bcf0b9191e1821d3ccd4dba695291776", - "0a0187d0a0a187720f4253932b575fad5cb547bbf2cbd7d681cea40380aa79544f1d724f18bed77f712fd78606a89788ce0a39d5e8470d622d4178cd46d5bc2487", - "0a00d19b014c7c1808a81ca06718010a9b0b5f91e762221fe98b201113ca618dc68ae0b1319a42bec3bd0ac40f05f4e7747de02f29ed902e75be08c27451c6585a", - "0a03f0e931b2611d2507a0567ec5c4aad28b7a41cc74821d5b085ae38fa67852e8a317b7a4994ff0ee52e71b3a773eedc5dff7353eb8eee576ba61a702b932763f", - "0b07c081ca9e125bfa1250e2d9e3015497904a8f4706914aa034af3496b0cbcac613263966718db26fdd1b74662269b3db129e8df484a5fb280b8fd65fcae63c36", - "0a03636ce3c244154f707fc09827d29bc248cb675faa39abd5edd0a2d24c544c1184c3e1f766d49a53cf92abfc2b30fc52a994cb51179907c2c3529b40239503c9", - "0b039957c074215e2a966618e89c73f97228f1ead2cd7f3a85d39becf47e97837f38a92fc7698d2ca6502f391650e4954ca547438cd623ee2676576f8aec684da2", - "0b00db454e7f2a56498190e2628bed9a65d30d1dde07927be343390abfa8f89bf606a79559a076b8f6fe0779a99c41bc40be5d65865401087e66969620801c9264", - "0a01349e53f8596bf789a87eb6e6fb133350895feac10f61609741a6f27b735d35207fe2618177954789ce8a29e517585d60257cf0cd3cd0e2ee85437a2b0c3074", - "0b0078d63720bb288e703c41ae3813e079e497944717e528a44eb98aae462bd1422acfd76a481165a09c4b0722c2c3767eaad884674b2d4f51800b80a751b7c407", - "0a03b236b6826575a9c794eff41b6101b9535d615f5592da9a48fe1a4419703726677eb3d44f90aa3b1a5abea09da188c130e31b80cbd904821ca87fe98d736f62", - "0b0495133245e87f323f5cc7b10f367ba48568e97abfb3ff38fc5705d379c1e5818817e5be0fdf07cc0266c20e7ec2cc5d37501b57ec02a8fcc70e2616707c0f5d", - "0a06195646b4113dcd2a9c44b2ac04e9f8eef0eb3070cce923edb17a037cef2e9ebbb755ed02503c952e602d998356c4554cbe40b25f97a9915902644365f8a645", - "0a067e0e204020105e685fee00deea223cfc70a8a124919a166e7bbae7f399eadc79c031c7dc4568f10a6d6b219e1545ddc879355eb8998385713ecc0a1e6c6d0d", - "0b042841040821407e226f6a026d574a712eafe17c3498a9c4a0baa794f5d65d09101f7a0d53d51c3447ceb6fbef114d90b98c76aa41c4724ee4373800e6d12678", - "0b07b89ffc9bdb298747eb71a49605676fd74b94431d1957eb15536bb21ce9dd02e38dd11657d6fb03bd235775103eb62645ea097c33221fcc72bbde3abcab1920", - "0b00fe9ad276d8e42c78f27a223a30621128900f7d8339423d1f4d2ee01815f0c8cbffe695be3767ca55f3b99d514af751c6f057221db050d32a2a7cf3cd2403cb", - "0a00979f8e500be712742349142676783230fd962f5adb1a7a9169d47461f6a77ec1334d87c3975a8a611306af4d6b823fc297a0f8e5b024c12ff17d132adea8da", - "0a01c3eb53527d9b0a6995b6eaf2946372b4685876abda3c62985604b1d9afdc3b10a7dfe639d30b5d3f6a3eee2049fe0104dccd221c061e13590421e0af8f037a", - "0a013a72b3071eaa98b2463adf47ec87ebeb6c11fa867e4dbc75c943632f5a2ee72833a50054a9877c9cf4afbbab67ee32da3e52b665edb63f3dc5d2fcd2ff38a7", - "0b083b3cc8230c9ae0c94eca9fe5d477a5caa62128b335b00ac3485b33c300ed39d6836877b5135efb84f5e3460a0e52faa331d1ada86b6946aa5e92877ac32251", - "0b03e6c60ea2bf1fca87b44d2a07f1692175c30c50d2f87757fcfb62bd7604b631ff785462c8b340048a566103eb7a6a59947cbab566371fd4759cb09fd1dab9d6", - "0b012e201d686ef474b7acab38a11abfc525bbf1bea5aee6be555d3c2636dd0783b570149e4fc2b45bf4df2f495c07aa53b28fdffd1d883ddd641ef805f72ed287", - "0a012be9cad907defe814cc9db37f13dac14287f1b30dd1eca2f4384a3d35ee8043bba6f71a8b44ed00e694dd0d99e7d41f00313d7119dacf7dfffb4e662e4221d", - "0a019289c49e4ad8b253bc52111a0abc3289df4b3444765a797711d61dba0ed718364989fc6865e305eff2d2664306885679d66cb3d3f81554a3681d642b8bca80", - "0a012bf3873d6db317a022755b966ffd2a00d2684acbd4b8bd592f4b8ff25d82fbb6186267bf9b1a4f1227c8f73dbef4ccf63ab16efd102698627d111577beee66", - "0b0698f05e0b727014dadcd01fdb11c43a34bd0bf001477757ff8e0b08c6d6684d59425326cc0d7ffe55d52f3bffaebb094d08ff877df6306c812dc4de0cf66f52", - "0a01f370aed76e7897f237e5af389947b2fb5c734f6be49f7c608648b94bbe74cd341d004cb3b2628b4e3ec1182a453a2cb07b836bdb16b465a18f57dd637efaed", - "0a07f8e54296d12d891c94bb43269e97aaf39eabaebab41b5bdfba58d88cb9e4be644afe13a4014a42845c4d1bbe647e6d2b26830fdc776fb340a305ca46fd24ec", - "0b01b6914feda8d8e49008b9321ecdd74343dd7c5678d6b0248e5a0977838293f6eb958faea59ca6bb07487553dbd33233e4fbde2c2d62048817cb69d35ed15cd7", - "0a01c72b841364cb83cb3ff8dd7576e0214828fb24527cff7476b417c27a81e427d6af32c914699eea2ff00c99e73e794aca4954f9a5c0244054181fdde273d4b9", - "0b067c60620bdd43e348a6ec3d8230f1ff7984891b0d4bbd25b78b2aeb3941f0e3cb1c92e4d4a9f279038e595c5a85e6b2116a67912e493dd885c93e0982e8533d", - "0b04235f8c8be2a357db3e54c14200a91e532f34e1f2d292e06cd3088edada95953447aacf8e4386da043960e4b5f3462bceecd37a116a9959ebefecce37d15b4a", - "0a07e105e1f28788acf34aa76bb3404679133f3e1df5693a863a084033352b780ee04f34c4c48db521b8b4d5a47267a12fb160934537b6b4a0d9d4d204f58108e5", - "0a026b13ac631c2ed31da258c46b4a4f24076327e8dbeeec70b4dd2ca1b7a9a7f3ac672150ac5d1354ce361922887277684fff5ac0c468ed39047c6772169a709c", - "0b07aac750a60930a0918e9d3c4333c8fcefd4c0b9e90045961e64388936dd320e05cff00260e28795747ccbe76b952f8620a9438d240c034b44338a4e26beffd5", - "0a0610e4372c00657f0b93662b7b4a3216822ff2334ff8247f23f284625ac408a0d715640f580b600aac1681ecc30042e77483ea9e75d97bb33681cdda6701ff78", - "0b0193c61953476c14f394e1c9b88afe25152d992d47e3c41f4d347dc60f93974a09586c407b90bff13c7fb9f04d25b3d3dc3ab5ea5e878ea25381488a99312b69", - "0b02d472cc50deb31592d40028b34e28c22b19a4df8c58e8c017a54809f1b4d35a4f516abbb96e91714c57efb5fa93529783c9de4434a6bfd907ee7af08c687154", - "0b047454ee9040affb36491b04bdc0835c19fbb9cdeed891907c263230d8f2ff48c317c6050e7087a2fa00d4a0d9e5078fca3da4de62783c37139ad7a9211627e3", - "0b070beacc9c5ea0a9ab66605e68412aa6d2fc8f5299b6b7cea63d01dbd551c5568e43e08e39c86c72196c2c023628cd14bd5b9b275f0001aeac8a478edcd0c158", - "0b083ecc6d728bb50f6312dda4c327df0c4508fd03a8f5f112a810cfa5d8d45bb9d8b5bfe957a0405bc0cd8e2cb0292fb8e00406aa24d438e06f541078745d4244", - "0b0287373fe233070d1917f84369dfb4485f8280bc014be610aed554b2d081f4890e347930e4e1cd60929cb934d57fe0b290ae515c9e38b85f519ec1d5260e8e3d", - "0a07ff170844ba858deb4b655b4198b0a0e58a0432427a4ed3e3c680fea286f033c9bc73212e918492a00f570a9b859b3ad8ca6318832dd82003f107978cef68d1", - "0b054e6c66788532fb7a07a7bcf638d706921bf42111f8441014dc18ca1b8978b64128631b4623b0b494c806ba661eb7598a80d76066731ec93a009b32380ddd19", - "0a0386a1449f539f2b7248e1b9e959bf750ca84975e0190930e136444e529429a7e651ee5ae0156bb3afba2157c4a3b718d7bc17157f2c882e7c4ddd33316ced2e", - "0a007510d3884daec78bc7341995e56c4cd24ac350678fdf5b1f428ebd0a2277cd5a630a3d4aaefb2764042058f7ffa2f52b84942990db74f16aba186b6577d4e4", - "0b022fa2db2be5116b46f642c7958885c91116b825d84d8e6908e83bd7c5d8fbe72ee2b44cc6993711240a486895e0f8e1db2750ce7b424175481a231bbd2dc584", - "0a068a6fab9350533a47c721096b9003201bed782211f6ad4dfa55c21c1294049884762c03bb024688079ab58aa9f905c749fca7cf703f8da8660794caa1963521", - "0b00444e5a4e6b7b600d96ed1469e59db0fcb9ea70424da9c59cc54f656645066915eb12f04859f4323813d4159da01ac59b63cb3c8a0918ecf2662cf2b6768fde", - "0a0009f91a0abb620a1d6767a0f57cec0ac6259aabaf1480e44edc3a544b94475d4ef55de2a6f77697dd8c062b9e64e4206c2cfa23cead4db7e7002a272800bf4e", - "0a02df6c29ac562a26cacd5e2656b5f7f112c0cfee6d5a90107b2184b25c2b3a8e8772e52cd917234f12c37a57fac3ccd467e3ccfc5a9c80b574f94ed84091ff80", - "0b03392c0e962daef38c6c10f9c6abfcb58c6ca258c2019a9b0064cd9850e482580c3d064b11fa2218086a215d229568bacd1d87fbb1a343c1b847234eebee9cc4", - "0b061fbabfd2fe33a5360b8833b39198f9fb10e77eaabb4f7c70206437df97c61945b8e1a9e87d2c3016b53ea71a57a3730ea5bd6cb69d3ba3e4c9f7c9b0e9fa1e", - "0b075f034745705c6b84e7adbacb1a2a45d8c3bb842319cdb54e824d28eb3b2e44b9cd546816df42ec7cd504f46acb963ed0d996007ba508718b8831bc213070a1", - "0a0206bd1d1bee42d3604e6c6f53815c2c81307460813032ff87bbac72f4a590b331fea482e303a98cc737d37a71a36ca41966e0963aa45302e69e89c74d1287f9", - "0b05c4e342350b5c1e609c9a9d91d3bba6f4ec6327ba82dc4f6b5ba32a3f6337297022aa065a08a883e03ea1b7c27b6752a50c9eeba9baea39f94a516316773a96", - "0a059a6c44362df132d17d5fa83e07fd06f7d9924d1d51a3ca15b3ee49989b599f2052c05c984d4254aef5937ee72c2a55249935678e8e9e3f292fdfa1dda75828", - "0a0106391c41b20c564e52b49ce6d970990c60dbd98e283468cfe54e147403555eda74e838a586e10e4b0d983f5a7d94818cf8f9e7412f1dc6fddbd8deb4be257f", - "0b04d4dff3dd1c56f2ec3a37145de7b319c4313dc7291a8c3365bc04d90ced2c90626a5adf277fd65b59638644eb85863254b96e96cd583b0b2178b78e7940b4d5", - "0b0666d0f37e76198802c84bba4bb8bdd20175707e045ddf40aa21ca6794950cb76b50336086276e32e3c65bb08d1be19961078a5ed57e2109a8d4533656418fed", - "0a018fd76c2240d11d6c20b7e4cbbace95273117f3a3e3e6cdf9b0fe5b7e18d0f7e2b3a486ffff8c958ee3ddd8c42b9892fa26bd8beb7474376a7b8a4f43c070bc", - "0b07e9190c6a7844a1928df86a3429e8be9f6add96976cee455c0c0aef5b624a380255456c273873a56b086f09d2a4aa8880790ef1feea0db1c9235de5e87f24e7", - "0b063bb7e42ed197d6117b76a3561105ea5c146fdeaa8a0ed7b2f723a09d3eb037d9328825fe47555c093f3ace61ac920876c800c79da7c65ee4df76aa07894c8d", - "0b0807b6e4e035111de4fa8cd154e60c8abdb208bfeb06503a642ca219332d4a9ed45645fde51c10947bd399bf5bfd4305e2e6865b33075052fcad0a1af57f7cfb", - "0a043ced844570ae02113e9e7432eefc09d4f383b7ad26bf78b4fe0616f8bd08899db0255828107429b9bb83d3943d9e6b606d3017967dfe0672e99bb2d92cd779", - "0a015d2015761c07d88c77f555047367acc7aafb8b1a36823ab0f690e424276f12cd951990e755a04c13ce7a966f40f8dc5c69a0352e0575b75032b098adbca080", - "0a031409fcf520ec8abb77af47cd08686524a580f7475c7a1e6d8d7451c8d0acefd6e83b1711c9ec236028fd16c4fb65314cadf5db46f98bc6e7462490a1d4a41d", - "0a040162c6609ce5889d6ff99dd72e1832595049788374ed5a6a0c3691b92ee03e849dacc3e966676461835265a5f1b07cd1935a4b9586041abe9b122b1e6613dd", - "0b05b486a2612827384753a4f0f65c26e8442fdd74a62f2c0e97b50336c43191519b242a5dcd257d195605ab53a45fee97e656e00311c9032fd557ba96e7d4a283", - "0a06f09c0a21111377274afd325649fec0940d5a63ad68bf4312b36aa4d5a004365e275c0cae578d47b865b17b2369bea5548c6fa484206704ad19a8ca897f9520", - "0a07255fbded55fd9ba4aa79022d35d59db0b92bf78ceade4736f66c411950605d9823c79a112335c47d24df58af983f848398ae2a72447a89869190f0e09b32f1", - "0a008ead1b21e0472a0f7c94299d5cd60b76b15b2460e5602630e71147634c02ba56db15f2ed3ae2e5774b29d0e09c395deac45724fe1276e295940cc67eb16b5b", - "0a08a662221ccd3071239238acf246e5fe07ea3369ee754aed3c0d96eefecddd47e24cf9f2d7be255a9c20a34e04d850537ad637bb52d91296b1e49d37cd667753", - "0a03927a5a9ed23ff70d705a5e0cf6d001ddaf180336135bd63827536a8789914eb7147d239bc3b4fff425fd6154842099d4421da525e09ff39d7419eb758a2697", - "0b007b66b5a737c78dda94482987dcdcd414afc38d5da81512d6d3fdbb933dfb9e84bd67d881158e1f8523dc055e2068de25b4ea1beaf16dad8f856a3617e1b21e", - "0a0237e37253b4973496dfb2cebd564197048e6e8920b890d258713806cecf3557c688b0034f9a17bb3d83f1bad8dd3783c5814b0eb0702540593a43b059836f5c", - "0a0371d23d70eebd8f0bd9f3f591d81ba3a5efd32061012c015b30b3c6aa08788a85d6fd30b00048c6a8563f4260b18ef8882395943453df18f2ddd85f3087c17e", - "0a01184ac3882689c6525278eea9c7f80a335bed176dd29edf13755823c5c9a88ecc8140e135eacde74dc410f059d4149a6ca3018cabb37570ebff59135b2a0528", - "0a0374658d36c601b645f71ed4c092f0403d0e59859810e7c80fca925e5530fdc878f4b6500f10cc28f7c18b126f0d01a614b408d802819ec34dc78810e2204c74", - "0b04d9f8428b43b90bf1ec258921e1ca4d4f2db9f370b8b8fe43a01e137bec6db7baa7010ed8635882f44a7e9e13b7952b6254643922fe5bf0a345970bd696604c", - "0b04d08bff2e3248ced6789fda86ae9ba238ee55ab5e89af8573f5e85d6ce6b5db6a2ffc47bbeb4093a88bd71bc3fb66f3f1221ce8d7d42d4c07156c5a77590f52", - "0a0247ddb1849de4793341aa1be7638b687ef00cd1549e21b8933cc29ebabd72d976b65a70bb1e745cab9a281565101f6759dc442c1a41ea01351f0aa4142e3557", - "0a05a98faf3e56a2695525739e248c884c12b4074018b38b018cb5cf9a3619900129c48a95e7bfb2a96b899485b36777c6215c0884f9a5a24811c156c2b1be7046", - "0a0844d68ac8237993f8ec3bac2cc03e475d50d007e6a16da49abf77468416a4ddb6778e4a363130eaa34df7448ceb40da143913bcb03f1a6f14ac4d50525d04e6", - "0a02cbbcd64102f1869e37298eaf552e22702e3677efd9b8263697e87d557c23a63e61fe17f030a5bcba0f91629d7b63d054fa4fbea10b464b8fe466665c43517b", - "0b0381dd43463f4589efddddffe097223f4d9aeebff626b4a1f44524d2aa817300185a87b09deced15a1294a5b0edef38eece73316ea9e843bad4884ad6773e16d", - "0a042ac1126ea124065a7f01f3039372a695580601bd6ecbedb0f7fab2d22211327d078def5e46af329a5d40a6f6ac1e8fc6cdc4fb76353d2822e43f39211dd4c9", - "0b04ed7b1b17d06bbf57ecebbd047332f8b1a9d7c1cf88df422ca66e007c20c928f60bd7e4988987cbb2bfe00204e931cb1f3f013a8929c147881362fb40e15af9", - "0b084c56c056f90379ae4e59c85f1f7c7228c2d0213ce942a6f9fe7c309ac95333f29d722614becec8e893cae0ff4ed4d6f2075f189b52003c9fe319bdb8b05803", - "0b03d34c5754b968f116e888537d6a38fcbdf8ad455192b7d2ee94384ee9f798cdac5455e7081c305e45885b99fc76aa26b5016c1eaa7533e972bcfdc073b39324", - "0b04b96f3a86518bd2792a48962f973638bad76f74b0bedaca23a7635d92f04b63cb5b0846ab744312bff0375a5a510dd8ce187fe5c89379e4758b80ab45b88fd3", - "0b04853865e062974380c0152a973ae6456ab9fc44674e0af29f86dbe1588c1dc69da4d9a5c4941d0f974f74603d79bc7e42ef922aa4b67ee1450a137d8a999fea", - "0a07d393a104361f8d64bf5581eb51368a2b5316131c79d4612567c0b45cbb52a4c972fde64a12231ac9ce18b31aac3922cc842a261a2b902e19d0830a2af32a7e", - "0a0011b431ad3a38663bbb9dd46ff7b500f1411bb76c7a3f052000cac06980930bf73701da98c9ecc9ae5d95114d74e68f2c066bee7bb6ca2247f0afb2e0c4870f", - "0a004d20bca55d6998ff7e482ed6aa3514da54e4619fef46ecf8ef0d4df1dcc1a8b60d5a636156c4c0d49b6c8fe8692053072de332d27cc324452bd8d7b2022189", - "0b05dc60203afa63bb9b3ab4dcf87acf53ddb8b8dbfe7eee5112a5570af1520f42c4ca8febf865350942799cf3b39fab3cd232085cf9d2a795c086afabecea0ea6", - "0a02d91363f103594c461fa1ba6a8328d97c722d7750170f44e0ea61fc30387196da5ca1ef487d36b3f1feade4cccf05e62cb47a8c0075ea09f06b3138de4bdbf3", - "0b0357df95847724e4f793ce7478fdd7739b25ba0972ae792e49c62ae4734e56897864d06f47026cb2a4890782d73c2f203dae0d1023a05d95bf65e998d116e255", - "0b0442e017835b67aa6992ee580ddb07f230610a5ea51034cc7aa0572c19758c644a52ed4536d52b361cf52a022b785464d1d5301c99e959375404aeb2670fecb5", - "0b00e1be392eecdeeb92d83b188a9459ec1f8dc00c4e55d624a50e937e13a361cbf363424158f1caec2a231766f5b426451470df6940a83179e41b93a3ed73c2c5", - "0b05410f5d1a0e054dcac841f643e19100121febd7b74c6041a93805e53e20bc27e51aaec11dd82afd59b56fccaa0ceda1ccdd10cd4250bd7a15cb156206554dca", - "0a023799c6d2e397a9f9803f6345b356fee7557f18c685004e31b74aa821d36e71777e3cfcab1beb133a931339ec38b5bec759f77adc7e071c4d428e4c0e5d6c61", - "0b08610cccaba740f321e8ef317ac39b2b64dd879801d7f3d4993d4a8bbb786843b2ef108d67df58414eddac01197b25d11be1b741f6c741699c2fa9ecd087edd4", - "0b0472b2146a82aa1d897dc9709b0c3663a115d22469412cca93727a3047a08f7a43456004b3e52f65526952b9893d55be69abde4be7160e6f95fb4d067b9041a9", - "0a00e9b0e0b61e003246065aa59f93e28bc924571528a424e29107342f90ca97b04327b8d8f100b0908ca49019163a247040254a4e2a76f2dd0199014f42fa38c2", - "0b04f25a3294be66e9ca4196de83a88f8a5b58575e6485a546b372e92a9e778ac0189e7e8ecf1723430f67d9f8cfc9b3b97dad04ae98bec8584a75693d3b153f48", - "0a04abcffbffd6e6cf642c93f3fb83cebf05c8499d4a0a4099ab17a208f0861f4cb2682d6d9f6d44ce948a0dd4d84aa8889a92d45404541a570b553f5da5d46b65", - "0a07ec31d8ed1a252edb5a45f6d532fe5e7ed6cd837353b7f98f0a07baeef9d8fb8ca14cfc8565beaf0aeae131150986200a04568399b47644110eafa9067b4686", - "0a043a5933bc3553b22eb3f7d4ba7df02f83a92210e570600984e431ce0104a89d14ce7ae415935415f7259d9db102ad10f834c0e20fba482c5116b86ef9c098f2", - "0a050e677b60be9a8b81258660769d20ae9305d1f63f76fe92c14c59a2c42964faf4aee14ccded931e6dc809d0bbd0dd5122e9f4cf7b18ad479db6acce79beff7c", - "0a007cb4183c87396c9dda1a7fff187a0470d2a4399968d0db3f17869d9c7f6f8b5299a721b5235632800c865d577aba8ecb3235c2c9a9d0613ca97566284c60a7", - "0a018e1a1f852481e0e12789aec4c2e6c572649603dd3e54ad4b793f78ce8a823bca1901cd097bf82cb55771b12e49590e4e5b73e2f5f5b43e0868b7a25368910b", - "0a01d4c8db559ddb2d30666acf8d55ffde46b82752f25ea43d33d06636ba7d0946480812b4349e44173bd245248bd5b94f3a7eb806bb80a2ebc3c384b7dc663134", - "0b03d57fb458dd33e867c8ca5a800b91f881b7132173e18fa580eeb7295b60f1d603518b582b0021bd31373c2ebb794b3a3d838fce2f12a61db7c775e2976a3b4b", - "0b06c8497b793cccd6957479c5600fe405b7b2c722ac07f5a6d5ca066bf5d2b9a29e0560a2ff5fcdebbb5159f4ec367814c393cd7b66f45c086f1ae6ff638a15e1", - "0a032d6c55ab1d6ae612cd252eda4c5f01806c68f97e1291383eb820a3a1186e5d5ef29b6192fdeaf4369862de27398deb6e811da72c4efeaf5667faa68c5cd486", - "0a04aee1177aeb18f5cd028e8561bd69ea0bc77e7cad9ec012c63519aaeb2632750c89391d0d071d06f68479727aa3020ba44b1cbe3edabe2b0b7108a97c5f764f", - "0a08211dad12a0ac435ef2a14f658a3ab82cd724ad878620724285a66bdcf4d87f78c7a3c47a27280c094a7eb23eb29e5886d4b707e96201f1373a560cd9c57568", - "0a00a71f080702fbf9f7ec9e902a83c8dfe4480644df91ffc58a2bbe03e1790e9063fbe36a75ca039bf956366a47a98450299a3b5f6832381bf03a41b0a96869c6", - "0b0029bbd91747d9e9bb1289b769f352beba637d109ee2d09c1fc64da89b7ced3fb078613823d48f819d61b6257fa9822c3a29fd50b7603867a8cfe7eceacdf48b", - "0b0067f30e228ff21198986157dff637018a826e4dc746984cd8ace1c5d901aee947d7470edde79d51d2197b5ae3bff98b42c84ac9786e68b483d6d7aac9d0be21", - "0a021ad942f0ee64249c6e30d78c28d78b669954ad26574954063e36100a676c453647a54c0ff99a1342a7691989ba01d90a5f0be6ba6e2a0eb0e13fe20b73cf62", - "0b07ededb18b1fdec4bce6a2ebda18c424c0b9275b00020662f0cf31699bd53e6df8b7bff1463fd5f8d13e3720b4e2e0b1a8b9d0f544372d79272bb5c467ffe693", - "0a086aba368c95f1a711c5beb8f594391709f01e0869eb47fd6b06bfe93d8b1cedeeebdfc91b673a94d3165ad2b46a4d6f86423d9f2f8074ed04f26b3628f8cfcc", - "0a063a47bea05e47b344b6070b57c20c59dd2ec72d32011b8348f14cd9b613be335bd9eb60311e65c4139f9d790c7283149b82409f07d8c7e4cb59dacfc14a4347", - "0a06b04b71a159a25ccb5e98c479588ed05844df815a148c325ffe447d848626ad46a08d78657f399a2db1020901669c40410d81c8dc4a43b53aec3eff582fdd8a", - "0a0336856316d923252a1be9ce4d316ca70a85e3366fb1efb582497c7b8c005ee9a6c950a593d1f48ac85a9add99a8b5bbb4f374584a08cc587dbe182063b5a9aa", - "0b020bf660a4119ec2a54c02fa99fc50aed496077c904cea42bda65d9c8a3756a35740171e1a5c8b100111234ffa827279963f005c1f4f45f1fa5321664f3621fa", - "0a00dd07e6b5844822952eaa95444562e03cfe143a6c1e1980ffd7b9fff8a25a4865385c0a73df54b79dd9a6616e021572b712fa58bc55638b347034d42585afdd", - "0a05d3a9e43dc0af8dfd71c29315855e5864df2ea10e83878ffbcccca0b165d739ef2b4096ee84080bb8b70bb16d62852a27fdb641f925cf8ccc508e136b575662", - "0b08523b45c84f7615b34a3c281d15ea533dd4a5c76d177c5e0304b6a7b53817bec54cc5281f785f26347f595ddd93303a93ff96732db311673dba6e4980fef68c", - "0b06e30107e3579a6d889b9df5358a53cd91bf7fee1439aeffbadc43b90ce56d5a8d0d578a47612abc3ee06edd7e0c27296dd106b541c53bb58091bedc1f60c4fc", - "0b05fb3971c0789843aea4c173442a06e220145709fda4b2e024f3fa139227e75ebc156fd38dd70690a85efab30e404a010d46b6bf9d00cad298a9e7928036f6fe", - "0a0851f2fb564ca22d39165aa7d2212133ddf5297d4c67c105e5f37e7d7bbce30d47cb02be70844b13ddfd369e0f1e26e3b6031720602797fad1b264f60deb7999", - "0b02a2d1f03a04f8cef1eafc28c452afe3b514ee5704d87ed56456ec7aba8c80634dd66c67cb7c5d2aeeb9698978ba47ebfb7a8e30eb2430cfd85e26005237af06", - "0b00c793c56f7573f81939b8814fcde17976d086d725d3f72104b8e57866f0236bfbbef95b0203d1c1344539c0a1902e1f58ce2db69fa09b702a0585fa34b07814", - "0b03112c072f5724c54a88a09e3df4df5adccb5fc03c1f4abeb61bb01330692e11234dc3420807b315d842c519ef93e858edbb0b286b7ed81e701d4db5175667bf", - "0a0769550b49492aff93ed03fc554601aebb47647ee9153a59a39754340691e4adbaafe1ee52efbdefcea08979bffce2ab24804203e27226200ce7d9b2ffd378c3", - "0a02d30a1db21123a25ee65bd988d241af3f15678b313dadc67e0ff684c59b3d8742c4640ca7eb91099295a9a0311deb8e4b3c0eb22a6c9ad7ef184e15690f0475", - "0a01d4aa78ba7377a969befaaec1b68fa5f73abd7c7a9df19ba791fb2178fe39ca3c583793ecbfd631f5861baf6188f352f4181138383d994dbcd72ae5d25e6156", - "0b02f2758c7536f764191405ada3e868372c0fdb8f4822cf5d6ffe390167699f7b4246478ea6febd08d5ba2155cd4ef6faae7fd437389d8f602ac9be83f5fd2ca9", - "0b088e03d4a890465e400fdda9ae2b65b06b128d0e686067ee1a043a3fb95a07cc8cf6731cf3f1843d8c95c796b567c7cf1f2330a8f55e6ad46d7b0ee38b8bec7f", - "0b08c2cc2b387e3eadecaf41f6863c0695bbafc93a609100febc3c3e1161f6805f9b21f177033b968072b22c1a4d824ba810bc1be3645f7bce19ca713f95836f87", - "0b0071120d99ad494eb643f52516705222242b84dc82bbf288153151c18935db60e0bf3c0a67474999b38708cb584f873bcc9d10fe291d00ae7a31b22efc97dcd6", - "0a04851651aa23092370bb7b67f64633366a53c77688e48e06918ba2e01d66614c9fc402c8a8fb58560ba009e92103c6a8e3252b88871e64cbfe986dd050984068", - "0b08c71a83f5cfc4b9794556a8c3c9f857fff54e8df82806bd064e9a52826a15e7f4dca5f41ce346d0bcd5a5948eba0cceac67074be119a64c2b00aa5f7afdcfbc", - "0a0323b2c6737dcc16f96f0211541e30dfec9d83562af93d45ffd716a11a034d601f8b1f80a95e1370feebe7f6a2f20d7a66e9cafa0c9c6a912b7d9ae29f608098", - "0a0071e4a3f4b26b741d2746c7683884e418baa9f93efde46265f8bd7113b7b5b0b4526e010c69fc3faf3decfde8c9d7d97813a11316187bd3a8bd727aee8f56ec", - "0a05cff930af45dba0e6b907a7c25610de89f6e8f2566dd81eda35d944d44bf2a05db3ba60e1f8e65d5f9257a058d57c1ce4b8269401c2b1dc3b8dda1b64b08ecd", - "0a03434b72569f70f5a3b016acbc3436abfb2030ad802ec9819f7184b8d79baed409d376f0be2495ba0d05dff4e3c661d54eb89238674b3bb66331de206363b7ab", - "0a0069f1149832f2b5d69ae1633a3e6398899e4161a91d10a73f586008278f9fb0bb6ec1a456bc947cf74d5ebdfa6bccb1dede5b3f2c075f1be7776da76a472d54", - "0b049ecdffe8c5a0b69b8697f88cc2b10bd012e4c711a24dd814e2d20bd1728d445ec0ba9eb7bbb8274c2072cb412719918abda1b0dcb0520324468cd165844a6e", - "0a04f07b06b9d8de546d3f9314a94130440e64f39fbf8734c3db0cbd4237f7336c41741f599e3170ea45cba94c0f44382cb3e76ac2686e8e3d33e3f83f54ad4b25", - "0a04a48545723cd5c39806b27c0ddcd9a7eb500b48fce5689973d53bf9359cd4266487a81f0c415d31d48b4ede2c544a2fdaecae4e4c8a44c4de32c4b4ee43fcbe", - "0a00a7f42a7200ae499fa799adde22452f236e05e906a6a9554c52bfedd0b878f3c17ba5f765dd4c817dd8e908ae0fb4ad2ff61f87a39cca83f0f8ebcf718eff52", - "0a08dc16c9cecc1e5da1b34fdb1de833c70ac41f5c6a34c21e33f692050a34d3c9933a8db92dedad2955bcfeffc04c96f1c049a0047c0976b685c01f7c53f93e67", - "0b002fcfe0bda1af05ff76b4692b7b99826c7eb4e04e775199ba69ee18614b46585a580909dd2000c1b6bc7b825f4de34fa07c00f41e6efac54590ca10cc8afcbd", - "0a0913ff80c02a407540804a722ec336ec9bb7a86115ce4d94923ad9f301c064487ae9057104bc84769e9a5627f772f067ec1c719f6b7b6b2bc0a3af83ce73b2fa", - "0a02b1310925b30000b9b7c090a656d2663261b93f62d500affcf11d78e9bcec093ac1c2afc523e09297d7355c37212f1c6e8774e86fdb23120d6c2ab526b073f8", - "0b00cb58fdb2597c08f39896d8e1f06d1d0d32ed418075e96276e3f05d41ee46a9b158af0e471723296cd29c7916a8734c4be1c27ec48c451c5ddc32ffdef9e30b", - "0a021b7ca1718b1c35d3d6442f75be315270874c36d8f471873783140544651f1f2e8a711576653c102a65d6a66c9e2622f3cdf514b5a9a5d15cac4467f4034987", - "0b04909f3d956a176d871d21969bb8d87b463e93cab730c3d475091bed47020283b54abc2e39872205523792469934e6643fb47799484adec35171e9a6ea0c38d5", - "0a026fa0ea1c06896b596010cd84db1a08757744644e9cd63f29f6527a1459eaf555a64fcb164eca94b9d5f4cb32fb844cfbfa4d83768055afbe0ca51d90fcc54c", - "0a023b54c032f168ad0317961889d778f0922836285987ff9031090ec62643bea04bf27557eee17c68aacf6a808613a660d655bc9744a680aeebf91f8eb01a4741", - "0b0385ea0907978523d6488ce0a6c1f34bee1d77a24c2d04943b780575e7bdbc818699a47feae7f5c6d65cd04272aca9589ee68af1b9f499ddf488a1d00f748f41", - "0a02b0c31936312815fb3aeb9ba452f4c0e0a586cab3dbe787515f279b4db7e7e4b6c2bed898f6b11cf0c70c1a189a81994932fb6b8b2c8044589f29de2bc032af", - "0a07c696a93811027f872e25ceca99de871f8751af889cbaeeea4539de98f06017c7c6f55555dea92945f9a14d1e6a9018fbb26780e129bcd8499780d7ea15b116", - "0a062e93fe83917d4884c89983fc97079e51677b8bb85e892ce072ffc3bdb74cac21922e3e1c69fca4ff6622e36fb52a64dcfac15adc7fb0a4b2eb7c4fb6cb0819", - "0a03c8fd9411568dc8558249058b7f6082b5238815fde5a6fa17f4ce0eafb17a2d816f5901d882d5258df31dec277ed6854478aae653468eded326083003c0ba27", - "0b037e133a462c89d31b9d8abddd3a3efc3622c3e18dc13fa72a00a4562317fc519f92bae9ff82d2484de1a4b8ce93e819cfcc9ae134772b139efe7ebd44b77a4b", - "0b05b61a96c261303de5d8068996264cb6d0ef6df3e6e87d4607ef6839c1cadab486771f9460a48945d2325f4af4bc7f93b3028cbab7aa84d88641530c9835d3be", - "0b01900b2d0925d58ad3bec61ad880f94088a3a4d6b1d3c3bc455e6f56bb8fb2d583eb7b17195e12092554d3bc8c02d0a8e2fe858794f9832b175a2763c180b29c", - "0b00a64610f49e9ab07092da3e4f63ec240c90793417ea5b4bce8f0ca4d1e91cab4b4d8b4049bf0720b75e63f34f22570299f9541fc7297001a1acce3a76f964d2", - "0a05d7c8264edfcda4d67a28169d44c5d6e12402877266d555c68064c23266832472cbfaeb05febed4296cdee2be5d13d0735b9eec70274ce9991c3d6dddac0328", - "0a05932835905c1302145341643ff3759b6130194b5f9aa678d68fda3fb9a5235844238c914d2164380899b7681b5eef52660056f5f6718d7bdc61152a0b1362ec", - "0b0071fb04d9e3ee2a239065042ffb4f70c020aa17b7b49b2390bfc8b09a7d865a07dbc88849d7c42c1849e098c5cb9d173b307fa4159ad2e29ae02122dfb6bd1b", - "0b0376f3e5de63aca9432ce74032fefb73f3c0f45d25463e8c31cc9495a798b6cf06c9e6e9687f72e00f65ae995b297b9d1c544be4dd25e620f8dee12ad6d32401", - "0a01e86a4aa530f12f0d7bfddfffeac358aafab0d220c2cff5b469b5c44c8957c2640507b2de872f2016550a52905fd8f2e035ef0e6360e8a6a63947dee25b126e", - "0b0649f74b014bd6882ff991b55d2b92477775f4dc0657be92351315726fc4afd8d72739c19bc6ed63ad91ceb8584849aa853023328bdf652fa72ab2f85fd38a39", - "0b0912a42267ba2a9ae43d952c598c268536ee6fb48a3e5efea1f3c95bed23e1169854fb7ce3d6364843877403e6cfee14cbe563ce4587829348546da1b6554f93", - "0b01812e0aee0a8a0ee87c7a81b92962d6b5b4750368503faf7593b2fb614529791d31ee8c20577ed7665b3df4ec58d1d231907ddfed585d0d28ad00f71ae664fd", - "0b02199e62eb924cb3fd07d9ae08db190033f5c3058855065347f6842633150666c1cf22a1ffe15cb0bc1637152f413fcf262d66cd87d7becdada2dcc2ae8c7505", - "0b011a852734ec26e7c76aea70f1f9bb1e280058c5f4d143c93abca222a62929f6a65c512ce2d2428d17ce4e7a599004ada0907e8a88ee2a371fbe54ecb859c50c", - "0a05b299aeba99d98776c149fa0ab960295718078f7acb0308b437a931e65093942a59204e76ebc733a30db2bf9cd751ea1ffc269ff4460592cfe9481e32dbb3bb", - "0b05dbc5d4bd96f021d24538851390d6a87ba38513a741fcfa6c4b43f84b5236dbf4d4fe5a948d82197d151fea1736bc363012dd89fe0ed01a8ce54d60e863541d", - "0a0735d616559242b94869858926e1de41bd1015ab537ddab15852d4d7205cb1d5bd0f51b21c735ed625af882e6892e229113d98949c00400b34f9a4db2decf89f", - "0b037b9f1935bbab0d10acbc96212d1db3d0e9966bbf74eb06c5a118370827b3a84be6ddfb251225dbcf340bb56ad5f27519dfe18fdab5949879e6384bb76facae", - "0a0461d1dd499adb129b74b5f0b1b9c2d3aa86c5a160199c0f9c657fd39a024c4aa13923ba60f150a36a2d3419344c8946ddb3bd3a6976c5ca34deffd47bea1a3a", - "0a00bccea325ec6b084d004f3690401341bbd7a96bedd13fb0eac74cf265b9a005e16015217b2ffa60b430e09e296d8726b85f956065384f43b366b10b1d0c0523", - "0b06e72ed2b487b60b27899376633e2798c95de09a5ecba29720a0c94fe72787cb3019aa20417ca7cc46061a5323bc3f25bc001b6a153b3f08d39ea3646f151f08", - "0b00f0677cedf214de907540ff669d890c75982b3d2289c335d00ac07c2ead4a2721f00c99bb43c0e2cdcc38e30808370fbcd6d5b6cfc4f992798cbd4d68328cfa", - "0a057f57e87993d75fc597c049cf746b714d79853af6e2acd09f87db224a3076463d1fbd154036779bc49405a2096c964b0584b566f584f6c03f43364f597e0710", - "0a006e60fa874fa79be8b3ee5a14300a1454550f59d501be15f59e28fe2f6e82510def04a78b148288614de36e99b2ae404177585105d4454d115f134b427a85f7", - "0b04c2d2296c86768f000c2407dcc69e2ca968708cbe0c68dc257b855df2cd009298bc1c5f6b68b89185b9d4f3a89fa7d0c15778ed53c634123ab60854aa3c0555", - "0a026dec76713144f6a7fafef6359c0ca103d97023861ee0b12300c8fc78630588ddc609ee2201b9b530c821044019a3d314731e435c51da7484c7574af0291c8b", - "0a01c9d8f4027d9e14a88cabffd9aa2683ca6803ded60921c5012047dca5c461bb9b040ec0dfba05bbb644a16ed38dc22e0b32565a2b1be5d655b440b1fb73d384", - "0b08e6d57b121b746bcac7ff4773e87b66fd0bfb0f7c36690757353fabc994186bbe8c8e361232b593f8562c9b5c6654b47c843f74185ed8889afac73238607014", - "0a05a10dc8ac2b02f5eb18b5c6eacd9f506c54c1961cbd9c9c8b864d33ae77c293a16792da925041bf8f85caa4950c622c937b13d9a4cb7ff3e0697be1c736c771", - "0b02df8e5a37d2b827661f6caa941d2d810b78be6f6b3a5882dd0c7bdd32fad066e8e03556da085c790e2750b6c5bb872d1f46efc7f8261018e6621d3450183faa", - "0a04cf4d4fbae0069ef003385586c3c6e4a02aa4ad97ddf63ec493b24ccaa653f30e26d1d9065b95deb9d376dfb9fdcec5e0fc831f5d8bc0ac57369bd8c1af8ff2", - "0b001e321074271c9832e9fe036673fea77cad7bcd7bb45cb8132f6c8e5839f2a36bd70f7c69e97ac74a3fbd5216017c3b152b6db283c755798ed7a2af8eb690ea", - "0b053f3fdf130336d47ca4af45909539fd2a4552ea197d6cc94fec351378347ff59815eab076791308ff7ba14d1a0a14cf1b5264e5a229ce900b4e505861917927", - "0a01e27ce1c11e38a9b386f6eaa92b5222023f3f1149d57ac5880ce325036366bc1a4a405375f6f8f81ca6f3b0f9a52f916145d5141ad3a35344071119eefa0a11", - "0b0882458ac97e6b3bb0135a313e3f4e1313c3f574daa0ef5a7c709331d762c806a5d937fbe6c72199513ece4fe159635b02436f8910c2bd2ef2c24a01d871645d", - "0b0647be6d63dea683d998cc0a7cd43712caf862a1f4c5ef7a2579513d78e41eac5685e3af2eaac72b58b8a704bc1592b44a4107b5cfde1769c6f4459c712d0cce", - "0a027e0b510810d7eb2d44b106202ee8655cb7e1eb7944d1bd858ca0126fe8d26ef845bf4e9e89cb1303a2484017c5c1e807d9b5f913d6dc252d2940d723220a77", - "0a02fc3be92fa555aea409c6b282fc531a5a763b5030af141b427571c8427aae27c0c06d612b23078eca825eabfa402619610be207f5c1c06da9e0e87e2988df01", - "0a013302861ce9155c902748824c08973ff1f4ae47c3108291bdc2a29190bd0ffafde67fabf86fac7e7d0de192db6f4ba16c819120ac82cf84a5175b8fb3597224", - "0b07b9e5499b42bda8340e43f823f16aa2688899d50029c667098eaafd9c5e604230886e41fb1e5351c62bc0131d579903e5387338e1a26ba20994abd235de61a5", - "0a029ed71d4b596a6a1350700c51da186d28869c4575788421bed4ab89d6b9640f91fb7b4bc1397e67d01643f3d188303b7183f51dc7063a1ed9499d17b0b7d954", - "0a05ccfc809cabb0c9c5717cd9f045e961e8836349c891b5f0d678a51828c4d465ca7ce64c859a02386e4cae445963e66610a738a31c0731e97058027f4f6f38b1", - "0a00c201e657dfa9d4eb115b57b25a4702b689a72b260624a9b4a206f3acb87548bd504b820785f3f6c201d4103a4d3f262101d2996516490c1b7fa9fd63b56244", - "0a034a01f3da378b72b9cb4864d834c8d662b8544dd89563eee4a09bdaa2943a2316cdce7c404522fc9fa689f6a372cdf4b083f2df811ed42f8aeb515443f31e07", - "0b05b83d3897d6749c2bffdac78c6a947fac61de0d23b042062c3c0e3248e017edae6529e5b30247c98c1f693f98369796df1e54010e3469f9c535a3f279bbfed3", - "0a0301fb251a1efbf880d6993126da5b276f2bd5687d0d0ee4405a08d45fa009ff0a925edbb36eaa40f172353a209262d7809f5660730c1a8ab290fd78c1e47e9b", - "0a066ba32491828029f020e1d9d6c9ee0c027262a403c0f5034e21de674da6f208427f4c5adf139a5e77187d3cecb11987dd371bb399ffc2b2563caba889f46a8b", - "0a05cc86cd1d944d930f2ce74bf52ac10004bd9978d74f45e3a3827c6473d46984b8cd035df75ad0b4fb6a25717a3bb845f7cc0cc5bc14d0f99268e1f314c71a61", - "0b069c72cfd4b237c6dd511c5e6898a5724c8d4f87c5589a80bd580d3d21fef671c0be8fcbbfde1f367826e0f6972956f1189a71eb5acda7b7f8b4528a0d0a7a4b", - "0b00b10c50d308e035d63b45c313f8982bde318e41e23b8cf507ea934c1678168353e10a238e0ee0b7067bc784ceaf03dae5d56fe74f3157a0a6f1a595579fc3e9", - "0a02a6d61e8b80b956afe360a9ea3552aa58bd359e016e2121610bdc64b70b76ac5192b71230dff22585439d74ffd093da4b34e56fc394f52efb7e59bbe23abda5", - "0a024712cd11c0a6e6f4d79fcfba1ddf3ca2c3209724f56b8df2e0a53eb8587622da2bc777c9764b881a5ea99b0a523d82ff83675f3768702afed015e0481be320", - "0b017b9f138d86e863c43c8509b5bc98b23159a3ae3bdd12fd96903b77b79c206badb3ce9dd780b377b30f347cf3290f57b1a67f0c04e0a6f73c15e4c5a162d278", - "0a088a37abb698c6f127aa031f0031893add9a2aca3e84b7204d15b6369a33fe8ef6d7c80454b96b4a58053e21551e06874c9cb51c31168bb540b74d6fe81d3e8c", - "0b0808254c4c15447c73f2fbfcbf84b2ecbaeb7173d38378dd5f01f04cca10eda8fa79ccb587aadb545de500cacf420aa057596b0d27c85f28d5af3726cb9fe006", - "0b0006b5ac926a888120d3fcbbe72239e9c12a50b8d0aa2bc5d7a418c15c7d5821e1c6b203cabb8b6679c2f8dc324b2204d3ef50b8f4a241d57a9774395e887f3f", - "0b00405e27eebe9a02e0af1335aa4d05644a025888dddf48ea7f1433028c4880f824f4902f460f72c302293bae0937e8f6b4e105b2daf57f02fe1c0d15176726af", - "0b05ac2c8d643e6fbca44018d9e0fcaae85525b9e3b3da1aebf94e8fb4714ce449028724fa262e2490818db2e08cd1ca37d86d3d7e7f242c1c78f29a3923967ebe", - "0b03468186084e37b532a29e4d7586ac931264e77c6fe7442543c077638fc5894a62740028054b07b92e8f692a1514cb33b95ca037e0b50fbef5b9f78ecfc7c459", - "0a0113fc28f97651d660a776e938d2abea2f62c07bcf34951af60e4a9bff504a3d60f8a4ba4cbe4bc00711fe62b56c618e4c8b2df22fba52a65ebb8f9f18da51db", - "0a0663dd3d9a87203061d1460b47c4279465c0ffdb4e69c3d6723ad96a308ff8b29cc936ac5a323e82721fec76ad3d7e7d5ca74ecbe620f2f6683a13d83f2ce6f9", - "0b0762693f0169085d037b5250aff2654032e82ab195eb34a73a11ffad48b5f296ea3e51d3a90a32e15fd3bc24290dc3a66784e787d25233362009ce20be1982d2", - "0a00808239432762dc6197a6b153a71113e85f551aa57ef996d4a259fd687b1e7969a038d26837deab74627d6d65adda4fe0c87185bfe2418f9bbca5daca8da314", - "0b03cb7dbdcbc61879191ed7c76923053020d27b4e8f49c2954777ae453dec7405ffd8378989057e7e66544c510088b180ad66dba635bd425c63c2e34b57c355d9", - "0a072707e243e400036cc6a09de2e16a6d1c8a19c5dcc8ea640faae8fb359e9798cc1758a03a9c7544aaa3ccad10ff786879e7373bd792bc8eff104addd01f750d", - "0b015c2ce01840c8ca39aea8abb2e864b1c644dae476b7663291eb428beba8310f5a153490e3f7d6cc0edf872a22e9e410d593cf5caad7558895a95b8fa38c2658", - "0a0140a2f3849c71b1db5a2815f311064df50e54db164484d86e3e507a9afc2c79186e01c20a9f55b4fedc569dd956fe2e933423b6577d4fe358e9da7bf19cd89c", - "0b014ed90294b02b4b0f5a99e4c1d4c9652a51b9ce1419712aaa4af1b8c73ea7a2646c3e39fdf1b8510b1f4b39d6ae33dbfc865b5c20dd1a66cd1231631dd85527", - "0b0415ce8d00d59e6eb0cc00cbdbbdc6293a20dad3e2bba2ba9ebc954e0c04647e0e6d8a1f44b5f98905df0e080c7b0ff2a384133d0ba0576926610c8f699ef785", - "0b02ff944ce58b1deec5d5e938016d9328a296f8c21d16e7423b0cb39c384eee6a8dd88b694f88569fc61fda5ef9b9dd1c469464547ae863de7729e8b59c5fa9e6", - "0a08481d94bc6a29303cd9d2087dae692a0e724159380454c11aea0e7a5e6c7d596e9f120ccf326bf8d8ae77438c6deb934a4f5390713a3b0df9cdfbf35e88b04a", - "0b08bf0637b92ff29a0608db40b625f3d1b724d7ebd227fffa367f71d62a3e27ed353b935a09f9c3f178168addd826f9838702076371309c7ac82e3fa276f4e519", - "0b05ac8d311c73112d4dfd2fdb9a7af56b3d5a548f1b77d9ce9699313fdf405e8079286b3e46b32ac94ba95bda438453bb5474fd120ff357693cf5febcb62a0c80", - "0a07ec0d53be6bf4eea2844edf04dd166e6611a7ea66f79fcf3b3f4cb92dd54ebb6a94fa37eb2e7dc6904105a1dfecc7209fb2c69693987443a8154443baed46ee", - "0b06a0acf752c71fc92e075846c0fc02b8d2b92bd5822680eaf589737b9ec0a18dca156bda026c527272b4f69d9df39b7541c0e349489bdf3a3a9279faac6db2bf", - "0b0679c82b066a856e431a372a04993aad660e75912c35d01bb9aaca600ccfc495d5daca41d3d04ddb33dc460f1fc235cec33200eafdcfab0ea444f15271d92863", - "0a0104d9650fa651149451c2d4960b4e7890f3d1b361da43f5191b5b1a88c206455376f24cb664f839a53f5d87e43c99d311c37408985df43ebfcd22fd951f1acb", - "0a00422883ff8ab0f4c8dd7f0962e8c6bdd736e4b1c236486b8b5763f11569e02e08824927a4746552eb46460366a67ed70e27ebbdd9cd581228822cfd0486b940", - "0a048779f0b268496729960f6588976158eb576e7f270c802514eced3a14825b04df08a7f688eb17331488f2ca39b921625fbb5362042f28d3d34103b248288be6", - "0b064faf58a21754e9b3ef19e426cd744d24121aef55a83e4dbecfff43522a338e1116cbb062593f396fc8d776fc8417534029baad1202f44a00c9fad1d5d3ebd1", - "0a00ff60af5a13ca17d6f2f0af82fca2d72e677f30e41a6f84d50ef4f927a4f758c9268491b698316a5d6b04e8673fa7869ecfd237dde5c6e82aa1cfb5aab914e3", - "0b07172ebbf9403e5f9175983c3bb0d5d3310cedfe6968e0ae418928e13c95d27dfab392c0922779ccaaa929f1a01661afb5cd60dc3a77cd93406e006771a560f1", - "0b0895d2488bd88ebaeb486e363ada26d71e8f9c3d3b61d42b71b06b9ebeb04934f8e993a3361bea8ca7f6e30ca33cc59946758fef995d4cf29a2cc03cc6862c9a", - "0a02a1f71c3be98863fc569c7feef64337b4cd8331f98d1d902e4656f791179eca0f7f37ecda8d13ac9ab808747f4977764de45f6cd1059a97d1f27403bf2588c2", - "0a06dc6300c896549c222f38c7490393b21a3509b9ced2997e42def982b2d7f5c5b59ae85f643af6ff5ec791c255f1abccde32b50a9571ac285a08749230712637", - "0a038a36911710015d209c79b1163d992fc485d59f960ff200975b535dbd90caf08fa6428e7fa325bfca952fdc6af4bbffa7ea04a2294fbc4652fa1420cbe8eeec", - "0b01ae8c20dec5b82201b43dc86a345de7bcfd6d7b69fc3d9193ff94569e1e083649e43795b670dad580b1d461e9bf58295876d18afa412763a6ad52a9b7972bb0", - "0b0688be9d840fe1a18206530f52e4c7dcda6915813ec519049fbf9e570d70dfc0d1c1a72cf142b475b12bfe11fda07237e95c4b2eee6982300965afb60fb32902", - "0a055bbcc428a24acd41293fe58b66d707434debbef6866d73c6922275f3c18f25f74bc3dd4d6f961876534df07f136d5208d34ae2e7c3a1627c46090ede3d8f02", - "0b04b3319e3d717229b4c2dce949b20af3ccc184c967c7d2e7628dd3938649416d5a448d43f98bb38b22ac23ebb499de3f2ec88a432df9933537195d32efbbd27b", - "0a04cf00ba115e56c48e6b8cd65b0fd3f01e7c8925f8c1243efedfdf3b89ea5db70e58b6425245f833c615655bd33e367a4048c466c1bcc83ead9ddcbc9160696a", - "0a01d4f31372d7dea775ebf4d5a3ad9e3b0501dabbf3c1eb65215a3cdc016d7944bba20f2e456062dcacad079bb7b83718a188556382b5bbda8f6fbe69ef277c74", - "0a029865347fe270ec2a3874638f48c9e5555f4563422c00108e471daddcfea9c7df4fc6f402dc6ddc61a17cb0c9ac9bcd2722545ade8939748eedf95d675acf69", - "0a021d16bf6153bbf619a61f84aa2437409aaab8964593828171699dbf5b78c30e36203b0dc9424296cca90f0e33fea3c5f144d54d6d98e0e49e1fec9874612b8c", - "0b0050239124442e102f74dd94984ad5c21dd49847a60835291cb9c1acb008956fe486a14181f1e9d5040112ea4d4a458f7809460146fa64f1f2624bf80bb14af8", - "0b08ba6218a86a35a24e51ae85f15396df3432aa134171caa708ba55a15d995e3250a426501c54da5e2c1642adfc894440bb36766e78deb7ef9ed0b031ef8f4558", - "0b07e7d5b3b666b61439e29d782fdf0a265af2e901a27f2c16c7c130b759cee00ae9c4065eaac73a4486a9ec58da84d8a59ad8804bd4b381dd99491cea4d2503d7", - "0b09206f8d82c2729ac61e8cc70919ecc8274d06aa6a4a5ea32442d0df5e65c0ccdb9df929c181e2b4ee64f92ec00b8e0d1de72626f806b412167fd81cdff63a5a", - "0b00748d204edbd76508d7f506620f9d38d0328d3da2f16c701e08920602c85a9ecb349055608cf5dd6aaf179d02b84441a2e0277cc5dfbf0fa6b6e251d614cbe2", - "0a02a0fa0f817c4069973859945d09f967b799c3ab3e2808e1796ac1ef0723f94997af7318266dca6c709e076a4c532bd43f58f026c8a4fcc2de784291d5930d39", - "0a0385a02ddf8e65b14e71725b88cf5fa631b20944564bbd3099a7e3b270cdb64561a42e77f836ac5d5ff2830b745e1d25fd244abe3cf2b6ca0f468ef98a1daf0d", - "0a058edc5572fd95dc2d820b9d33c0521e6d4dc36e9f4bfc26bf38df9ee6a051d79a1fac53736540c2decf02c4aef515e1613a68b9115e22aecc051dad0c6604c5", - "0a004be130bf577e8cfb6b4d5993dd6c27e2e9457f86a85c0c8b0437116335e2bca57dd1768e47b36953468ecb39a151f7fb7a8c2d01c201568efd3cb36c68d9f1", - "0b07d716dd77b85c60d43b19f20bf2954e253c4a54febab9761959c270246cd28b480b4016ed2da89c37d77bf2e84044503d9645e06b7226bada3c43f9bc174a56", - "0a05fac6bf20f1026e007332e93026ff6b6a51ad1227c8c69764986c5e12a9b8b6966565779c638c69cc2c0db0332b2781847fdb9642f3c4ad7ebd76d1a02fc7ac", - "0a049576b7025587137cfca4cb094956d687001e3511e20a2604bd2f1eb754f827e76d2bac849c79709e27c39757ff582f8d6f99c07b35cef579996e3cd82daf56", - "0b03246908de45704afdb3701e2d6a85efb70518ab73855898d62f99fb736819fb69267ab3d919aa3e54cec1c21e69fb4a913522212280620fc710b6c1ad14ea6b", - "0b04b00346b43d1c965a611b9139c536d28cca3e6abbd4aaeb69edc12be7514b43865e1241b96f3e97b58e63c5b5ca6d42b7b26e51da44ee88df9877ae7a27cdac", - "0a08ccd1ec3de1b1babe01a48d326e4b04a998c3c93adb2832d78c842d103763f5b915846c3bf626a163b5f26fcab732036621173ce80c2cfa5560f25ea780cbee", - "0a04cbd5ad97380bd74783413c0e7945fb4c1f7bde1d49f1564017e1f6533269ce3206173a3ff2d976ca21690777dae3cccda8ddec1c0ad69f43880e3bd7fbbe63", - "0a07b9fbabef2adabb537165d33c9909ee54b02ed030fa01c19813d23adc4739ff9f3e1fe8f8c033a325bc6e07051a89deb67d14c6b7fcc5cb095a2ed9c0d2115e", - "0b01271dfbec7a2839149f9de68844affd73bef47ef7a55cda4dfc68ad453777557e0fe6be357fc353009092f697fa444cb1440a6122f228974267ff82c43fa946", - "0b069b898d81eb679bd40992f56d0d33322f899505c1b114702e3498ae9cffcf971ddb557dc742c3b1de35a2c2fb9f051a965c2e45b670c7f7143d994302a53e16", - "0b05a0b6a4979fe92f09d721620b39b8cb450bd42263d875a536e34d25c8d0afe85018b7632d98386b0030f3bcf68a2f8ba4919d345d73b54d81e8669a81302063", - "0a04ad0cdbf0572a8e1987c5db2bece2882072e7081721c4b49a8b3a9a90c97a7da39a079e25188d4f85f35982f5d06037bb540620f9438085a1a37ab09c20ea76", - "0b0713b12fda5dcad876da20a0a81b0c57fcb3aaa8369794345efb97678698ac53ac2560b80fcfa1ed55b3ed0fcb802416feaa2e7f99bc4de8bb83cc5c34e724d8", - "0a042f80471195c1a15cf25cfd52ecc081286b77ca046b4f136b4a04c72cf0a20e2be53762dfa676bbdf5a9fc4d76ca9301f4b79f091d14e82af42c633352c049d", - "0b003408a4ef593f76124c778f8548a0c178be2d3a3f6400a823370254baa8e05b7d11c0a5ec37fed88218061d4fdc6ef90de349b736fbbc82292bd1338169c2b2", - "0b0878b99e25f2318ec713dbc1ba1128b9fb3cd0c2dc9d3d12adcea952adac8221c7bf4120202e63310aa6b717b493cd4622fc4933cc779d6dd1dc15a73720eb1b", - "0b0282fad461f4ca5801fcbf1ba49e41e8c0fd606ac093df3b24501099959f8d80583348cad6cff735f3dd55729c0f2249c071d7ef207efaf0eaef4e3423456202", - "0b02325a42ea482438591dc4f24c5eaa2867823e83fab58a345d91641022ba16ac0bd42985e0a0377bd5bc53b2e93d7ec5cd00ff8183db80cc68b90cffcd2ffd46", - "0a013a44cd46768c519e250549fcd05a66b2454cd76fbbe9ff1e6265bb47b97a8d576412c45168647249e94436068e75fb7e1e4e21e249fe7f9c486ff405413306", - "0a05feb3f90ec5d24fc15e9e3c55077af4a83dce7882917e7bf434d76e9be95fdb8f96207d78b89f2f7fb44354d1d42091715f61e8116683c6c3ae20b2b7e796bb", - "0a039d1e0dfae2f1ec02f07ed0fd2d32f9d943e83e13854d554fc24287ac1c6014aeb793c68405055db38362def0f0cb42228f469483d9507445d26fc3714a48bb", - "0b02e555e3b1574b5c3c5a1802e3ca81a90919878e478a58af6297cb726ff215b0359d304844053a33464a7125951c01a71eed4456dca28b2b96f88db0adad093b", - "0a022dcd2b7a83f044b0666dc2373fad467df87173c7e08ec76e262bc3d57f5a5fa210cc147fae373dd0becf201c4cf5137fbaa99617496672a0f66041b957aad0", - "0a076fe5c3045389b4637c89bbb14b0246f5947c405a4c032648e79c1125c46e899e19ecf4a7f8013a74b55b4d17875fbfb61bff51c92cb42793416d3dc60df0dc", - "0a0265dd7b25ef3626dc1691a70617622a3f4e7e8ed7df439e8441b4c2dc751342e13a6cbbd294414bc2aced933c4ac443702fe86c980539aa5cd21a829283d7bf", - "0b070677d0fb4a1605671377800cbd0536011d0adeef38b40d78e29c969b90746a75858c55a3b89fcae1a0ffd05b57995b84a8fce13a981a015f45303ac37e9e42", - "0a03d45f9a188e0fddb41ee3b010ac6af3f814513f7b9ae67d827cb5cab9814d37f3fd44afe8f5a954172d72758cc72d80d35e210466806802079d389cce3933f7", - "0b03512a77a8d12733346ef47772a6e21dd2655100ff7e2dfd87093af3d31fcac7b456009b658ec6285b9f3b3abd00a09785fe3a50da06c4fafe94ecb586c626b2", - "0b0348ec6e64b311f2434ad015c2d7d7d879f8247cb5986b01cfa59ff41867605fe30ec7ef91136d6199bf7a451769c1f7db4e62309d109bdc5ea96730caf2818c", - "0b040136b87339f2081f8db9f9d9affa405077c02ba74abe94cbb663e3d0bfdff320d08b3976a8fab70ba2ef1bde0e7765ce855f1796e25ecf1d2745e2eafb2106", - "0b02cfe1b6956e1e7b883aafb3d8dc75bf7af4acd4b0102d367478a165a04b52e1cca62c61850996a87ddb7ce3900834c3018557c7d3dade2a8196abb75f4e473f", - "0b0538dde9bb07a391b6383b72f19fcadb1343bb12092c5915432309e3b07f06945be19e553a46c5fc8b32d07f5c0abfb5d5ec478f21f9feede6c031654d06daaf", - "0a06a59f1972bd8b0a22452e0e1fe9a07c5732aef8130e1aa6b8d1af5dbb7e62365e4a0b0d64c3363a255f051a3eef378132cc9c79df7ee0b62bf0aff14f60c79b", - "0a028d9b68807efcd0a9803a38e5cc4afb144460c28bed6f13d9b2cbbed9978144a62054150c53f5e353d53abb68d5309fbb6e85a72bfd83a6ede8462d1f4923ab", - "0a05b0c188c3aabd12b0595e8efa0de260b41fefe0843113bc01a026bdc1af1b1e97f6e5caf3b56b8a1c6a2991b9afa83666b7744a9c2e2eee8ae6580f36298b66", - "0a01819fdb4b39ea34a9aecf00269e0be461ee44b57cc7f765dedac3cac149f8cbb685252809807c3834f081fec878e6a47024b21ceede05402d7f16e1d66d6c8b", - "0a06e67affeafe583e16af54aff3ec8976fc1a2caa9fb0953a70beba0b2164bb9ab431ca1f63cfac4e4459c41d8cfa0382eb67fce85fc9793a332e28a98adf3694", - "0b001abce28fa93edb2a73f00606250b9f6ca32d3937196ef3d52ff5342bfe310e7c4cd43840bb5236718b996c49930d3f475dde50fbe0e8193751a89fabe86d13", - "0a0119cb15f5c6197600ed508215f1fe4a85e80e30b992fd602389a217d104686ecd62c249cd5633ae78ce50f706012feb5d75f9dde78e22d397b8293ca3e3523a", - "0a06f059b8c38dea582226532924bf70ec6b7593e8c421df0e49926dd2e50f297c807fc14c62a282f2033e315d9ee1d3ef8db5b627223f1242c0971adf4dcd6564", - "0a0338d68fce9d290ca59bc2600f76cf3d98d637d8fbeb93717d1d7c0ac1dca15f3f83e6f6ce80e2244e7b14c351445f989f3484190483acf0f3bdeb237c5b2421", - "0a0901ce63438b349d7ad0975caca02dd636b4cd778bd2d305347eb1816e79036bc6bd27eaad6f26ef129218eac8433bf642092f8a2a7c64698a101e9c7ffd9cee", - "0a06a1eda88490377a6a758e7fbbefebc78dcca673e40eedb5c3f4252b2e5a1a68db082cdfbcf0c5544a3e452b3ab32efab8a053604815f2e8ee9b41d4efdcb16d", - "0a0907d498ad49fe8864e5996206a1fe31515b15cf39bafe3fcf6502f8fe4e3ed3e0c2887a885419a63f7b7e09d3712ee210642169ad0597091c46ccc01f20e593", - "0a04a3a16d3b83eedfbd6b6c3128d70e0bf3f2fd7b0446fe72584dbe183e172c772455a275c2bea4aaed0d83b63b67a7df2b6f2e264ef18a12b01788d298866844", - "0b0789f6bd8fc10cdc83bba280b2cb31fb5287e967865b63cc92d6e454d7e4f2ee07f381c445933b5f20dd0cc91db9661f5fd7d072c287778e93aa5aa76d949268", - "0a037bfd66da54a3dcfe3874faebdbafbd4c08a6dca5ff624807605b524ac720f1c0315204d61a4370924e2307d814f9ef2037fcee6ae893248b7349fde7524564", - "0b061b9da16251d427eb25e8614e708b63c1b13f5cdfe2450065e9febedfb96ea2822481da4f6ab79f294495006ae93018298afe99a3a65646895c0732fc1c5a9e", - "0a08a2529a197af88a348af03c8b571a3285f3a7e4ef8cabea0d816683243378ea3e42c6f53a480b968dbe473a69b58a1e2006d2821aecb9f6c2cbc17c29411447", - "0b00724b5294da9374407a874c58a21d4ae0509a2abf4437334af24e37b14d2bc700e59c4d2004abc1306c7f7c4c7dd9cfb0d59d6b340ba4da837273376025e381", - "0a05660841aa7cf3cb4e590ad23e3309370161d26ca21dedd90a257b97e765122fb6a3a58971f1d2969520fad073b4bf431d5d115852b73e9699214542fa4c3b28", - "0a007bbfdfce42e75bf1525124c6b8091c9e6ac74382c564dd024e88c1c16f55fcf02cf1509d1c5a115464ee2e269a1db71c669def2c9dd4ad582c01bf765be2d7", - "0a0236f278a7651d586b9ad59766337016c774d4ffde329acd9ce98baf3a782d59c9184d298c49429401a72c3d2d46e54c9d675a6f377b63ab7e72b41b08c1cbd8", - "0a04546a20f222f3c89322d59f8d13ff4632e46cc65d843b77db7a4e5b2370bc146c81cbb89a0eae432ad358b2064c4b8a9b27fef0d2b5302653ffbe6cf75ef6ba", - "0b0412b2a6188f093b58fdde98f65199a47242808490be164a648839f194d2d143d8d32fb349dc46bfdaacf449063a51038c1f773f2722df73a136b16f603e0047", - "0b026305235cd704f056e958be085192bb6d9335f042c3738731f1995267df0f98de2dd51f556d595da8d3209c483d868fedac3d05a64f26bf950f5fc8b9d3dde8", - "0a000c899df39b1f896a1ec0018ebc50dc7751a1368869b0ae42a7154de51d5f239b48b9b9a547936928c59138c8b465977edad593caabf42e18b1ebc8d8358fbd", - "0b08468fac498215af2de2a3c07c658d3082d17fb728c604cc0f4916d0fe8441eb393e26aef5c8205bf8fc52bc3ed6917c551e2cafa46902f802cf8fc69c21d5ee", - "0a002edb04c8347d4585e0fc4c1f4af8a3298e5435a92b1f7a96edb7b1a674e3536c45653faf09192330c0bff184ab05cae22ee807d620bcf08a3cbdfaa7128d14", - "0b018058c60f7009f3b5a78c373b6663afd16309e3d93259f256a3566950ecb6a9177c64ebde4c05c08f58425182f3f2c482b2c20cb7868e4af510650f290f7da5", - "0b03083ad88a95847a3e6b367319bc8fe71d83c68a09d1006377f8f3bc24f7308a9775b2d22ae1ccd39df42642260648c3b5a91d76a127c4056851b0bd65769a0e", - "0a087072f3bcab1aadd08e42edda242b8701553d34a55c1ea738cdc0227310c1330ab6f4440fdadcae0ee5b3102e35e177febd29fe5800c28999e3c05b69b26c26", - "0a027ce259051fd7ba19212f569d18c642478515b0f384a373718714526c6ffd7d634bf196b5b5ba65efa5c7f6684a67b8ee8944839b6bb7b80581a156aa46b008", - "0a01ba78e430f61bf375df0f0e9ad423a743523af171a3571f3eb3b506b1b7cfc7fcbbb44c87de13f2e80897416f4415c365b6097f09d08996fdc0e5c6304843f4", - "0b03bffb80ef2ea77e20ed0ab124ee2f490e0076033bc1e87199ec5a047863fd8d072bdb1747dbccc2858c79100598dcdb0d4010c6f2c6adff27b0f8b7a8ae004a", - "0b0726dd7904ab68d279837041587977139176e803134734d01bafe34a7becfef56f6acccf05fcdfe4c421f1c96a365523d4c9116ca3e6d1e4294e5d4c24bf008c", - "0b065f0b8e39b7e6f023c5b196c03f3c21ae1fb84ef40c77ca288321fb2d69bff8b21e204499f6cf09d6ccbed5ce89184ed0a313b98dd106aa2cce19474e8695a7", - "0a05f2e6d64d2654a2182ef97c378d5f63a6a3d1567917988719904f8487062a9a41c83603f717a2933cf0a98cfca73cc8c3e6af9073e54b533ca3e72e170f5f10", - "0b0806f58c3590b413b40f69ed2f19875f451062920511bd6216907916888b425ab0bd8b2120977612264a6708bd415dcb04c9c5944e4a41efcc5ae348eefb112b", - "0b030465fdbfd307b224fd2f203086e2d4c8ce4b4b7d830b5aa8c5690806eb547ebe4365b80240f6f632e21063ef6cc68851858a2f2b45f8acac0b4302453d7582", - "0a029317e9ae813b40e1fe11a988079121d46a56102d2620377dd917d1a76dcfc288b00f7ff808c8be572dda76b2b13429c54195b26fc2d329c548e7309f69e8a6", - "0a08779e2892371a84a4c40008f459d26751edbe0430697291517f283a840c0e9f09fef5b7add7ccbc66aaa3364054d8851b2d4e0333b24c9b8a67b369042d61c2", - "0b07610be23ba89e6f057ba4aae2851316c74b0c42904d71fe4aa23079412e0179d9c1868ef26715c13d2acf45a9d282c7980060e07189e0229a0f2ab7e0bc8edd", - "0a02e9311559942f8ccaba1c87235a266e39e1c31a3e5ee3520f37fd7f18141496d84118ed9875e50fb458277080999d4a91f2fc923eafd4b0249b81ee0fe29a2c", - "0a0641ba7755f1f0e389d2d3fddb3f68a0b252325013bd95c6b456cc5e48735033f21de731d696f51db063f5cdeaeea12211fbe5bf268d96dd0cfd7d5f8374c8ee", - "0a00268ce168fcd252f356c7a51c2ddc41f671abb4d5b116b40160342fd454968458bf02af98682d390d9842c79dd1e7e0750086a40d7116577b20b37aa063731e", - "0b07ef1b4c8b96c14180e5756aeaf2463e4e15cd9843ea0f95005867b3b68bf91ba23b4996e0de0f157285fe3a3aa998911d28d0d61c6c56bfa118d2d720944a6b", - "0b062f159a6658970afba89aa6dcc5a441a960858b1b6bd389669ef3fb12758a4051134b55009465781c27591e9e4bfbaa8b3ec977f5269edbab43ea63b01ec1ce", - "0a08645623602ddebf529007c9dabd295ce7bc34737576e29eee6640191002d5144a599a07aff092da7c423b1d76d532aede6627d65e05c56aec6a162dbf56db2a", - "0b039a8edf4818bdaf74afacca35cb16b97a79cb0a88b3a5f1d00aef37dea22eff5006241e654f2d8fd1615ab90a8217747aa53284875a7b5e8163d509cc356317", - "0b0647d55129f7de85f89977430f26ccb4f2a5a05f75da3b89acb5cb1ba841e5430e9070ce2305b88ab90731d5519eacdcefa5a083aa31e0e96172c9dd80df3e7c", - "0b085b09116807e244f811a5ca6f035243c7c77697b34e0c2fc32a5c084574495c5fe13f4010fe417c5b9237a127574ac2c4eb4014eecc66905fdc496a802bd943", - "0a070c5be85b441c7dae678b6c3eeaedd5b5020e4a0984e728eba092768cfbe35329a3b098e54b76c1a22b55e28fae93fb538377f84e2b69ca2329361fad4b93c1", - "0b05699983f52d55bc97baa4e933e49de26289cb42e6f87abbe840b11f4d91de04c386fd2a303b8e7a141c438385cf420ad0ea69e3e265ab70c3cb10c2d35a2e97", - "0b05fe6fc4b17f79be8a5d6fba1542e60d6105285f2324ace2287af4c67448f99e9ef49e46100c62d5e81c16f45e025fca2da2ba0b9144704936d220787d3e0a75", - "0b05a9e19a77036af547bc8d508874f12d55f98faac112dbcfc06d688a931e73a4b1d55ff6dbf43b577bb2c22b0be2656756b70a0907c4c1b2fb80a7b3365dc70f", - "0b02669ccc2dc80c0357f8c71b8c9ca6aee3a4557d8131a158a5b4f28176dd59b76504351e7d5f19d08ce77777f93bcd1cd215c39e3bf4d1bfa62486b5018c7393", - "0a0484afb77e40e3ea64f0da8ffd486ec272ed9cbfbc059caa5e6bfe02351d7b7e607ffdc1f5584765b11b28466b5a3615194ec9490743d56d04dd719da9f1c165", - "0a0269bc90fde5992513320e5a5d6e0472737c9bc1d260a4c1032db3269c789683ebd3006ea2faa0312489411a169d10895d66430f495ec243f2191fc9d8d32f1e", - "0a040a5417748fdb90157164079dec9822b9313357b0831b21fdbedb33b887d6c663c9911088b618330ac2eb28a852a76fab5f6c0175329758f0c0c248ac55bea1", - "0a04b51f2a6b8f0f0359ae2cae4400e4ad3abee106dc813477b03d27cfdd1d5433ca0b800f4de446d95d6341b5ad439561df0d0b414067c3a5e2adc8455d4c8550", - "0b010cde1507004449c19dcc50689dfcd4032ff68997f2f1a7644f7118dd4ba9bdb364d4bcd2c33f959a929e02bc56f1a665deea083a7ac1c5cc3b832394f7ce85", - "0a08ed53afdf4c4837637574f07a2eb8b2f966c481b8e8cfd08c17bf2a1ab65632635a27c823ada3c74a473a8c291035cb72a72a3fb27335a8bf99202f0effa7e8", - "0b08afec8d75cdf23aad79eeccbf5d67d53a80f5afea2e9ad24ffe5a139ed1c5a2d80442e4a6c7c447a5d38838ebca4de82591f46dbd270f4c91367cd04f075afe", - "0a05f8c1b9da15c71fc0ec2d47bc8f302a40711c5144192fcf34f82edba3237d5e20265d134534ff97624f7c07812797f3e6a68a805cedd9535e5ef8f6278e4b9b", - "0b073f022396f6242fb4aa8cf5812af3964dd3e65111acdc8b62b77d6ad526ab5520ffaf9595ec08f7ea0ef2e0770ef99bab94efce23cac0dd76c33d493a7041c2", - "0a0142126399ae5be83caa813708c09e268c619a01289e8aa7d8932a89d9cd58c5d9c88d4e2746499cae04177ac3ee2eb3464be7e849a72fc7bd286d0f24c56e43", - "0a0016881ce1292453bf4bc17185c2571a0f6a779227e8ec0cf01c065e16d02009566028d03707e4232528b1299d095b2cecc66e4df85dbb7330036546e1f6a084", - "0b04a8e652f5c5faf02d2ad45bb0fd2e327e4c73ad84a981d5a783686c7b8f44628e310524166f4ade31f153f33655027c9828af29350f40a1a9282e7e9040dc4e", - "0a089aa4b89d2ba7cd7ee1a0bcdadfecebfb65b9904d0dd6dcd29e77d25e3f60cc9def2f8223ba51b1440c01199e00164d63c45f23ba0f10fdb97351679be43235", - "0b0179b2a90299e991ca18a073ee6e9dddf50e46441bb9492edbb660ea9587aa4d3b7b10272a8732266fa9571c1f739055e0a0f4f7eb82520ec87aee00f14a1f65", - "0a01ddcc94c21bbc4fc0f3ee252d698fa380d0075274d53a8ff44bdb7f98f442f1fae91d9b2f2dd9da09af1beadc94c5c00b21670e89091760ced73c7128558194", - "0a019bdfdfe3d7527be3110544c301eccd26918a2c9ed928b508f72e2e7fa2ba84a1e23db9eea6518d0ad428743db38cc3d88abecbef835bdf7b266a793f837164", - "0a0449f79b7350caeb96ccc14d39fe0a5ab2bbc8022aeefc869ce5a99b3d35ab330708f406c7fcb7c172aba08980042d87677b00875a0b33596cd3505205933fd5", - "0b07ee0231fd6955faf6c4b4de011f9c0e1c77d2022875477793f695bd7fd51bc8f3ac8b6fc067707d9bce8158fd18a4a8ce0432743f48a09cbc676083a821d37d", - "0b05ca059587f8b31b16564e593149fac154ffe4c67472ff9677bd6af0c2b8b29b122f38a4f1b8785096caa2d7b5aeeb897e1156cfa8791c8de29fd50e814fbd35", - "0b092360f04f42d06840f35acd4d55704a682f80e5924b3f61cabde0ee4add457b08c3b1a9d87ed73cbc977b76331493ca416bb18fcca0a4a915b82e50511f0282", - "0a01dce26973970b9bea464b263e1139c88e4754c8ce6652818790d76d4b10ce9fcca85d5d24c358daa4e681ce67474797f3bf5e00ac30fa0e8736665aae79a15d", - "0a04d0940692dd392d329810160b11024ac739657561f10b394ca99b5241b886665d263e09d7a4fd4114dada2ba4176bb97d635bc9d99ebe47379da3012e23f698", - "0b06f4d7b02931611b26b902c14b7d011031a9d0c8a0582bbe996afa1e095eeaa108737b464297838b7ae0fe06b31afd3154a1f415bf1e738810c0baaafb7adc28", - "0b0513a5b7f7a5dea34107ebf66c27a32c648a21487ac850fe130f94e56624f289e728d50ffe46f2eabbbd542cef7e65667510fd2b367b60e859adeb70f2a10ae7", - "0b005dfabbf05c2480e614914449b05042e4b33381ab718f8f9bfe67e16bfdca5b86d0be36f616eeb53c71690e87f0b3e962a933eb313a3ea71fa5e84a110e8b24", - "0a011afea782538e1145c1aa829f8611e0b3878d4ef5efb501fd3868161c05c659281b4e1e6e443108814436e1516a5516da5d90ac4cda45dc458fc4789114cd7c", - "0a02b0fc9c727a46eae18a56fd7b12e7edee957696615e87a176c91fb9b08525c30706d8e767a717f37bdfd0b8d8e9547ee5f29a397d3b9769fa23949886e924fb", - "0b024a9128480a3dc4ce15ac23838d740cd7f73d9d66cbc0ffc93d6a6fdef03fd30743443e60210af2b1a2e8126aa4bc84dddc2809400004417b843e8e221d4a52", - "0a045ecf407577e2c8244893df58d378c387a34c08e2d27b0759f34c5e15e09e9585a612c0f179ebdd82ae5a7118612c8910dac9f353455003f8fdc5160012e11f", - "0b063727d8edc5a25717d4332d6fd8ebd63bb9107446048683ff2740189120b036c73b420e2c2980a365497278f1ff3cd3f5b2ca3337ea1111676b37a7407d154a", - "0b04f5767e1d1ceddc4eae8719b7a0b48d98887c39c2f544ed350265f16aa16662f55a1f6b8b94adad968e36cb3ca64b2085e25fb2677648a106ecaa2c155a758c", - "0b0230a7afda9faf7f31d9040d7912bfe4cde7912bef256fe542c31b74b6f07098604a0bd3be15df0e387aaf2f43ae7eaaaf4e33e2fa37d1c695fe6c3334fb6fc8", - "0b08841780adc6a00f9a644ebb7a9c3ad103316dc2b93a0325ed8a4941fa12c1eedbe4f20011185c13a82c4863a85cfcb7009c95a37c0af32c80bf81225389618b", - "0b030f11eab31aebbb486eea462790387278729c62294654d2c932bd3a458fbd48ab9b33bd84fa7a6fd78fbbc71173a68ba99af8ea7041186b3af013c51ffa8381", - "0a07b9784bf28e920e1346132846ba1f01c687187c0d6fbab40ce4318093e0a93d586f10941736607623b82be68a2abb8ed5f3564db37091e0636699a8d75bd811", - "0b0264b6c14ff802d70fa133657675fc3e2f17726ccdf8d7a8103d726657b9819f91be075fc5b96ee4e6b59a0cad3ccad0df333d197ee00586d0f7a781e0c5faa2", - "0a0309b19aa6ecba3f19c9a61b7f863e0be3bdb4cda41834bbd74eba6a07d3440793ea0bd5e547734572d327bb05cb8b12ac8d58adaece9dcd9b0877a585477390", - "0a08a9fd75cbe2bf391bc70886691b020cbd7081a2229620e23e817b3681ae3c45e6cb3a20f10a2a8c99053817fb7756271269809ec21a15b5d4abb65db1bde0d6", - "0a0739564874c4161684ae97f212671658062c47fb7a9a7087111bd505eb96931c233a366ad807dc14e8dbd94e68bfce7555e855dcbbf04824b5663d5976a9fc7e", - "0b0641ea21b91cd862d98470b58244fc95ce1f5e7c738b13debf041141903516bbd320569fe62e71a2a1212aa166691cbd48a571e656916cb9b874048fa2036a62", - "0b0788490578363112dc09efae1f5efcd22352862e7ae2eea8df45783a535fde4b21a7845189bf341191f12ee515078193b8654053ef13aef6f3e73f2e2de12eb4", - "0b08a2a36ddc5610e45f8b4efb8edd5d9a79190f5e401d3908ff15a0de6e834271d9705f0ae420b874892d6c50f81e76d28ffeb08b3515edabf2b76b18e3045cba", - "0a005beb3fb8248fe178adad4bfbaa0264f98c749ffcf55f5c23cc7c549623a016886587385e55db4353d59d1c09d2c4c8603647f7db5b1a4cad53dbaeaf01fb19", - "0a0371bbe9ed7dcd502f12211c9766a16845ba779a0b40a36804c0a0adee71b6b00730221e83e94c465af0c4b7ea637f2be651d1d8c5b68c1a4d3ea514db710801", - "0a019f1a7488405220acdf2a398f0ade8d06394723b0dff17a8314d296676e45c530ea85e4b26554a7faa01a151c6aef22fdcdc0036e9c454b0c4c1d06e91aa3dd", - "0a0247804320f1caeb63e69fc69c843ecefe7c49371c77d51171a71bb08b1ce912c6311368ce044966594ab4f7d379f295cedea6d245bb27466ad8f2ee742d701f", - "0b02de28a4620c245c009e6bb8507ae7b67fdacc429fcf4ae19c1dcf848cee6b9105fbe8903d9fb97dae5b229a45ccfbc5d9c00ce0756af659b33d5f4a170740aa", - "0b015c8a7e388b8890985ca44c8dcb042b29c5bde6e9955d73189edac5fc1c91de43b4cf1926d6b64074fd4eac9a53c35e0026d02ad64a611fbc9d48649595fa98", - "0a035065a75f24fcb0bc13584709ff4d63bf94671e280bce9811a012c743db8ac4ea54aaef84a0ebbc7c492398759199baab0c3f4d281bec268447fdac02e8a104", - "0a00bc039d73be3fb893e7acf5f482cb58842834f2a510290b42608e03a0b91b7838a3ece1f094d30a4f5a0b557a9feb8dd0beb2ac4e5ec1d2bb17caf5748affd8", - "0a054ea25dc0ca08195145504c7231cadb3f1bee1210412f999ca260a629ac9563a38f9d0bb1e4ed29f7224926c5bdc23b82525e09c92c0d0f9dbaa5f7b0a57bf0", - "0a07bea53838fd343417098830a647b14e6de25a603de9c6caf232b19935904b39ca6416149f376f8f6a73afdfca1e13d1b6e1f28e52377822439fad8c1875081f", - "0b08ac931955499b2d8c36222ede33fc516ec4e33bbfecccf6823b03cbb794713cd682f7429a6a244fc944f6e828de6831d34dfff92167ed9d50b3cd6cb83c7f02", - "0b01d441a40c79220dcc838745531c7001be54ef62c7c0f2482cf9b5581008a2895296bdd1969b41302784b4b0aa5d36eed1b2a9b47b42fc516d1d37262966fe61", - "0a081dba68162f7d57d878b8090e292d73ba262d0f1c698b68e81c26c955116281e8af57e97766c8c0ad2672560fad73b41bd71aca8e88ae76518e75f0b4ffc8dc", - "0b00bea00b290d7fb3a0c525e6420b96343507da3eed6285238a2344f7c7e3addc02cfd8caa63daa8e6dafe72d0204ce102fe617ce150e4dac272ba760a846bafd", - "0b036ff80d3f1cfe2a4414fb46ee6b61293c53fa2dc3652d06e3df95244b26ed7e8dc9f0cc4833b7c30a38920d115456c6668f03e9890b68a344562d82c9488b93", - "0b02d29450f0929df5076840f4c70aaf4079ea45cc2bef74ea5af0768322749432893416135b0f03f89b6da2de8343b5d52ede8e944116c71a48ed0534d5e274a3", - "0a0328838dc84f64c0c9ced8976ae2835b1c47c28cc23dfebbf89fb1e5f19107d99dbdf12fe9f442d7766bede04da8be214b7f43177f90635b37588a476e3b8a13", - "0b081c8f6e3622075de4b05864e7713fcc073cedee77008a37071a52ecaa83fa85a4d4d1c5b0ba30f14f19735e5e4a917e6114a8d51b2b73a180ce6dea5cb2b10d", - "0b006a9dbaa8a8dd48a61100f48b59a41e34513a02b00528940df89045c4021aa067c7e323a702027e9bb8fc97579acee94c26f60e5e53a3df86edb3bae9615021", - "0b0436e7fae353432830f585a4b8685aec7d40e6d3fa5bc3c6207c537063ee359a5984ca048455b5f04be05bf027b0d74acb1aacf7c77ebdd3ba57e5a8619007a5", - "0b001e77cb24d6985573b9c5b42a88ede6beecac3ca5f864f6ed9a97051ad3a12be7b07749eb5fdf2fda9666dadb859b9ee4ee46ee97bf6f6150cfcce469e8c234", - "0b02e1da03f0c6a9a4dd1f6b0a784483506ca8a07e36fe7127282804948157fdbcdeb5a709e0a460cfe62fadd80466b0128eb07f4130ce1cb7fd0d8b65a9f5fa98", - "0b087dd8c99245c73b5c3ab641ab6ab153a86fa60daca210ffcc52b8d4a6473a173da55b8213e46d12f67c473db9278cf6848c81c464ec538f4fcc1decb12ea6cd", - "0a024d97dc7822753ed85b901072f974e892ce4b8bf514dea36ee49f1c84897de407abe14f5122406fc2ed9a6f7b93adc4f5de2f2481cb84faf77a5074dedc50f0", - "0b088c7700bc6072502bf7ce86d0fe2083e26a7358e1d61627b1ff1b3c05edb4020f33c935365f91f2077a120495d26344707068c047c587f03abedb881d9e39ae", - "0a0275a6bac3f25f7b893ebf0d9a63be166bc45bfca3937ffb74427ccfb85f87a25b096e825dddb649a179d7d485d58447167d4b3c873e040dda401495bcfba3a4", - "0b06f26b0ed1de98533b2ca95002ed74c232726d20af3ea54fd7e1d16f10b742c480fcc2809ffeaadedb1c40e29efba3223d3609920b91f2ee0102a978efc5ed67", - "0b00a9869a956fe9d7b75b186d9f86ab178454f902ec938b31a6c456c3eeaf9233045ed6bec171c84478198e9f1f5fecac03ab0f950988625d6e56d97d2a95001a", - "0b051ecac02b43cabadfba6ea1d2ac76d3475f95b8a73404b91a0b1dc47f779874a9b3bb947ee6e84011fd5cd74557b14005bf226a130cc7e4a2ca2db1a5ad5569", - "0b05f15e9714c1ee564cf37f9e6b0f5f0d817d7921fbff5745fa064f165d92dd6ddc330f1b91280695ccd385853cd00a90d9360902ecc249d52a8bb21795b2dda9", - "0b02e46a434d449d9609400fc96f08527df8eb32f95d03d724a87f9da7e709d6f20def7b35bbd9d896e4d85a6fa409325d9030b4a4c83459cfe61495b759316e39", - "0a074a7f923dee982637bb033d44f715f314e4908f3bc3d83a30a042c57e79c75b79f4364e8fce633b6c832ea8eb1b3d26012dc1b6efb470edc4354b3c7bbc726e", - "0b08985a1165b36e1f7c63c557b27651e7a37f7b31b5d7b6aad4bf075212f0bc18cfe50e52a9a3f9bfc92fc22b3aa771d82026b23758c21ac3c189a9174716da48", - "0a0876c1b8d4f9b8515cb17911e4b1641c488298bc6ee00b9e9676c09659031f8cbbb8c5c0217878ffa9f8d3a6126bee6d5e5ef96fca07a5280f601ac436f02a1e", - "0a043f1e34f1d05259047cedeeebc1508ecb8463ad15761517214af1d1b4bafa4907facb5659641004796e6a1fe47cc9dd32ad392e3ca60d0cb15b8b3eac9d4b7f", - "0b077cdcd793b504e6ab0d70422de5382d9f15b23412a8dd45470a6b6d6fa6a45aa74942c3d2b08cc8b4ba056af615738d5dbfec8b8bf992e3f91270d2b13cf68f", - "0b0417d614b8eaa32ee950d5f4d4fd1250db69ee19bdfb18042edfb9eba0420a8415a81a902b95714e792d3a3d141f74974708bfb7dbe0a2fe075d54a9cab4f7da", - "0a0326f5908a089ef7710f5add80f4e1e7dc76ec897079156a74b11a5ca4d77bebd6e6227843ef6f76a96826292c3f507aab0d95ccdadb0cfd7e5892e9efa939ae", - "0a051954211256e290607b9b22815f51207f0f74a0dd8f659495aecdf4e30b654b1cf94114382a84e3beb5560aa8a028689894766f670a2055e412cb885bd99015", - "0b06c01247ee4d3301c635a362f65f4526458a8dc6d9baddb12b9dde871c0a6817b39c8cef74e69c07505d46a98ae7d879bc3ada6a1123029d3927874cd55e5fa3", - "0a068af660a110bfd78dc68f35da055e745da48b986ad7e8fb4c46b27908ddeaa1b3b22ba9a2cc88c05e691a378ec8982e7adbaf88aece70ab280a6a08033c7694", - "0b0621b4ad3315226ba0019c8f6b5ea3b5aa5b9b3c9dfc8c31393ce8b7bcb0f4a3b0c22f96a9ab0d484e1fbb5a96b05021c6391c73765392e8ef5bcad112cc4b81", - "0b02acf538cad4f2c2800cc7885c017d4e7b987fe76791c2c23f9721be45aa7547d24b7e9a05918fbfc8819fc473ed45989f90fbda7ae6947b926cb48b5d94056c", - "0a07f3622ee43a1c1383117caba994d2ba13bca791f5eaab110ede29710ffd99ec9dd4a2bcea112ab1ab4d2ef045ea3acd522334b7104edbfa3117c9105de61ea8", - "0a06b7685e4b1df2c0d1c185488d4d4ecb0b75276431ae0b6cc72a5d536d60e6609b6e272a5f02270b262af3a0d811ee150d514e5abd7835c460f146de88bc2ec0", - "0a0762bad68d47b91b85b063f4cada7657318485a1d0bd691206995d4a408a28b54768d0875ba92c9c4506c9dbd5a5113adad29a6d2ef6e320432c3b1de3fa22f4", - "0b026a4bfc3dd02bebec7e8d948e6ae4a777ba7c0a1d2655dfd3a5bb3776cd34b37a7fb3d7e960b08be642bfb8f58909d0bfe99cac6fa5beebb4768c956f868a0c", - "0b06de69599328c5d45b027ed9bd25d350c35d509074ab15e5c35ccd0f79d3bbf67640859b34f3f4590cae03fa2e517de0f7f8f0af9b70e41b95e54945c2063df4", - "0a05b9f7a6ed291052a11557cf4f3bfbce03ad04dcd807a0e2a5f3831b345fcca6c5b0864d8ddcb7e041ce2f41b956312519603b0b0f41015eab0636e1b322fe65", - "0b088fdc708a4b863b1bdbc7f3d21ac8d2f1aeb31f242a948439855f7befa78c47b7941fad5a1c58f63818e5c694737a8c3fc8cb8fe55d01df3a054a0fc44c3155", - "0b0906f49d3fa4ebe8567529a99de34e1d28d196214c6d9cfc29d266a1ad51ee24d27dc382ef181cb2fd426446ed70e277384402c1c49b1e9fae641568981d9ad0", - "0b023b1dc575dbaf6b9f454f766d3eeb6b144092a2eb8480528d1bc3c7bcad72d4695b7a572edc504d58943f652b2a0ed449f44fce252b30124971fd76db91cee2", - "0a07b49d67e11008b156581385cf8cf5de2e4cfb172dda60b6c2b3eb666f60a7679e62ec63b4ed0e9fda2dcaa333625d504507ee07561355a29ce789dba13adb9a", - "0b058ad29b13412ec9961c1d0231d722ade9af485d7a2b0e41e755e0a8d4d5502b033978ba3a667c9e64a0de14a280e117d1c6731a410bd08df2b125faff8cd279", - "0b016bca1b9b05fcaa60fe562ac9a2eca5793362b568b2c04bdb0f86f51de3ee361243fac6ef6efcb4ec08bd70ebf92dba7a387dc36e78f22d354e5518834616c2", - "0a02767874fa9c849f6be601f60dff40a9de1505e5b4bd95933a85ee42e3e42453755168564872708ed5696771e26c32367c0eb6e7b2e2edc3ea6f1b91828559ba", - "0b0507c7644e329673f9d67cf8692475268aeffe4b4c5849b8c34ba3f31bdda76d5511046db0fa436c094cb3a8e85a91b264a45cf552ec25606a79d8c1e5b147b3", - "0b0711950b1d862ca512e37588250f96bd10e660a3b19d1f8dd0465ff3abaae88b3e7f7a7f45f2d1518a38fd4c7f73c27dc10ef51ee5fa557c474ce1a4f16353ff", - "0a05e5ac237109bf41ffa6b7d240152229ed386c3ab09fa8dd6c91c3726e5c7e50652f9f163ee6b9c04ca2c715169a3e5f62708f5e08ab506258a4adb8a34fe7df", - "0a03f3825cda0583bf0702d940c20bd68a07188ba93e426e1dae9ef5b68960595268e19ac3869ac3101d90e13508986169e682342d902d19b59a5dc86039c72882", - "0b007e02085dee2d0710c811e80dbe66043bdb70591aab13383c906d0b4bf9689c2a64865d624dd038146057e5d68aa43c0ceac47c86b3fc3eac05b0d569c09990", - "0b08a22a309e135a696f001636ef304757f73cd2bedee1fc04be094ee8b1d611b0a42d5b3972430392e45a544f97a9bcc5d77974a82febedcc915771af4aba6981", - "0a00e7f08d51e9ea4f7287d32c30f69e15aa6d9d193a38654c99f1bb30d6a0e55e6a5772506f4b2e426a0a426ff55d9a821cfc12070f7bd53f447bd6090e256382", - "0a0260628d934239e61bb40136e5885b91a480b8eb78834acf6c9ea2513ec203b914f8f6ebc38014fb9d4383a7449d5cc57378172055dc732ea5778e805086dba0", - "0b05a5678c446b38be5895a409b24f8866fd7aa3279bc76f7ac3db5ac259fb4ea0ef395be86c96fd8daaf8416178359635d26e927f3eab306312452f2507dd857a", - "0a087e8a5ce30d27b3390918422a00c36a7917b9cda81bd08a1d33e579aa57d29d4855ea6557c16f3e93d45bde8e5db8070c3f9b74e4fbfb260a4c69ad19f7ced6", - "0b02d43117280e0d89a19cb781f5558556f4e274f92f699eec1dcb5117f45e0de1008caa7944de5e42af7de2b9ab1763f5a154d7346462eb4e71441e52005da620", - "0b07e9365ca1b2852afde8ff080dd6020072c2f20af352a9f9b249c949a481150351cdb21541e587b825619e6b0f712579d1529510225b3e06bcffc1a443be2560", - "0a04e2984d4fbda5d81995d9be5521458f05e7e395fdeef602fbd2f4ca1e0a1eeb1faa8870e966937feb38a165cc442941c7456372ff16760e6bfaab14b20ecf6d", - "0a06277e062726eb20669b7138e88b27ffc32e6e2ae81b878d54eb434a72ce343a1d143d060e22522082fb7eb28cb3f86a3877bbf1bf23b069805724fae76b8e38", - "0b0029f4b12969c898b82c125e9822588ee461d14510168b84ac00552a9da4ce08078395d0a57e37d43219d57ded64fac45ff777c283e7c8492f7ab54dffc5a618", - "0a001a4695aabdfbab7d1b4a3899e0818a5c8a6879141c1fba48a4e639e2f761e6e74a42328062a46eb96d5b578da4b5a72ec7f3e6dd6c119b5ca2bc2f4aaa7f0a", - "0a01ef3caaa5ef580421d659657649a539143732fbbb808a441485846ff99b9ef4447ed46fa5ba899c003a70dda8372e68388096b9e35038af190b0b0bb8296269", - "0a082df76ce887402461447a9c23f43beaeca482c5232c0f6b91e2d0c30fe35cb8089a0b088404e38503a8d4b4bec7e731ea4875c23faa82d2085a422acbbe4abc", - "0b0810e6f36104199c861257eb3b7a03be874b31d2de111f573ebc2e272bd11c1955e3a31c509a5d1bba7a376f97dfcda0cad81a102017982cf1c5524d185d14a5", - "0a01e9d23e956060b742b4b93fb7306dcce130285227ab00f9526b6a67721ec6e3b09293bd4e5a1ecd4d449eb7821b0cb9641ea1127234a3bf4978d13b20637763", - "0b07bb0a285254264f99274d34275aa01904e7bc63372610bf1f8e9eac3abd5e16331771ed08c358460f0f22feb7c8aa8c5841bd0c9d15a57524e7d5ad6fbc7d34", - "0b0796c6c33c39dcf43967c6796151c8cba6dc21e66200427de149205a1d137cbd04977feb7b074f3a715c2206a2f4376c348690bf0e044e1c04ffe186a71f4298", - "0b0197d9a835b30234fd01b38ec1b62e2a0da29834e6335f40f6a57502f49758d66f90d4647b106402b9c4c318ec82b7a75037a146b184375ffce6009c17027c5b", - "0a057776df578e2acfde4b180107f2690a2ca39d6495974308161f33d304d232867cf0f4f42d6744ec294b00dd5498d999a30364667099d908abe5b2d5363fd90e", - "0b01a7941aee0e95952bcc2f23feaffd47d9ede9bf28f133e99d35fca7417ad4ffd58309da38810ec7ebcd88a7c9b9c2066d9f6683cfe00c28967f036e0a8ee877", - "0b06b969f1b65923ddefeea442ede0ad7d442468024464222b006e6db99b3a0f0405fdb530d8806f5854a1141505a86f3a1ee715d5ea03e7517e61e9d2a9ede8c9", - "0a04e18dc82ec7015ca3802bdbf7d07d2f7b70a92c7e492d380f41474ad1c062d3c40976f69858d661f31a9cc09b23f14123505aca93057e2ca66c87f5c6296504", - "0a014fefe928fe90841ed4a1a90879a5b4d777c174e100f7c6e83cb70c645518b39cadf8cd7fb1832d63485f4ae96e80f218473e5fc53540168ac11b591d177b79", - "0b07ca2557dd2596ffb3fab0a264c4c3f5d3700feb80ea04ebe15fd3f7d77a253d5bd0237217f9d896ea0ab5763c520d9a065606bb502173b4d068a4315f80b0d8", - "0b007ce4de9a3eebb83a64c5510d603828016fe900f72be632ffd4f52daa43afa7c818b773ccf39a232f14d30db13fa9bbb989b94a0e1368c37dad4e043380c5c9", - "0a04c830d7ee1b4d61e6d8877ceb5537107e95e5af8b4be7ddba99aa811148bb6acfc5cf868ab157a951344addab688483df0ed62cd5d4ab733abb13e067570eeb", - "0b05cefa1e3d3f17bb2c6e5069befdccb9367d3911f737e80ecfd079bb4f7a43732c75c7ec4128474d79723516a20bdae53d55a81ac1b53ff196dbb8f64568d5fa", - "0b01e650891fb080961b6ccae3cb92bfbbcede40ab039e95cfd27cbe2ec0a6941c5e8faf1348783aa105bae326040228909039abd0d7825a9a8bf74c076de3968b", - "0a0810275ffdde3a4348ec9382b019ee07c9d185417969e598060e0f2c5d9754e4766c0ac69f8f1900c5f3fbfc1820bca0c442a020cd3ec1620b9c2e0423b4927f", - "0b03e1265ec7e2da7381870289f7051482c456f27b1271ca575870132f7322c954c3f3ff5ad84447fbf132ef0723e6a77f9d09d600d74566a6ef875b53fac3d22d", - "0b00de4d7013f4c6e89b70cade4396e5ca622309c0e776f2de494b9dcb8cc4fcd492c03d511bd2e9a6466a36b150ce934a8949c1c1228b2b9ec98e53801719db55", - "0b059138911bcf34a592c1ba6f0ebee553aa425eaf5b10d026b6546ea3f652855c6405d8f3e05ed97cfbe5a5dd8dcaf10983d535515e20c09f97fd9d818b47cf62", - "0b064d5a48f2e0670fba054cf357248e3480e598b167e37ce65d284436558a5087b8be223eb452b76537b1602cdaf39b9775d3d54b8e3555d9e9caf5f859d73843", - "0b0074ef49f7ce5f98232cd43262a94f16f6702d3721be9c576f8e02caa9e2803fbfc4ecb5977278e6f0e3ec03bd5aeba5c9b50d99271804b99a57092456f948a2", - "0a010006e19a0a31d43f62ec586feb9c34c2a9c659902dfa368c5b8058c5c95b73e4be998c69d6c6705c5815a4a0fc15fc2dfc8f4ca39a592d6e42ee8f5b0dada9", - "0b0231584958b4810a43df7bb5131d8f490b9fd806fbda3a29dea7c44203c4c70c41f0253a524d79108078f02899daad41643a1d6470cfd116a2f2b77a2205705b", - "0a01ba43d86d8b8c25b6c1e1bc29df8cc350a8735be75bbd68443e7ff7e09076b2d9e6181302dc4b79ea54f40af475b89c624982301aea4e9e3bb587be2bc9f52d", - "0b05cc50196901ea436affe1adfeaf6d720377e993b609e74d01f9fa301ca1b881498a1b7a0a5d1c7b7c78b8613eeb9e22a3f3e9b73a049ebef675cc86ede79f81", - "0b069a7156f34ce38f4bbe576ec66b0a9a70225ecb012f040199867c0bae43e51fbd7c842da64f8dab05a2e8f2429f94ba14ef1702d7c7c1ca635ef3d6981baf2e", - "0a05a192f218926f62b6c7c7bcbff869f8ab59b0e94c1306e135a38d847151162069d9946532d0bf090aaf4aa21879f3a2decfe2c0ae41b9de06746abf68fe0a4d", - "0b06a3efdde8a47b6c8704abbc06adbf0926c6a5a23833b9b97614b7cf316ae1ea47e1701433bd01e9e5c9de7ed28067d7989df15d2a29a67053ca132e5fb5cdd8", - "0b0607662889722f264bcb365178ebb59e1feb5cd751fb2ae2dd9d3919dd474278e7f2d25825badab28d5cbc4226fa2b902387cdec80eb2bd2b0dbcebceb0ef01f", - "0b03743e78a33ad246146c53b53b1d20f2c706ba3d078c9510e0cfa78ebda58735c31e72b58043de311862b4de95f8bb973156bb3d5f0aa84f97de93858e3958a0", - "0a07b5c97cae20020680bd016948feca81bf9333ac9008149d0d5a0c855863f4596064ece1951cf1c8b0804a3e7d6da3ed713b9c2de62aa3799030211c1a28f11e", - "0a0290e7163493cba47f759ee10fb6ee72cfeffbf385adb5d52aa73f0f4aa061a069f75e0a2ce861d24ed6edc05a0555e0807ea1a5fd99d603c9be5302686b91cb", - "0a08a0395b8b923dfd18d0b98f1d562e4180766e55f9718f6fac73b034e5c251dcbedcbee1720eb49ed2761dfae8da9765593aee5f1d72ccb638cd679133594d54", - "0b087f8292d6ef830e5a74b847275a1c41632e5b963fa0f534d3f1e3b854ffe531fd9383e6f37fa9eca476a4d2d02e18a35bac0b0f5ec7356ce064cf44f61f5ae3", - "0b00389fc99cdebdb12f6ceb35a336b66b6d65f9d7d434712d33582d11131fe0c8c163196024e78f95f9c978dee2e87c19f9e6d92a20abfb3c10c1bd93f9d5d10a", - "0b08bdebda75bea1066887c3a892340159d5388dbe2743057977286bb444efe4647f92631052663db0b052b098a0343074e749738fd2e7bc5fcda188ecda49f6bd", - "0a03e22bcf6cb434100cb884ab20a4e21de48fd063b7149d234ab49a3093c51eff1438eaf7bdad2ec3b8b673788c265c5f9ff3c6c4b0f3632207d87b9d437ac78b", - "0b022159a93f894a9de4fe74063b7fa58c1658891fa2602680f1278cc97db7cfd1d2ca94082f35de919720165b390e56b450787d118676087ce1141de79f6face1", - "0b060f0910662ea9d13c542bda019e7fbbed7d0a5e4485c37b82a1a6c69fd3f1a4b1ebbe4bfda017f2c0907e1a7a967047e7ab2f7f8f7449ca73114664c8ee2499", - "0b08d9ff95cd4de515c7f448015b8de93c1c5e89c9b53b3b3124f2a4f1ea8f0fa9796b2b5ba372cc96d195ad4b6c6bd016808a15e857c3e116ae6680a335c07fa7", - "0a07e8ad96359b3b7acd4a4e8afc39337c528bdfecf25dfebf21e864a23e5cfe021df9c8eccfd5c87aaafacea98bc716f0ef289e0ad018accf0627b926394e654f", - "0a076f17a851f6ae7563c5b76d9e9861c428c9f740caed49c73f6de0a0a7e1aaf5f64347e69e23e9b6b3db9f5d73620467add58547266d180d915832e04405b4ac", - "0a01f23b736bb55bd7481f7450951db25cf3f78efa715696782d3c70b171038d982db2058af398027e1f511930da02a66f19d62637ec19b44dee41e05ba2bed478", - "0b08352cba33516b987e844fee941de42957eda14fe8ad1d8d02617ddb826c25b075b595b15021935793ca5e272a8c42adadcec26523f0719a87ade4f84a7ae14a", - "0a0917576e5cbf384ac34191e2bb50e5b47c8610b0cb9bd54bbc03fb3eb1d8d00b63cbe39c21794625b5be5c54711cc5242fed6f44c8f43e33cba4b1b5747a2bcf", - "0a078e7b8ad2f4c82d1547ff80062d0ec0bb98d757c836e5067eaf066c6b88329d16d92ce75a3419407440c4bec19c269078fef813e690570e3aa52fd5785ab1e3", - "0b0696950af73887eaf5d5671918357ac56e5829e8d403e50340d3b1a64d10f3724e050b4ebf69287877ec9430716741116674ecda8cd59bb5b0b031004a8c5762", - "0b000f4206c82d89ec8bf182b3dad596fc11194ede5c5c610648f66029b8d7cc7e331e32566bce4df6d3d8b0dc4310a9e7cb6bf1f522be479b916d04219545b176", - "0a02be081f94ab0d1d7048b231c40a948a49ccb63d7033b76fa8f5c59a50c5ff4f185e7940b6697b9b7dbdb0591d38d01d06a7a922c352dd7751b4bc9cb0162bda", - "0b079ec4b05c8b31a17d0f99cb6b45f8bcf0330b94565f506d3326851087f8d3d7ff447bc296775f606f3ca29eca52d789fdb0fc99d0d41d3c8b38855879030a5a", - "0b04f9ebd3d05c519c39f376d6b6d28e3e09d3bf9086f297d77caef7927fbc39d608ee1f4f21aabcf89b74685d23bd45362bbe395a2d331220da648cd36228f6ca", - "0a085d1c4c7685fac40af950f03e6e79807d2521a69ed964109d21c09d4e811486aa7eb9c979867d077206d98b9cc2e60132e8c52897c36034b8421e24f659fce2", - "0a083bff489b2ba80c8e1c357ac91d1c5315ff70c4fab0aaab97a7e3a893912872f586286c9eccb6b3ebcaee589b9001e50d02084d0c42f310c75a431b6d1cc9c9", - "0a04d232a00cf1d9a39e4276c19e02fe93e2d3d14639d6e89c8181870c60632601eaa768f226064b15bf6a01744f54df39f6bb7a620993fcd52a0e6333febec2a1", - "0b06bd0ea64569dae8d7bdfe38963f059642d84ce70311549e30896ffedf0e7838943ccb2ca2870caad3c80cc889b49e9223179ee05f01312c93b296bb2e80fb1a", - "0a04786461cfb4eefe656e4666ad9f972f9f3f00df36924acb91dd75489317f2ef1b122b8367b72b7624d6b289993837029a2b222c91776a0f161bc9773fa861b1", - "0a04b99c234d71150817d0e7f1837224d7fcd658e2d053d632cc0576c96dced11e8c388f54ad1f48be09530f383222464fb89a954f6776341ad22e968be60fae2e", - "0a007f57c61c85244e327de68c7e86e672c6778824add3662eadfc9bc27fb9ab6fc51bc488cc87c891ea0ac11b7d0128e41382dfbe17fc00b8507e1493a017a5f4", - "0b03d96179674697cd7ae0bda0bf2dc6dd834e222471715af30aef0464f9a8be1573c27cf01c87628be55a0b28bce3143c8c0729931e46a0ea6a05cdc7a2b188c7", - "0a04a3ee92e057184f0ee7ee4739faf48fa6d0775e12172863ccdd872ce7fcee5451517e6dc4885c762e53efb5954b2bad000890850696a42cc2207535883b994a", - "0a00399ebc11dbca5ad579e86453344c148836b7f5551e41cd23b7654b8d3fbd25dad2a88c4901d604478fee9c6e5c6f245f91fb2a2d009ed83eb6818e3c38341b", - "0b00a3eaf5115059a16d9a5f2b708510a88f3a6771e012b59a9eec1832c5e5073dbe7b865041443d76b9b042b688f70921b9096b39a71a2a8e0774e539311b2e24", - "0b01e3ea6792a01b09af5891999ed27cb305919673f9ddd54a4b4472efa246ddcc3abbfdbaccd2ff670138500bbc59158e9583ad7821451674aae74af3a7e0ea34", - "0b03694a43c7c6a30cd94ad6dad91780876d2c80de0f96343dc815ccf4ebf3396fdd67e6f5349f135d61d26c2d6e3275d8309bf3ae2027f3e69563cc905d49992f", - "0b04e2d946cd6de22398d407e3302b4ac496d6809fe31ad20051704d8733177ef79f0eccb7bb73a83b5460aa6957b5884b46953f455e14050c7b38e853ba595a5f", - "0b02072902665ad905a9d6e6599bd70e6a60c2dc01f8fe80e28c41e5d0d9a13648caf26bb77246bcc59e8aa2dfdf26d029e4f47175ba42951162ca4d49131d3e97", - "0a0171f786930a3d5b5fab987ed2bbefdf639252fd2fb1dfa4f167dc98e00766283f17a15e7b0aa60db67045b5f72570bd30b33783b0abf6edfa142b4a8e31fff8", - "0b0251e57ba2715ac264a24cbf258859413293a4c910ee03da13c9e6ddca90fc2d30f351a7c104f02dacc61a88d8bc38ca672893520a777f70dd6891d2e69765bd", - "0b008aca096eb6fa9fb969171f28036c3a5cedb2a66100134414380f93496e30ad58082cb29959848352874e24c79d2fb6f086ef4107ef1aeab964a980a212e4cc", - "0a06926eede112ff16cee029fef78b91c0bcfa3837dab4593f91d7e8427307c6d69e1f167aaf322eff385d62bd08587a5ac8c145985b63224b59076013ac8b8e2a", - "0a055a6a221f0cb8a12489ea9911a6dc8f122c3149615547379954ee613d64db4690bb97c11b4583be351e1b00f91c774378570b85aadc96d2971228641813f28e", - "0a01b638918345cd4f1d92c4b05d1a2f0dfe0fa3173e848b4ff9796ff1a0f00e46ac13382970ca17bb557ebbcb0351fe597b54cbe0046ff297e91daaa0a51797ac", - "0a015af60fc69284d713373ef6f35998f0c8f85b8e54aa81fa485d372a41acea474e1aa1e2914c90fb02e1a913da629b4aeeb1cf0625e7a79375f5ce6ebb826a18", - "0b037810528c1532662d348f7fd8860b9287286af453135c96eb585ab77491f231e4db9e270f9c7198a7cbd00e553d7aa37d633a0395aae9791555df95b06389a8", - "0a07f97cb8656315d9528a077d453affe7098d91665d80ba227fc688541fda80a0be2e9dba71b3f2d1597e12332d3b201aaf628b748b33a2da6acf59a608579aef", - "0b032da678d2883aae6465946c49fe4a45b19e7be77aa5ff6f4d9af45411f18b3dd6961ad6d037923a05c6b8f7dd0cf0552a73cd1d43b1a591fda56e390ceacb29", - "0b0211c68a0ac9906fc9428d79d87948f64669a4e3d7847f6ebc5d7ebd623f9ff3ee88b67a48a0d36617cd83caf408b8b9dc3aa66140527183524e0c36c5bfcdff", - "0b04be789dfc6b62aebc577afaa71c11368d988bffaaf355901f63d02ebf6735af181a1c959691cfebc84fc3897682c8b4a3a3d36ae54b73e8e1136b474b1c50c4", - "0a0342fcc97dcdb34feca758b208b13a27b33c93aa23afbd626192c5e73a6b21c842f433420d5d48d7cd700a5d285d27bfa28ee84e53ec065f8f392e6c738f82c1", - "0b02038f8d0fe57cdce444bd9b16e5636dea234ab915f33069f94190c82722432f39420a0482ad74cb725f7ea743bf05a904f725339cb81748e721c40bc84a5525", - "0a02e74450bb6551acecb8c6ccc9c3b2b6958837dcfb932951a9556f3a516cfa46b78e53727f0454d3af019bc32e3e372b8f38e7e683c26dc021902ef2adbdd429", - "0a06ac50ec75a93630921aa2af1b99283baa7ab93bad61eae4f842a4dd6f9ebc26023b70db0579c63741142dc92cfb3e4c627ea8f13768acd982889d3a89d994c2", - "0a02fb631b8d4f84611b710c5c607e0193a127eaef76469ba98768aaa548a20594521ea80cb836bcc21e144de49439c79ab6e7b04149c003a7cc9f212e71f2eb7e", - "0a08f847b42b3563ecc3aa1bbd7c12362b43ff282fb9bf86d7a85ee295137fc8577f5f1c72f880a781aadf5d2bf6b5cb12d49943de780cbee54d01a085cfd6e9d3", - "0a0305564c117c3e11253ad1c1ef0339a2cd6935b1004d947349301709c7f042bd0ee99ea5d3c3a2e61807f4ebf4ffc734cf81f2eda36aebb6ed81d516b42341f2", - "0a05bb2ab0a2ed91ada6791ae1659525501718a5c754fc9d7aca922df43217548ab8d59e1b27de618f87abf732e46199235f3df7ed4c41bd98361c784962477599", - "0a009557827de11c640159b80280a07c19bf8602111444e76fbc938ff56ef863edf93284274ef28670d09da7335a8b88076e06a996fbaf4ff8a1b6f1408d29aeb0", - "0b05bd12149658b36f99fc2ddf1ee660526f344a15b3ae169739a2458bca7c9b1cbf8c27d3612226147ae182859eb8a36d9a098b093a7979178d9f24d69b2340c6", - "0b0314a4058aba6df8bd98e379aed2c4ebb00c9f0a0130b12e0affd630013ffd60780d8a52f819f0e1b412b510364c715c11aa3872866650841ca09b291c28c995", - "0a0124c1189a21a04e476f80b1598b1d37123aa5174745eeab35a1d81d1017d17674d26dc472fc66b102cd684d478a84e19ecddb5e6fdbfe81cf4827b155269cda", - "0b082bd65335405f4435e34694efbdd780eb66154b220eef80c0e72fafc42374823ead67f214bb5475060a942c824d8087e0d165e2f9a6dba08c385f51f9abc055", - "0b02a65e0c99f9748e73245153b9e0e8c1f23e33e20ba352a791e1acfcbf2a5c2cbc77cf2a596d7a09a339227ba675640aa2a269219e7fb607d140457b87ba331a", - "0b08b59203c0d2b0eeb42c14f78b2af5a43099668609b9a7bb74b930f715dbd8c99c6ccb3acef146d48b17694a8c2307f2c74400be6fc7a1604623f4330ab53c91", - "0b06d3ba515ae5baeef6f53e00ceb4ebf8be78e110a64ab6499569c85c8989cd4cff62ca48049db72e8938a84a0b531254e7ae44afd43f3cd36943925e86f0abde", - "0a02b2a6237da3ec6ee281f989c295cf68e781d6e6060efccbbaebd62a3ab90d6a51a8efe799939de6337f001b0a6b0d697fb80dbdbbcc9292b96e8bda29522c6a", - "0b02e8c013a287bfce4bb47f23dac8fc16d61015843575ca5b2f630e1fd40be6e6944d73c909e39ce9406cbeb1b74d1e743a0bced1e432879d426cadfd12df5a75", - "0a0316a9fd7f34003f77c4f7e0bc5eef0b298079da17a0364c5b696761910f6920bb6633ef7a5df90308eed4c1e7a845924fe26f89cec97b871bf8f08bbf1689ea", - "0b05185e4709f2d37528f802be4a866328faf289c8f634090f54cecf0ebd3f731408f9099609e1b81ef0651c59fdfa579f5b66a92f14072d5331fc74bbfde8aafe", - "0b05ca2b5abcbef457a4caa7d8922ec4b3bad13e38c0bdd2da558403edfa46de660608cc6fcadc7796237ad892ae33d6d1de7efafee39b7dac26ab0a9d90024d8a", - "0a0228835dec62aa2109424121e533ab8253f51e604c71c0589bd39fea0a035899b918895bbc650a8550d98aa287f4a25c7d80678d06c55f214c36b33830054980", - "0a07c58331f0d35273fcb7275439f91942fa9f5c423d252dc3bd698810fc4daa4ae0984c7ac36019887a59c915f7cb27879bc73b454eb32912fb2ce9fb9afe3966", - "0a0676ad44e0b88a1267caf420193d1527cd07c41c018ce4b16ef59480d08122a24ddd3b95f4a668f24e686b8127d8de702971e31d7bf5a42cac8a42f307b14551", - "0a06718de341107a69bec746f82fba38b4cbee09f1be89c9cd56fd1b06ea51d28d1ac4c8450fc67a519f07a4b10dde7ca403a5573e061fb2c85f334d09520baab6", - "0b046f613ee955ae0423b9077af2292fbe2861d1063e9a65996b95f16dec88192aa47f8390f735c995c0a06c139c5864cf92475050f99cec3ac1bfb5ea0149c64b", - "0a03b46c2ea81be9fdee235dd03ac3bff4d5875d903550a208d98315fe94138d5f4db2e305a454da1468dd8b789446b4e1b648665f5e54ede787926e20a75413b6", - "0a06e76b186962dcd58788f8e9e9d3ce712d9214638c609774150bb40b59a156741ac2fd663f68e6746ddccf9c52fefe94926610e51897e997a00a4c66d5540e26", - "0a004bd8dc060427b32867910d5e58112db409bfac1c0837cd56566dde2d628195645f0427074cb5cb611995fb47a73b2de4c98e499f377eb85ef500e6c81bea29", - "0b04e3aa62fdb8f628edf4c59b4dd6025d6d117588a7649212845946b8fd1c41e81f38be3e79e7f2ab7abb2f582ed494a4d909cfc03185be7fd30982c5e1322668", - "0b04a70a9eb89a0a73f1e7ade04074df3b7071ef7fb7745d77182d5b7468acfdef1515c7c097146071f87855033695298766d0bdf59745c02fa96bb3703ce33879", - "0a059b34cf1622ef3085c16c666a2efe9556ecf1e854b8ad0678218306eb5700a3d1e15d1c9246fd24e3724c732f98b3f551ad43596de608fac2b9b1d8ba2b643f", - "0a03eac7c5f90a33160c61e22b5bbd5af4dd6ddf5f5df140aeadfdcf8a83dd0590e1eb22d4a9bd8a6e8ce1c378a7b72d276a7ece4a4dbdebd230887b9f90db4c14", - "0b028cfcd7d15267407c2c81c92814915edf89978ee95774e40a41eda7348811907f1f281c4e0f75933ce051776723c2290fff73ded4b6198154fbbd788ca462c3", - "0a05cdd8ca21e5bdf98ef41a0d024b025d93c617727f184362d56bcf4a54a999ed413d0fe8b8610b0867ab4505593703f9b8d74fcf3a758a3a84ad237ee037cdf6", - "0b0679dd5b4ec27459e8a865b7294859f5954230339c784358139c71c7fa315accf13df14a2b6eb47ffbe37a024dc2f8ddfb4019e160fcb6e9405cad1576b76386", - "0a0029e87d4183824023fa5e16e2a358104d0434171c95593096f74a48b0837422bb202502acab25fc831f7b0daa634461df009e8065e5d4607343487354c70060", - "0b07480958268fe7231841c273aa9e4560f18b036d8f840f74cca725411fe9d6e53c423c19093829b65f8555435a4f2828000fa154534c2f98f0b393abe78b3fff", - "0b06d36008e683580bbe133de61d8e18542df901b3d072757c0db72b5efe4e197e703251dd97126dfce00995a670b1b81f7a51c8fc4f2088134baaf2c12a5a901e", - "0b000fdf4c96d4be87d6e4a064f55fb2ae3d97cb3dfd7cf75362ad3afd08dd68a7ec3b410e6101d862d364f34e7c9dd03a1b7e9054980d85d05608a2c9ee6e3ff4", - "0b07656bdc01746064b3fdc30b12a65461022bc79cbc843ec53bc56daaba59ef29e325790ef9c93eb53a428f8c2ac56a72707795b189f3e54af52d8a398e046ba4", - "0b04225ecd4b6aa72e308b7d2181575da514088f850d7346e057be2095b923f634589b4b585131c3267c21bd0fcce5ebb70b9496d8330ffba57bb2737e9f838429", - "0b06954bfe5d503b6f17357401cc90937bd5f064a93122c37fac6f2657b0183675e1d33c44cb132c8a6867e979450b9c84b0f69585b8247fbf1f6e989339183930", - "0b053fe0d1f41c57e0d0e898a28ebc9f64ff82a80836f237c3222a40595babaa82dff67261e68ba9aad45408282a014e91ee3d56b33e9be03ddbe29933ea55dde9", - "0a00309daf7c092945a03d167ed4d6c60fa53dfd5f4826eec7c9413d04e14d8e543568da9842828b7e947699163b6bca1186cf6d72efe578714a3a092a084bd77c", - "0b024c52f1249d1fceaec08cff16e96a235dfb5b78dd472091d598becc0083cd627ee305dfd7b0c82752bec178537e6c27c2be6b1a6444f80d912708933ddb76b7", - "0a049daaa97c29e48d6cb7736a1d95a3a9c6d16329cb309ddef0200dbf634daa994a580fa506007466b7b9a6b350ee37e8efc78cf9f84ec68a55d8359f5da8fb91", - "0b03b482b8858df4d5ec0436e2cac737a6b3a90c09e7dc2c64cbc0962088cb1e275fe7bf1ee772cb0b685ad483f537342e58a9e35320921b1eeadde0780031ba07", - "0a0666e881031fe142ca2e53a5d61f90a3d94142346691d5ff5ce5c5a2a642a699b1da5c939711755bc3a9c0f15b2645620c43ef0309cce299d8d3a10fdcd1d6d7", - "0a054aa4f826482b0e6f822e1b5a09023a3c38354f473e8109ee9e0fc353593dfaa33a3ee6d12e57ea222f60f17f79c7e65b761b333b8f6a0f9c1d604c05914375", - "0b03d9e10105de19bc8ffe8903f377ea493c6ba81d8e7997325d2d466aa105e9dde042d82b09e99945962d499ea59b0cae990e489a14a29d7355c0d70ce17cb1d8", - "0a07ac14fbaecdb82f97834e52e91a53a9cda3316b35ba0f72f4a5d159e4a178d8f03e217b557d84983edfa7b5379daabc0ed5ec36a0cd0a726e0725b3d20c1992", - "0a05bccee3a98e0a103679ece72fa17fde2d35baa1c17c0806e3c34f3045fcbe3261b89faff1926fdb5b088de2a9feee19b2829f61ffa7166d293da6bdb0359f14", - "0b08e7bd556979ac5c381b49eb34e5eba3004178e878e016f3c83e6c239ba040240c33a85ba3eadbe43fae0cf2b19e9f61fa5c942c1af9c023b0525ada2ceac5af", - "0b023ef605877fa06534c7fb7e4b9a0ee83cf64f87432427e3022f9ba983eb7caed8e8fd7d7d8fba639f50b8acc23f29360614cbaba09aa1b61af05255ad36535c", - "0b03904121bfcef8f63704f5a4d192203ea67b765d49e33589c4dd192511985f8a7995572c7cbb85d59aa426b1fe32ef86c1267256f24d2d21f6c43b0d62942b8e", - "0b03b37d73333a26265c3747b4db75cdb8b4946ea69d0e22ad2bc6ed3e64c05cbba73b2a9eef50699b34591517151faa78e400072135a48087317a88f73b4f2d02", - "0a00c6932f326ebfefa292cb749e66691f0237c9a00d3f73e7db8890f9fb7bd421e7ba775dc0fa9daed3764241fb4ced92c3599e020ad1dc88c5c3ec723d53ee14", - "0b010ee17648ffc416bde467483f6fb7d4e40e60a078efab8e00bbed132f54da7c1d5f43c305a3015bd70bbcdd90a95559955eb05cc2e152abbece48d1dec007fe", - "0b028ed988d84786b13ab3c447b9bc427615451bbfb014a2eea6648ae109671371505bd13b3dc561c43afb3ed67332842feea4c77ff5a048dceca18baffa360930", - "0b06f809fd479e390bfd3c3010b1a86759ad5291aea19b39612a7066aee4c3608163552bb2ebb88e84ac2320c5f1dbc15cd6dda49f5302a2988c2c8885479c23b2", - "0b0384fa8fd9f094ed2180a1647501a1ec69d7ec012ae51427e8cc0871db5661e093b0356ba6b84539797e3bdc53a46fe4bdd899ce58789ff0d2076aa28e441cae", - "0b01bfb984fc8e0317317cb016e009e08a9b0ba94a5043d23ca33a218d435d8f27daaa8915efca118c52dfedec1ed6171e9fc72633251724b7d33475ebe8f7a2db", - "0b050e40f487ea910260067c386208b501411f09c64afd6c0f03ec37bd3e5fe4188c986850d4566608a04781e8dc900082298f3d4780e205523bc7eb00ccc1bb55", - "0b0723ceabf3a6e22dac7e0dc3f3bc6538db18da77faed6cc16af0d6ce547ca5a3676035818bc2d847b6e3ec5a9f1a707790553410ad8b0ca0cab409a44cf4ade9", - "0b0669ff0ba4e67eeabd121ebe8750855f0abb362b58811788d1a68e0fb7a2d826eeeaae720faaea0928d44b2b96c08e141a4ef7f549a47d58e473da7c335f9563", - "0a05edaeb78706f1fbf5d9b7facad521d21adbe094ddef79af7a1001c04070592aa6167a714febb114645d2562679e69702f942a05ffeda6072d2a9bc63aa78ab0", - "0a091228c97e8d5c16640de4686984af808d0764a7ec3ae4ed008e37f1d24928b96cc6e2facfc5488ee7c76b4ea4a497aece001ee0dbb50898d4bf6edb0d2784ce", - "0b07031f1f4a5daba41af245e5c7f893b5b163e52071144b05530b4011d2fd8f52b3838babfb3ac3aa75d4059d7590edbb54f950939415fde707d42171e98fe6ed", - "0b0526b55f4ae00591cf104ae0550cf6bbddb41492b9c39a377832ab1176919dfb521ca770f04e69c16042de538240c26e05b28a7040b93dd69ebf6abcca27ee8a", - "0b07a54c05a8e8ef8145d4b2352afc7d11f3de71e3c4479abd429e83137b99f6bdab3be0fc36285c9120ae5a0ae180040e219793c7a97e3df6e22a299533c0b9ec", - "0a03fb2b5131846fb3dea1ea68a35a759c0806537516866a3bd4e0d24bff5e8111d1e28b00eb66f1dbba88b890f5958377bd42bd3269c83c4c3f51e275cc92fee8", - "0b07eb239cd5711bfebab8715db5411b8a9ed0b5a9acdc9e31b4ebc5d63e80c869a38499534875a8bcf588016ee5131df551e9744b904c20bdd6389626281fc999", - "0b0557133eb52f71ac4ee85dc6bf5ce1fe036f7ea597e9ed031a572666454789ee46b1385a3c76491c57af196a994dd851947ec2f285407bf22e2e90b951e6d871", - "0b0918db71b4e7c3b72a37abbb323523664b2abab236ac22011caf3aa1f14f3cc7df115c6ce3750d0feeb3be611d36c03c7ab3bb4a72b8c8c3bd2e755fe88c5c14", - "0a071944c464b130add2dd936a67265a84ab8a1118ba409b819872c2c19cb5fe3a036737af5b9b07b2fcdc2c63e6d1c60d142177bf15b3c6aa0de55fe4eac12226", - "0a0898f907271dc68bbe839ced786c7cfe470ea94277194ae0d51ae8a396497617548a134671f8db4e98359265b84df25459d138c668880c0297457645abfe363d", - "0a00627ebb7b7c951d12da9f79a1395185325c85ea9b80a7da68bd1d13fda6034276b65b2964832d39675008e703b8d6d1e5ab921fa7ff57dc8c6a95fe3f659e29", - "0a0085a9eccee83a6c545a8250abd597a97dedd6266609a227406852bda9f5ade831501a2e8270ff909b529ec2a1bb3b41f4dcf350f254cb191440e58e2b1a018e", - "0b02514c72ecd413e5e8936223633e2828770e37188326f2b3d1738ff67f7dba25fe0189cdaa9ad1f108ae5b4852111c0f652063827eddd26339a496c7ff7560f7", - "0a07d4955eb19e5489a01d62e0771d72444896be24e748a29c815dfa22c6d4e92ed0b5ecc68e56ce8cff70dc5357734e50a49324db5ac7e02fba289c9cdab2920d", - "0a01645538066774c2d4e3f27b3b467b3701d61edc85d1b206ee3bc254abb886b03e7c86103719e61717a6ffb5c79fccd495657af97fd0c1a4fb2d48ddd8b704e5", - "0a030a970b58f7c6ee91ade02e5df0b0202480de22587e437750024ee7f745a41f33392330f286c0a0cc4664e9e02798c102d0c2a9fc753b906b8866191d6bea1c", - "0a02ebb750cb636da468a179a288ac48abd3dac29e25436fba7bd40f67fb0832fb645719649da6a37ff123f3b22c936416872bf897f4efc97451fc371c45246391", - "0b08c0bc4ff8715ca106c5226ba020e3c3bf73385d8e6fbaabaad63ed3fb7a9203586b758f6963684878df38d4e7ce381049ae49f468230c9d6e30c5f57a300440", - "0b00601a50f2f3974ba71485906bb1c31a1444c290fba8d72fcb22a3971dc7816428f17f9690d826ffb92a0ebbdebca88e7ccfabf49fce3620798621c9e5018364", - "0a0173199d1f616e4b18dc2254e2e380ddcfe910f6001f8dbc99fa66c0a989d36f4c1c802c948f3d27c00bf7d486fe329eda6c77fa38ee7a85f674be77c3c17ef4", - "0b062b875ee1343f42b821341faa85a450a55bae9d3261a3dd3ccadfd183b69e8770301a11e281adb8acbaea43ebe64cf69e293df380e60f9ab7d6cb4420f122a8", - "0b00c90ad7f0ec322c18b245c386988437519e0594f3c586cd8f04129839e4b672bbf3a9453a5dee9f6f6dc8c1278179fb541556cc598dc67c4b0d6ace716eda0b", - "0a0111ae2f2d67fb9e711ce84ef7f4da149c627ff9af3bd20e01492878bcf67564f4a123afefd4c19d5c7cfbc4e9e7ee80717b3a8a01dd661bb9497235ed03f0df", - "0a04a062f3fa6d24c363bf37ca222ddecf96b8361b66f95a239af03a45e3d9506210d34e5d04287ce8770ec8771b4fea5cf92c62d845c187b2a55816aa93ffe293", - "0b005ae3299f27c5b2390b63b59b8abd9ed6dfe224ef6572742b4298f2c8af86eee480b1a5b1ea7667608e2422fa1370a1ff1d0ede2ff67fe9ffb564917925fb0b", - "0b08d2614eba3ba8aa1a34e6bd6170e562f843be20b831c6e9ec91ad7a7538f4c07a06330cc93e67533c8c3f1a8e25bfb27c7944be2231156ad064cc5a59399afc", - "0a07eb714d1f780b3a75a35ca5ee729465efb5402d3363e3e0f61f1047abd163cd3166e03a2aba0cfdacdd136335068273a134d9c9e42e767ae4681d8772f55d07", - "0b00f5c1a3c87f9581d91445134becb827f868bc5491496d591f23f2374bd8a349642f1f08fd510efe1a47cdd0a3545a832e752154b3536518edac427985a5e1ba", - "0a08625d6bcd328e4222ba49ca716db1a164a7eca46c8af87c818c43b73809da6cd47024ce06fe9d834071a1bc99b83858819348c5d18216e2f8b05900cdd28d66", - "0b004592dd53e98a525868d2aec5a345f838a2dab1e1ffa99f98567def67aa3bb24c135693b14602f6cee3098d5dee813d033d3c090227dd5367ce6d86902dc808", - "0a02379e16fb99dede7fbfd8568ef075d7a0a7e3e34b4b8cbed89699b9b7224eba3c5c9f93970e31e6905eecabccf16b95db537856e27fbeb201228e1d0e588010", - "0a0048047bd36c16b970dda69010152adb44caff4f5ba0f7ae0e038acb62af48ae4ac2debf0b2512b7e7ae38c7c4a80f3a354fced18f18ad177519d35c3d0c6ed1", - "0a079070c2b3d901db7abb5e384148306436da90bac6b3e3f1a2721de24dd9ccdf8c1bb9ce548a1e31071574274de54bb320804bb75ab9d6bb0d6588e7682f95bf", - "0a07f3b65188e4d0db177674bbe20f08d25b9e2d550be9b80ffd614e715371c73461e3a6f8338a14565994800b214cd2c596235b781a5d687f76fea3cc560a3668", - "0a010f517d454ad01c2d3cc1ba2b2d3e736f06a33526ba5d8a5c1a21a63fb436adeea093a3d081e5499392e4c845b024c4c79219cbc6178a8f835a5ee833a697a8", - "0a040c8ab658ad39a7f0c742fec1a8505cc7e0bb0ef6562c0f134eaca03793cc80e85f3cc2a6754e315733da651d8b93779ecd36a09ed2b98d9d53be76d19ae881", - "0a06ded04d44666e6d39613c824e34f90f9d2fed17820914c2aac4da58fdbd1827702db87f86cedd753ee22230506d8ac161c00f760d1f7b68e3a97316c23dc7ba", - "0a03a863857c97947150f72c65a3308c9e76af99b67ce5e93eb7b3965831a1b861d908960bc09a132e4b09f5ef39aa780dd559a00c2ab62e36ff074dd80ee4bb41", - "0b087f97090a6eeb0dfec67fb8d8bc9b6a44aea320a221398777fd02559f6793a3af03cb5b783e73da05f08ac6c35710a095d4d5b69766c4f93e758e7fdb514720", - "0a0484165953419d8362b7a7708bbc6b6b895d273f05600815802d3b27ef24c30edd6b70316858628203c3a73bf4fe19a6c55f4e2fcc7b2737bda67395ef82034b", - "0a040849adb6ae5ea28c0f442cdbc472bd5351405fcb075435ab4f2e7e97d565e2132f6155b1602698c63bcd6030fb3d2d82f596cb77291e2c3307303f6f5bd9ce", - "0a08095470702f0ebfebc9553aee4301ea853d7c3661d9078ee2b4045145466e6bd6cbe15f9451723359ad6b8078c6361ba44d9918dd4844c90b91184333012442", - "0a03b9c8bf4cd4061ad6541d7131c7d03a0e85019a53d17db08b3958edb0fe3e1234bd00bacc7832a90183a3501a827dfcd47d43d52192e98dfcb6bc06e5bde753", - "0a016a7c4ac9a0c1550e66e3d4b0d87d141a5eb22c22416f4c2249dc88b5e0bcaca5627125013f497aad83254de445c1564a0967d0c00fb3215d157a4ea884ac5c", - "0a05e4d7e9df3fb49af63d6304637f1494b71cefe40a906996b249537000d062b8ccf5e815c186e72a767483ac95bbea3c25217912656c4dad42bc2cbcf0207fbb", - "0a004658670c727adaf67458cbffd9972d4310eef636022025093ed716012732d4da48f0bddb86809ec61aa0c7f20d017b7f8ec457714a5d703416b61908a59e8c", - "0a048564f21eba083b78970841d867e51bb5d79905d047bda67dc60fa4c15445d8ac679c0162657efe260596d3ac5a0351703aed5e16a429f1c95a6f8cafd6394b", - "0b0217a59669910e290982e37240b4f6c3f98b86a14860fd44f159c0f30f9b5680031f1ef5fc25d4f56da30a1b26997e0d2e8c873e070425b04c3636b7203c9564", - "0b00120f739e9b5acb8ea6460bd8f174b2e5cba17512e39cdfe0b0a8fc0b7d7769b8979b33746727b53706b7e63c7f9867a32bb3d59d0b1b59566969b91a75b4e4", - "0b0211c97f934c396fea4e5d92b0f287376319a3800c0be39117e06f326fdc8c2c0c92793b830fb5118b476a9a53053bc18a0c79a024a1ff8cd56ac7c2b5572852", - "0a01fef8ac1c384e7f5fd56cbf166909b05075fcd8959a13de2ed055ab886543d1ea8f6346c6c738b4f7762f62de4625d30561e7b43c999e14841e3397259f2255", - "0a04dcac2cfe31bda0a977412969e411679da426dd8982a48aa7f9273107482869efcb79b3b7e8b54f25f2a0eb2366c0aca511a9cc2fd45006865cb90ca887377e", - "0a04cd41ea982b1741e98512000338c35847440bc6bb3b8a2eaa02b6556edc32bfac47ed76516131ee8a0a486ed0b96070f64088bd597afe99d4c95d295a26d5c9", - "0a01421edd4e1d4a3e57938943627161ea350f2a5e37b5004811dfea1ea5faaf1a2ae9e6ed1395648673c5636e5b4fa43dc8eb9a0713c788786db632db6a6887ad", - "0a05e239c5df2bf1f0f7fd08fb6cf2a3f69c92902a7730ce769c5200ed52e18cfa7fdaa324744b702ddf1f8564042465d3fee0f673789c13d27168eed5fcf6391e", - "0a05ba63135a377edf0a12499a4694114daf9913e48351939fe791592a2bb9c4cafe563b0aa0a56bc6750a61dddeaa401db203f24d8e60763ace02bacd8ba10074", - "0a0528120348f1627e63882d12c4c9475b8a3c71c48d9f2d8a9ac395fc0609dfa72d7bc7cd80b99f8cb166dc19b5977934420c1341e3a92f36e47da3aa72e4efd2", - "0a076d1246d157f64c7bb6b30a8b0e9a35bef72440f515a9a2f93cf498d4863275800eaad673a81851ce1feb7a087497a1a1104c09767f950ac087d31591c3cf4d", - "0a069dc1f128731f1916792960cd0e4baaf16a2f1f3ade0db6646d3948ceac233999a7e6c8d30844874154fac2c015a8b1e938fe40233a8464382eacf9d5e8c4fe", - "0a03eda742fba60bff66dacaf8cac087a8e78f5faddca4671ed8f7673d5fb0c76bcf1a10a344d2f78e2c1ed44e27950a74a22bd16c806f4d0de8701f7f9571034e", - "0a07343c94e19512bde1a58f6b5fef8c405d49276306eecc0afc25ea9ae109304af5b61463e1a748b19acb9d4f45c9d6d7a1d76a544424d52cf9f05e7ad02f05aa", - "0a01c6b34963775fd1ccc6b6ed01979164c13674d6a10c719360081b5fd04d05bde26617a1c7a66eff85a9f567a63abf4664735ce6090d51eb84a8f00158327dde", - "0b00c5f29018228465c3b6f57b3dbaae41fc7c5b3bc683423d0221f27926c0fcaa7a4ad72098108fd7689c54be9a72d1ff0b3bc8e0251f9bd14e33714883b5391b", - "0a03dce29b72534451691cacdd85b93a01c45cd5365958988bba653f448d454eb803b56db6046939b0fdc6322fc1f493f8d226f30d27493895930823faf50f6ccc", - "0a08746370284ac8bf129d4b63ed18047104dc0e18d88e40534fd0afe9839489b812af4bb39ad24b0ed390c9c6f496e0192021f1ca5bc87e0287b8860200fb8a71", - "0b05cf2fbeef0dfd31374f4118d3b94c22c56f3c8df8eec8d22c123312657b54b1a7f9c5e0905c04c07b5175bf4c6d72a5855791b72bd89f656e4cdc8b56705f91", - "0a0125fe2d7baf9fc2f3d864a5e90c1738200df0ef180d68e5872356204b84a8baf46584e504c4695990d82e52516fd0ebc34836fb98d8810bd80e3b00c6ebac7b", - "0a022d13063f1e47986351940921e73c37063d169fd71f113ea3d3f074fede39bff49e93ef1d7ecf247d855bd8a06d72c0d9e3d0e6cfaddf25d9e375dc2d6e9c74", - "0a024de90793b09295bb692709d94b349f2011bacf3908ba25832fc4a3dee44bff8a554451d8329a5834d4df23e545e34daac286ed3f96b5351a662d447cf43cc6", - "0b039c5ca37e5937ae1ff823119c7589ce7b2e259d7025aa69018787041c5d23ba87d21e8aa2454a1ac3841397f61c0590ab710cb29559b427906bc66b7bd5bbea", - "0b01b53de5e4628c946fc1e9aec779c93d1871d1a7c1226bafd4805d38212e60dc9d54da9265ebc9c330dd324d4ba9f96a6d61bc52b32c0b49230440ef16928d19", - "0b0079924c0a495a8f09d478624ad04539429ea0a818307b23f6f0f5296d24f496fdd4956d8ae334df2d116a88562bb7a70a92cbd641c0086ef9312c2eeb4b514d", - "0b043109de80997dc27ce9f0b2e507c53b5aabb6ac1b1a70dc16d5ea398c99f10563fd594c1e739b6143d8d74a04f8d3f84d76fc61ef4abd142826dd667b7afdcc", - "0a03013456ac1d5af615d1a53072c3b857b1013faa6521d1a1d93d27b5339b56d803007f9c6defeedda5dea6fc5677bd47283b0a809fdca4297ba3dcf2ab5e2614", - "0b02099f996cbe1b80cf1f564ba52bbf1ad716ecef8998b0edd33292d776dbd02ccaff3e79981ba6f59c74cb8a9194ab582daf5c45784adea685de03e45fa72824", - "0b01921ec34e2f9ef7dcd188ebba5801eb4653c8923b657513f20fac808c7a3be2fabe374fb45d8c4979e7cca6f10fbae486ed88ce467b047285861da80de25567", - "0a00a1d21d81ef2522b301111774a0a7e894ad52eaae752b74f6134e61691afc324aba03da5403aa0bed85f6f02e2387b2eef05c19a02eccb05c4ded481bb71666", - "0b0217c857e58565075000cab4b7a668228d5672bfd4815619b6c705c46b61ce2eb52c98ff1361d561f50d02194d3397ad2edf039d14e0d702418b79f77f383ce9", - "0a086ff0445bfac39a266879ab790ce6119ec70ab26569da488b2aecbb50c27788a45e235e46909439cc96eceb5eae5a163c7b511e1e68cd3a5b6728601971f5fa", - "0b0343b931a65bf479c9615aab650471c2587fa3f7b999179d1abc2d368d72c10919b798e1102ba99c57848c083ed33eaab3e20ee3de7f11f132c1539d02564c21", - "0b003dccea3bef1dfe466252b80f49451315451fbc0d5eeb399c3c6eefe6985a09b72672e6034293515ffc3d147ea3d033197c488c9b5c2717753dc75433983682", - "0b015125a7864ccca86bcab84f8a25f969363bb9e820bdcd90c6e91356b123c60f669fba1c49cc2bae106c0b8f18c206fe023439f4b350a3e3a68b295487360140", - "0a02e3d296dd8b98053b60df4ce122177b08882aa08901b01eb953f5acc4b0cdb726d1ad8a7cf23b6c9264f5bdd42b28ad99a7a26a960fac4a627fc51e3fb48edd", - "0b059bffc4f0c3c360b34c23b510c7514fb0a6525ef36b620fad7553061e19c7ff5d2a258048e2948f036e81160964a1460bff1078a6e62d9b57b2092084ebe80a", - "0a046e0090edb51a65fbe8e33041c98aaffa8bd46c8d64517c93fa5e126c803cd475877b7786d3d48ce9a33ce5aaa854c12071aedd38cfd27b7674fc2c8e61e106", - "0b00579a97a52ac400488d496c7d13dd5994cc6df4672fabda14c6d702ce84dc47e9c57ddf12b0c0a33a9778965448022634b39455cb37836075bcb18117e1329e", - "0a00b329cc267f85aca7b2e8f6424b981661814bcdf36e59df02bb238fa54cb534d867eee36b2032da2ddd5f1563108ff42beda59dec91a8bce31a31af50b99077", - "0a01371de5f95dfb121cd2048a22629a6f304b7ba21af920bcd331177ea66e503a39acf023b80ec6eb627b005464c95f24927cbb07ea286a456641451a31e98442", - "0b04d113a1686f358958f8b87741fc58422bd158b648f139f2a5c14ed8771812fb0b2e6364c54e81ca0719fc8a7051a892bf93ded026cc8c6d6005c20f53fec7c3", - "0b04c2bc8addcf7cd956ae0fe2779fc6999e5ae155a2bfb3ea97cd115858288af0d4d713df59bb7623a09fc9cc421e84078a6f7b9afa1a847463acca5cf912a24b", - "0b0134d3bd78ede7b82827b7d8a73206baee5423730b5f1b98177120306e259e86f3a409dbe45b2ada2ae2f86af0e832e76179a4df3ed8076b43daef913eff670a", - "0a0338ced64e81b6435e163e67c92a83ab3072b98ab27a28c6a6a8abdd95bfd2f6b0c65bd55a5aa3ae922b15b5e33c4e255fcaee20377b8369cdcad64a82c108aa", - "0a07d6ee9bf930ab3767d97be668e250cf09d6fcc02c88fa00d1967c933b78c605d8dd779a9184a9dea20fe42e820e4d4cca30f2b940cb5fd3145f88b3e5b50ac3", - "0a0129c13c05811e736599bfb4dacd43f748ffa275392c69169fe1a65241ac4d2da87072c786c933df1a25dc56ce5d128921208b1fc4ea5c4ee87ae959636bd2b4", - "0a03f7536d7472baed22b88fcd89017e607c1efc7e0812f3cab63a6678c691f9e2703790964dbfbb72f382273c5ffdcbe5d0ef293fa89802fc698981f7f825a48a", - "0b0855beeac8122717800884e67119e0c3a8bccd1cc407d883fb5d063a1bfd0033af19cd7e7f8f8c9248da628497eccafe4180104573daaf17f392b266e038d1f7", - "0a068d71d05ab3929ebfc964f20f5c4408a4a93d3f61b4a24036c9fed424232663992b06b687c66f1914a86ae2ed076940f472d065ef6cca48c3570d016da882b9", - "0a00bb84cba357e27d613bdd79bd367ea0e9cbe681013cb0993c52ce1f0a34e40128576a6cd29ab7e0fadfba08fd77a7813ff06eb232b51e4219abb132f4a50a7b", - "0b036db8b7a0c0e5bfb4bc74d3575187cc90771cc6ea9682c71e4050ac35e5f6a294691729e71005600973ebba26328119c8a651e7a3e0a701e831532803802f0b", - "0b05614322a3b9436641be8c65bf0ae70ed1abffcb0a06b8b8461269d61276487b44f2bf466ce1326f13e6b57c0d9e07706303c7bd1ded9d4bee48bc3e0b65c11b", - "0b02bb5fdd3a2b2c7fc42cf50bdfac8897ba5d92ca9c9a5dfd2648df6490f61332acf5be3486f5f252653dc10808ea82eaf62f42b948454fa02a4ad466820ccfeb", - "0b00213ff375c988ad71d7075557628e0af53c446e7453aba40d432bbd740a5b611da0d8bfd64447f10e597075bfbff4c68f66ce7c6bd6445264c47b051601b70f", - "0a04d7a3e605db37a86a01f466995269cf15b257260d6e0f6bc096eeb3e839d29c83f001ccb232f9339b354348f1280b1475c2312eb3acc261d4fa443fe7eb3e7d", - "0a0671e71a1e84bb238d5137b12f94f3181dd043148d464c825ac3defa8e6fd90613290b42f2ee44bfcb69232fc4ca81235b69e13040a6922169135bf18d0c7f2f", - "0a044d99f7e281bef1ea46242cde4747d102e083c502a0a8a2c3634f3af3180c6d9f11783d9616890c144c6334c69267a77f0bbac9e10077e9b5ba78e442ad7f06", - "0a027a7d8c9f9282c2b56d14678daf51a5e282a7360548b412ec4ece708ae5e17f60411213e6cf1ed3158fad6fc9e8af79f1f95b9323a448c592d72fd778427f0e", - "0a0631b32ccfaef641a88d7cffabe378747ff4702ba9a0d96908fff1ad1cb3b1af69b9abbea9da6776db54d0a0a56f730e3dceb37a8ef91f89b55226cb1620443d", - "0b06198b5ce003de6cafebc06ec555e8b80a7b4ddd2ee2414502953a77d5b4a51dce0ef6e9a66caa9985be0c908866bf514db71cbfde067338803f3c7e0042ceab", - "0b03782f1a2bd52b0395f160fb94998aab31d7934e5ef793b004e13b0da071d424162dba6018f0e99df82be71c473302a906fb2b5b113e0379e90aad17ba487a8e", - "0b05dd69081941036a8d8cad0efea5c3b2567cfb40e95a4f693b2b2dc6ac5f65ebd78b356c7b45a4841fab15eff117bd743cce512cc60721892c60671a7760f802", - "0a07942881f7558c1ade383a93e933072299f76a0ccaf8994c6dd5359a88ca4aaf9c0361bb0c18d45c0d05af707ff5eb80e916485e05dd53a9c0681ef53f7e4b15", - "0a04a42a579948a8255935d3792451a76f1ee0835e285c59e3fa94907e3c833028ebf17524151099de008e388ed7555f15d09d32506f257f596598d17fc2b8b4b3", - "0b02287c61e51223eca2d4e4f958fe8aa0185a399608b2ac5c8803d147f563d798af26370b53112ca2853a65030ef5d83ad89cec100a0532d96e3eddf6d3b39584", - "0a08db900a63147c2aea0ad74bac821eb914598a0fe6fc383aa6f0a71a9fe1785b6dfdd231b7d7384371377492f0d0dbed6c769361752d673ae1bcb749f06ff3df", - "0b076134e44e1f9ee098fd63d5a8083e4f5b53a8851968e54bc12520612bdb3b4e2e6793496ccfb05169b09ed831ec2d22a20ec17feba90433e62f6687f985ae07", - "0b01931ed81dc43d07072f6a4c35ec7177e3fe54f305a612b93b6644a1901351956b48801d311ec601eed947b49d634f7b9884defb77727d42876f8922d761f2b0", - "0a00b3681e1db368b841754b0b72a2ef7f32bf9cfe4a4ccdd71705d5d91127e2693ff15d89e0889276ad13c3629b2124c855be0332f1d8adc9650038c14c485ce5", - "0b058906c04698aa3db5b0f8d0693fd5f75f8830f2ba409f9a624d0703133ff506e11c599d069af6e0323deb08c518bc33343544dc89ddd30bbc0b85562f14b213", - "0a003b5eaf5acc0267ba31ab933862d8af86d44945d169493d37ad0c9106b38f28ebac353241ee5e1fcb40858682311c721315b11b7aa90a0cc3d243dee13ade13", - "0a007c6f464b34ef9167488c37998ee7238777e1bfd68a81fc9fd137f29d6d44ef6d02690c3af36c9e8245eb4c12485b8201e3e88ed1b2dc165465c0b2a05f0613", - "0a0594a5924bab4ababcfe172420b43f55fd2633c3fd286b2c7ae02d7e98c3f4d1b89baaa84f820a42001efb81a410c61e1e044f40d00b3d22915a3919fd7b1947", - "0a05f202def6451dacec0dd7d7636b13d483ca6fb750eb6dcde68d4a996258d5124106f492ba42a38d9cff274b742d176a163a0119d27457552d0f425b7caa74fd", - "0a03a8915818084e08496f3e4302c16e85acc275527c8a5ef6c24257ace897c83f670458db9035e2dc7786df655911eb35bc984f29e0f572cc49e8dc9fcd5cb79a", - "0b02178231af79680f5997786e2fab5c9cee6d1f5ef26c051ec2b0c8bb6064c31727b1e8b002e0f97a5addc2788f11e374ee6a74240d3b71889a6f15c5da6e11b3", - "0b0529c7405a8e01d6add5d707b6bc4ce02d04e6aeaa383bcf9a445cebd53890eacbfdeffc6c9c4dd680fa499ddf8181709750dc924c161599d6da633d1b363a8e", - "0a090930b5a3c9ca8ded9075702aa1f2c28bff8a79e494457a81bf262d8d4bbce70f7dd36f431c6d35e29ac8e29d1ef39670f0e89f4fe39121accbace929fe5d13", - "0a082efad30d2986d57e7af51a6c601e17f45d2f7b78b4cfa8f21dde27b13168bdc8cb6cf4c7f1a43171c15a0e4ab693330048fdd931bbea0973d40605cda97711", - "0b04e0c96ecf0e7a2cb9d3d3021d15952daabfe9d3d74bcaf8c5801180c2b7ea856917a092fa1518a940c6977298391c46a1b6ff04f295451f6975f0bb978fe931", - "0b08385729cfefa4fc57a2836d94b1a6900b1b8f9cc11e7c28799e04e72a878129cd21a8c31b490c04f249effae0e02030f2f3ba20fafacd4e88feb11f96cafb75", - "0b04859e3f4d73b0c024d8bd2df3472d2acd20115c321d5cf734de5ddfc503e11da73c461f0f52e48843912b701fc7d93478af107724645e0e34bef169ca5bd12d", - "0b087d4656daddd66eca7f56917ca27a07bcc2f5a85dcb7f704d693ec01143f8f239adb4bf28d90c573f9a6108b3e81ba6334d224eaa4590efc914225c2a704494", - "0b050f32c90c9533626bff4971cf81c66c29211996f6aba3eff18166bf45b9dd4350eb57c0758e1fb50f65de6f9b05df7b14face801624ba6612c54d800c5d548d", - "0a0473752bba2fc4033f0a446554a3ebb4dd8f1b394f8fae6fcf6deaed058ce733df1e93bf50728405903ae3fd058b64fb33fcc5f2e7d477c6eed13a268b3bf5ee", - "0b06f2895c8be843a78f7b24e89af82b74c360b6d5844d1a1ed1d3e6f8275a54728dc16ffdaf824e6945772b3ed2ef80d2d252a58ccab7f3143cb2a345a8d3270a", - "0b047e5af98454276358850deb384ac719d2b3b582c6d5acd87d4892b033a72493b72c1aecbd0c4cf0487f8b46e5775d18ea04af24818bcba15cafdaa36f6df687", - "0a0540a645bde9477a466f95031445a6a7ccc3811c941a1153f9808344d0d8981cecc6b0d9ebe7d6c72b2de1356dcd88fcc6cb934bd280b55420d86c94ec486f8a", - "0b016674f2acb1f4ba2f990e11933789e469b2031f6402e9e20767fd118a1b342f00ab421d65e4a53ed522e6245d43dfae84adf68686858c2653c33406cda53eb3", - "0a032b462007c5c456c7d3e77580e013e964f4efdcb6beb480701905cc9001bea5c73ece93607bba451f8e593b430dbc8a23b8201eb89ca5a68b727171a8592264", - "0b08bc7fbfc7bafad222669ecdc804e43b2c50aedd127567564ec6907e68af2d6a79ac88b08c422327ad6f9c36a4e4aa2447d89dd936f789b339eca029dd175256", - "0a06660cf9a79cb3db805095c9519b8db3144e60d51f5114e908aebcf13e743591dff44bf8ffc4c0f1c2358491b28a9c2e65cc59bcf445e5a19308e24a3f2f6c6b", - "0a00d5b2f1c58f8964074e7a55eaea90bd8f55429e286b4f93da792a7998ffd5f067fb4cb50795bed20410daca75132655d27d6ec4592b0391652cf0754b6fe8ec", - "0a08a3e9c492dfc296c0b420561ae6775218eea03e4c2a55c7945a6b6d416398765b0541807b59fcded0d066909e6b1510bb6106193ddaec3eed0e27ec17bfa8b8", - "0b06612c7039d96f6f746cbfbc144fa00e52cfbdde54dfb5813dd2b619633a8ed0413548797f43f673b2a796bf143b74d7bd9f2251d2cbd4215615ba2782cc3de0", - "0a0852f38aa78eec49339e3a5e326616dd2fa33e93e1fc5df30236af3085cd80e4fd4c28e847ac964b77e074e42aac56f1cf58c27ecaf961d7f5d50c82f0bc5d93", - "0b0400a1b260bfddd40f331b628cb258e26f971f4d1856f67127b2dde6288b8cd9ad8b93d97aafd44f51410d732eef699bc0ca6afa73e1d588a327b7e81bb4a85b", - "0a029120b56b584a8c55043385946716ada8894269b19389037d20a6a1e494ced4d4217c819fad7f851642fa7214779de4493f84c94eff1354f67dce57954674a6", - "0b0431d479e1593c96930fb347854b82efe8032edc009e217e33b48bad7e3caa26119ba208b9cc01a2867e713cc0c229702dea78d678362aeab0dbde47b3810696", - "0b06cef038f4a2702112b305fd45954dd8cc5f91ea41b713dca20aac935629a5ce98e1250684ea5ad5fbedef2d263f7a4b85309fa1f7c8e7416bcdaefdac326a32", - "0b0316e7f03de2f30680032e328966feb3691de0071e971d6b01000a6b5add2e1822af57adcc3d91ebe223655274f553f5047678f4425f9b28ba52ec52e3ff56b2", - "0a04d027cf6df01e416e9bcf251d215358456319727f479f5129457a22f4c59fee866b16c059fb0b3d3322a67090d2c06add007052d723d7930a44da3422d66613", - "0a067074eeba33e54ff3c72c7eb28aed076920787e976a966c64506315652d6359fcc4d08f59f7ad4d28050050aca7718e5cdf7c93728a176e355ac0b01b5d71ba", - "0b032d20248960f21df9b0695afad72ca64a9863ff066dbdd5773e12cc171ea52a4d10e7510745af1ad6c1a707188b420ba4a3792958ba1f6db5e578b599eb0966", - "0b06f2f25753f03b3b06f5ce79d5487dcb609118bfd74215ddc2f8d9a563e5fbd6bc9c5a418edb958131ead42cca31e521491fcfa7a283455746b3428b7b6d84f2", - "0a018e41330d0df478bb238a552b26dc616a3828f574c83ce1d9d59e81d922f18dd86ac936d6df478dcb05d255c63ebec846a92716f1213ed6371e21c0df39b2d2", - "0a02b82192a46b8824ed36cd629df3fd43870162b99b292bea1dc1b03a96fc5dd1ab917b67f36939a1274f6fe636b6e8851c593ae1f5a31de458db66d3694446c8", - "0a01bc04cbb571dbc091a84a9ec7a5dddf911dc0660caf7600ba8501c937f129c9751179c787dee9d161396e2db79faf94acebdcb98ccd744e3473c1bdf793f902", - "0a01bfcd8b90e07b248c36523cad3ae464c44efd7c8afad41f9135e201d0d52acf022ff8e81b9171cada5e1ec288bc707eec6d607e4ed16f3e2a0d2d315790fe0f", - "0a07d1815398b73d2349ab97949fd0f93147e08fa78de05aa40089d8a90e666a76dfdea0e7efe9b4769e266fe3f5df2abf924d989ac5deaa8050d44120f5eade67", - "0a070a91722b064ea0c459123dde9467ae08723fc867c4d1d5ba4f3fb7ba5037345cf2c36a1e6a161c5d4b410bfe9d2591c83bae485c22d17177fdee5ceb18340b", - "0b03401a218093d7b5051b9d97ee0944a8dcaeda8e749a1fc61dc430fcfad338c75e05538f952098ba9e8c958a4a2e8529566ebf1a8da9a03c13a1d4afee807576", - "0b00fc69d28869e6662dc3f469180e8c0caf17242f09732eac3269f586df41cd89faa22a38ddff833538767da2cb34ea0cec05a2122553148a01dc1c1778f26ba8", - "0a08a06283158ba0b3db3fecd67be46fe30668701f591b41d7a6ac21086215b5bad7c3bf3a616bbfd819e1659bf36e69489094053152826b93f0606ac727b73b44", - "0a01871aea2a1b777ef9dafdaea9f050f9bb54d9a6ccc0a0442c983c8be5ab2e8b934372e0014f67198c8de9aa3e203ce949af45e93e5b75f98f14081e83edba2e", - "0a0330f18d173a130fb3768f90796aa663d4e7002271ff1c21ed651ad3cde3b6de1c90d309248981bc9fa253f0b4286ef7545bbc9d4ad22c90d66c7111c80cceb5", - "0b08cb21d15fb2eef8854d43b20c0bd798176e29cba68f0617e30f9e7e08deb02aabbe152e8b240bbbb5b809f51b02ce8dba30aab5dfed7c3cce887f3813f2ae8b", - "0b04be1d95720ce4374e3e2a6377a59b86a4a97886486083bb03f89f7c9ad866e14350fbbf12bf543bad401e9b645bb2193986f7039684017fcb73a175a70e6a12", - "0b0911ae80232a006134e3fbb2c4232c9785bbd5751326c7b8bf6333814966c9c9da940b2beec9cdf4aa776cb0dcabd72290e05f2bcd1cb90a4bbdb9531fec7075", - "0a04fe2d6bccc34ce4348d211693c5c54c9ae4e5421ba4c6b7231006f402a3cc243aceec52470c94e584af4c0ac255dddd2bc0f3b75d42488cb775aa08499bc2b1", - "0b04ddf89ba9ec8bc8a4b78bb916fd3a48622aefbb222e6bab5d49cebadfaf8aced5521ed8cd23035ee8e96d89e8e3e7850d9692a66fa484c1c2bb07581ac66356", - "0a033d3804cea8f86458c2d7e770e983b774cb5964e17d95b9bc3936811f974257eb74306264e49275b7ea34c9121f5236fee53b4419121009a1531ff6e9cfb9ef", - "0b00f5ecd808eaa59032100032cd8195b4c6c08ccbff062334c75b63b69f7100172a28de2d7effb76b421f450098b5118777c7f6d4417e428d16b5ea8f5a6cc4d3", - "0b01dc91499fcf5c5a435d335c0c6295f0c2e1b6de00835fe5f9d8761fc7baffd02ce46506e1d2e20fc2f5ec76e5aeba95c3ebd5fa6ef8e5d4164bbb758d2852d6", - "0b056fb818939e43f0ef5f4684c70e7273a20a648648eea312ae2d00de601c853b24d3ef3999c11d9243d6340d7596c5c88fe11662ea7f8366286c6b2d27466021", - "0b04925da95d93420fba77a460fee8f6f6b91b3e3a1fb8cb94f9897142da994651cc9cb54e2c84c93b665795d7e10837ffac33b75a7da32f22782d5d9d1b0b9d1f", - "0b002d0e35758d740d07d4c0a54d992a583e6fb6a4986151f3de6fa1c921650b0f5e63962d3a5e5d26204f51cf8ad307c7b8d0efab89563bfe08ffad0c4b462af3", - "0b037a1a44084097e45c09b5750928fbd3332546d372e6a6e95d46549dedc619086f1eb6e3a35403f5e2c010ac9a403ce243d64c7d5c84dd37afcb15b93d7c4ec5", - "0b023d3bde03504a7b135f0bae8c827fbf9a5f79756c0ff7d8376faa8c1e274b58062b1c7857960f75383ee3df5083558f3b7ccb986e68c473d5d0ad82344a1bbb", - "0a07e99e39a94ee017ec68bc3d2a54da8b97b1a7e4a426466dfa08c65ba25898614108e25cd1dfd88ff81dab83da2b83c3ed0793af565c8d6f36fe1163b143e35f", - "0a07d43c28550bbfb771aeb64a6854904894d0efac2dd9fea6a1534bbda305df9763c7f34b4e6a4305f1b1e8b6c744db601750db46d45853f81303abf97e271b98", - "0a0704b50374a7582691a380ced38c6a3dc04759d98fbeab6c55ca3375229ad9dd6e31a148bf97b526bfcfaf60d22e234117f45ea5ed4817bca2c2c0f082b970b7", - "0a067edf617c657b63517dc236e783a73d634bc2e8ce552080ea38e2100759117cc6217eda2f1e8b2c1f47e894b6d8860229ef5f05fe4e103ecc60753280f1338b", - "0a03a87dc7b9f75fdaa0d8aed6d89e879b6ecfec41d68b4b5bb0aa5673f8ba198039d36e3ea693c793e34fd36e5b7356a7d82608c52b84b546c9f44baa4523815d", - "0a051384d1be544937d7614a7568af4ef09fa982527b6c1b2da5d80f1ca751ca82e32ad750a9f71056a93aeb03ea42cfe3e5adb2678372dac7c2e1a34769ad845a", - "0a08f1b3e7bea35ef7a628bd938b5bb8adbd0cae41531c9a64625be95eb4cc7318fcf7b0c57a69a97b5df154b5955e5cfabb7b57caec3c9f77a4f394321b8cb742", - "0a082d2536315811dd7a8165a261357e6515894ff33b6617e5e4c090be3aa6e9bd38a07b398931e141c61c481d8e608338802e5935ab943f799699fa0d80364801", - "0a0466bdc5dc3590dab013ca77754b51bb4c06d2b9975423334a24e064b9ad61999529561d5fafe0009180e6777fe14fc7e104dcd87233359a2475e49cd39915c7", - "0b0531f883842c9861f2043979cac8ed0d1276511fdddaf6be632876edea4d438f9b9d55c0ab2e01cfaa6ae95ab5bbf9c8c3be209c810da8795c3bb205437bad11", - "0a03f708be144fb52f0bd5539431ecea05e2b6974f4423541d8b9237957da99ecbbfbeeba6476ba117c4cbbc4690862dd6a6e2fbd9e7c78ec1e741572fb7c23ea4", - "0b085b5415e355d9a8b1ff8604f8cc75d89966297d30ca57e1c61ac8ced0a33a3d752cbfee54f41ba58ad103e2e15ccaf8dd854cc7a37bd76e143933b5374d4093", - "0b0369381a5f9568d0d4ae80167fd506a29301860ba6255cfcb9f81bb9857d15fccafcadefd641807d113a18fa7ef56e508eef78273e8191d9e9c0a7bce5c62a20", - "0a062eb3531a5d473c402f79f662a92946ba95d769d035ec31ae495a02bfa8c81037f7414722e8a33f285160c23b6532cb35ee87cc106b54ad04c75763dfc56531", - "0b032e0e3c27a14e0313b1978f5e19dad851d41bbc034d12158db1b07edde98c0c7915a031369de588b45fc01bdff2f9d364743fa9817645cc60f54b7aeaf01077", - "0b055e1c5aaec8f720a6b3fa3df6fb1b5bf1f4fde9d05c76b93c6545f76dbd095341312b9a0d55433bca8a957be4c016cd933750c2dc6cf64ac34bfed6cf13d380", - "0b066ca15cda3955dd9acf4ba13b972391f07c1a21d0779428335013cf0fb069b4e169f325b9f0d25341a780aeb8102d2cd38d3891f290863d0395761449eb5b45", - "0a07e7cc7923ec1c3a60ca920495ef3103df4890cc310fd9b7739619889f1487c0a6e456e6692b77e4e9d99e42f78eba8f9a668019ae2dbb6590985ff01081b25b", - "0b02ec81da0650215c5b5bcf463d37e159c0cac3e821e9687db4e47916acc69e581dd32ac255faddc074235c4dd077d38a13f44a275f359bc0987006a7dc6a0c14", - "0b069dc827a256d3763906faeacdb8265c599f7eb7c256592808bfaedf95715fb7ac706f38c2cdbf9793f98c4d9278d1bcaca26eab4ebbd8df5da1cd51e3332cd9", - "0b02ed06d752c540d785e510c8a3097d34cb14086b815df13cc1cc722ab3e075aa6aa1e8451037dd75b36d6cf0be10986914fbe386d9b3ce3d9e5b035e800c17d3", - "0a06bf29a72a90879d2bd669599571833705263af93523c76fd54b108e2abde1fb4703004443edd7c4ff944b044e00c88383f941ac3dc22a801afbbf23941ffc9f", - "0b05398e592e0e077e765b72d439740e214422ffc6f3e3dbd3069f90f7a085b450147b310368dd4e2f78a1c5fc6de66a006da42f0f4fcb5098d0566c8f4ed21087", - "0a0752f6c9316d7c02176bc7c4f1e31e65738cb777ba91b62e98c8f746acfb4d23c294960aa6a74acd1f558b4790a9b23bf1140530ab462762cfbb4062d4b5f7d0", - "0a00d3ea5e6bf6a89203138ee21b190a029c5331c48fb01b985d688195d67d6b182b3adaf5e1e559ad9f856ceb64e6cbd28352ecf585579d1ef43c0b728647c121", - "0b0455a13411b884006f3f3af36bdbc440d00ba23c4fe01a292fda62b60bf6196b5a316428b0fb20c5567d19b8324afbbc1f00f280ec2a8d76fdd150e7259b72a1", - "0b0529a97edb31193d5c14191f6255dbf0c9a11ce655409a640e6b021ebc2b8c8eb8afd9aa45d84991b7a647718fae06cd9f1f749dac47f62e7e6bc3b6a4de6272", - "0b0184584b4a08f65a7f6f38f9501c6889c8cced0928f63b28dd8c2b133127aa3eb292a535e6b83f1dd37471d8ed1779e96b6a4d57d3ce2bac4d6b98f24d661082", - "0a0375a3d8c03703572ac9ad9948ca8a7dc1f918bd6a113c85da592665436cb18bd2c08f7087e751da4e98d839dc9e3f2126bd08540d25122033eab7744b3f6cdc", - "0b0113867395e971e072b497fe27e25c32b24435794ac1f2862f3f35a324e6d5c713d770122c8a3438c2456b35a4f75e8acff31b1fd688096046d065ad2b10f034", - "0b00286f01682204b7c6fb9dde4335e4be58e7dde67e19a99e8f97bf17af6f25db6e920fb9eff01559700d9c3680d7624377679adcc179a94be01560e89320a0c2", - "0a0159cc52543ef834632f264cbb5d67fad32b75f49980575e011e3ff06fd1d9f76f51126f74cb7b44d0c5561dafc00481505fc4738c218be4dd497f4a6eb2a36f", - "0a0555570f653eb41b6f59893e55afd7ea4df1176a181c283bee9faf20d8ae4c733d8e4d86e85d35b49c8a421d2776f927b8b6dc049bd860faad83cc86cc660a8e", - "0b05c2755a157c11fea2dea745c0d62ea14f133da8e4c62bb9bb9a8f3b3e9dff0b28771dac411822d69870fe21b0df589b4f3812b86cc910c355af3f7aea50d4cb", - "0a00848072d0f1806946d2324d39d4a042e8c96d2fb849ea35d80eb5e2830ea7c4c2d5712ba89befe0d42eacdccc6ed172bf87394934e92a2916e5646d38552a32", - "0b07e2b6c996c3ba13b969a9bde1c0a50a5ca736b57010cf795ef0b0d514b6c9b60b7ee10f5898ae533feaff5e69a554202d9b0a4de78d98001ad370d7e02a1934", - "0b022b4cb7eb1a9bb54e353fbe2412e0f258fc588251db5192a6551735998f5e4d27397d44595e9f11a72e538d9bf3054e3f3aa084b63cc48cb2df729cb6ce0f88", - "0a0117aaa0876bb1ba986d31a0e717271e31d286a0fd048213fd4ae396c0f7b23569fe7782b7810c49afa0b60183a6d4022e05c69c005a8a8cc49587a1fba19bd4", - "0b03a12f28b790c79e143029da9a685849f5e830441b958079bf09882d1ad56c43e1c131c520c8768768de81909223c2870a44e43168a6ba037aa8e7da7f8af70a", - "0b081fed0aca3d953c80bc36029a3ddfb0f861c8cd713d0cc0d7483600a9b71b1d660439fd354517c5adfa798d14c248c9af2701bf67c24a2ebb0b041b6f63b88d", - "0a0780fdd4cb00d84d2a635dbee1c64a5c8a8a8111d8bf53ce8917742cf4646b1e8ac65a335a8673cc5fff8a4f0e4c3a4c9e5e86930d63c33cc978a908584e825e", - "0b07507ea22c4887f11c1b0a6d16a3951fe442883caad010d5c0aed4e1b54b02d0a1324ffef5c1c5a261e39eb3324e411cfb0490f7bb42baa34504a6dac44ab183", - "0a05db990d072ea051bbda79dd98f752f96651d846136bce080346600706ef03b09b6927c7fca70d6faeae1823b9783f571112d7b8fc0adb3e9d4ce50acd2b8677", - "0a079b16fb763cda8b18e7cfebe31b3656f529d3280ddbbd58ad83134f64f1256fc832a32413ca3766ab3e6440230256f6e18da0b5a635aa7e00dc75ec9ae69b65", - "0b07c74478688fde54b7cce5f29506ae28205e96edd342be2dd6f314bc18b4af729a9abf40259723afde4e457fbddd6a05117af55ead282bede4e9930e89c7c1d1", - "0a061c04dce0dea46cfa0eab63edabfa2400bdb7b0d0205f71cf9d7369f28b7e7e1af8d1fb36c9c7840c417b86fbde356d487fd4df6d3182e2a711b15adf7a53ba", - "0a0876013d89c2364cd46785bf9486e78bc7a7536e18f5ec532b05e3062a8489825a22a18541847ea452ae7603e025ec55398b5d3bc92bf1501cf33361bcee2a52", - "0b04ec6a913efced07ce2ec38d69357e69777fb583b4eb7d7974142fadb60d11ccad825dcc70deeaedfbb41a9706759b08a98ed3bc72bac9bbf4216e620a4ef509", - "0a00f6befbbb50b712ec0f6eb3654db8dc99f0defd565ff3af91f3793c3f294f864fee0f2756ce51617a779e53c133900caca0bdf9d79d05c9ee8ee2a967dded98", - "0b071865f93bf9f4e1ec39a6af94e6c47ab9be97b16464ac4d92a7ec6322e4c603685e36a3f913bb14c6cf463079c345671f9def802f168174575b84f3ec78f3f5", - "0b06659eb765f7466d4e5147cc5b750c312362533196d40b3cfbed1a308a4878cad05f4310c4246fd9d85fe4f91062aff87a592550d38f26b729506e8dcce15420", - "0b01419d26044c807633ea036c688e71aa2ff447b952ad2e382cdae1041bc85151468e7adab0d95337727c4b2f979b54e0a9c8974e5e55b1302ce71bdb49cd1e29", - "0a0382d20b45f343091c16def98c73006058e983ea8b16a01bfad1a7a358e9f5975ab026adf1dc206d16d9abce764ab75924e5901d9e7ad5ca89f64c4bf78d1287", - "0b0065588d948e7146f80406d727a343804377d22270451bf4d51de72db4db2edff034511fa7ac7ca524337d37abe5ace2e8a22f7a70ca982c13e83b1cc46e1b43", - "0a029bb5c8462190e1e5242d1bc03eb6a5cb6440f75a28e5d6578344a98b8c4724a89e64be1be706783703188a916f81a80c5127059be66a1135127e25562d4f61", - "0a00aa5b742ef9bf1b99fe6a645eb020f5e2a58955181c1c4070b319acdec057cbea01ea41fe4b0e8d6ebd23d8c05f4c3c78f8bb1e0656d7d1d58a08f11fc3841e", - "0b0313ec284af8fd05a17200f5aa57c2019655ea177d76da6cc5030caafe5ff4bbd33aae5c2075047a046575e33c4c49fcf01be679ae6e5cb0cc0d176115f12d4b", - "0b02dd6d4021c9a98689c4cc1a8050dd7d7119cb7127637cab50fc899d925f68ec293c2f2d10300b875d0420bb465e6b2c79cd433023b9325079348b826d203da6", - "0a069f94dba6ede7c00e1c0f8ae0722256adffdebf3a2f685c299b8f0344ce33bbe09b4c5b04a7ada6a1ed7a61b2013c54b2b8b9e89364ba68f8e9e04121ca4fb9", - "0a08b2b0d36ea08f34a62a015339fdb984484522f60a0541c8f5e5254a464bf32d328c300b3746ed6b0f635105eae561635f7a50785ee55d1062cf13c9bbd0151a", - "0a05bd12ecd800c86084bfc4a507489565a176035f9b9711c37b7464f72d1cd8c0a8b8c350b15b34800529196d102d9241680887e764f3dbd2f2701323b02c26b6", - "0b03f23d7bece6423c7ae4d020c848ab370d02c502d6d6fc218856b19e798351e627f97928fd9034febdd03215696111848f2ec173716562cf0f6a35befee23513", - "0a0805784d0c269db0ace5845cf3ca0f39b93df95171966e02f2b3d9e32a2e77d1f406b72b305bc34cbee5d5c91d0e12d8a67a0d778e09fa0846bc879f0c8e52bf", - "0b02e9bf9108ab735f56c1791ffbff82ed2f0ab759326eb3c74d7bcbe9f646e12d4c62cc38fc172cc3629959d38216f3b588c6c225904cf9fd1318cf80f375febe", - "0b07471d3c9bae19b54a3b3c528563c45d71e1aae288a050fa90286393e896895b7550857466933aa6cfa84d9ac3c921dde4cad96842b4011d9e68f13bdc5f51b4", - "0a06f6c795d4a2dc1a0b7dd92c4beb03fbfe0e982c2683f53d702d0022308b662594c953a5e44aaee997cec00d3565f007cf3f367c8933463da7d76f865473b011", - "0b02863c2fa93b7308d8dbd0bbe92e6f19e88f5b325f6aa6e0631d0f28b256d0fa5884bd02d384f83d9b055a77b7e81604b0307784e31434be0cfb77d4f79f9c1c", - "0b00401b74067656a4c11180b025e328eb53390c2968e77e987d3d7cba9be6d564ca60699e27bb55ed27b65ae3117893139bae6b77229b38f7ef407d7fca6d15b9", - "0a01fe8558ef387fa2a582e2af43a1b94a682f2a0d4e71a3804b106129b9509b2628b8d24ca2b546f7d8248604d54860a8adad696c391be6b485f09f3b6015409b", - "0a04e211b8920377eb6ed65d02068c5726f6bcb14129280e9d36128ff2b93bcc9eec84a3655302461b4831e58661516c9e0c40f2ba75daf2d0cf94af86507ae5a3", - "0b076927fc73b0ee34910d5cd0a77540bead9bd80ecc97ae79b9f5e632ce6ded39b0727f4db4a80b2089cd0f82f262c1f29f8867242f31c7f3452ad97656f911d0", - "0a062ca8869be4097e3ace48dbefc45265a796bca641a4c2e3a1beb4de346a953dc7cee1d0c6846d7d127243e05ec59bf264122d3af20bce25cb4dbeb64cfe2d92", - "0b0906bfa188fa376dcc6b613798db5493f03a475312eb6e8c6d41c60e1aa477f25e4087f672193fbb6146584c6bb2c3a03d464fba843576acc21259e0a7e17812", - "0b0224af75feaaecf564dfaa76f2fa24e407e28697363bf7d1e9eaee67cbcca495d5432fd42244a4b1fbd339fbe0ed5b0f539c68dbe7ae27d24a1abb9437b7dd74", - "0a066c305cc3b03afb077911bafb30047f99a37efc8e064ca5633e7d7d7bee41a18cff4e5bf263ab9f2de38350f0bd4d2ecdaafaac38ed29888a92e5b86292ee2a", - "0a04126afbfabe24e067cb7e73af1b466506558eb32fede9ab6db2367292d1d55ef6269d3076cc1532c1ecbecce440a94129525b7d0799987e85e4855e9805685a", - "0a016059cbd422fe0b7c49b55f7674327f61d2e6d4f37822d9a04583aab2b78c0d6ff7213fd8d5b3690b11df5678225356f22acf556a7101a185fe7d46e24ff09d", - "0a06454ba8c4aa70d0840e5043d735f43ae5934bdcdef7927b771ab0fa0d1c13c781c2e23e557b478b3e4a52a69f823d4d6f5d9bc416eba629f6c03673436d477f", - "0a008f82199451bfd5e23954ddc90c5905daad16d41a12d2dce68ecf1df3dd3dec15992a2df129823f2ff3941095011e7269b2c5829c299010be4642894ead4572", - "0b050452d6ea28dcdd51f51b2b0e35047247c9505ba23ff136448ad816dbc1f961201f4f5596dfcd14ff292c572dd34d066cf4c8661359365ac2576c5efb9f486e", - "0a000fa60a78614d91f4f2d93d51f3c075ee358d5392c5a799c632908794a0f88195e89a6d6cf5023bf0e34f0709ef7fc8b2632675a2567b91c7f4c25d263fbe6e", - "0a050dccbc3dc08cd2154e5dbdada420fedaaa965841ed844e01dcbdc5638eab9e3fcdb27abee4607f59cbf117046b457420d3c23b17c968a673b650f7fb994247", - "0a05a52663778266a5d439664cb25692a2430f94e96cb13ee522fb66169efb3927bee357d4e9d2b314954836d334c2c9c5c0f0f06676c07d68f92ff716139baaeb", - "0a01ad8b185f340dcce3631b5450607c441c1e67db6d88eb0a5ad8928eed756f1e219e11e06016dadc1bdf47a2865556e205e524e3f75a1452dc14881e58a1b44d", - "0a07473792d6b9934eaa427fa72eb24c511fc99d1464d95ce135ef6d2486b36621b17a4c63393d9bc05f2b2d71163251f1e1c95d720a3fa2cc483cb5ebe85622d0", - "0b0018074dd054e45835b79176fdea28d49699f7150fddb2c955876ae0b19a044110f34404a164e9043dc416a16cface00e1273b8911c3b3c749a9f02c89266ac4", - "0a02f646acc48bb2350944ec161d931d6bd32572d7319ee7b22d813b613da8c3fc8c3fe462dce5ffad2a27af5fb88b929a59302da84bb9eb8bc591157e8a832636", - "0a058166f8bb9a4c09af929a2887922fc750296f15b66718de69c7be3e293cc412a6d48aea7313c34b31a85ec1452cc852b106698d74209dc47831a32608399f7b", - "0a00903165ad38b319f55a4f5efdd309926135fc3ec7b78396c23aef5f5dae849eb5f3217fc66976bf02197bbac0b9aeb0fe2ec557e82c8e6660cc4baf9bf09bd9", - "0b03f2687d42e934afabf5cf8359ea777d3835220bcf08a8f67c87ec374c43814126114919590b93ed53b39ef80fef0cc412f8f08225608532deb34d72339a83f7", - "0a08227fcdb6fc8efb730ed4cc1525d8cf1d1958e5b0cd1929d2b739b289a5a2f25aff7700a72154838422d53bcaff8b5d4e866f495c245453e860c5a75a578b60", - "0b01093a060f010b5da7ff2ac0cbf1eeb2360541786fe50c36ba2f669ef5bce82845ab940c1dd5ca9f907a1cf62d6dabd20d12c9ddef84ec16332fdb2c1e750f7a", - "0a08f167c270d10547b6578e7ddb1bb904eda02216f214915d53ac74010cee175f4426cbf4eb061c98e253ea931a005cfdace2f598e8fc49dcfd03e405c2aef482", - "0b02b85494c0af9edb48dbb687df6edb76960a4c3b3443fc9c4e565595b1974188c4e9d1e8e4a31af1884a141a4d35f3293598638189b41cec4c23a95703f554cf", - "0a07dce818464a0a4bfe1631a500cf65802e81c662edcc72a1c8a4431bad4b41e90f1875281f534e0aa08bb01a743a62a195b533b5af67c8ed023948680d15ee1d", - "0b04580921aa006b7d1bbee47c06cf48bae188b5ed4fac8a0f24aedf9f5035d99d63ee8c4bd2605f03d07d1cf964ae6e366530160834f366951f67307a165b1f2f", - "0a09224872e1f99d04e9eec1e6684b7e1984489ea03057a90a27e25f8e01cd157411f514e52893fe5f78f40e4caf9fa3edfe3b6d2685e872e74c83ed600a26fe12", - "0a07b97ea4d3a89b837815b4632d4fe5f129ea4f6c14ee3b9ebbe3dc8f1ce945ced38bd5d9bb804de69b1be95145e4935f5a6226a308e0c570926359d3276016de", - "0a03ea1400a834f63a468f11f25984b1dae980c1e8aaee719126294adce04e091429bae557f6dab622c668637d218d97dd72ec465e2d372501cd95ef5b576e46eb", - "0b0330f09abc521c4d31d246f4c48fd12bfa5e235f0e099be3665b6c61fd379aaefca9a6be838658b2c740e60e71c3dcf547df3b9ba51cf123affa052dc29856cf", - "0b07860b3d1670d80a325df6c216aea6c08c03cf4915e1ae68da940210de4ae23acb22ebd46ba1783d706142b34cd5647243cd521ccbdff6a1a47f6cf405c21cc8", - "0b020d04a99fc60e03c49d306b4b5399475ae5461fd3c87d1c15fd4eb9b31ece8858fec73bc96de7bc5dcd2be4fa642dc31e11741148445145e39356468bff250c", - "0b0332841c7a871f8e747cecefceb358eeca769532810f720125cfeea3a1f9f71f62bd3efd66e82a2a9802eb25df7d97efe81eec27a9cce968f35b91ae8d21c946", - "0b07d153ba629cc9bf994ea6dad3b0313f24db729144088fe6aa73224eacbc6affe0245e9d6df533ff3c09aa3a3b0145c58ed0c6c4c3760fdd395c210fc0b36efa", - "0a0299db41eb798c9f8c27b0b126322ebe706640639043ac7435822c02c3bd0551d754a62b1b2de83d5072e81a0547768cfb2d4114a3d3e0d1c84e40679431a874", - "0a0340e02636f08c4a05e4749b6f1aba2c05f6cb4c1c96992ce0e06dd1ec2993a9e946d7a5b3ff0be4eb2ac56f3d5c851cdb3392bb615eff63c509ed0d83e7256a", - "0a0150ab2f9663724502e6875827d0612bc746bc775bc48059b6ded868592f132561b024ac9bc6b08ce1a5cb98f82d32c41620dc679186e3c40494d9609e81649a", - "0a07ff79755ac55a83b6609a97e17a77341ea10f9c67f13c43420a7e854da97f5a893ab7f533f5d506b00e856da338ce1ed624ca770b8a022919212ad4e05008be", - "0a0072cf09d67cfd536e23c3f854e8698e193a470099ebff0f5b341102776b4e9a6176b658a76aabe1d18273a0e221655d3eb8a9e665c116eaf2a9d80679dc6807", - "0a04270a8a9c45304962cde9b3752542354e1d27e4651e7b4d24e4a68d0447a7381d9c95da1d49a214a9b0768d7882d399e9a9031e1e90bc2d29b9bec9aad64d3d", - "0a06db4f6d7cb1e044bdff4d1a3fdcf444d5a337a8a1237c455ec6839ed359eb3d71c0e3d5de3dc1cba3188a1a9749edbc7ce2bc0b4cdeef3b9af497c304b0a3ab", - "0a0246232cea4307dd6b02d3a98fab3b66320cc16a5bab74a401326bae178fba582672f72525bb74b6642a73a41b134f1690cc4034e03bb23287b0729f5469a11e", - "0a05619afdd05bf45e6e0bcb78ceaef31e03d3c987c310c1b539dfc93b1d39e74aa06e9fe65558c72ea17ecf8a90bd9a6e3412eb1bc39dc0687c4d6fe41f8b8e5e", - "0b078f840ea07e1f0dd8b59b7b57f1b7b2f6364e02ecbc1228e8f6eeae37d0048567e41ae6986415ef610c5f6a97f778681889cb6ad8421d800e54d92c3eb552f5", - "0b0468f427bde4e174e07596023c33e3b1a04baf0b4424f6878ae45d66fc70b58ab5d5cff5eded7436417f73aaa868922160d0f2f899ba338fd8772f3bef4d513a", - "0a0679b793c33e144e5da48970ef4a7eccb37a6228a2d9e97e0c3d2a3e763d314aeff622109b37cc1e74aa16b9a04d186ccebfe7df220d3db2c0b4c42ced780f49", - "0b03102876be102446225d909f9689727089c12724a899484b2a59dd087ba5662b99cd0750ca3ddcc488ed5c887947fd6a057fd04b9bbede5e86eef04b7aec701d", - "0b01aa01c9048ee15d6e6939ecb0f6d1edea4a1f60d9710c039ddc540b8c10c1c310cc82d018de32bd8ebdc80c1a14b81d12c3f93b789521b60e0dc6503bc768ce", - "0a035f7986e3da8716d01e20c94f749dfeb1528f61a288651ce1bd57a00847ec008325de3f733fb07f6e6e199b9bb2a8451633775585286f52d44dedd5f62a8c65", - "0b03e6f90dd52ee258d46be2e51fe40ac3a3f95d9c4b7688d315df32921f640314334c649d8982c8af3d01cf1a5eb2d9fc9ec2b8af77877800de39c190c14f0479", - "0a01c5da1654e83e53eb047172c7ec18ad1c0350e921e32d75a9eea6ce79c0b78a29698a759016585aa46aa63fbdc21cb790f70d091489a5e3c8641debd96fe8e4", - "0a0770f304e0a4532b223a3045868e2a45d6157e985b4b63fcb3d080f875e364b9dcfd502e16e94e7c990be1d403d72dccc52445fef10fabe009144058b9c891ab", - "0a081dfda13575ce549272189cb4fb2abc2586e7e5050bc1a1149db142b79a45e25bd90c2124a8c0cad0a56993b40ca5041ae85b12b0bb233ab89f2aa56d5b0bc6", - "0a02efc8681a15ca52ba8c76da553087f8b3073ea8a63f05cb448ab3362a3c6e9562bf61e5cb32ca1efe9459305eb4d3ad12de2e8c81d68fc75e3f0d9e01e8e71e", - "0a041845b46253f6a899f60f42f0c22ad4a1cf59de757609ffdcf02bd49e4811b92079ee489533b38b4b32eadd570cb77c2e3bed66d6eb750605a979ecd25dbbd8", - "0a068f9237f355952733b3efe0b4987a396666bee345c3acdcbd37ec8f9700163cd9b077b7d37ad12b8045673149a9a51a24d0a34a75cae20de486482ccee35ed8", - "0b052f78de6a34d0568dc12587ec290a6866193098c222021be0f59280c1c3b5f394f5225f816a517368683c3e355fb48da0294d65c2290b200520f1713055c36f", - "0a0584cf86027f0d47bf31dc24a1c892e302a82a6a26a30d83ec3f79372a62688e31aa6fdf5e8818abb2a31b3c895166a75016ce5de4bd3ce83b0c8f1e930744b8", - "0b02ba7301c284bad052cdf58750a1b3d7c10662dd65532678fa049a3e38db2a9ca42c784177d90aa79f7d2c0a2d8b8ff9c16b450802480d01c69dd48a9303321d", - "0a06620feff8a3b800f34313c8d6c949d5e52243686279ec1302de7ff38b3e1120e02ba2fb35953b93edc10953a4b7ece2a29934b7917bf73089d9fe52680b6c65", - "0b0059060203f84d121bcc31461ab94d1157b170891bdbd2f5cacf6da62f4bf72ae4b22cd6e7dac769303f433d77231322179a7016353753c0b1c3769c78389151", - "0a07ea4867b9c92774da7b1a40c104747e2381be65abd9c17265ab5c643a4da028124f5201fbac094e3c4d8325cbd457260b32ae08119825273ae2d0c072eeb562", - "0b03325e9e455eb771dd1e58438d9118d07b6c5a329348a352bddd7e90c81e2f5239510ac0d83e435bbfe97798c92616679027bf6ad31124a63e8505a52e7824ef", - "0b04c5c5d2a790b62c74762814a012cbe6ca2c181d6b9c22fc9b3dd16dcdaa2d434ba6afcbe80e23470e5a568623e0947ac61d066c024a7eeee15c15c22abcc1c2", - "0b028ab986d3f8c840f57115f04e6c879c135a6c80479728927efbad85dd59b6a132f85bde2a674c37bb1cb56a7fde843e3fcf862824afe59b55fa71ff42462b01", - "0b04d58ff8d029564cf43e9c5f6f718f009c0d8a4b552535d33c0c3a196619e6e88f2102814ac0119f3023d0906ace24a0aa21c3ccffb86470009e161ff963b12c", - "0b01fff9a62006afb63bbc032b3592553adfa9f6bd7336e20d02731fbbb122d705061c47aa7f90eb182c78959059199caf022b4857d703a0d0cbeac5d17dd231dc", - "0a06f1330526d0a023b32c7f8e58679f2575b7b75b21c0c8396e3cab1105235b97b08320c6691f52a68c6763137ea3301c2a38a2dd44ea8a9dc0f5de395e8d84b3", - "0b017f6a6ccc462b2ae762e244f81deb2414b58b82a5c9f042484acc797e1bb82646edcbfbbfa06e44ed5147dcd0b46456423da04d9a393bc18cf7e6f24ca9b57b", - "0b01ffc265d19e40ff52417d90691eb4bfc36161fdf5c0b37b898a86a5cdbd11149cb410ff48e2e498e1d9a68040ab255382781f07b0950be64c92cc591a68a46e", - "0b0911b3d18e662e85cb566d0e12a352d73487c850e4b14dfea7e70d17b9a77480918163a2bbf6aa84ba0df0e6f7c04de68c9c1f00b28af70973700bdda4cb1e6f", - "0b047244710c62c4a612c98261de2c70e0c2f94cea1eadb1884a7aeebe7e9e54420f145c715d699f11cddce191b79d3097969b901bed7a27d18720f141dcd97f5d", - "0b03cd3f7ccced81308b729ffbf23be38dd9e50f60bba05d32d6eb08054e8484f6b8f5e6a494b5b30d084525d1416eb698dab2f6ff1c85ada5507f4e2a67292198", - "0b015709893f61edb51dcf33eaa503612e4de57554add366e1a0f61de94ea355bb923b8110f0b37295724dc2f10a63f124f6646b3b93600017ff941c986d51a380", - "0a03ddd0b065e233fbdfb0ce954442fc5ee01c076ab67a257f11e855c05c2a23189bf5f1305bf3e88c672133a9bb9c777d8754abf89a1b99507543e757b0ad11d8", - "0b0082f5708bba39194e9b6328ce6a16d800343957f20dc00d1f90363a053b26cdefce96eac152dbd556b40b0d6b11dff81320336a33eb3be444069544c52c4ac0", - "0a04f5ae39b85458a25685f2bb52dca0006ef843dbc2b147d88802262516de4fab6ec40ad01549b3b8f401422881111c78c92e3a903b73cd6ccdc513b3e5d2e2c3", - "0a018eeddf43cd9961c5b399aa9f22405b3ca55d05e18b27cd57287252a2c4c3f9e91c48b1c4e04e1c4b77adc88f5dacda822073d067d42df2ede49f7c47868397", - "0b04f4b8fb0ae06390d4c82061eb4b4efaa4ca58a5b5ca6c9a9d877ed52ece4eb62c15fa85a8e487176746d4ecc78e068cc9e8be40b527ff571a8abecfcbdebef8", - "0b03ff514fdda94773c1e02a2339ac04e4d916bb5c02bd5f2a44055e7eaf2e8f644b2bfbe0b9633f68dbe1ca2b773ee83f4d201040a09bd0b8d33f5b63ddaeada5", - "0b01378a1f56177f43ce66cf1e25923bf8db1ab64ac4d497b749d22870b79e20b186020170f63790549085e909025847c1f5b99a91a0eab7f6201e1fa21ad1f83a", - "0b0522709253348ad266db8e7c1296bfc9874a04c5f092e92b09a1913fe1c4a4497418d0a355a3aabe59790a706a3f28d9ff034dca9ad9c73de0d0e9606921a22e", - "0a05e407a459ed6d12e8effe3bb110e096c8e6c921a8dd96c50da93f20f76107babe188dedfa51081069e2bf730dd01b775684009f7ed9ce414ed51e163428b43d", - "0b009626450e2a61090e89e683e909be45175b2a1e9c7d35b8a16dfc3ef22ca2ed7f2eadc5b22807322b27269ef45ea84407026bf071a9bbe8f5f633967aa0bbaf", - "0a0025d68e8ce9a0730c47ecf9d05eec61003a704d6b3e0f9540bca787908aefaa0489c3c6ba2f8fb47844de39f3312065a92a45cbdbf93bdf31e2c4bf4925673a", - "0b02aa4dd3b508205e7a0962b9d7b22167d51a04d90c37d34baca3733f6feb6eccdd85f934b06a6d6d00e093fa5a28cb3abe7c2ea2973f6c0a12e300294c0a9f17", - "0b028a2920cca4692df7d495b54ccff973781ab57d7d09d1ea7003259183b65d50ed348a381210a0a2fb3a447810c7add22f1c7ed4e9613512cef943a95e79f1a0", - "0a0638f15bdf0dc4311d74b71e95eae0cb8d4d00e5b14b66910317462e998139c254b7496a7e973aaf16274a73f2f28f05b533168dc84456c9769082d34022b1a6", - "0a00b12ecea464c863c2c9aafcd87eddc81a443c24cfde51ad4e752e284857b3a9297a625cd98f4c5c62b7b5618507ff3368a5b8ba20c2cb3ae3e021e8a07a44d3", - "0a01dc35f0f2a9008167fbefb8d93ec6b371730d53a606ac7de8a79a6cb666f90c94ecd3e420ca6b6e35b1e2717656850a23c7b788e340c297bf15d4b0fb5dbebb", - "0b02a653907ca0bf19dd61b9f8aa6c814acd2a4d631e0941d2b5de156ae1e3a2f44a611309d7222759420663110cf7926ba2cd21750f37eb9cf658211681862e7d", - "0b010751ecd6fb807f66c2a38c4c2d9a92583abcd25487fc9de4ed5f2cc27c3eb31ada75dc7562128241ae0787bc9a6cfb60533ea4e18b71d5972e5b3648e5395d", - "0b072b9285247311f99fd83ee4f2ebead984d87870726dc6110455911d2013022286e699ac1261a388d4c429850109db88a828bbebe8032d5a6859ce51125a70e0", - "0b073fbcafd6dd935996ac3d33eaa1026b4a30a52679df94ab3979779a7f8990c76081e6167738e2a3d19b59ecc407d98e4bb63782a1efd1ace2515ac956c6b042", - "0a01dc60f780b14fcf3b991be42fcc1e6c80122daeb6dc48fd7ec55bd499d2eeb9f89df054dabcb09c003a94de76ec339b32eff81acfe8d3d809f0cab490884bd5", - "0b09185492e1883c1f2a716148bdb627defffcfa9e598801d1c9212179bdbe5b666ef3a69c3158f08751c943d3c524af45fe02edeb60c3850f14771fb71a70af3c", - "0a07ffc2ea42f5f5fd6bcf3db0f3f283a1fe53fc8f0f3047073a71507ead72e37274cdcdf1fd9086f6672fe636de134c868014b0b3961b8b3e4cd6b522474b8c81", - "0a018270fbf198235e6463c596ae94d5eb3cfbc100720570810c0dabcd6cecc22ad3123ec79bd31eea898ceb3a26b4bc1e804250114d96b01d4d0980f8ca81bd95", - "0b01c6c1ae2f4de833643363b0d8f7aa243a13001197f6fe2c5b23730401a2bb5e33056cb031e592b2219978fba57fac334dc271ec5d27210c22f5a3e21e40a369", - "0a06645a87b6191fcaffaaa35e33f0da11004ec5e4f3e4a85679a2e0384f22be68c35cab913ee55e186ab2041791e2ab4a4da1a5e87d6005a0de6eab625067d248", - "0b0841fc3583861dff8567917a14511e15f7ecad8dc0b3cc9d747b34505c80f66387af7cf97fd23bd2e9fe4946fc5dd3ba661dfb655f8aec7f1d6c807a7ca8d3f5", - "0a0439fcee8d158f5935f4b8f0f5171a36fd93dfaf470edfd3941e14772b1fccb782cb6563cc00812a3cb11d2059a075ff1d65dd5ca55d943daf5ac8dcd8f966b7", - "0b017a8ee77eba4bea3963cb504a3671d3e0110993e9b13f0f6df018ac7f8f9b2c8a1afc1169fe59ebadf375587b84518426bae918c204ddd3f08627732d3ff775", - "0a079649d53a1074d6faa266cea903c4ec5b7037a7fe8bdaaa19502e5c1052283d91fd344602917b31b9394f04c01259696b8068d7cdcc53e229c7edc5e3633601", - "0b020ccd708815a775f2c8844e0fabd09667ec1be6fe41b87d85bde77446b438a275b59a121ba61338649feab34cb720283e0745e0eac9cd5039ff25d9087a4c3e", - "0b008d356ea38c7bf8d5cad8102b53c9880ab15c75f18694b8191614d2f74c39f6e265f5a6d97d46a732a7c28a4bf3277b1772278e12216472e26b124d4042cc52", - "0a0117ce4fcd5736b95d7caa9ad83224c73fd899710c5746110ebe9055ea62fd71918280b4821de4ab2ec1669051f114506084e8e5e9c07ef5a2bf49d7bf3deeae", - "0a061482d68da4c94a93fdd8caac940c74f14867ded4868cadf49601cc0dc9d6a0d9a94285924460bfc2f91ecd5c3b0a064568cbd56b3cbdd8436f7d2851556378", - "0b051a8183db4643e6739688bc66f9289fb2b4a3f8fec64446c78d34ad49ef05b9f975b1654cf54c40d749c1e5234d9b4ff7a3899c5cddef3e7a82324a723e9bd4", - "0a05352b358ce612c290af32819e8d7665bbf1a2098604ad22c1b805410d2311331a7171d2b09c4b7830235466b6db8daa8fc63d50d15fd6f84f209a8cb501354b", - "0b06a417645a56a1e26a6325cc57e09f9541455cb2119f5be22f0603cadec73c9f285824bfd62ce146d84218e2533fe9c6c8ed34c501f33afda03dc087ae1f66f9", - "0a046bd15e61ac64b866e402493b3f63df262f297f420754038a61fcfecf563d3d3ba6b5636d9db705ab839d577ecb6128505bc151782c7ce978f5d03332c5f7bd", - "0b04cc1cd17b384f4744215c29202bf596987413696b3c751398baee5be504078082518e25628b3194860f8ee78d3d0c51935bc311bbc474f3cb1f7a1b02e8acfa", - "0a02c811cfa994df11cc89579cf3a9473627fe96997c1d0194645668ce7fd52a45801aa1daacf9a6b1370c12640cf42b38a53920b41fa6a69768178468354c95a6", - "0b073e52b7ab05f82795bf281543e4a5022923b7db6e11de3b0137325bcbca6115c87b3ab89547ab5de914f7ebc75b122d50fe739be4ef433db1ec2e04ba63005f", - "0a033163ed3ff4b9261e58b3aaa06af7eee3204bcc66b95254611fd7df5971ef591d731771c7d073e6bdbcd7047bb41883eb5348f9fe0e9a46494b8f6023546d66", - "0a03a4bac5ace9b3facdfb4312277795a03c7f828d84ff1c839d74a5bd1218dd1e8d37d532963deacd6edc8edddc26d93f77a56df2402a0353467b8c6762ff33a5", - "0a0655e2839303186f64b750219a9e518a83a95c8407cf9494c6b5d8ac8a2a74569e7ff3f68b707e183c9a39ae44bb5ed8b78c6111814ee71e698963a4903c812c", - "0a049c04c973533ca30aa4e2a9a821b89b0bd8b1c9da6622653340f6226598baf43ff2e855e7ebe3dc10f1930b32de81e977b4e9fb0fb418b9dd7b14b1a2a1d5ef", - "0b0658cfb0932687368dfdefa532c3d18aac44851b2a123ff6cdd88cd3411b24ae875c65a8bd79d29f6941034e544b59a7f8fd2585cd6bb37e26253e626f8365f1", - "0a07d5daa95e2cbc16ebaecbec79ec52041b75417f87507083834825855accd85815be86ba161b82da9dc106d1e4a285f2a1d3e821aaaff6d7d82b87c5bcf7a5bc", - "0a006ca5f891ddfb9b07f7f3dcc09919773aa3d954d2bbeccc953d589b2cb2cf7ba62ef0eed2bda2b3e7524e988685fdaf37f6c1e3158e9b289b8fac8ba88d1a74", - "0a03c9428c6a4fd4678f7ee4c33c8027b110109006c9b90aad24e0d74db5cb43fb473eee4230eeefcebdce02286761f37acf058aab225e240a477214dca50304d9", - "0b00e13e0079e3235598f157b5622efb2a785d24fe5f225de8bba8b85ca2cfd2f305f4b5d7b0ee138134c04b17150b6c907b94dd51c0b6f104d4573594999b86aa", - "0a023f5b96c0b6fff47a5cad45965fc04c2324e745bde32ab4be6b7b652c6a30639e0e15ea2669c353821acfe17bb969c8dcb66320ace92a76f571f1c050e0d722", - "0a02527a52df5529593cb832c26581a78c66e58048f4ea19a232c408c4d7c0af4589436ed0280640b616c51f98f9311d715fdc9f7c3db97ea339ca7fea9e06a28c", - "0b07e0e653579506acfb07ed5c7fcd0769df568af71136a9578cc5a5ad55a74da3511b2e0607b2d6bb96aa17f67884d01b38a8a8dd5e0573c062028b9bccf2336c", - "0a002727d9e5462cc796ba2bff560b52f52b1b79b3799583e01a6eebfd6ad5a3bcde0153610dd66c283ce2f4db8deb067cdcedcf141129e220e3448816f8bb02ab", - "0a085b77eec4a6fe48f0a1725407011dc60c9c8d88b12e03b0e70193b3d2901575e1fd630fd96f5427852f8b5d86bdf4aae495da3caf39beb62c149a2e220486f7", - "0b01127a467bcca7d309ca871fae12cbe8441dd4e031e9e8626dc46a3c290952d29869e851f0d3c0bab902ad493178e6b14d22b72b198c72a433a44433313601ed", - "0b03b57ca27567d1aa467f9fddf385701a24713d1b7d017f0a508bdec72f99f06b08433a5e7aca963560524aae094ab312c8721861ce0a7a5414a38f2fb268d754", - "0b026e16d9eb156bded02a828f1414199643f3ca6195f62107503a6ffa4e87de8b0640d3e3b6183dc51b1c0324b62258185f2fadd78f8ccaf359476bfd9e4f034d", - "0a0253ecca3ed2bd420bd63612b3643da46c00ca9468ac3a56742515ed4748cf2fd22cbaaeb56e8373e409808e9fcf33d72c1fe4f1054e7e86be01e8621a848979", - "0b06069c89af4e4c5c6c1c3fd6efb89b0b952879c8e1bb9a00a295dbe908e61a9a485b59b458f14222734a581851d1efa6176d0700fda411c19f6b31cc380a6bba", - "0a04213891d2fcf55de8bb11d86c63e19aaf50032a1c7afeee0662a80e7ba41c054e671f97fcca5052f61655cbef21797b3b7d8fc3be65c75718b3bc3f09b4aad7", - "0b02e85f38b6fd7572eb32f5f09b5e246463023d75479999520a7c2c7f5e2b4933dd842a71d3b8e19f7651c6f95021bb7ce6e33eabf852743c62b8189f57057afd", - "0b08d7c34269216d5e44d901bb9d1cd3bc4828261ad91eab1b2c7dd10650613bc66382e669fda754761c25bd543ba4ba9af9d7028eb99a73bb23ff5af5d65bb502", - "0a038184ad45b0e65219b90a4bac3eaaa56758780011902d8babe0bc1f0ff045591ba5cd7c557a0cda64a2994c9d7a6391789e0d3b2dffd08e2ffeca0e99e5c995", - "0b04016768e3bb4c42e836a92b2eb315d76c805dd51b569839fc442ad9151fd1ecfcfcf87fb4758bf1c491edb769a0f289055384506b1397fa088e78fa0bc2792a", - "0a0385852d0700e60bcdf95de2c3cb7fa79e65b7eede022e2a4fddcf044b73beea78aa4deac6671b7db3db54a9c33968ddd3f34ed6a6937d78f879e41fe22b8aa3", - "0a05c2157a12a847a9feffa6850c3d4e59a3862a65dbf2041aa372b2b73e69d1d117e7adff2a8684938f071f76b0e6c0a76d5c539f2ac8ff3308e8cd9abd9c72c6", - "0a083e242db6303670eefee2eed0e226ef5d7c8f9aeede85afb5fdc8a2aedc940ec727d92f763f692c29c791d01b5eb3c165854b0aa832b763f0968109600f64ce", - "0a063bef68b50fd42c58afd6ce0ff542858224942a99226b8d447f907ae833d7917bf0474979298a690f3d1e778ae0a3cc29ddc4503ab40eca55e1d31e3d222a06", - "0b0715954192b04dfc8372c81e555d97d4acf388ae465f185558584f0e3c2b0f98a790151bb1aec3056ec4611d3a505399ff542ca8ff3577d7d215fe7e9661f1cb", - "0b0124f0a42c9509b409fcdfdf524dea3f90f55be33a142e865020a042a836e0045283d994d97cb787b75d0fe101aba7ee60c461148dfc17ab3b2c471b3faf4830", - "0a016ec6671a96ac6581f3f86b88eaa16a30f963ff2cc849cfa1f79981154a91535cbd3cc5e0ad9dbb5b8c74cd30c695494a38116c06da40da5d48fb2555dce1aa", - "0b00f05809f78db4d249ec1d2b6f164149b339fd52186e18a5db88050b4cd6909292a45514a6383452ce53eb48a1524f99632ee1c34d404ef95e9079b31c8db888", - "0a065fb6d6b8eee8766a53358df3a7f407a43a1f3bbfba6dda64079e9573775805c912dae2d49bb8336724bc8f2be93ca866974bcd9b32c9614e7fc8116ea96f07", - "0a031c5876f2d2e30082027b0da0af216468a20d5e8d9d2a9ce2541180b8feee40d3e3cf11622ce21292bdecb89fbe08b774d98fe4bd9fadc9c7de827c5e2333ba", - "0b09228a4d8c4fe575e6b3ed0b2c95dc21a3c9450540ef255ce8ea5c5cf94b9da3f4d6f25ed3827070a12ada0fedaed30aa6e9ef74ce1ed19c81810a87d9c57ab4", - "0b0704e5fa53413728724685271aad18dde7e798491201acb9f39506b14b85f882d89b43f93b3d2dcccb9fb537ca008bb83538614b28b17e42b1eef9258ef6c06e", - "0a003ce39c2a38a2433fb6956d235b89e2d2d151e72d8dcf237db371aa2225bc6dda520c821b76e8e186b33bc5d65246592631576c97f8ed365c9e5dcead52fa3c", - "0a066163148162861c94f363620a32588def01935643d7a69b0388e9c1bc3d8e473e01e2354f8f1e66ead5529cb390e95288446a0a5d5a9f6bb1355aa0eb30b960", - "0b02e1797ef7f746b37d6c87ec8e76231ca93d74098df9a3c6822134ee17d71469b2084127578ecadf11104cd2d32f42b7084bef77b8534393b232b38d215ed009", - "0a04b09504e194d1b50d3a92847d02129f206ac791c2d464f4e9e047000f9036bf7fe6a394c4682bd5caaa230f5f412324b254608ac58c895ed0cfb2d8d7b703d8", - "0b01340451464147a987f05dc7d94007c3eb3594fafdbc8a8aaae4477f0071f34c9cc3db98a268ac399fa1915172930680ffbaec1a18a1330a2ca1be950f2c3941", - "0a06c7e3d3852deefa8d19679a0cbea9ac4533fb59e889a2fd303515571497bb9aa1e1c7ffd17dd6bc6d92829a0a21961515d7c66175327ee5383055da354e5ffc", - "0b05ad861c543be7926a0c9b5fea07942e2e39241bbf20d3fd60b3b861fcccd49542fd41d6a8d0265ec2f30220cb504c442a20c98ecccb33b0861244ab2afad9e5", - "0a040891e9119aafbb49a7df1d7fe3077e32460d6a2c578bdf6586d9294e9051b31685b4d480460cc3814c8b45ec912a747c7412e22b8cc583e6f119fd99374247", - "0a086875c239e1534ccc7175bb3bb2d9d75f62681f0d6011445cf1e3fd9c4b4120b49697b16dee77b5f09250faeda43ec6d5d86fd32a7337fa1c44dd6cd3e3ceb2", - "0a0169d8d002e908b50179ffe4ac9fbfa96f8cefca0b27d86689c1e5b1fa16726bfdb9fdc219426e33a72678d20e44b4e5ede0d20362ef8d9e2d5e6714901b5b69", - "0a04175ac3c2d8fe5620a7529aeb2574faefdf11bd19eb136feccd26abf439cbce97b5331fbf844267a8c5f285cbe3dea87124601f67da8d505984ebea6728f471", - "0a025249ebccc9ecaf019c41c39495537d7d736cea8f113b89c7fd195bb678f5dad601960a884b443820eb55bcc6d7044d45e3780e9b69dc28c3d7387f5635b0b2", - "0a04094c5fffcbf4d54de60def4c49e429bed3f291d6a9a95864f2857fe4cbc461123b86b0920aa03db8bacbcd4b0002276847d618d3545ea6bce7a4246f64fbae", - "0b03bc4e2845dd264297d36fc5e8bf79d6d41311736c70bda0961de22614e39782e7b29e19b6129de8b2e5baa3da9815434e29ea0dd3e6964b1b46c01092d3fa1d", - "0a078d465d015f927cdc3a61047b679f422cac2107dac12460e718c5711fb484bf512f9b39ba18d2be071c6b952d58b9b0839e766afc1511ab5a850a074b38758c", - "0b02e5ca566a7084fd1f297bd9a4ef06c0cd644fa2b5fcc662a2aca6d702ac77c35c2f2c3e599954b0440340987463a1e1b33d9dac097d18281a6f95b6e94ee717", - "0a024fe47bccc631ca8ff3beb0cd4d2b319c8339760cdf45260167e835e128aac6ce5eedb46a1408a1ef02b8baa65c5a8a9f24d668d9b844bac5f97a0a43867c86", - "0b08eaf5b649552cf121faca6d5431acdbaa20ac01c25ebb61c3690ab38af32a7e188403ff4d68205ee0fe3715bd11444e5b24b7a9331ecacf3b9ebbe6d7ef8909", - "0a05603380f531b646e3c3a24ef0f0f48a13701fa18ea502fac856aeeec19aed9ee8309ff750d01bdb20c304c3a7df17233b6864d5b1356d8e75e47dd1f092ff5f", - "0a053291373460c8fd07a34186d10aef6056f792e252f951a5c3a10ef59431a55bba80aa10cd1ea75994e9752eca13c26410efb5e1076348eb285f9f62810dface", - "0b00b8adf6580a654b20d63bd716912b6db4ca53e2835cfa5f81993af11b13800217c54ed8a754e869194b5bb53229782c1e9cd729e61128e509e7563981f5261d", - "0b0924cc779363421d76c99d685568a19360d0423d943e5ba4bdcc35103d6916fc071af2f819f0a353546cba5ad065c1eb5fb2e11add8598053ce7684a61313e48", - "0b01deec8f83616d6a05fd2cb0b91a27e1d8378e9600baeb797ce8032ecf894674469f52906a66a6255fc4f9fa54e6ce8bbcb452d64249526b9865b1483eaa28a0", - "0b04e8eb55a1d04762b2a715a0b03b0c618e13477d0a3a365d5ea365671924d87330eb0f2f74544fca97a454cb3d22c2cd440925b2a053051abdca1a2fa9b0c283", - "0b08238c103b8f353553780792c06ed370a3a03dcbdbb5078ab562f6664df47f77a3083bffe14d6c63cb763fcfeae43048d99d328fdf5e6a951f3fca3c66dd5499", - "0b07fc3f5bb8b71c425bfd67d7aa0059b6675b388a063db81dfd57148f0e929928ae2bdc683d8381fef02b30358c7ee8ac12d8d36262cfc0342be2952ae260ee4f", - "0b06dfa7cf48b302800ef8efcedc719f996c09ca56bae604d72aac5483310b1c0fc4636cde648753bcde820ae5e5e88d20f3d1bf3b18705cb0756403688285227e", - "0a022e2a7a3eb698bbe31fb82ae8c04b10d6d0c42f32f53f5711f99949cd24a41bc65407cd2c5e2ae6ee356981c6c657b207d3c6a1399100bd68bbd7322e126419", - "0a071b56a6efdfeb44b75ca396b1752246ca9334206b4a0522bd3370c52634a1dc2d3080f84f76e43d114d8ca69ce64c571a314962d5dee7f4f5e43a00d1e96377", - "0a08864f76a78096833d802747f9ab38e3eca2df586fdfeb7f17a6cc95d7801c320488ac7511858ec88ec43a8cfe065ccceb163091be084c6e6642d9a9152f7e30", - "0a04467bd163ce69960c8ad62c716be53de13a12ddb96e4988ad22b3c50f70fd115c07b9803ef84bffe6d647bacfed5ef1bf745056b71baed0e1d5eb066b3ed369", - "0a048a5851ea048e5d0fa7ba370dd30bf127c77660ccba797077ae5548add4a63d6249cec02e708cae013e8a4af6ac28047c8b520534a10b2589e16688c4d82210", - "0b0594238dc83774f9a220fe3e11dda513c267832be35585e672352854d7258d4ee71f8f7a10ce7257016788cea4217ed6125f0cc44a1e0f8b3df27ce35bc8a504", - "0b00637a7eeefce02b37fa8c1d51771ba430104ead836ef1cfc8227e9816bd83eca45f0d09386160e428a7c95cd2b46721db0f6c9eeb1bc989b6a12c02b7510a31", - "0a02b3914a29b4a510ab9dc7f3fb50e73d77efa79e8a56b54b4a0cafaff29c83fc57a132a1e19169a4282d488552e88dcd21f88fed22d7347d2d174e986ba8ca89", - "0a091a068fac93308d9825301023dba8da2a6ab2231b9ce176903dccdcd6fa53aa2c3a3af36f85581faf404ca0b199bdfd8757f43c43a1cbc8176dcf072d5ff7f7", - "0a07ec25b3955e14fc7001558fd741b199954324deb420255807edb88add0dd5eef5635c38453038cf988b0b803b3573506ebf764005ae2693bc14aacc3721da15", - "0a0540b5b28fa1936418e8ca00264d6677ce1ad9ad9bd73274ac4bca2a4fe959fd71beae80c2fd2e12ad0458706a4f8066130b7b641e00fddd5f338b25316c7c5d", - "0b05e619cc02229947b3762adcfd0b28e77c2f68c21c28e9bcaf61ff5a4b7e0dd4e34efea2b12a9a314af3c48886f0cd06f69f4f6e756d3ce4ade2296149fcaf31", - "0a0080d99a3a9862abda0576fb50b2886ed3d6cd0b109998a8f08fd4709915693b0164aa109571341b5769c0320bf8a28f6697a5255bb9fd095e5436db6a523dc8", - "0b020dbbd321c6c3e7dd11d095af64c4539c834c5340e7381cb0296c826c35c43c2d05de17aba65f9bd7b7774e338b04508d35a0ca06dd26ce464cab16b9dfd514", - "0b01e56fc2c00388f7da3ad66569f83e04e94ec036f75e985eb8a62221905a950fbf534e0553be9e1296f93bc94d1ed30ab6884df8953251717e10da259e69121c", - "0b05576294d4c9d50371d78a198c553db771c946a4342ff45dd3fd50d4f98bd86bf73b486412b0645277d4355f3ebabbd6ad26b38ea994fc890080c616ea6b7e5d", - "0b0053f4aa4efd0bc6d4975817bed0af94f833aa038c95c331cf80d984aadfba3a43e3627b0532f0deb02f57d60d4fa67fed894a0e6aae0713927b9f18842f0fff", - "0a04598bcdf72cce65f42ab8e796633f42001c1fead06a9c0085676868afa8ff49972d89a65032ca1acbe2c6578323770d064160268f45a962724a3027221fbf87", - "0b034ba4753f7f4d1ec310699f5490767bd8147ccc3e55b5349f63f1f3aa0abd5a28e815656548b17436082ba289fa57a75af15dd055b193dac83a0cbd886b18d6", - "0a069dbf1833008dc9f36bd424203d85c67776b6bbf6e4b53b43ce75ec97c7c36ddef5a714e343510db9063a746a6cd9783f088d1eca1139365a2fa5120e0bc005", - "0b0549a277903c94e0940e0eb626ca9da84a732cb436e09b2530bb41fc4a042105bcf25708bcf5be9ba45f7d75e74becdddc159f9fced095f85c74bdfe1f67d42f", - "0a055d7d427a11e532fb6476cdb86ee8fa63338d5052298e6b2c0e07ef142d449ced9514a97806ee9d1707320e45394561a8ad2a27c440bdcc4f0a289da7d4076c", - "0a0754a459b5dcb76b9328750861a685a4763c50dda51be98dc4d7ee86aa6f13190bdb8103fcf992346d22fdf6e0091cc050d799b3e3a9e8a06eade78570a72041", - "0b04d662ed199abbcb3a5f12378462c6281df0b0ade09b5d729a0da3d08c82c20ad80892ad0eb33365da7d9a9c85135291d18205cc4dc61a97fd4b16d421f046db", - "0b0759a4169efe0a63b553b79c86deaab2176c2709b27c38d414c8581474a73c9b00b112fb2e096cb0283966e2a81600c43e80202411151bbc5cdd564d1ea91db1", - "0a07eed25d414bbfad284280abc9f4b1c54ab6973aef0bf3c2039fdbec9b79dc0846b94cdc0c4d374a8f837b2e1c2efee2e808c0e7b14e2426459423b29286fe81", - "0b08ff6049ee963d0225cca4323c0a0f54dec65d6b73305e602f4fcdac52b4acc32858ac20b209a67085270a0093900bd1a70e689d44fe3793c34758089d263d09", - "0a02e256c29161dc0dc4f262ea8ce4de7d0afb3681135c6a43ba0cdff7b670fd2db797373a0b0d3b3f9bcfa0fa38fb60f8c81815d5afdab64929ecd86c18324977", - "0a08c20cda6563d853fef461f4796658fe36da102bb1340d64a7a8bf129c857016d32a64d25fef96c69d15344bc9cae36169fb517aa006efc65b902e531d01c970", - "0a077eae759ba66ba8cdae4c5a10ddb2c570e98cdde4136885ee97344ec46f33b93fc745c1d326b943176efce09558c409c00b66e617a6cab525daf7c4d53f09e3", - "0a04eda36886b1802446baad3e75d638220a03d4b55f1051c1266d5a7ae8341e5ae9aa3ae5470770e59209e8e5e1b9b66703ed170af2dacd8c0c00fa541b7283d4", - "0b0166c11ad1e60b40006232c7d1d7c32db090af33733d1bde238bb583fd9864bc2bb3c1c952cddf750f4ef0238a7721a009a4514d411627b553904f963cbc1357", - "0b0665940b380888ec233bc7a1f4b33f791dd836a9ddf2aa31c3d00543aa76a79cabe6bc7e572b82d7093b5f90295a70cf56448937dc5571fe1dbc148f43fde8df", - "0b0552bcb1a19a2dd49c88062ec01485fb63c5b6b7edd8ec4f6c390727c7655cda0e36e5055838aa7958323b9319f3084ece233fe271506571db9965e3b8e2c491", - "0b0485169d3c8572b3253a2e8ae46a48cc1842478c3ae0c5acdec857025680e2809f76187571809dfd61bc48a8f44aa2cc2fb2af5ee557ed303662e09994d478ca", - "0b05ae1c70021e83e24851f7811cd17e32ef4c2e3b4c3ba6836aad7d1edb44ef623934ae9e6ea7b884ef4921959bdc81290c3b87a15824e4341d7e13432d2ed76e", - "0b05c49fc20ee4bf5f0842c061dea470f6feba82496755528f67efb00c2cabbac65f9c22dc062d5e7a48393c89290de3fde92162889df7c05c46c5ffa97683dbe0", - "0b07773ea884b8ccad3eea654eb87598702f95fa73712f002724ba22ce3e9904167ec6208c7057dc32712323857fd4cfc1214ad934d225644419862883e52bf960", - "0b091ce270f3991e5d07421afc2fde5eaa69d13a2c6abd135d4e061549d564b975307bd8a92fd76c19a0c94a003d8e647cdb7043400a4910b816d71a76ddf72b2e", - "0b01b3edc28a61dcdc243a73c7afcec9b336ffc29002514ebf5378818297cf4fff5e0b8e0c442b36a52312cd23150751b75a04ef4f393e2490453b9eea67db97f1", - "0a02f8d962b3e9935d37ec187c8e3c731be7f7914f25754bffe15536709c84960c2418c158ffba96713231f874c74c041cac1ff94fa91625c1d102fddb55c0fa26", - "0a0067b2daf804af5a2663c6d5d4e52eb636403c4d62f28d9d5eb139e15e879de04ff130533f2829fdb48eda43e2e5a95041cb01f7b762717552c6ca9a54df3ac2", - "0b0507f2dfec39af42b80c294fc91527662e9545dfd901e32a6b89726adb35366e2236251f439ff962ac731bd80dc1fe8dd3a82112d4b7e94f0b68c5e52f873684", - "0a060178746f74befdbaaaf453a2bb93ecf26f197d3073cf95b2ea714b23c7032fc5a8a6847e54ca5be78ffa2c43c362ea64726827d55d5cf21e222cd74d1b7428", - "0a084468501dbd54f00a098d1866460a2b4ae80f71bb180e71ad637ae393827dddf36548523b6dc275ea543d6aba018e097f1ae23c319863b31025b2621c92769c", - "0b0709a13d4d28891562e694b5299d6e0e1fdd68e16f0e0ba178283e533086858095ddc0cb5a9086976e6994ccc6b1b5745b3e9c4e70c5a319fcaa47213e18c7d4", - "0b003f35aaebba8af6acb46d68d50c15699c73df23f86b7a90a5031b71d0056ccd10741b170fa938a1246a682a0d9e6d182a5eaaf10a979f23a04b859ef9aa4b58", - "0b07e241885f32ebeb5821bc941e28c2608adabac97e8e1ef2eaa34ff497a1743f26fc01c41caa6a203f978ec6e00636093b56365a715d8f6494a803c63cec0156", - "0a01dc005109a89197cd4310f052d67e3e0530b86dd121e9d3047180406a7085c1d7499cefc184b58b17c9f0fce751c77de9bbf1d38f545a4bc273633a7b7ca3cf", - "0b061b109d89649ec5d3b830c3bfcb0d1992621739e104d87a701794811f049b1c66c06a2789fb5db074484876c60002c4ce584f08f8c7fbc6ba89bc0460740396", - "0a0800c99341f2dae6d73ba75b3d958ebca2ca5985dce6282c151acbea547f66763598e7083f3195cff5cbf1e6d07be542c7b9b7722e3b1df87768bdbe464359f9", - "0b036592fa607393d9d934804418dd6e19be4aaa05c4bbf83bdb65d6b0bcfb1337469747509a134491642c2425c9ef3f633eab4db9dd6351d34650cc1b16957e88", - "0b0529c332b5e88f92a17beda1e7cafcdbfb8a20887710c703525d3fae78d857e777f91152fda5a9b51bc41c86006828da1b7ac140ffa1edda19906ccb05582c55", - "0a0712b02f041c26c93f11eaf1f2b9a8c8397f4246a869d24ac0e7cd1c05da50a396cd822031bbbb13489e84847d9c18419fbc427fd7c4e7f63f23052a3c53952c", - "0b084e3a717bcdd0420e3495783bad4df4ff00fd2598896d6faf3825b33d291a370bc3f95abefb31d5b0aadb9fbeb627c40d4872ff20af5e854dca2ac6a0e5b465", - "0a01d84e504c21b06f9c575c277770a8bcf51c4ad992571e42d0044cadf3e8889b481889b190b78ea7641f5a27742c3bf602b819b73a332ce732d42247ea4ce63a", - "0b08147c3e63ddd48e5a7fb293d7b300ab0dbd889639d8d276c64a8b4c614059e3d51cb727ee0062a509bb42435ea25ee22988519692cb5b70f52a8911f47b8eec", - "0a08acae29721bb3f1062825f1c99cb2ec0ef1b887a8fa3e8d3d2637221a01b784bc1f903657b81100801f462a52b28b25273f925fa8a25bc4c6aa2ac29346c0a0", - "0b03d5f026ebb3ca0e83050505cee75d2e3d4786351e49b8c038e26b1009601381c993841453d03d4127d89d18ea150b89e25774939dd6ced5fe8773f141b0d6ff", - "0b0744853b6bcd365b5c6d4b0cdddaa8139b2e10c030716959be8cfb8fe6302032fdab321f1ce6f3b8418cd2d76ae6104dddda63ae60a474992a7e6539be057f0c", - "0b08c994939c2db74aa594a2b1e4bb9ab357ebc7b102b50a73fa26cd8dba75c3b263d56f9f36cc7b4ca15527ef28b775e3dee2e2d557f8e46ac9eb0e9326fa50ca", - "0b0407e3b52a2ca856e50b07f0b6d12366ab8ef66d4963eba568f75d34792599ab20a496dcd5d338846987760343c30f655c3e8c4832c97c98a86aaf101188eb35", - "0b00f35668ee148734d47f20fe6c2f068c9d411419f687cc35dfbd2aee7c4e25e62509de543ce0d67aa85102492cab5de8cd6cd9950bdc2c3a61957ec376e462eb", - "0b004645143fd8d8ebfe8f725392c5424dd78b6835293a1cccd4e6321a69bcd8d7f7fadcffcc0edf188a8c08543160891787f9353152b8a4c8f67ffc04de82e2a6", - "0a00d0e55d5704ec9e70c5d35ed25b92457264b18480bb9b00a9f9275a7e3b251393f4881762f40ecc376145f8419bb8dc0d4e12cc7bd8e11f775b47f6875dd40a", - "0a02a921d670e89b507689b9e687d32f3229cab9e604fe66717b606647cf6cbf3f882c029c575c3cecf7d99b049d20937920c349c360ab80ecf34233d0e32fbfc8", - "0a024787dee7772bf61dd1f555fd15b0ecc061bf9e652690ddd78c3654b9f43e12448ceade18a7c22e286f899270c2efb8bfcb2e8bd66f6902b7f0f7696e649c6f", - "0b01d5ba9bc157d6f5490de370828cfddee1d9dab2a12bb885337c87a0f1f3e17bb76f33552034a03ac15b855ec366769ba8e26ae00738755c014166f09fac04cd", - "0b069c2af406607e358910692f93365355018db425a3ae1b8df539499bb0f0818f4f7235a61407ec98e9345a7e5f2bf649b8d8d819c542762404a9d0fc4dfae272", - "0a05e183c0174c6654a314d95fc80a3460de8b7c0615fa6ac4ff89e78853f90e32438c68e5ba5bfc8dd4dcba0e9a4b14221091be3f93916857b6b123367deefa89", - "0b056c3d3433d0ad86d98e7d94f6d577c3ddaa4328ed950da7eaac542f76f5be74c692c0a688c87aaca10695fb9c667b713615612f0289216b99669b8d8bdb4b12", - "0b0667b05ae226663c9aa146f42d39105aac96a32d7f76f8dd780512f2ef25995732482519c550d2d612632357151a7fc6cccf83aacaf390384446da6ce3b56c2a", - "0b06f46e9d9deb65ede9d29c0f2285e8bc36c811017f6ac96425122d10042e615ce340a696e37aa00a80899a7a0d749a1a40f607f564e840cfafe4bd693c9b8920", - "0a0673713e5733dc4dfecf3328afc72f4610fd1265516596d2546e2ecf30630044b6722c05f744e62f839854437e4f6c571fc56aecd418b9a0ec91b8b71cd0ecdf", - "0a02117336c6e3eef9293d39a4765b6f26b2aa89e2b108c7b4b226081cd7bd88d00852c1484ac90b6ed159c3266e767b4b05ed3231f84466c55d1c30e73802966b", - "0a001517b88249355f659ff65234c9afbb76dfc62a943c958635a7e07631cd04df4c24bc2d8cd7840b4e472ebbbce5af84f1faeaa851ceecb4919d15307ac2bd00", - "0b05fc12b2e54eb2adc3d7bf8030a6ec9c42fe0bc48b82c29f7510e7c7961c3353a4b5b3da2c53da048742db82886fa0e278eb9de14d2fc794409f0ba70fb73233", - "0b01bd917bcf136abbff8ad6fa0257f83ed56669cfefacf7bba76f24363be214488915983d367371bd7190929887f1defee9b8b05d030405d052dade68be1813ba", - "0b04fbff15ccfd704d40538508f6c7afc587d7a72c13cbc63fdd5fed7c2ab1ec66637efda1023cefffc68044281a65c8576fa207e4a42c09234a086d06579a36e5", - "0b018f2a3d06b2c14a8e555f5e5b66d516b78b1b6d8d3e08c8601ebd90f89a38b910e6eea958f9fa01892808bad9f00ebf334c678b4d3b906a092d33278f68bd67", - "0b020649a5d0ff5e5729be38486ae921f7e958660b3e95c9546b02dce58a5229376c1131e2b2152d17ca7b7c34e5da0badf6c8e4556c7ed8ffb906c85285d54cc7", - "0a022bcb21ae69c75f28a1e709a3bc382a3304c1775e291484ef25ae676dea951b12a8cf8636569e96207e969b72b667359233eec0571c4616ad1378952e325be4", - "0a07c7a3f4412a7353d990b7d767bf398d133c08da4d8ce9381870aefd8595c242c56123c6fa2c85f3a5bcc3d44412e352b1c680b558d474776c99777c27e752bc", - "0a00f77cb7112e4abcadcb028726a5c7ab559dd9d2d801586ac9253017fa9bb7fc9a502428f223f63e555466b2f97467cd9fefe1f2e1404e1625a91252211a6002", - "0b076f27b2a44b31cfca4f753f612ff63ab926caaf3a45050d667b6df45e545b0413cbc83a116022870248ca4adbd10c83dc1c02efb0cfe573e97f46d6b14450c6", - "0b063692bc101ca37b6fb0930a6f34fc2778a8e5984c23909a1915e22b653849166fcecf90074eae440b979e1d700742139fa82e6828bba2a57147f0b57188fb4d", - "0b07b01eaaa2b2b2b0157eec2d60524b56f07daf60204254b82376f506b7b49ec6a456642275bf1f3e18c89a98a2c7f76d522d80fcd772eb0dbadd30f29cd551f7", - "0b0129c6c8ff048979d30aa6f146641c0bfc6feac8ae3f0056862ac583e9354f5b7f5895092c55cec872e3e66d912d1830b9f16de897df085874cfd05832e8f817", - "0a08f92ba5cd58f9efe8c76881e3871a97c4aa2655f4e60ecbe8c430fa40e3403c1aca33157c85e6c22c38caaee5a00409706935dd5b63702b6d80dc4aa5ddaadc", - "0a0527f9f06f8dc4914fcb8eab685ffa24abd6023ec57c32a48c017910439d27f2e35185f715bd303addff5947eb590115a1ed2d893d77f4af1fcc3caaa8f6fd5b", - "0b042803975d1b818e79d311a574848d1c2bb613f80e605efc5c8554e0599e88e0b76a6ca86c71e40a9e222b2f261e6e601cc8250484e0a823a4eca0870310d21c", - "0a00713dcbf2d5e80642708543ab4bfa0b3f17869475edbced1eb7848717e7953c96e463f82386cbf284c9602eb96436e8921541a745c2f5e31e9de1b3ae4093de", - "0a02519fb7bb8c7a4d7e325ad7e508899d24be86b069267f2d063bca6939fc5701b73ec658a10665171c1a03a50f466bd9a6d4c894333fb79dc171c6c277f1a43f", - "0a01df2d7a4ae6419898df656bb9b9bd7c08b2f5e37fe821449bb7737b268f09c8c5d5edc6e425a1c6f114e1f49ea7a88df3c955942bc170eb60ea6d27877ba814", - "0b03b7a5de34bd65ee5a1bcd9bcaf759d3bc7e204f28eced066b00b8ac60a72eaa101f076e49e7ea799a458893552f8d53ebdb94e28936c3ceb451ddc01b6d02db", - "0b01e7ae05051588fb7072a04c747a30f08e508436cb642bdf3995e7bbb6387a065a03e98f419d36654157a79522090e18b3f94c261fdf34605bfddfca13e2f667", - "0b091ce473de65920ab605f4d573d7283f949142eb0c622fa0cc6625391e261d2b584397c29ee7de33334636bea2fc5bd0d94f13791637671c5e4dc35efb45a573", - "0a05a8bce1eb1a42ecdda4087e5912f73c1b4a0c1a4f0c22a82df950dddec2a6521ce600621ca2bcf0c7e8f63f07194d45ff1c48bdf6a005f8cb3f38c4df9bf1e4", - "0b064ca387508905cfd2f45528ee03ce66282d42182bb57c3911c45e82c29d533561b1dbc3ee4b5e47fff3f8ce137e5a0f334dbef86c03808ce0af7d34e4369e40", - "0b087360b2d7aa83e18d95b60958655bba5fdace4a0ac8a081f4b597efad31ae0a6a72a50f290edbaaf9c6d3ef2742c63c9c1c712ab118667988a30a0d9cf95867", - "0a03cd09fe74037001f27ad8a6b985937f105db847e5171c253b1c1b31226b5ee88677b6017ca27eee827182c7956e0b43611569f52ea08f4faa2be8e84c800474", - "0a072fe1e535f98b8b962fecb727a6ceff5f2d34f77b5fda84545da9dcc62c75e4de94420c19be50065d757db2909f89c54004bfdc3ea3b4ae6f74620c5ed0b3ec", - "0b00f58e81ffa08b218467fd13ac36c418630748ba25e674273d120211e1ccbc14f005bee7b8bd362535d1d1fbe3b7a263560d1c818328149896080874b32adc23", - "0b07c0d13da0cae3817c384b460a9de286a8b667155be3893249924ee01a6cfda7a85d232e3a4f3176cabecc593b6eb93d2607b84b6b29d07b5779347509759995", - "0a06951e149b4f7bfcd596ade2f78f626a0e0188f67d6c0fdc6af398c57e9dc7f1250d8f200373173b29510663d97c6406187931a6a41fbad0957a2d7df1ee5368", - "0b0144f77d8dcbf74ecb3334abd2fbf5a39d4d5e7c7baed9d8d5ab3ea9d3b18cfec437dfa7bbac68d0a3a42babf662a47286774a60994177f9b88f3ee71d4b814a", - "0a02476d826a6ae792fdd58e8d452bd425ad5759df0a9fdac981c2a541041dec88db578b56dd7be63d4f02cb5526f9b1ee8d68eebf058531f627282f5e40ea8c83", - "0a015f75851b296620f1999a6ad94eec1da20e5f84c9f58c3dc8f8441ff1d769b0a0d8f75cd10537c36eef59a4fc39f96388d4bbe921c11a7d242a6e583e66248f", - "0b01ddcf053b26124b860710c5233dd6a5c1f8ff96d20ed823942130137948a16c65c0cca6cf3480e88f62957215970b63dbe977a99a6d64a23982b78a733226fd", - "0a07950885420205821880d101e38d5716fc365a0af948c82887150b6351a409da35dbdb933df2a4ef0f8d51643ad2f0af8995aea8bab7b728a916c633418c3c2f", - "0b066c1e2271180e24e13718c5d2093c2d92536d8403632dff3b03cb8e2f2bd9eae45be08a26398702e27114fa35fda0e2c8b574c9c1dcd331c72d829292fd5045", - "0b04c7817759189bd6bc11a95de59f6f7a2eeed81ed02b23dd477553aee9a5dd67b458b2d7235db1aa9d87cfdc534bba24c016ecac76a6c94729357402d9b1b294", - "0b0100cd5e18d1b69a731cc54ede8afb4aee426359fe1d2fa7e48fb497619f7f591730171bdb365bd7f15bce9cd6ebd8c41ae39a5157b1bce24cb36a066d9126e1", - "0a0344c802e6775ac67db40d3808009056d1b712f95e64072ba00dcadfe84dcdaceccea1e8ed7b77d6f5c432222abbeee4faceb94486a012cf63df38cb59218440", - "0b0743bab1f00f18fddbe287996f412ac32a7e9f56797d8a8e879d134c5039c2f8ab80a96d2eedbc1e74e01666d61a6f5aeeec297793e70accc85df7de4ce92db4", - "0a037d771d0667e3e7f712df91642cc54404e756b643c1e43996ddb57f6dbe8fc31e95869f104d3f7baeba2506c0894743a1fcd7bf309cc688ca4ed0736aedfb1b", - "0b062c7829c5ea555b6c91477882b9cb1a697143c9f68934ae4414a3ec0f4ba0f6e7084cbd45b50bca8f47c285af91547f030aea0e2296833b380068482090727b", - "0a07cfdcb9cde13cfa44e98b76e60c0dc3bf6532b96d8cc301e5703fd1d0518ec5bce6f40e8eb2c351e71c3b3a74f196d915d98c5da46671229ac3116e58826dea", - "0b02e6ffe39f7425e081c852044137531ad7048357bd9be538fc88c60b20f80ad2ccc39ed44b936022db265b78520eb13129fe5c545b9d6d2a8a6ad703f1f7111a", - "0b0337f4aa7af82e75483c5827e87513b4beee1f9b426d85af8f886216d59a45f18ed5871b88d53c5f1e8895570b774b2d4067e30263ef29ff05a8992bd7a2d373", - "0b00df07c1476c14cf76a919c4284ba32d9b45319381fcfef0ac028f4032efb8c917e9ae3f43b74b6b49b8bf6123f0673b4452e2f38d3e982ff8599583cea9ce8a", - "0b00d9ec1bbc1db9337f7062f68936f638dcc913c94bb283908efcc54d765fc24dcab8bb6146ed2f969a82c95396bf79ca5de8d63abb6ae5b08f1591de6cda50c0", - "0a082287850bf3cce071f5413e310174c692f39897de86cc4f96d6e6b2c01b06026c4fd0bb31dac9a255f6f6b941247ced2b19d475fdc8bdd9ca121007c8f4c733", - "0a06ddca56d6f30879e4c3698201246647683f9d4266fb35279413df92dfee762dd970b9e1b7dd288b50a94910de2b7ccd48d5804426a5a113cd3b0c95f96fe05d", - "0b08f876a5f7ee6b5c8696d245efda87dff1de0f72fcf5d7c078137dec0f30c4a90c9123883c03c5bbac0f7c825a9805cd612df1ddea4739162f3484183ba82f4e", - "0b071cbbb33fbb1499b9d07e3ebfd2d0160ab9c03afa10502ff03ad137885663d421492b33196326e6ffacf512c75533d6117f3b8ec7408211311f56c44d26ec4c", - "0b0640e3b00c5a35dca09c8692373f5b6915440e120829fc9b5165b4d6e66fc589f083e62cfd0f746aa6c3fca8de0d11766dad106def3ad6768acb9eab893f8e2b", - "0a03fdc8a118dfb49cc57028dcd0e5270a1048b09b44065317ac359d6a9030e73ad19ef8337ba6b322907a94255d184f2e5595a356fc85c12f77efb287cb0912fe", - "0b000caca307697cd2313759a145284e71483bdf3b695889e163c5a28905d929913152eb2fd7af12ebd1b3d6127c0d4dbe101cbcca5f1f235693d62daf4fd42fa5", - "0a06f518a8ca96f3367083cb2ba7cdff0bc36d527fe2f7fce085414b600782767e19dd9e02651bb610bbdcd146aac22d19e5c6d23719e0af53d747985e77fcd0c8", - "0a06b74fdf7047a4f9263773c56a836db5d8e3776d363ce9f4d693955ce0eb02e3c82cd200cf7c9e5aa15de35286f56cb2c91773147af17687bba815fb551e5d41", - "0b016e9d7225f6f5213c928aad603907eccfa4da0f679efc093bc242254755e06235408e7eca9e71ed55b47951f0a41f471742f9c184be7eab63b7a727f25a66cf", - "0b020527fc0c9e1e72ebc7c096c24a6236e2f91a29b264dcc9deab3b91901ae25a6cdb36e00f8d1f0713e3e5ab22adc60fc558bd301d8deed7c3cbe5359a93644e", - "0a057d3034ceddfedb7c792424a00f772998ff83b5e38301d73ef08d43e22bcf18e6b5aec56e69c5413c6d4fc5da1d402bbe2deee50711685db3b5db78f086d71f", - "0b0500bf770c553013ca395931a86ab98427c12e428c79228bb7abb468ca0ead28900b49dfc033af362220898b88a8a32972320803dc6f34c0063f09c43a907df9", - "0b05b2d53ace4607f7e60269f918cd3008688d52c552d722d3f4efb00cea036f26a9060a3f1ae5fe17c726930032ffc443df7df6a9a8879cd3a5911a1bdd8f9f7f", - "0b048c9e9611de06eacbd7774620685edb9e6be41f4a4ae7c2b7c7240304da6a746df863aa7734c42b6efdfc027e3ac60d1efd724e28c2275e3e0efde1aa10edfa", - "0b04bf533e424c219c64c861d364a856578d2aea42c6878925c1466c9129f6e79d23a5cb73fddfd2bbf02b49f718a84208c3e3e6372231e219d4fe64ae9fa5764e", - "0b067bfeefe41cc7219e35fff33911c6cf2b3492c2965a987cb2075fc77bd3c8a570a422549f1bcb63a415eb5cbb78704b782e0e8ce41e1c011a6ae64156dedb79", - "0b04296e56f81fd3e776c7db4dcbe79582bd34ca2d3d02c26ea92edcaca38b39ea759d99c1222e793767dafa84457977cac4040db1e37af22686980a06ff4d4aa8", - "0b06c41775f0e102c0f3cf758001c61ae84fc57fadc6bbfa50f04f29ba8752907e1fdbdc6c2236ac4f894ce8a5ea256773c13f40a4192a21a1beafb501e9a1dcfb", - "0b089ff9c3fb8b09b12cae1be7fc3e7a6c11d5646af8a4cc8f04ef81eb740ad547575410195c6c250e5e69eb1b46b9ed20841dda03a91ff522bb8199d74517603c", - "0a06b0cf6a464b3b398955293b6682dbd603d66dfeb1fc314b02d0f1dff7a3a228106b3ce1785a13c7449ef2ca0f3f9bec5ee407cdfcd0be01045b2969f46128b0", - "0b039a82fe1ba867523f48c9b24d193d87090c79fd2f42c4f73afeeedf794ce87cad8703910e183b298ad8d022cfac5b2e1305a89320e0ca67477cceb13faaa2e7", - "0a05322667feafbf3b244a302738376fe2eabc447cf8cf6f46b09db7c1c51ea564beaedb958898114ff1a71803881a3b4e346b2a3247b00719ad4e173aa713af52", - "0b009f0a0b984c866cce55f2e84b13500a8169745d95405540ad522d8a25960fec1b0baf7b5132d094edd45a62919bd41f0882e3afad5de76f7065476e80d95fc8", - "0a06a5901ecd6d4f912b2204584687e16604e79de78d5fef048c0949b9c43b12d2f33f6a9ba87f3863582883fc2fc9a681283df701d4e624e69b4f65bbd9a9c2da", - "0a04a75f3c297b293ec4eb6fbb4167327d66b9ee2a7e5242c5458543d7c020446354277de1c966d167feba17a8c6c52c07d7ec525fe5edb2f5b1c3bb87bafccbc1", - "0b04d293f8c86e93db1e136d4cf2dbf966f830d48006381738edccb4a062fdde32382fdd97ec25d2fbdcfc0985e5663642b108567476a4ebfae38c0687e5c1f34d", - "0a06661f6dff58c9a55825dceaedfb2935539f65586eb19a6b6b0391d26c4352588f3e280ec8479a3026a62f58f31c389bb3b6afe5ec50d2f61d97b2bc34b17931", - "0a089ff1dc252cc0bbba5a4ab4c229684266a9f3ad4fea05debd00467a64b8b7469c8fc02433af981c27478818e5327686e3f7e9e0e65adb040fe0f04168dba4b3", - "0b013c3fbb23ca1703f345cdfab79f0eabfeca55485c02e0bdc930b8ac88360b1752768054a539656b4a3dd28f3d67549b35f10ba01ca928eb6c84fdc1100df83f", - "0b0906932956e41fc32249c8fc784273d65a0e470c0109d28f504a02855d814ed0fa9477488f36938615d95e84259f5460ec4b0ea3502aec1236644ca48c1d5e81", - "0a053b04a7425bd88b235bb85952abbed2fc9ad72b10f4f9c5ef924af893f132e06ce4e1b10166220d30683691058c795fec348514b2520b79974c9c30c5fef536", - "0b04f15b49b92e7916de92b480d226717f7cc27ebbbc83228ada5a58ebac762ccbbaeb8f782b8619763f29b6b191cba591cc05ee1f3594bc964e038636a8342be7", - "0b001a24f11002eaed7fffc7d0d3f53e9f37b0b18975c56f323203ea35c8f6816b01fe91c7694c0f330a3dd5b214db58adcb1036d52a21e8fbaa5db5e4313d33ca", - "0a06485edbd7d1b2422fe1b3b9e4f0433dda9b3c0f0f58c5f69c7f3f4e9c601be043a02da966bb8f511bd0a488ec714a53ce472ec03ec52ce5157597bdc485ba8f", - "0b005061ccb245716600c3b6b137ca52782f8b70f84847b693570d04132c7e6cb17e4edcec828b39feb260471fd67ed254391adb62b59d49b217a6c9e0752d9693", - "0b038ffb61402e042176874a46b7fb164037b675501a2671dcfb4c7d1dcddc531017b52a40e553655f90bdd7a76194b56056eb42f8f91f7ede412b587cd8776e95", - "0b00a16983ae4523810295e3db893680102bd2b5622a91e7734b76096c30365cd911881d16156e9c505c8fba2f7338c0b39a16efc1cf4ba9ce6c32c31179ff2a63", - "0a05d52de83bb5d183c8db6e93091f6c76fc3b065caa97ce4319cd881f9cfaa329c94fec6b43b310c3d57782970287fbf23a1f5ce9f21eda5216ea6c8c1337ca80", - "0b0738ed7467c66034f0a10c59b2f90171abded2c92c0816bfd44dd5d99b3a0cf3854ecd36f7c38f3b8ab0a4adda25e0b8cdf6d60548081cb4d95805fa2dbceaad", - "0b04f4faf77c50ddff511228a48411afc7760de01e428136e62c3e6c626af07c3a6d849adf4034a4d590a5278b9b7a5bcda43debc07d1e217b233b89b4348692c7", - "0a03e9b1be98e427e498f752b03d5648ca50d6932dbc706aa65d583100e6df3836481b858578e6b862448c920e56277dbe7c48b3af5ae2a916b30debac2972ab83", - "0a0062e411e480cc521e8301fbc900c78b9f99bff9dd1a1541b2d5add3135c57e9c249be91530c5b0e3966310e457513169b9949f8f27fd99e365e207402c00d77", - "0b074a98c3c6ccb996e73f90c8f4e3a37b2d79e8f8b9c0a6e88f25f4f99d087fd3c4eb1aed9fd385968953d319140cd95750653a510945c5b9a51fb2a01355b146", - "0b058bee7b067f02f3a2a545bb5d9dee98ca9c11181fa865484999a2e5a1e1b40c61363bb05732a014221758abb148b3419c15f74bc5bdfe06290bdd3861dcbed1", - "0b089848716e21cda6119e6d1be3b82a3b7b0e2fa085e199260248bb96d7f7b3885ef6093a84d034662a57856baf01986bc21dd09d56aef62f980292d13ea63afc", - "0a0094c7a9efd0df4e7ddaf70e64a214b6202b987e2014f5b9aa1612d1ffeb15d54836fcd0a25c5ab9f9ed7ff60e9f49b39a0d7d87d0c867ea7b89a788775f55d1", - "0a07dab8425a05dab5994a4a8eb578e0e393fa5bd8d5916de3b6da2e3f9b62ac53f5fcd3fb641306fdce436f1c65613fc58940baa4d48c39ee1375735b6343edab", - "0a00857dd3ff566f0f20c4f97a4e265bbe70246eb145d42d34712e618757ac3587b9447cf637d263a497f3fc45430f4b7bba4e246a593ca32fa4556b2b644b5198", - "0a0645c971aee44bd8bda210ebf458fd87fea711ce7ac8db323b6a0b779cdae5bde41f4179898d98d8234cb50c153107be8ef6de4cd8bc3d8f37f98a6f9c0f6f2d", - "0a00d884d18d6d260a74b03b5500411aee98b4ecafa7c0da86dda848c8a874b25116431e353bf2e2edb322a20a695717f56721f8d9eeb73c50d1c6c0e687c4feca", - "0b055d1f5f5eb504f20f91ad826aacbd60c689169a924aef44a701316836158386f82e3073819a756d451dfbd1ad1145b6e414760d8d74a2375d9d6c74daefadfc", - "0b06d7b43b20d4d2a71f035fe3a783c5c7f1f93da3257d72192ddcc1629de491fdc7c8d74d40828189be62b0c3781846fb597d6ef39399b466896ffa150fa47f4c", - "0a01cd74f504ecbe351dc0b2f722db6a35e2b87396777f5297882ad4b7de9aa0e03780f23460a21d30716b42e43202821ba1200a653deed0e5896a1082a7dfa558", - "0b06fb466f8da71bf384c7e431d157a8c6c571e96d567aab8d892c53b35176b974aff5374f7d5142312dcbdd7f67cf3aa64e36bb70cca9d2e4f244074a34c94ab5", - "0a05a8fc7118900de554b405b2515e92af5f788a73830ba7db5a64da9d1bc5375522f480a2ff4fdb90a4903be54d4a8907b07b80db5f66f2410a6cd203739d78d5", - "0a0758144db42cd312aa09d90bee61d1258f23a1387701dd3e02e2a62efeb3092c0dcda5ea1d154b71298d46453e01c033e4d124cbf391b22a464cefd7e9b17c40", - "0a023573a176eca8bd9f3c30df4d5cc5c0ef35cb91882356f9df904eaba52a9ad9f905557346dc2c7af96174571f92a01ac75ec74fd9ff291c6c52e8faca4f6e61", - "0b052f23b1acc410f8b1f07815e96e18dac7493041c5b74dd25b9272f61690db924be5a0d25bee8340dcc952bcc991d6755ff495b5af950e94e9fe22aafd27a842", - "0a0697c3a563a77fea24c1de5d4d83388d751660ddbc7aea890c16933dafeadcddb19a6e311bab979e9c4ac55e802d01b9917cdb94c45cef9cc5d8327d927868d4", - "0a02a18187da0d6dcff47299cea9b0e5daf2461b035072d5c87567aee13578699175b33b2a518a85960238ae357eb2743c4f3caaf69d188d09df61a89731bf133f", - "0b058c0420f0f09c2eea66beab3b0545ae81ec8c9f4bafa782a6349d3676ed2ca57dd5ef5b98d16928769c50e1f1877b52da633c9942f91487926258b6b933beed", - "0b03e9232d8e550f98b406e47ea1a8839dd6a732153a8e42043d72d71818dc9d0deb40678d7b5e592f94cda8ca6495bf8e5f12df0a7a4fc6a22fad397efdb014ba", - "0b018616c63739405c14746d5be5f3eafb2c179e40cb2af0d8effd34c91bee837c881c1715e2b6c37f292f43da5ab878a24e7d1cce821ebfbd7e2dd49720493fac", - "0a04bf437a68d42b5b7a7699984d75a53b272b297d04524e77e136ab358e70ca53ee5dfb6fb894c97c5029e60912444e89ba3d9d50fec4bdd2a812514209ce1edc", - "0b0839186816431065a4db31ecf649e5e44aafe2968b4502187e2e30e5670911da96ca3688897e2596b58782f5a12046100c09732abb78d52f6af91c606f7fd07c", - "0b06f3a47b1359e72182dd682e917bab13cf00df9e005dcb04ae2c7de20d25dafb4fb781f6151c6a077418168575501193f964b10742f710f10d18ca4d155d6bc2", - "0b03f5079f72c590eb06cad2a9b23fc38a53ed7cee5bfd232a99216d9701edfb191d26af841a8e23fe7dc2af0224bff95e5ca23a0acc8de4e01c1cf0f8972426ba", - "0b07f4aec40e7b1018dba550208414e6580c23c9270a47e34d3a43f80b46702ada7b9e6c136bb397396261ad5a9ae0fef4847c34cd735a87ea5d5dab6290a82a1f", - "0b077c8b90bfab7c8dc4255831b49bd15512c8b99513a901349f469fb5344478cecd33013df3a1d8a9301a20154a59d760b07c7e1a6185a89f78703b4f34895e9d", - "0b0031eb730b0537c97872f3d0845262003cb281de1e5ca2abc5f1e6210217191c32009a5b22c45cab2843351d0c49208b4c8c8c9ac62673aa70042f53a938cd31", - "0a021d000329a9f4e60395e0797d5fc83378dd18497b686a27c1aed274f173a3f661e0ae3454a6e6bbff92574443923c648464ee1a3cfde1ad2f9bb6be17c1e80a", - "0a010cffc55fc6ad31ab540ac9bd38432ce0254000eff4f8bf34e8c2dbe7cd675cf889e8fce5e69f6ba374643d0cbc462fcd8cc9308bfe8a9c211494e6e3cf40b3", - "0a0869e600fc6d5a64ba42cc498380c022488590065de1c06304b3927d5843c4c55be4b597f83ed36cdd98a37b73e9d56e2fdac0651a074d4aeca0bb2b92eddaa4", - "0a03600240fe72d1cd547c0d20980cf8ef2139b1659edd73fd2c2d1dcadf35960c687e09a7b35d5fda39ea818ed84cb637c85746759f410a263fe5f9295ac7fd4c", - "0b08597fa627cdef9fdfde5a2d42e8e8c36cb5d3a91b4692760a28c7f3a92dbb9025c445ab08878db235d7455436f7c9928c7f9da21c3d99bdaaeb8aded802701b", - "0a00dee3a65215a673816b053a02594322031ca3f87d68c44e0ed536ce67e403aa45f485f7ded0e38569fb34ed56a6d8d436c363ee7ac3c4f84f5e6599a2b49b17", - "0b0821fa1eb90ee333809b0454129cbb4da5b6bbb29985e0e58789919fdef5c698d2a6d6c45a79e841707ef24e7680ea6b7be46c2ce194714d5d892a2e22cf8070", - "0b0042a88d0c87b414bce1ae8c71ff3e27385748cceaad863a990dae474ba873b60ebe26a421322b96f721c554c92b3aae0603d998a93d2f2fe18fde39a95677bc", - "0a0470986095a9dbb2c64ad42db2d1da3b613edd1bb4b3996130af2d34db7bc500e219ae00be54cdda0f7bcb432b4f07dc4ce06063b5e22ecc2c982d1bc5d6100d", - "0a022d2ad57e1a5656e27267e02a31ddaf0b3cae584d94a0af6eb20a70b1dfb0226b044311c76b27251c830625850ec04828bdb0ddfa640cfad726d792c906b6bd", - "0a09248c9d48a09c9916bd4b10016021d0dcc3a327628758520d6d3725dd99e1c1fd736bd733a11c20fbdab54b5187ea2bc19bb9b2f30be2d947ecbbef33a0575a", - "0a03f322fbe91d333b7706c1f69e4d64e9c380d321d64351281ddaf02935b171d91762743fdec469ca978e6c7208b809d67ca3e53abfa04bd6ca595e60432a42f3", - "0a0472b66914680a535ba793f799656da089755c49255c340f7221d64eb318238c57ea135cb43a49d81a2d022777388898df455218865eb606ac2e9dd59fecc9ea", - "0a0253fa91551ff2f52c402ccabcf1152374b8321db178a6113720145dedec1224b72cf6ad73a9342c07c91e8710eddfce1920ab5b45b11ce6009346ec64e204f6", - "0b0767169c031afa9225ccbd57fa8097c2cc080e59d933e2c1d10114b55236e720e4d5170bcfb9a082995add5a68c9a6bec3dd457bfca2fed259529a4c5e20f97c", - "0a06a8ae9bce80c9a002465c5272404905526037e7846f415fb7325da27090b675e68af6a052fcd5d4693008d5f163f2d58d6866e4c70c0c971c7aa88e6e1dd2af", - "0a015dec35001ac682fb6f36931f52a1e14d817121a6804ea16475a4e969c255777c727308f747313c2a6e0dafcb10ee8c02faab45fd26edebb96a2465018382ba", - "0a02ff0e35096877b440955f0d0b995b85f9799dc5728f9cece06ea37cf465bc40bd5b9f1523b73b13534cc8f1eb24dc7c0ebc505d56a7db909a3970a3ae31e9cb", - "0b00b3e65209c1e184b2cce50123590ed32e9847624d677e9a008f93a8138939365176cfb35717c22ba6961cd8ce5ca63b61794b6a3199e94e00b087b316465936", - "0b03aa7a57d19706f118d602bd7b55aceb7ba75b291c0e65fcdb77ee656dfda00ffdbb31b8aeadf2a85b161a88339a2bfd9e73dce1c3d9adcf14dcab755d8cfdca", - "0a06cd889e610ba2eb48c5cfffd0ac50973e716040ebc67727a06c951f12ef76f8a4b7273fa62b14e70ce4a52464e3d5922d3074a45cfc96575ac6e0a8b359ca2e", - "0b03bcd1fae01f20f89f30ab738cddcb565331a0826d3b09c18523a56aacbf325977757b678aef1cd21a13b8ebc438603e4977d0c2be9b13d32466b51cc9a1856a", - "0b022847898816679ac0f3d01c0dd55832854fc48cf2372971522e22313735a91cafb089dafe79a79be9a82940779e8fbf5deaad6e4535050759dc2c909801030a", - "0a02448fda0cbfdf79e5b7d8a9df1b053ece78f3d10c990d31cf040d8eb9e1d1a9c993f631cbb03791ac5bdcfd598e66fcef56789c6973422ea8a0dab44283fd8c", - "0b04205021e0b1f3ebf06b2cecaa66860f3f3b489a3d305f410bef32cf09a5b9b413ed29e34d1bb8a320005b9bb9704d3799ad3a94eb047b81f15d54794cacc9dd", - "0b087bc9dfb0369f65f7dcec60c51ae91489164dcc0279b5cd18f6040e7d6d9e49927676ab99351967f7e441b4e264cca676caee048341bf870c1622b69967e9a5", - "0a00546e13b09cb0925fd512717e667e8901bcdf6b5472a75cacb56566dedc196abf25c74660daf5e8e139f4bcc16c9d94bc47fe4db88cd689969f14be798e1556", - "0b08e87d53ac3cf5f7e65c386f4a7157eb5e1439e82a73a57dc7c13e525cdceb2e504c8a55ceb0816d049f03828f610a24db8ccd8b7c23d72c27e44ce0f8d13103", - "0a02f39fc98ce7103205f6ecc4d198ea801b665d25e76a730202d29e91a2bef7a2e7a32402fa13ce25158724ced7064c55246857bf73b13e2a3e44ea6da964367b", - "0b07e6f52ac5fa0bcd1d35ac9c75925b2efab928d1ad17f987d0d645ec82b7c37e77de0894a00b884975db0ab9c999b80717cbf0caeeb7ba3f0c162649a45a472e", - "0a034b9f42c7b4be5693053ffa328249db73ee76257ab31bc14e77fd9d5ee4b3d080a81468e49c2ba161bee2a08b5da80623a4d63f10043c409a4301c9b220ba33", - "0b0793194aef72239618a0eacf4d82a554f591a94d27944cd87ce26b636ad10b40cf485f47b5d6773e2b9f1c04b3b9edb8b3f2fcfa976c52594222eac560b6036b", - "0b006e18e22cafcd6520cb57088a680c0f8389b3771d14fe17c82076d825f3d5a7439371f0be926ea2c688ae25f0769c90f2bd59512fa95acb4ca297bfa87bb506", - "0b0563228c4e26cae5036b7104adf737b820e15e83e7c5f599f97cea15542fd0ba30c7d917f470b6da10198420c7dfb6e8dd1aefc5c105835762263d39ddc211de", - "0a07dedd0ee9c77d8b99d1751f48c437924002f2e56742ea8a3c52b1b66642d1da77ef53b5caf4b680700232b643266bfe94cd99e4c13122448c893cfae5f4208a", - "0a00b15322d760406416ed12b1044c593019eead2deded516ae6b741b9f23f3305d2296a15329051d5b14827a30ccc315525b823d252440d3c374cac1e597756b6", - "0b035afd5d1844f7b5c2b867201b4c3ef3d4de9a0b041c0d8b518195b778809fc9c645f4c271a54b1402eec3dc151fab295b12adcc41bdce8705f9c84f46f8bc27", - "0a072148daffa8fb13a2e9c70f8f030145761a191a3ed6204f8b535acebb17c55e7e4ee7da64de015920c9117459929f34ce1e9bcd44d8d3f9867070676ff54f7f", - "0a01c93984b2a73af9361f50ee351ee70b70a19daff063fe887245b05a9a52c43d7446b22b6ad56451550587d897a0c53a47c3388995c47106d07ea88a2bed97ab", - "0b087c437d250bb3c34c344297119b7c71ac147b0ab80c14326072456ee057fb6eaca6779d820eb157c08c316e101d62c4fab4aa3abf7235f37819e34461e18daa", - "0a007739e66da2344b28e128f70ed679e7fe3cd6f21d2d6ff9d469d61e5655999ae1f1cb409efd1ae715946d8485aeef5cfa5c50e6dc5b15180178c2b132fdb15f", - "0a03b88bbdd299c2334624f502fb7709a28f8306cf71ff1f643dee6582e33e4552b6e1ac1b384d015b54ce5108011a64d4cd3497e515d2ff262ef54ac25ee5fb5d", - "0b032fb65c24fa7a498a2ebd3bb6be35add9851c6e96142818e634b54623856971a3178d74e37c561c1da97c941e5e8ab71e04675c0178abb03856655163c49c49", - "0b08f06a3d7a379da59016cf4eb7b447ffa4ca6b957e8f0c02c465e0a38f7b5f15d0528d6d6f8e480384f7283956b92f20185e2a0da7379c757d56dd1ba00c96ea", - "0a01659c80e322659d6f2e5de4e669db8ebe5f68fb4a87f0198e1d3c78835f4db9b263f47b7c1e8da444ef98e789e072aa95c85c95460116192caf188c9c0657d9", - "0b0304d2b45267ef5f22520475619101dd0d91beb93916897e4f5b185f67344eb67022d72ebb46acd0f817eee218ce789e8ebc505c4b659fae79b37bb7048a40ce", - "0b03f82ca735a1058f5488c6412a1c031bc60343f2a728853454732c39f347d17e9c0fc9d5fe1aff7d77ce1af5918f5aaa17f07bf722ded2965d9307a3373907d0", - "0a040dfcfe06501272807eefdc469727390339c3230ac6ac3d3f9b7bc60befde7dc13e53d89dcd300feb536dfeb97481a19235dc1e56df1b3692eded037f6dff54", - "0b03bdad4729e3d6c992f7bf7ec3cd957ec05d913f9bc3e036ec581eb78b0cd534154684a3521f327651daf3f4b6077fd7a5ccb5b07dbb0d566d66b2592b08d957", - "0a0367141ad8fc879f79db040659f3d2d0d688abefdcdd9ac4887be79c9942ea98aa4833177803da8e931ae58170a6ed7b5f30ac99918f1280e0c33aac95364df6", - "0a03d077f639a790818ef03c46f530f337437c13b9da1c706250e912340c737eff0b933b6388d72a8dbba3d9313aeef8b834cfa3ca2c790d9b2be5a537602a0192", - "0a05f6ad1cc22cd4751794498c1bcd5d23ffc4918411b38b7cb846494abcd3136ebe6480f70c4714888399e31d40f19511400be3775ff64be3900dd2b9182a5a7f", - "0a0835db936b14c00e90f30a9840488597499c2b5749bc9c5547232554c80d5c1064027ad9d13fea771ccb5658d3e3b01ff5162abc54e3ca5c9566a25af51730e0", - "0a02b4dfbce211184362f944e8913df13aec361fa4c6bdc8ff65ce28435f950642c5c313183b8f70fd7eb9398befb295533803b8b039685c1a79ebc45b14110e5d", - "0a07200456e23a4d1ae833a7cbedc3ee28c9cd2b640270ce1b742f9bdabf0ba8377f0d68349e6217b4524fe2c1a42a5071861de224270f6e485988a768aac4c6a6", - "0a04ad9d7c6e450dea62ab45107bcb5fa65fff583bce5223523722d548163f82f861c56a39c5fd2284aeb46ebe13df8298050d29f04dd35e465a63fc2acd058544", - "0b04d77d746115edf244654267bf9cb52f373865e482111fbfc373c4f1cba6fd87cc0310ed82870a348b4d65fa748f685499860355bbe3d66d051f5b16028abcfd", - "0b052359464f6136210b923adcc3067fb701c135c09126d520e5aed7b4dac78e6d6ef14b23a89b2c4dce1d3b27770336dc0a8237089ec476a55f442337796295e6", - "0b058c3c730c244f064216f04493ae1da2d24ef1175ebfdfa6fc68b583693cd3b04f72c605bc91f82c4945a5a6b9d9869e0ea8c6b835a7d9ae748a89aa72145301", - "0b065ea7605fdb7dfb2b26e50dcfe3bc545dd327ee14a31e1655d6eb0a44468ddc295b6ce65cd9a3ab5735fa854829cb63d4f41a1cf663177d3af58b406a01fe77", - "0a00c9908f07232144b1c80d1f9cc74e2871b4291c6bebab302d4f141116e17ea2971482d9457f08a49595aae03f5ff5c6612cf3542e5059efba8c69aff20f5750", - "0a0396046abb6e6ce7f56d875ae8eaf0f4b72356eed9d94e0ff492d1a375bc70a3824e6cfccf09285f6cc07eb7b449684229935238d3f692239db0e391cb3f8b4f", - "0a063ab8d2b3ae39fe1079e8d8aab03fba8300033ff136f3488c280b7cfdbf2963c461c81fe8ae7704e43cf97d5008bb84e2ae589d1663621d3c7c580bb0e6739b", - "0a056316c8f235566ab198d925f94731aa4cb8ab43ed6782d85a5f8e189d527e480584bf581a02ddeb4f33d758fbcca784c081d5c55fa611ed3ac22640d9ff0982", - "0a029fe053a75d587898fb00afba416b3be4d8eea65136b38f61413f81b647d1280eb29986f1166208366bd6e291a39bbb09315e0b5bd74913ea9f37b21d4d0a1a", - "0b088ee140d061c800bb97abb984ea059d7dc490611e92acb9d4fdd536db17796eafc6fc406e2188be502e768eae88bba8805f0f6efb3c64bd9c4c7d40d02c1f69", - "0b040e746f5e7db03fe10f4cdd8c3369dd87862f92210255a799d9e23df967bdfe0a06ea92a095a3fa1de5a86fff7114fac381f61df416300b7f562a125e042290", - "0b018348cb85e5ba99f13345770e1652b725a800f2d57079f323ddd1243f50b41f5fb14f38dc4938e0256745287b6adeae45de86fa5e8b8479b6fd6f8bda8158bd", - "0b063e19298c0503283eb6e3bbbdd52fa1d0031241b3b9776cc79bf635b1f10df6ab8cec8cd0764f308f5032513701fe5bc83c855170429bb32c46afadc43293c1", - "0b02803dfb2bdf341f68f8a1b59b8de55d9a4659e2c5040a1189f65e30d027d37fe4cf4a7df11cd89deb9ffd2b4246b81d3aae83b7591ab0335c6434d467e91306", - "0a02c4d72732b39d241c55a6578242ada493cfdadad76b7088a1a9217f9f32684006b4f0a63c7aa5d5ba0d228186dbabcd2c13a1a233429875b81a092dde672f0d", - "0b01250afc4f2b96864fbfb2cdbb5e51fcaef51f2c6293940d4e2fca72408fc7617a1f9013a8267cebc7d0649e81f23a8c3ab52fc8aa3a983f84f53f30cace2ab9", - "0a03169ad24023a56b90ceba5ccd4894f1a9fc7e9ea914558effabe8181a02b0113ad3fe1f2ef7aa111415f0066fc8429bb44e08ca02022657041d2bd46968efef", - "0a01f540280eff4893f65b63cd2e5483ca4e2e5ae4fc9a3c4fa69c710014bef2f876a4a106af53b62992b7bc5d4a9f46d8e62a853b53c026a186f717a2bc140597", - "0a008f33aed1882d32f98d5cccfc7d93a3f329c2302dacbe88f82e51af88cd6eb8b6e554e7f02293606807457a6b75051892ad6d6531a7704d5ef50662c2230d6b", - "0a03eac5bb7c3df552d58f0025ddcde1606758f07a102ed2db697d33f9da6ea16fdd63554f20be70bbdd6a8c0ef20ab1ce2856fde849a2123b0ee511c781a743e6", - "0b02e492cac8f0f912b65b0d42f16c28f835900816300fcaddc8c809f6271ed6cafeca0a6f73deafd2ad2a658c05e0258d57b1086fff29dfac877367b4210bfacd", - "0b08d8429648173b3593ef1d68d3e7ae7ddacfa5e8c17c8482939da5e09f0ab6f7143c471361c31929b264f6c55bb92d28f26e28a94d94b5a2869543b290a582cb", - "0b0218557acdc9df6ede6f0ddf2d348c0e4c8ab431db00a9b2870080e6ca3032fdc89a776b873c16c30444110d7f3b0ec59ea94cc7849f604a00ea0e9fd800ecdb", - "0b0695343b701b8023d24f201f112e0eb301a58f6dfe5b2f148e09e22c8d83fd99a0f7ef1cf8aaaf986909e6378a2ac1b78ecce10f4e4908788950ed6f6d451431", - "0b08e7ac471ab8fcbc42a75ea32ac6e3641e48cd6fe6f7c9e11871c2924fd9da1456508c1bda49eee74af37032f92d8139ea87f47126a1966eaaa082241370ab60", - "0a03bb14fe6e7d5aa2d8dd169cd7efbc12fac03cb2c422add6ec49f33c0eaef6b1aad845e1bbd985f7e6ab3c92f0c27c88cb554fb383de5c6e1d667dbc2fd1baaa", - "0a07f68ff52dfe8006f8169f43d411e46e0a101a9b5ca8c65c034b221ecf1ed7b551ba192a3222ad1c4683c8c67912b9421e0d4bf67bb62cd47f2ae9ded18c9e6a", - "0a02979b14864ffcfb73a4590b65d78428ec4eba560aad68a90eb8da0bfe238d814906517e83ff72b688d85844f998b965de824d620ca569a10d75f345d0aab407", - "0b043c3d67a17e729f5d3d90b66f494ede6488345004bbebfae6376c2e9001444a6249668cc2db465f38d712949f4f6a844cafd9f25ab524cf2fcc2d6ed0ce64a4", - "0b035a646f3b997fd56a1bba762c784c7b112b01ac0ae91be8740804730c9214ed7eb27f40a9608bdc1d6c76f9d4fe154a5292255035401ffff0373542dbc97d8e", - "0a023a32c818e4a821cefe4daea3599ba60b2770a4fad37acdfc384b20ebdc116c378cfdc800e9d072eb225e2f65ae236b50ab419ad0fda6c21f22e4692dd6fef5", - "0a06dcc2652ce90bc34a53c0943d4b757527a0760bef229c5c379f41fb82c486a54f7dd85bac160d57ac9572ad3c2bfa2a8fef01843c2b2a3e92827aa383784c91", - "0b051acf88d261635ddff5866dba3b26bacaf10cbcdad0683495630dee4ffb1a947ff4085916c6df32a65a1c898a28fdb37b4f22c27bc8ffe6900076c17b0762c0", - "0b01055f9aa1a54a715e9ce277c336fb1afc217908a08fde9b824f17f4fd420f8df887eca3dad610e9aa54e5b7b73a854448543eb53b78ac25d8cffa77f6929b45", - "0b0256711220a8bcfb2cab52043ade2628744c91e9b3591e5d10417627ecf688d66fd1ead26eefd29b69228b86efede27d6be09648fc7aecf00c28543c86e8681f", - "0a07bf224141e0a76cb4bf278701245a1a81b7b8828586839c51bdd1bb84ad046484a985e1454aaed1362b29f59451fa9d345d099f38a565892367315bb30750fd", - "0b013aca0a9e6e850ce73e8badd78a3833590fb3c091e52359e8cfb8c4aa366a47bc0c0dbfad2f2d30da5575e834d32cd3bb31ed5f52f9da704c01918adba7937c", - "0a0240e169362e77670a4fc41737b281deb4fdac97709f3e194d356afe4001cb7680ec9797d7ce5de81369d1d9ea5d1fb7d1ac20534b5d670f8fb42a7ce26b1996", - "0a04a1548f2620d738c08df455cec2a265be75b1a6e9eaeb9f72e602fc1946e1d57c9e869c174a1c1338f704ad15d7addbad72fc78b8f5a921066c4b5e9f249723", - "0b0866b3ecdebc8752d24e551066b33e66d04f20160ef76e08d444d72faa0e98db553bf9027c7a4a68d241ce7d85a64672b56e31fc2d78d71511aa79cfc521512d", - "0b056b5b7b734e14575bcd1b9ec3c6066f30627dc0db2e3a1696c666ccbad0eaa53e8ed79f8cae45c6dbb86b8e75a8860d4645eb95d7b0e177a8cd7b1588a811b5", - "0b02a01c0d4a814f278bf9d6927651e897b3b6ddbadba2042fdf6e58b837e028c7062872dad3d4274307dcdca4a32528d3cd90740e50d059e5c97a9c8585066b06", - "0b05b63600a492035b12b543f7a1036ddabfb56e4185a3ac948e929c5ea323dcc9dd810dfc34e46e3cdb23a1bfd5a21c53aacac7e1097fa2c070a3ed7853c70d26", - "0a05937f0382c2056b61016d7c6d2ab0d7ae1d0d9f5068de670110d0edf70e1a38f831481f458ef03d4a854a4fac3ba5c1266921ea8ea3d355686c678376f40eaf", - "0b008d8003fd8d70e17b1346a55f8ca0a643d2eda321b738f09d49a16df9bdd5a661a75988d11c1d30f410ae7ad8e6fc820ebbb285dbebe965018fddef2c8f613c", - "0a034570faba00ad33f8e2f4cb50496815d845764f3df9c0f23758ce698010b37320694474a863773951cb4e3fcdb759e01daccc57b7cc29baca0fde64a9636eba", - "0a032aa796121ecfe1857289e793172a105b56797483fca476311da70cdd1e1c41a0b99a2a037099ce22f2b99dddc77aaf25db52b608ab0834e2dfbcf8c9ae3495", - "0b0790b0a76968f966019a6fb19b6ca099a1829880cdefa1e8f2c45ba7af16b5d12e236c2fe72ada8c754f74aa4712c962b04fca83b0e51b233e2f8f55cbce3bc8", - "0a029324102399207f79d4f4c0d32a1412fed6a5e6352c0e74b084eab9cd646a61b6c3da9ccb49c458a42e9872abc52dfcd26077ccee52986c8824ed6eb6ba2347", - "0a04626abb72a997eefcba3178c93b121cf9579215225ef7c9f953162ed7897bbd49eaf753aea6cdb13e6a1ddef2edb17aa8f0f5b27fe7e12f925cebcb5eb045bc", - "0a05195889d6f9ac3df3d4dbc017a463af7c39af567272759fcc32e8f214ed737ec33dd157b6e612f1c722629955e3ac7e349c41a1a60d97610365f25d41b313c1", - "0a057d5c13873971f0a7734d0459afa9697a9cd40fb760332274bc789fe1850121bfaec519d32fcfbeeb1818f18457ee1ee614813518a11df342312fd041bf340d", - "0a07b2cc91fdee11e527b5bf71b75b016a01d3554f821987ba46c4479a15ba1f88acd1033e70dd99bef3f482250f9b19c3fd0496ab6ed29b1a22f7e98f16e73dbc", - "0a0101316544c1efd7e17fa7c9fdf4b3e896efea51bd5e11b5a43afed33b5d105be2048d169ec47235e9f89a1181e6faa54268c011a349d7af46480034ce09c32c", - "0b021c670c342194c589880f9c28011dcb190ffd4c90a46d45b87faaade8cd9db39ff70d0016790b56fe4fb82f1d0c214da43860f6d7c7d06e1f2599123754723a", - "0a03c1d78a3f3d1e3ed07f2266ba96351edc0b67eacba24e3cb750f4e5a907b233ee1121ffc39a6cc84d81231e63f53a489612fc75afe6a9676d1fb22f1e2a70ed", - "0b054240924e5fddee0f34071d66216cb0df6a6133cf9ff8b42e228bba5e50d31a5d6f4b2c85bc5144b834d4507bb11bd334f3a32ea517316c40ee10e8cf724692", - "0a03aeab13231b10e4eccf755ccdc98eaab76bbd4cb73e4645e271449fc2f1354f48519356099a4afb4e65e08cede33edf1cbbd1e301e8cff7089c246d0375f9d0", - "0b01ddc15fe3aeff9fe5a1422ea185a235bee4ff3a7bec54b5f2836af1492524a120bb24c4bc7c102cee884359b1e3e140cbbc571fb92785d1d39cf0ac4574f09f", - "0b004ec48973330818099a54e05fef4b85ea883bc5cfd5b08fb0875e8f6f0cc3c88a98b5d32678d4ce6931837a5c717296a05f652cc637344a60f3c1251e0d64a7", - "0b05434c53d7767dcfd0e015f9138a95da208c73b7a1fd1a12b2bae988f828f65c29bb52ebe36fd27165a4e4258e5f6a006ba53ff5342e2217bab54867868f4159", - "0b0261dc8a62e6f61faa01d36e97c663eefa3cf37acaffb37543776ce6abec9c0321e1877cf13ff1897edcbd08faae4c9ebb56da37eac72598c9a47efc6e2460bd", - "0a05913c4fa9599dfac825a8874231f67f8be270ca2c432bf75133608e495d7c300f192c98cd4bbf78c32cf23a94e2aaabbca460d069acde2343f2752a0747782f", - "0b0512c9ee49311b5d15ea2666ce319b0215d74926a8c08462625eab1c0364720b5f579d0026b62edb6113c49b41c207cb4be8c8dedf0b0ac95cd35d67ec41c0e5", - "0a02e531b13a60028ad556d0cc7804b2ee06b8c01857e67de78ad90cb82c30fa30dcd000e42bc4455e2cca7bc12c986636bf90a5a6e7e6b9099fca5d1206eda6fa", - "0b0223dc6bdecb19d1fd9f77de3307e7ab2e60e0ae9966217a8fce205c35695541528b2a492a2b32ee69c3c954ef7aea49578393977472bcd7e38c4d07d3e4ec31", - "0b05766690d53b81da2f610f65e40af78ec31dc0ebf9e5d75ddbe02c22809441b8e5c2a37c01d3a7c36a204ac46f83dc495b49d968cc9f48fa1f82d75d7ae6bf45", - "0b057e588bae484431ba441835b7495eca92cf584d2e29c76214d43907ad6404643aea02fa07f1512d3bbae93afcf0957005ba263f3b648f524afa064cd470dee1", - "0b0053a28d7f6dc1df80fc755fa220fab215f66aab3e80d0c61eaf2a754ec8312db102e264e546de019aaf6c798850b29ba729d9cddaa37e6fea2c68fb8154a35c", - "0b03adcfca79e54c55c06414271ae00d7e59657ba3af7981dad7f870bd8157e4149d056e1ead962b21c275d704eab54223dcc3f0f3d4ebf595fd954775126db9b5", - "0b0507427c161283cf865775fba6d10ba0c4be2fe62d5ddd51e6c24717d05d454dcaac8a5fb192eb87152b23d772d5f26615527ee09a82e88fff6b9e8e8c9b6a2f", - "0a053e6698b71e2a9c3b61063f6057139e760f64441d0ed8445be0e792aa912fc3865859704d4f223c1e2b4894be9e3e1b0bbdfce05bffce4c02d7789613117dfb", - "0b041633709f9632ef5cd1cc797dda05040b15c4ac8c70b8eef1a28ca90927658606538ce64c534218f35f9f272c8c0c0e5951e0afba1a3ba61627e2e4f6d73411", - "0a01064802ba9c5fd3b6dedc73113a29e57c056634ea74f42e21754bf61f61ac5add37d4a7c7e08e5c326689604c98ecc3f90444b756f8729adc6aef26f994a717", - "0b08127627a8d389f4519c083406295a3987e80e0d5911e954bb17e7dd9256c136dd4a28be85ceddcba1ea39846298c0849fcc9f2f53a0f78f32263fa13f09d1aa", - "0b08e0bf143dd1678e4849132af17944973c6d029fc27670b2753c12a1c98556284cffc26adb757c331719623cf753cb103c725e1036df7b4af8ec7c4099327829", - "0b0748279112d30e575c7101231414c0d5e1380d378e233b04ced5bedbab1d76e074274407e1e035510944270b801eecd51cf9e9ddb72bac23d5d2db7a27d1f927", - "0a009af3d17730081801f1c01805617cf0f3923daab2885d9e014f90fec52e34528ea1e4b2675b6f5475c18f5ec7580c264d915568ef8eb2700dd7128342583e0f", - "0a07858d22035919758a8d25a067299987a3d0fb50c89bd6d0f27e44af0957ab794e9a625acbbb63218d746a892a8c670d0d0de1e7fbb219041f00e9055108a0e5", - "0b0076f2e8b727e008f70696c5128f03e018e2490e32aa007360ba0f997189bdd1a73c8d99f73c19ff96cfc6cbaa2395910c45f03ed33c84c3052131d8e3e6885e", - "0a08dab984b70bbb64dea5742e8e3c6726cf96bdfd61a5348db45317b3ca759be48f2e721f0c53646e2dbc9a86f1a9a7a6e309a3fc4da03ea70896a37d0fbf2a6c", - "0a01aab7a620d1265f1ddc0219bc6620ee971f222f0e4cc7587d99c18ef542e4451be1fdc6d97e4caea0139a68fe5f17cb1cefd9c047a6d98f700f66b5a359f002", - "0a055ba67df848d778eb174e1b1d83c762377f74a5faa155359762b87d4c19db53f816b17551a6b7d8bb863072ec984a90e1b3e8d8467dceaef2e08077ab6238ec", - "0a072fa5661b0c551153f952bdcbf068ba5832169ffdbfd7fb3755c4a9b0df467506895b1bb20ff3489cd0921b5692f5a8c79e551561985b606e56957810598366", - "0b02fad89fcaa989c912f71d7aa1346a455cc32058fbd4543327075a5ecc49e39f5df6ff39577b9947b6d72787332c35e4b8179902f55565c3fc3526dfcc50c3a2", - "0a00891f99fa01d3f3d9dcfa9d845a3dc5629ddd66dc4b895fa5443c0c3b2b6bc23a3decaae6c92da54448220497e8f5722db739ab21cdeacc9638b25d9cc1b5c4", - "0a02490a601c587bdeacfa43a24ce70d542f2ebbe3494f01cca1a94052f4412e42494f4a373f1129dde916c99471038c8bcb7bdeab5497dc1c6f886a650ed7fde1", - "0a03883c88415b744438651f19c0e13aa9f97dd20d67927c16cb80fff60a41ec2340567780dca24211f8213b454cda6cf067e68c1807992aa296a99960275cad0d", - "0b02470152cbf4c81a7dd54c1e53a65aa84851c9c8f5b4497385c12a962d92e3f78df06451e924a15ba5f39852e0a52340e81a7b24cad76731145df45185add486", - "0b048afeb8d42aab9ec867b4e1fb2a5829ad4294fce785934e32e3ff47949812dde45140a04529e50609bcdf3d86f802ba437d53ccfcca3aa7aef6958ad4a73b70", - "0a0914a61516827f3c788cadf998300e76dac82f9413ad87ef123ddc886fe8ec0fa2a51b82f3f7e540b4dbcd73694edf881df5ba3d4759f226bce5985e027afbc7", - "0b084253a82dd53abded7a02b4d1f31e854eb360c69afd891008d34a60fc76ef4293ab7c36bc48103870bbccde1373deaf9c69ccc53167f5472a8d8365a0a91315", - "0a016e803aaa02200d4be37d6bf39ba48b2f88eba623ce28af6d8b1f0fee44756e54c9993ad0ff64c47a85e39da45521c1a0e43c5baba79feeb45a9b3502a51023", - "0a057879a4c9a908b8258bc45834a7d52a990a547539339b54cc31c4e3d57643c9a86bfbf80da59469318d1aa69362cb4372fed7fcaacc971be5556792992ddd80", - "0a0583421f63bb1d9cf693d6b1e12b08ea13ae146c900a33ba9fa31613f0f7de13570b2d2def92fe9cc5e6b90e02a91592123db08ddb88f5163436b8aa7655bd32", - "0b0665a80661c6e452de8db5ae60fdd966859a8abe4866dc8403fa13acc020ff0acc3fee16d46237e1bbae187c7894a88c4ccd10ccd98c2f7dee799b156f6d1bbc", - "0a0897212cc194e30d8baefba8ac7445b90bf23c86bf8ad62d24fd52d7b19278ac62b784b72ed9ae1e1ae192e0d165c4b551ced83eb636f597df0278a356e7cbd6", - "0a03819a82174283b7615ef9a54061f8996a20bfe98c6740947b7f1db15191e60840449ba5d894d1e38a37a599901e1d0a8a104077fa3ed4748433836d82d6f604", - "0a014a88930d1bbbf281f2349d6ffa3b84c807c18f9c83ec08a534412059856ccd20f2026a2e8acc11fec0ee383c66dd97a6568dd126742441b31bfbe21248889f", - "0b053668c2c75d7353c2f47b5a55c4692dd8d597b598128a4996115f66592b15a6ce4dedeca8458228d5a1808820da6af9dede3ac4f0d745891de469e556b9fd62", - "0b0812a161b56d3068b9c956589bf53a8ff7fd43095586bc56199f36cc0b29930a345b8e8570cca1b7bd1064139c5d7f6177793a477d73cc4205e7ac05803836e0", - "0a066b6982bf007ed5fc4dcd907e9cb7e70be1694ba659fd2f56a6f80013ca4975dd90e29c14020acd83ae2d260293f2ca8545083a1e20eead88e37c326092d70b", - "0b065181530da2401ce41f72d168b69a82d43cb5cc2e7c7495b0b3d5436b9436a5e6bb052438f2b755314fc9f61fec4bea5bef44cb294e400b1bdd8542c0e7170f", - "0a077f3130dc2ae193170a2331d0be1d031b6c7f03313e9898614e1cf404c0f4d041ce01f1445d048c57f24b7e5d93861cfc64f4c38f444a4c7e77c572f9a44928", - "0b04a865c81f38a2c8c1db2a1c83baa47592dddf059d82c877545cfdcff8d4d90766caa3b12dab6faf58805935022952dd2d7b2dab97b2b29b2cd42589c3fff37d", - "0b009745b33a162c919e3aab3eb7b0cdd968132133127e0560115483036de0897870cf7620058e8880ee57cd4eaa3ee38517bc8a33d748b78b12911072d481506c", - "0b045e7fdc6c38eabcc09f4545951302ab4a24c64eae3214cdcc3a06cdd6dd006ce78d83ca38034a2090ff998765239388b72d364dfd9ed722bfd5c01b071fc2dd", - "0a018fd8ca9201725d211200b549a69d80f0d7405eb47e561ea83b6bcaa8e26e4e70755af2f8c0d25099597d6c1ee717128c4bacdf6c52e29f8f955b63396a7310", - "0a0714b02e25d40a8b5bcefb20f717a1f4e18fe510aee0668db0a8d3507cdb5173518fc91a2f8f8aecb62e2641512ab64e07e1d19e35773a4e7ef081051ec70986", - "0b01967054be04bba81a68431c52e61ed50842ae2b9cc72851c29010a90d93fa08bf81897cbe8b78a691af29dc5f700ee859f13fe47b541feae6f1ceac7abbe48b", - "0b058b4ff2105067dc8cdf7f31e9d603d62a199bda49a34aeffd72da03e52ce13c0adb1a53cd5bf47cadd9f548d19fa39f86d83f39c6719bfb2fa1b87d746763a4", - "0b02ebe36defc4b3e185e11562ff10e5b6ff1a8a572cb5fc854cc9790cc37321cdc18e90d54c15e11b67cea1c1461b3abbe5006666289918f77b70e243d60710ac", - "0a0254639ed074eac3205a81ba475130b6f75293592b83b9f88a2d8c1a354d14d53cd99c7699f5d8554b87021bf679930f8678fd72d6a273c4de60051f35a29580", - "0a08ece6d08686b128596fea4a72120636c83da199082b2546c7675e252db17cc1e71d401aff91113e01fe2a5e2ab73b41ff404d1979e2cbd5b01d8d07c6734891", - "0b06162d0ea96dc8d86fe382aaf68d38b712926eefce752bfcae6de7fcbeeca889adf6a4dc8bd0e250fffa8ac482d76142f5f2afcb19ad42180ef0ba742f470a1c", - "0a0204c026382bb6f97858653db3ee9447cb88f0a19c3c4859f6909acad69096d3959abf82d319eda28359e7983023230c5be7eaf5da170645d9293fe082023d72", - "0b02aa30de0acb0c4d0754aea50075951381c779b4571cef090ab4aef5c3a24c084c7720eb32f30cc07e00509d60ed933c434c469e0fa7388d27eef06c2473c363", - "0a07fdfd9ad4878b79c22f7011f6f0b7dac5e3788b67cc3208f26f00b23a47fe0e39e0835f31fa38881d56e213ebcd62b59d5bc9a92d9140ea9fa7a9e23de17440", - "0b02e9dfc46a60a890159f9d220110b33deb6c98e65e6089cc4c58ef1980538e89e6cc839bb912c8f17482297b96bfcec20ef374b22acc2d307cae14c0649cf510", - "0b06a219e5c2501ac1816647d2af23332d192fcead8e326fe4e9bd4fa3257533e7db83ef5de6f9d878c46c38d8bc5de8214d40be1642066ae431501f18e64dfd98", - "0b0762fa5e89092fbbeed566c264fbae743804772fc745622aac28ce820284cfbbf6d26afd80c8f81ad458ef146e9832f53ed8f431392e279097bac2e3a369ac21", - "0b0199f6f72502bc14212162fde59bea309ce3b9cbbaf0186578dea281f9ce5a0a75d00cc09e32d24b0414a8a6ab6a697421dd6d979aefad82174b24efebeb13db", - "0b03761064ba676ff7aa53ec5305fd835bf2eecf7d530d70bfeebc11c4e1d70a58aefec2aa4fbf4e88ac41e8b7e85d0618db4a3127889da6b9bf7ab8e38e3ac4fb", - "0a0177f27048d83163e0885e7a8ad32a096646613bbfb0cf128fb0e1afd7aaa7115ed78c1d3b327d5c003c04c85e5140f317a2bb244d9169aee4dc7afd730c16e2", - "0b0500134c930dfd604349a103cdf601b11dd0dbbe04c5e50a3c017cfd88d0930159269489fd136405d0b3322062386de4a25b1c25faf3adbacb18dffa10b69931", - "0a0417bc510828ce1d0209c3dc987d06cf077f1216d452a56f197dc920e33b0f56c9d68716168a0fb951a19cb391d01659c96bbb73fc5fb34fb9f8fea89f30bfde", - "0a030cd4789a94b98c581b3145c7b44d5e159ace18e700bdd8161713da2c3bf5049ae81a941592258f15e7ddb3b9729bbb8f5540e4a94e5eb8d333cb244906b15a", - "0b02502b848414e68d4cde4b4a92e17bfedfe6edff1b555f368ac15851c02eb284760e20a2e99b2f4832335261a38dbc713b3daf0dbaf1570dfd5f4f6e7c586790", - "0b02ced808d565e81a82c413ac6c9f9a28428bcd8451207e1784f786981c96a9a97fe8c3c6d9616241610d08d6daf0fd3a0b0eeb0ed4f6c6a3d11278d412f2160d", - "0b0218d2a189caf0090396851771d3a8d6748ab53397515bee67a01cd88562c1f26f06a2df171847fcc6e7d664d113a9898159450e8f47d4f52142a3536b10054c", - "0a002b1806c339c5603900133338790316c511c0096643fd97c094c4e64d2e5a5103eee414907b8bc988e82adc39bfc722025f71c2533599d848d381cb77c69910", - "0a00eef4bc201795267ae14b7a2742b33a00edc9ba454105edd0a73d9b7a90cc59f14d51888107b75f88fac92b5a726e548a573ec155a91d4446155f323e91a07c", - "0a04350993bfe46edfde9f1c35eb1ab7c2f6ee274cf81946e8c68e3657688badfd497304400f47fb66be8f5ead3b9d7106fe3d70ffcdcbf8db2767c12e4ae415c6", - "0a014e0b4d639ba76b3221f6c56ea42687eefc7746db9175a27982d6daa9509d28f43dcb9c01520f181e08cf4e2d92ca24376a6d9fa6ebd6dad2e221bd1e651465", - "0b02f470b3405b93163c7821ec224f93e1f33e0436e94fc7c7456bc1db4ee5f4ece422334955c4b9fc1179b55be6dca20fb5b15c91f9a28c9db477234a7784a9f1", - "0a0449d888a8563e750eb41dd1cf7c0aca31e55e69b3c6a365c8843bc5de70529ee68893d3b59b491cd6425708a63bc6db45bbe4b18bbde23718bbf8f2285a79ba", - "0b083449291018f9badee29c662e1e8cf6788db43988193cb3b9bda94b1469d61c894db180695e2c99130b08dc298bd402d5c336e1ec42bfcb0d4c12cee141ae6c", - "0a03fbe50cb1384e0ab4a21b360ec53116d1fac6508df9b2c217ac6da24d592846d125c993279d9598034f31fe2d90b3c8ea6c78eb18dfd0a50ae8109058a9f14a", - "0a04097007219a03956e15a6b2e8e961151974c4ea3baf43bc6cb0d6d752309b845df265d6245a2983c31bbc67661143ea932a9af106da708fec9d238528577e2d", - "0b01a3177ede920602f739e3c78a530242237bc76905b057fe1915906f3b8cfea5b547d5c7a55fc1218afefe51a1bb10f256acdbdf99069a6a5d3e129798feaf60", - "0a07251426797e8150850e32eede24c8175cc44c2efe02db29587588fd8f11f1d99c5cdae6cb9bb2c7facf8e3094e15844f40c09fb1ddcec2036fd1890d7403ee1", - "0a08f61146a403ec46fe291bcb0bc4904a38fa61a21116261901945aa4b6f19b823ba39faffc3e61a6bb414c314cb157cd748efe4ac8e173960246d376d2bad5f5", - "0a0747ac6ff3c1ac197e007f77929ef214104ea5a8cc77cd6398afb3b9025a16695903029e05250bdacf3f529df66154d335374a2ff5ae7bfc6045edef2a5d85c9", - "0b005eb5bdf8f8093b04ab6961a2ce4beb7aa1b72a4c2b61ecc794b8efdcf2a93e278b7eea5f7bbb155d6fbc5c4aae7c27698c4370258e252c711eb29fd951c739", - "0b071e6a0e75d37ade44b283a9a122e69d8cb2649d044ecb2c526bcf55b37337917eddfc5529da3e37b89ffa73e51b0684c10976551edd7984d24abddec49b4e98", - "0b06c00ba1a55662d43a303a7ac34cda44eb51141d03261941d8dfdd7cef04d0655fcdd115be659a8881869bc146c38f5fe5bd1abc612a152b05928bd0d5af06be", - "0a03e28f1c31cea08bccc98d844e68a6060360c8041cd86835c52e19a0603cfb1a17bca7c064c7a875fbd1eda52713eb9d2ca1b082aab76a7dc99fa76f9cb04880", - "0a02ece9a92c32d8acd148fff8528a491bbf4fd1a96206c75cc647618300b68d00e200b84f4c459e2909ff296586726ce114864608711dd94f0ff8d0967d9ce65b", - "0b0857c6ad0af3a815dbebec0998265b02d70b8e31117d578be4ed9c3a49958fbc745076b163a14457313735408d294f8cbaedb337fd311fd555d5dd6eeb93f0e3", - "0b04b314f4de7eda1d461888f9126373a75c7c9e0c78593ed0bc09bde494e5b709137e31ecd3c6ed941e5e9c2c625596e11d7642e2e9f515d81d4c42b180abceee", - "0b06d5be7676bd7c4e05c87889ba9a1763cfbb4db5210d0263b20a6d7a8d890e1437ed54e8e1a5b107f44eb136b132e48ed61c507b0f9a174a2d8e2204d0a58e13", - "0b01bb76c51498b60b6030fe7159483fc9f1de2c29d19e195bd3cb4f3f803a02a39686eadefbd4e586e54f31c5453468807c591787ee726fad7c63096adf0d3722", - "0b03a09e23e4b72a9d75fc0d6aa94e74021a893df89e6f3bdaadcf15c591042f4c9d2e73c0f0e357bfdc62c00344a70fa2af20f601f04b408941979a2884d7ff15", - "0b02b8c1ee527c735335e0bec224b261ba9ae186e65ee4813e62a6187f8cd4432867724bcbd7c302be609800b0a70c7aa187f9d3d7c13728e2f526b96f0e6c4fcc", - "0b0744de5a16b451c0d791f40a00e6863c96d7d7dc2c2ab37bfe1c9dece6d5839bc6480575bba67bc6888e08a9ebb001f72ed3f2f257c3ae29852f11ea1ef55968", - "0a026c0a75861fb02516918eca7fb6d48a107075fa3747303fbeeb4fb60690f2a673ca9c66c4873a08b2e54b003ea609c411f815755a5919b63e9ce987658cc794", - "0a08443b03093f240f8a2440146cf3f8d1b4b497c4fbcd960a350b15695b91eaeaf52297c42545c765423ff41937ff4d98f7db70a7cf6782576c1b61ee1c54e191", - "0b0447605d62f2160b703e3b52948d4a5a97027776cab3daeb3d2a36ba61febe7fd2e875a8d8218412f0a15b91e9b1918714532aff84f78011c008db2fb06810e0", - "0a03b35dd961f6a3a008e107cada416b9b0ad2010b6503ad69f57414088abc1afde3db10f924993ff25122fbc6b8268e507416188a0f60b35855b7e46167443235", - "0a03a134e3064ff5cd1ec8c779623d6da3df14688253cdb354f7103fa47cc9f9d3c6b850e11d5c285f1265993475e58312906ddbe770a839f9a1b3dd38166ac791", - "0b02c520da7cfa4a4b6bda37da30ea05d6a860950984f959725bc3f23953331809e083f14dd3a4bf77eae5c43b56e08e579a40b13491c9a6d16a4398c11c090d53", - "0b05010deea8deffb2035a6a3a09c2e308bda870ffdb56dd1139863cd70a189ed8721a8baac9ba47c389277ef8cd23fb4459856dddb5acd343dbfad44cc9e904d1", - "0b053b21fe550e812de29eb9a265b9bea415c5cb57f786494a251355d1950605f5e4835afd821876de44057f454ed3e777b4c76ac61115a9871a1fbb550404324f", - "0a0585a5a14a6c2a9d51b4f9dedc2f04bd147b5e21637ea51a9a46aab90d193ee1d14f4bee085d1b808e47a91875d14e48e4d8c8290fdb67695adb24e4507e7220", - "0b06b30ecb43d78b1d031d52e388e83e5d55db15675e74871869449d8ac11b00ef5911581caac2526bbb3c9a9818b8ea5142b0eb03f46202a8fa8f2d393eb08e34", - "0a0078e28785f200f73d9e02758158b5ba1c5c668fca010df8c9cbfbaf7fc81ff581d0b047b667b138c16e5489fa71069707cdc1630e32d35002b73b5e6c571047", - "0a0607c6fe950a7c08987f239cb960491949324055b0e17e2b2a64601ec521f274f107de301625b18ad0e290f8e440d9a3ad2bf61030bedac6523931283939bf2d", - "0b0067526cc221a9e9fd9417994aa760dc6b626fa67f21596396fef16d7d1e9d274dfd7dee95400f165418b7af3584aa90b8b5a71d7038052ef1134dd1c9cc6fcb", - "0a068a4e6819332d869dce679db42d0286f86b836a04e67eee6d2b41b86d852ecfc490177ac212c0d78f37ca7d9f66f410628d42eb361871145fdb8831fabf063b", - "0a02b2270e7f096a70cf3dc445d86b59ddf7a1b95c455b5897c71d9149a1b08d00e0bb71ea88b4a3ad1538e0b3a2b2ce41e2b2516ab3ed7574aecb4218ecba14a2", - "0a07a6a87a7f7231679c6e8fe8e67f03afa45e58bc67442adb984b0df085a5c92a658b6bd53c02f877518c7c3e8385b4779b424fe55fa93006ce72f0c03cd29a58", - "0a057250a319ed0a8ce57bf2656e4b6c2cb3a6284e61a6a83ca456912a060f5509498fd456ed083a98319e8a0cdcb6c688635e3bed4728a6168f96201eda7cecb3", - "0a06ef8fdb74d6d6167a44a17e54eccd0c0f5e69eaa9353aa75ac2d7a1ca7231a6b6cfb64074100df7e5f03045f0cc41e1af8a0b1632597c5b9ced9ded69affa1a", - "0a080fa194ba2f8510e596f2b0edf39718a0bb3af0057b2a7543ba49ff3b62a924917d831a70e0874cae988041a20d9dc7c58ed20d4ef9d21c52d7d52fff83bd64", - "0a02f4b0ea18e267e3d995157a8ebcb941942d281664dcf9f6c221592d20e3099bb62125390d154515fbd272ee49f31f6ed44cc852b0c52eee5fa3e61c630a9a3a", - "0b07e9d1023db6a6a494c9517a5a3c20314841f423d72cabd9d4a7b824326fd6b2d6813b423fd278d7d12a35e44ae44c32aa6d246a609e1844b033b8354f4f2ccf", - "0b0421a4221c1dfc36c2f7a4d3c9ba43128f2614dbefdccc19eb1f650b56e31352e5d4686f34aa015fd5f6bfcf5f4facb1ff71cc02dd9924d537325aea157a0984", - "0b07ffaf099a6205d78bd20b50c5dca2aaeb68459f95eb160d4ecbeac5dd1733a88daa7131ffe867113424501d7cff13de27fc61c56ce1d75adc8c3b16ddad96d4", - "0a05c30eee6458f258d92b549ce350b3a6c3426a6212a8b799c172f2d37564219d5ab840fbb0b88b1cae9ee5a63ea2fe8064f0a3a4373db9e915b0264ba3e95623", - "0b0773bc7e3557a33d53ffc9848aa43fb302b36c17b604dd4e8497fd69e317d35c878ea77ff8bb60165dc857e60605fb2b52b1c10bddf1d46c30312e29be9bb4c7", - "0b0463dd6853739aee87ddc11f222dfe00d3c61b5035f412a23764f78da7dd16d1f4691e68b71efdb69b512a252270e4caa16cb7dc71c5561cb7c4b5572628fc13", - "0b00f92d5b6730e60fe218b15ea6c30759aa6e496bc853e124e439e4f9c847788a63cc8df005cef5fa0ec2e425166a0b49ae034ea77baa088e7c49a4145c4bb605", - "0b088d278e61f77ee7a85bc004b79322220cc7a18beac237f507f29834facb37b7230812be47152f7eb232760b49c2b4516669351762847525ba409a0cb793dde4", - "0b017cd8e3f87940b188f2a59260fc1b112770ab54264867fe6951d1fd861370c5a07e3e0fdcc002eb7f8be05148610237f9a0a6630ae07fa3f54977914d80aedb", - "0b06bae6bffb54e9dc6e0d91c6111c412cf58edb30d087eda8e26bb794c1975ee98b3d9cbaea50942029d6bc40137d442567d06bf45e7bcf8b0377c2c9ee10b24e", - "0a00f40e4482f6c2ac46e338e3e340ab44202acd30fa49bda1290d20f1d59dd3a20f62b8c919317745ae32879571b9c4be180eb036debd427c2eba9cfa9f6d7640", - "0a08c30bbb8930723dbb6c286a25830dca601eefe5f5e091b47d8fee44aeba4322fee9d1800797ff909088697c8f1fc51b0336410e4d5fb29ea8eb7e07f5d9048d", - "0b02c78a1e2578e11728228238017ecb33e4ce9f11a8baa8bdda3212e42cff29160162334f4a40c31ad1c430b0d54e82765e2904d1f89f7a85bd4cac23f45520ac", - "0b07ef7967a854409d463ef85d22ca65bc9c2f68a3092a13902bf9c44e83b5782c4b0ff134f8076ca31544fdac0b2305f915b55919b47b183ed3924cedf15f4c85", - "0a00c2ccc0aeb3ec9d3b9dd98b0712ccbe9d21c2352771e2d37b7759dc563ac6f04c1097f152886a01cf9de7a6d451076203155eafc69270e23351832677dbfc8f", - "0b04aa0cbb4981f812124de6b8865bbcd56c19635025a61283df24baa9ff95993ef4b3404cb8fc186504d3494a6a3395fa5e0fd686dac7d586d684ddb33d115af1", - "0b034bdcbdf664e7b1a8ebbef723ddd270bd69b196c76bb7a16bdf5b238e39f1016518dca85baa73595bc389f5ac12da65178b18ce98c4c03175ad538ef9beee50", - "0a005fdf4fcbe560a3c1b77f204bbc98026d6289a4a729894c027a5ea64789686ad1054ef9d264f1bb7436f5f80eff34c2d4ceff6864c43dde2d0cf2c7fdb1394a", - "0a08f8fbeadda5709b5c6f15b794f287b94dbf8353a964d175660c09e94a6ec1339bf3e0d6eeeb6ef8752525fc082ae815132d8feaf6bbeb9d303b5bc9c43dd353", - "0b070999a921a29675aa831565a791ab3b81ebc5850ce3f7df968335fbf85dab9efe1dda0a435a68af15d211588d4099c874109f631b01e64796dafd3db94a3713", - "0a0025d4436d127be1ab1929f2ca98c3b2036d2d87bab4d491ef59a440eea6ccc57ebf32a857868f7d96c8d0ee4bbd82dd8181e229d7b8b5776134fdffdf49d3db", - "0a074b379be6a0570a6c3bd819a01829df4d9c91a74ca004eeb30db40b0cccf1d134df4cbc17212a617667df5bec9b3854796ef37399e32966313a938c8129db5f", - "0b05dc4852ebdef1e8b0a58ac56ac13ae73ca5b951ce869e7068b99a0098c3f1e444dd06424f497b40400f9553a17a65043d9e94086ca965e9fe698e1fd8b572be", - "0b071c15679bc55736c9432ee9e2f2bdb78a4993b1c02a0c906a6d63ce4d7cf0bd977f8b153b64b5db3ad8cb76e03117901ce94cef3697114f81cc34f2e4bbb4e0", - "0a080a3f300025512ef110684ba0269d928e568a66ec272a96683b3b20ca99ca74b44ef662eb5d6bdc7d0ca77d78ca3219439cfc6a26e566bcb38364fb6ac2cdf4", - "0b0258758bd5885047d25bd6f56ca76d6c3775e422b70842dfd1adea51cb11315f0b59bee0c14758f6adba8079104a9ef3744c0efd1ced728b025b0501a7045ebe", - "0a0063bd63def176a91ca4177742e87c659ccf871c1635b5e76709583e1d64259fa856b50961c6304e1a6bf6561472531355c28be0a5d180635c5194bd2c2e6d6f", - "0b0008d4cd8356ec702361fda3bd426708eba3c7fa9daf57427cc0c38ef537805c2d5fbe7640713724042c6b66a8390a291cc7765236fb153997eb1df417d52b93", - "0a090b478b10bb3d2fa0cf3e40df4f9dc60abaec5361cdff2d9df5eb4dc9cbe63b09222afb07ebe2a96c48e365f606b9c40fb7b36dea7841a047897e9321268e04", - "0a070b34240f498ad0e0d200b724af789f99625c914214622fbed93afd3dd1bd14a2d0ae2899d9e27c02a918c01178d311bcc153fb5ba9ffd2e9705bae9fdcfbd6", - "0b07d549d907317342e92ebbd6e5748d461556bc3d005dcda66d20c4cff8c85b8c7bd1b51a806a1b8b5f4a924b9494de642073affc396fde8e3d2fe7c7d6bb9f10", - "0b02f9da25386a6f8ac184645ccaba7458a1a74df0fee0708b5d6b8198c7169377c7019e4e014d5e63fff2be46789be653e381416a8a75f02293655092dbd3738e", - "0a05775a6b485b659d51e5f1494dcf57430ca8db03595b9c274daf231c9efc1f8042b8b9c75aedb4a2d6698cb686ab8eaff584305a64b19b7e461c3d8095bc693e", - "0a00e1faa24ca6bfd9f91d37affc3d2d91be9cbe44cd2a69cf145ee9a06d86b967f4f77a937c48ceb4d0cbcf08070d164321574b9d494436aee344b4bf7b92fc26", - "0b0022a98316a92b1cfac2728ceaea62e302150aabc7183d912224af6801a756fef5ed3dc604396fbe8975ffff19273e03fcafd6436f491c091cc3131a74f680f0", - "0b062e206d48019ef86a2139abc47961292da4616cb0350f0a16ac7da50e7229215a17f121839c305f2042e46aa55552c94a07f1b349f808147764471101ba3527", - "0b0633d57f68f2ef55f0151c78b5b9cc17307c0b8e10a1a6b31b6a09d51b1a9f4dff3feec04795cc2af2fba20364f63d87960bc34b57d369e0239d981d16adae99", - "0a07f9dec460c00ff0ddc6f2d56943391b8064c9601280b639ba3e6d2f32bdf1d3e24f2dc93f44f5a1b92ac74229729a1469794aa82fcb01fc9608ea539860eb4f", - "0a05f4cc54f9954d37270f057cdfd568f6d242eb412050c005c5bddde8d1ee565cec45f36044e2f96dfcdfaf5185de4192584c03274c6ecb0e19ce7b111c6dc190", - "0b01b73f8fd6572671fc8903e4622ba016a20e8536761da015bc94bb73691d1f549e9488e27c58ee7f2157a692119e781461685bf20b2e4427a0bd3b8cf2a8db3b", - "0b016265e44fae11053bafc457cc2745b54c49f2d4f4da88d8c062f1f966e83de758f266057dd35c58387e3261830c59beb32b1a5a09b06bcbab81138741ef4b1c", - "0a01c003b5ccd5601273c2540ba4b65af9209bd74a94b9856d9a1e1bbcdfa31724977017910cb40f13c09e4fd0f54e1e7eb9fb5bc9366b84e48ebb05f23e97ea89", - "0b0504d456a7635f0e48605ec613b14c2e17dd02f434d303d99236f99d720ab66a449b25cdd26131bbf049cabdf92863483ac08c9a1eef8e1f0932e6c49d7fe0a1", - "0b0467e64adc7c2268a343706e025b1818f53850249b313c8e943be73dfbfb79725650b85f9d98499f24513cca3bdcf97ff7f095767977822fcb71678f5d3a46ea", - "0b03b4bf54ef54dd4e37544c357def8c90270e887ce127786738f112252f6274a26d8c528dc0eaa9520aac56ee35a06fff66edf09e2fe141adbbe3580afacc9da4", - "0a03eab19823e42dbd7a99ae5c1091384c588bbb7473111f5b6d80d6f9f5d8ab90b091e3444e8f9cfe6a7f0f7accaab95029a4546171429c242d15354335b2498f", - "0a091472b02a3a8ed966113b38393642ed4eeaf46a1c8101b5f896060090ff22c2b28455c97e61f15480d2ca0b30965b36f41e66078fd6aa246e2c4dc9c1ae2ba4", - "0a044a99944474f4f5452238c2742defd456447f43949f03d0fe322f50aef8f4171e135061480f83829af5752b7ed0a86931f706a27b30a877a617be4fcfc3d3c3", - "0a006896665907403b609b2857792076e0ab7453d69b3d302f47bc968990ddedfed6a6001f5048411bb1a35929f8ee381c1563d0d6a47842077f6796be1b78e3f6", - "0b040d62c4ce841dfdb2dccbe0d96e73432a3bf7615ea09745eb0f34bfa409a5d0393b85cd20ebac669f6f7f1910d36f04d5ab84f0acfd2f7cefb9324da8dfd011", - "0b0219d808e8ebf00c2c010b92d306adbc70aa8fba74d761c630af9483a36562fe8afe54329e3030a1d8364c8bdfffdb8518a5065d7fb04f7237a1b01f7f724c90", - "0b06523a720ecd4d1f37718656be0b98da418d5d8d6ab0849bb579934b0e9b8c18c6e4e3af327bdf917eb28bb61967ccae0a22845ecf09541bbc78546835f55a53", - "0a0504b36c174409c5abafc865c1659b67c1d13b8bbeddd3dac6ade292487f43b2f83f78ae182bb8893a6070a09101baec6141fd3b5ea069c6ef9c34d8f10756e6", - "0b00d0d30d48a6b065f57e7bf1c15672fbf4f8918f44348846a386ff40f7353a0c68fb0cf2f66e7c21cda43f77cb6c6d9c6d9a86a5ba8425a2741c88d946d53d89", - "0a04aaf35e801012e4720c03454f4e2c23ad01528bfede6dcc9e05b1c9949bafd33f352e3083d0f232d69801b77b841dc515fc83d414526bfd38d104089e3bcacb", - "0a02c4fc378fce44f5b5fe75c753b576a6bf03568ad4e533f864723c81d7c546dd6d6f65be0dcdd3d29b202b613446c79bf972ff344f2141c70c31ea2394c85e78", - "0a06bd5c6ce3201677fdfa74d4bbcab9b34416296d7d0a8119fb7ee9536e8315ceb873cd6346c85fbfa830aa8031bfa4b8f489b165b4c7eff495d4bfc5ad564259", - "0b06c487d82f720ecb930a6fe4e5ab0f0558508c9f9980f5fd3e7e19260bf4778beaefd2e97d11846f5e24144dde8ffb0a6c33c430a0ece467d3b35a51358a8647", - "0a0415f6eb1d45df580b4b956b7b07b0207200c809ddded763156ec5470d5f69c714c2014dd6526bafa9a083e8837a3e331251151a2a20e271fd6492a181343e93", - "0b04ac416b24cbf451f6537fe2a22224c1a5ac8969b4fa0783061ed153c6eb0785af372f3586fd9ce997859b5db665e4a1dd05c850d7d1521c910774d728f8f499", - "0b04ca250a2475ebe0f13f780040dee8ba915334d04f47e899a61f4cfee021e7f08565986e29dc47ab71df4a1ad47bc3946cea71373d0186902b6255f073d2205d", - "0a04d7655db64fcbba4072c87225de3750803c1be8a3cb6d599c9907c2c2970c2fb92319f66f2d444ae6982106c776a3ffed6ac9b099649793f0812e4219bb9af4", - "0a07e3ef1f0d3b090f42dedf52924ddf396c1f749bf330e6dd6b2c68b1968bac480502f302cef54aaffe727d4cbb6790bf6f570c10f792c1d9c2bca88f579b4033", - "0b003f16cebd362fe2bcba742d02834e4986f81095bf9a81610e8b3d424754c4299eab3e931449a2bcf43fe8f6f708c22516f3f0ea05f7cb31175b2caaee120277", - "0b00bcd7325de75794b4de11396529d4e0de66a12e820f80fb293c4314f863c6232fe4b0ca8c31e0d220f49ebf8f361d578f3ef5345e9f87183dba3714182682f4", - "0a04753daa0dc2f4d7c958a344932d38b2c93aafa481e11a8970b1ed9756989d041dc7f2c7ced6795bd419ecc71f828d80d39a7e7f63927200889da9b169367789", - "0b06461711f2097c84af1f07b2aa8b35ea33c3f4b1387c3c396c4d275140049d1d49480c88e6b7271e5abaef8ea06b2dd5cd6a9800ea76c1c12f5be29db3c5cb80", - "0a0011ed4e321de70cde9ae4ec499668196cdd5e92ea257b4c50d82c474fceb92228e78e2d7888d522112cf70b471837535ab55e08e77015f3521a8c5c6c338d37", - "0a02ab5b8b39ad5594c2b0c900122919e798a62a7e02e7ce367322ec55de571f5843719e17c2c984f27a056f46dd9f27efc92250829f453a057cfa83b7f38251c2", - "0a04c755ace9f8b26480ea5a4349c0b69e05a783f851026742273fe5e69059dd0c1077a036d65e1bc6bb476b31ca75a13924a56b4794a113d219428feb4bd60d8f", - "0a03aa3cc450d0a45e4482d802deb9bb9e319ea7cbf64f967690ae413d0f0b2450628a5f4021e3e6275de7bb1fc269d022d6c9d3a1a75c373b11760ecfbcffd38a", - "0b064bce080ae0d8b477f27492a755c78fc561f90d9e2aec0330df1d03a911de19f1c18690ee8669bc1de65feb4ba01fe0331f197372728d136f0d89e3ae293aa7", - "0a020e765875fa0dc048e8885e07e61acbdfb45892fa93954bf54efcbda925c363867cb78b5a240268b190b5703422d3a335f474b21c9749549ee22ec02b11d6cf", - "0a02f2bc2e924f1117ae4909d48995601ae7c399c41f821091e31460d9bbb01b4e3e120c4b11d6dd1c05e1731316d75d1599407d6447363713167cfc2aa0d2d3c2", - "0b08099794a1b65dcc9eb0affd75b2e2123c97daeae5abbe8daf017f18916b08eba545edb686a6ec95c3d5e8828970cda778b474d6bb8032dc1f08dca8c9d5a32f", - "0b0483e21f1cb06a9b20b4a08e86f17ba4f83e927c2e40a01c339f0e165f9d1a25583043ac2fc9df8970eb7aeba2127b412765b23034e696f2aef9bbdc7abae27d", - "0b0503933d175a03d107d7ba137ec4b52117b3e07201ebfaa4adab655a1ce16528d8f6aee86e224837924b79dfdef9e2c2a9014829fac76143193bd76af000483b", - "0b07f267e38e2f12c4f6ea33db344cb9dd7784e7099778a210205719d9aba60582a34fda7a848afced85c4129dc937c276d00684b8e2b33eb4efd223d80cfa09bb", - "0a054bbedeedcf158e29f19eb217dc5bbce7f62b859f81f380b7ca06901dee66e42fbb4c4843748b79e9f105c2a31908e49d9e24ac62475b6383882d389069d32a", - "0b06acc2cd9fcc24d0f75b9056efbd4b0c0ec2ed76f61d5213668b270f15ccb01917b4ab5a1ab131a0257a9d7e9031203931c7e9c211d987acd481660321f96293", - "0b02968650d62904e002bbe0840f63abc4c711155e76250945a6241aeadf41d62e2b5eef4b11c1eecdb990a81eb92a4aa72bca47840ad0657fb6d98537228a5566", - "0a0319230a741961232ac374ce16631d76d4257b180dafe0ece3cb9e14b822fbe52926a85cd5f6658bb3dc1f6e39c7d7032632d55f9b354b32c207fc214477a595", - "0a028bd839a887699f6ce290c500236480e2994486c5e5710bf39d7daf06a539c77cb4648588e5e59ea89d53c86747d93bb95fb8ca67ca342b9d1a4b27e3ac962f", - "0b043cd0a7fb9e5c7c6957fd34d8d63ed73e690d6309d91e676f80e1a3fb7a26c0de28dacceeec42fe4fe7ad4e0ece2f60d52dab2a8ce12378d0142dabf2d0d3bf", - "0b03b71d693d79e06767cc2f8b1e48019c0bd15362cb52bd0ce9c3674e810c5aedefcbd67303ebc90a479f489635c071769c499abf4b8ff51c8ca1f732ec565b27", - "0b016641f97295e7e1f6be068c134b6f198e686845e660073bd507aa95c24509327bbdd844f7b97300eca2624b6a6b2622b06d1c494c719170c5949b64d4c6e389", - "0a0017e27d90baf12fb13fcfe9d0c41fb354797172acb1491bbed4832e78f7a9fe80b486164ed5e5b495ab921b76dbfb7b862f677bf4274d33937d19149e3e2035", - "0b0678e1ea23434b2d5167bd28f5655de2f32ed09de096903a3ccd1f34428e1480aa2db24c58c6103e702065e20ccaac4c24cf64109257e1880e24a88b05912437", - "0b07cccbbf513bd93916c78dccd2a2748c32f2ca2d687f6441ef78189757ecb532cd33ecfd1e55dbbc2fdcee0446021ffc8b6af619de11b426e34dc40618d1eeb4", - "0a02c0302acb495de554802afb334443b072f6657da7e7e49bfcda33f185157603ba10c7b8642921dce589fb1a3eab504eb5c0fa9cc596268f950374fd37511d92", - "0b025c71f69615e9e3f520ad024fcc0facaf987c8100d567aea3fe6fcc8384dd7b22e944024196579787816335b70355e354f330c9364925df5f408a5f9b8f6e28", - "0a004ede521f0808f1a364a6c4f7a35723865423e2c39070d8aeb9c670d181cfa98b79ac0c1a25c682cca61a859adc06ec43dd322c9cbddbc351f603e105724993", - "0b0036663f2ff610797432a379c40c167684e8b05e41a2f18448cb618a059b0560fbf72d0c8b65f0d71076d7a2b311fa7edee7d95255484020874526e0cb9e8b3a", - "0a0572c7ffa808681c76137b8ce9fbe869cd4e27e5ee483466804321d3950d3d5dade124c153e9be0bbb93fa89f938cb95cd90a6f10fde0cd98f0c83790ab3573d", - "0b071257339cd3e311ec80c2570db79b6ff88076a5146b4fb3568a4ef903f8d92cb4a85d94cfeb10d2ef17018119b6fd0612a98fca8004bc8c08b1eae1ac72c482", - "0a047cc8ba16eb07470a821a3358ad6d7d4bf50acd9bb225bc847aaa591ed42c2da3b7044d2e7bc41e35bf893aa2de200fe8ccc089677ee5f6cb9751f5a1b1ca1f", - "0b02f01682b981750604394cc08b7edefa078dc08aea2a75fbce5d2065ba983f006ad65267f6a91cbf7c8f21f19b4f40947a07b3cc76bdfd557be010a36ffd0fda", - "0b001f3ef38af317e9ad95e3b88471259ea173f53bb34a796c6801bc8f8b749482a4741282a0d4328de9978d56f5522f306ea2801da46c072a6a5b990a8e7a4d2f", - "0a003c7b80f924b8a025fda898219fdedf6946b3e7d7741511cbeb8f3bf371cc6de204cb4602fdca80e9068f936ca1c05d2fcc8301fcdca623feccbc4d95929cd6", - "0b08f24c3b7da52782199ece35da68827411e04c5687e9e678e1fd486180872d244c076b9d94137fbd599c4f2e5a305e00c6b30d1f48110a858ea0dc0ffe019542", - "0b0397e955eaac5b256af5483a00760e2e2d5e84400a42bcb51f9725f16c59d4a431f6c01321c5931d2de1213f8109a8408249f3fc694cebae21311938202d33be", - "0a04d46f1c5519776f0c1451481f0e41baa2536daeda26bf6dc6b1706c8350974507aba812cc7ca3cfeb6e6920efd4cdb863f172578aea36f636114af004881fe0", - "0a01cb83a0caba49313f2afc42908c154492e3ef638277ae8d484ffe662d749a7ac3a703734d455bedbd856361f3bcb4958b41ee4ddab6ed2b492958b919378e9e", - "0b07937b7edcec6489f1670294093907861bd27aa674b3a01f42306bf42837e7cd2caf1adab994cce1d682bd481b89abdf4e15b78d093f527b91f83b31ddea910b", - "0a063afb85b2bc9c252f0fd4f1716fa8edc103a68324a105221e32a11298f01d4bae63436d45c209aae895ebfa2cdea54dd6696fab257b6a8f0caaeaaf19fa1da2", - "0b026a3db8fd6c91020a5584b0df897df97f4ba0521adcc290fc3ce1eb10bf90e13a81cc86b003ed430a7316f5940597e0f03f0986873eb9e78c37125bfac9a741", - "0b082a5c0736e6527bc7f36b28ab179002f896d96304a74b02d39c759aa548dbad2c293262aa000e6342636b7bf629e4ccc054fe277f36078181f216de76d63d95", - "0b01aaa91e3cbb1ac352bac5f4e5628c74521f771a69e1502c1d38ab02be7d2d522c2d6da822482680c0bfb17a2c25f262bae6464fb5f67ddb3f68986f353e6b53", - "0b03dba07c18d237fc7ab7f97aaa0a372833155285aa6d4c04ebd041298c82ae5d4e31582e7b03f0a950ce7c10a6d091b8074b5f7f3927fd8af082f11343f7262f", - "0a032451de36efff8b6a35661304141ae7e80cdeb9b623e2bb14232cfe04dbe2a05c1b8d93c50de61b0686d73cda5cc7de76fdea65a322c6122165e16b9ee9d004", - "0a039ecf2e2339c6961dcf1a283490a84bb460e5753aec377d99190ec7f7b9af974a04e6d24f634e8517683a09c19b46c4b8535b3e54044ae9c79263982c782039", - "0a07eccc11c7c08d92c91234f8403528f831e1446c0ab54ef12746393116ff0eccb0c80dfc70d52795987d4bf8400dbf31a186c38ef6b561d257c897c158c242d0", - "0a0473cc02dad1af62276193ab35963c41d0844038665ed380b95c145b752ecbf58c3430f1df90eb2efa10b2f9d02fc2154e01b38f60b3a8e27ac96756f0156057", - "0a03accdc645db43a2315ba210b1979531ee0d8235315c2f3de62c5f3b44c732a56967fb05a5c018603e47fff63919ab81885ce3f310aeebba894c6464b8948c7b", - "0a02d9f544ea68368daaa0ab2f85f3371eaa3ebcfac5fd9e41ab1e302561f3a5c0e0bce1c33ffa735190f1c4337ed351ef0fed759e6b3609e019466f9c5f3bf092", - "0b0188f21a8c6cfb6e6a888cd5887373bd4bff68828ff9b5aecacd446aa4430d02a4dbdc643723bcdabc0f6ffb5919933fa412b82898f2d17ac0f0fbfb68becf53", - "0b0032090725351ba84f57e0dce374f19598442a4c436b0678e8c8068500d06fa076bddae687ead8f29c11c5588a035cd8e1dde1856ee516c56e438f49c7178777", - "0a0741710d8fdcdc1d2c5e7ccb04875278b1f41e030d3258473f52293b6e4795004b8e817114a24f7ec08d899d9b0859163bf81ee8d583b493c71b70e59123b1da", - "0b033033804957331e7a5fae59665e0214cbc960df5bcc3b3ed9d846d1a78ffcba3fa1bc8a73d0deebfbe9c98e6887e220b07d8d651038d96b7bc92fb055e64eae", - "0b0253a92517bb242cfd7fa078d5b435ded37feb04d1b4a4f92aaa15e68b518fd3f6b6f41f33281262d7190e733341473a30c483ad227aa00084a70418ca122152", - "0b0653a701215d822e09777ece2c30cbcf0a1af8b09686f921466dff04e032b3846b26e922e246f74da921e9a400de2753f82cac123e243a04d23f81aebd005dba", - "0b071cee3748c094434b638f2a0e2dcd05b1b52fd2d645489bd4651e661e8fb96dfbe2fcf7155987a03764ea3ca56d88a9eb39337215ff198e2b0c332ac88445f8", - "0a06754ee5ef3f7174f1e5bec2546724ef31d8c17c2417574cb6fe862ace15a75b07459b84beab43dd622c4ebcdbc1291b6a319a9f4da20c7d0b907a2c4ba49d8b", - "0a06cb397ac1afb0783c1f43cdd624db12d91172b4e759d1d9d7c728da7477230ddff4e5c5cf342d335ef1da16b8d0f619e8a5d2409eff61ad9701894997f6205e", - "0b02e846a3c13d76e46cad1eb7707b112549192caac4122ac976ad9fbc62a9df9261c1f8fddb6589ef2d69fa0e41f209b47be0a3a303e6e453636f91786bc44066", - "0a0364729e9c9790e1d72668ff7a9ecf84fb50535bfee19b3d73a4e84767abe4321fcb709f33a90de0d9579768c3ae072d6714b89ab98f7724e3e67982929de99f", - "0a006a7bba581ad5a5211406aa221a71441d0da7acbfc4e2f1152bdfa1f65c59b81bf74c06606f6cea5efac2499af38bd72b6555b1a82add7ba55c1c3e17b7454b", - "0b02d99feeacedbdf8b0adc87000ef59eccd868b1faa0bf0e4cd33d8bf982d894a6aea145e26a7f190fd46fb4a579382d3ea04aba480ed90340bf7c3e54febbc27", - "0a02ea40c941e8f9741dc98cb271ba9650a013101a78cfd92007f7f733d7e05164700a849314f9d15b4ccf58f21a2b8b0f8eb84da8b8f39dcf52bc1e0eaf4538cc", - "0a0142a1407dcf817de3181998a1269d1d7e6cafd6fa193603b73c63cb7521cef6898a59da66ddac7265d48c074f1cce5299d324f022baa4b3bb8ce6991fc3970f", - "0a0221ead52c8c8f9e647d5c8352c8bc4c63c5a80e7f50574e5f02d02d656e6707b869796ae81e21106372c235a284502f72908afc9caf553c170affb2564fa7db", - "0b040a6b51bdb4cc99063b0de2313088654a4e529a0f6ef5ba009af049aa659a321b287ddea0846a9402e536f952cfc8eec11ae683a37dd9338a7516650c57e21f", - "0b0842e92bb1ab16c8a46fca898a03ecdb10779df39c19c25dc3df9f7f900ba33822ca7a703ab056da623f3f6fa6726b411b18063fbfc1613f405e94a31e8481cf", - "0a06a54e5355f0b030693d6648967bcc4706470177796a9d047b897f8c81472822c14e908492b064939885096a95db81533fe2ca2cb07b2a8cf15b8db5c5b0d472", - "0b05eb58d16d4f079caf6d5d0d63734e12951bfe0de68c9dd4b1e2c063ad9e367c02bd0ef742956b319473cdafe5b84f414dd5ef708553dbf7446f9990f761ddd6", - "0b050a4ad95d5bdef7cd9ec5b1e20b9959aaa3559a8e012b203fde24a883aaf22a36f61f4a6e14ca18a8f4d0392bd063d4c4560cc5e9467113a5fd384fb9938935", - "0b0749d39c6cb42c2c9e49db5ecf2e03379ec8cb600f6e5631a725a885f5fc9909781935f3aad0f5933bc4d95bf8117c52a04f1b0c13d03752bd4fe84617ff8d41", - "0b00e47f5fc7e0a5a97ba629562072578f8bb98d8c6bcc15bb7b571bbbdbe8ceab69332222aa7bd7ecc19ce7291a157c83fad466b65889d741d017f3e37876e571", - "0b04b34bfcb988c2a3236cfc6071d18ab9b4262a817fbd0b5286c602d55286be8408321043c2c8fbc98ffc490f3c2d2e2f4a0ef3c7e5ff850721f637c69f46065d", - "0a04a1f99e9e074a84b12b6fd069ba50487b3a44794d39e8f776d22c0242ef1c575690850e3785c8e354d5d48cf8b1f8c829e46b3f99a184143886d4ce902ba94f", - "0a0668e24de4f599114ac3a5bd9e92f44b65412c1f1c5332e1fd29b1805d70369c8089a812ee65219d6788f106c763fbca9cd4f5f9a99611e123a098bb254cf564", - "0a07010a2692399a8781712bcf99cfb46dfa94834d1ae8e74f9971b195851a0561603fd803ace94357a5e628c08a1b3e48232414400638217e2100be431b9880ba", - "0a08524f01459b59cc4c71e2df46859273d6d5a6dffd40bd6da795d570c7e10c6e6156aa3de91aaf04b870d5db80158e1f604f2fc69353f891f7cab81758cad9a7", - "0a05260aa751db73462027a9cde908a1358c0a9129f908ab3c7bf8404cfcb03d454cef6aedef23cae32decf4fcb46071276545b19bc382c38f0ff269c86a6c4b1a", - "0b02964cffb1cb95059786fd49c96f6424175f91961789e4ee34f38296954e89b201cf8d62ee333d0f901ad66ac6c12a8973bebe67191706c52dbb577dea50e141", - "0b0607c59b415f2135daa2f949beef3d29582a0cc989f521225525dada6f5b55e0470c775b2cb52be7cf52fa5391bf24a5a5d2688e56b030d82a082744c4c202fd", - "0a01085f27a65e8337d3190b92db89eaa011a22064f585202b6c9ec3c391ba477eb27040e70bd8a20b81c1255ecbaa76ba9e541ba2bfdf7a7150ade54e4867e03f", - "0b071b2a8a5e5768c21eb6cf9d2e9ce5ce39fa564d6557b171631f46f3f0a6278061c4d5a2d0a8398e7cefeaee7fe72f52db576295abd4d6c17f7ed3998d441fff", - "0a01fdadcceedfbcff459a87bf0573cbfceda1e3a600332961680babf792f1f2a682deb64f2bc4127fb6ad9add2dd6afbe86fc718764769909686e91c4383d4467", - "0b055a07dfb377d12f280adaec552f5e4bfee535cfcfa3cdac6f9534016a66af3ab6f4e1ca009a2b8c147576bce215c7504c87b59c29bf2a412192338952d3a904", - "0b07c53e56da1e0ff2b12515052158988f3ae28647342c30c904c1e47b1a120bd45f5625ae1c34b39c5adf20b4764bb28d388a76e55161e7722fada3e6b172057f", - "0a06060328bee25318598070752eb9ae139f8941ce9bc2abe06faced31b60473a07d6b3e557faf1728e4d6401679ebee450226d0a8564a7b0c215858fbda5ab32a", - "0a066c8c121b74278769541d905f7379048ac9e3a13de89da63f8de44c9a17d81a843923cfbbe932e2d434cccea18b280f48adfbcd70aaec98cbc225b4cc8365cb", - "0a046e65f4ddc0d7504dfaddc7983ae678f23863df593bd575ac928a003d53e563b17ae866d9f9ac583240a55336cc4e9375e4439e1961b2222351ff23f2d78e52", - "0b08eebd708c565d9e0aa84e91e3a89622ab3d5a7c37a5ee8da543b2664c3878aced63ab4a4d8a65175e3c4985070706a1e93f11a58b4dc628deb3aea09e7910ab", - "0a03a3346dae3a56cc00a4a499dfdaa88840ccd6ea58a29a13a7deff3e7af631a7b0b14c3e106cd23fc981b6d33a2eea2b0d757f1168186448f4698392578335f7", - "0a05dacfbb1eb4fb5c7bd904633064dd979c3fdd4b94e3d3a5a0bec9eede78d1eec0afe5d75637cc929c971037ad4cdc9f7277bdb4ed532950c7d859be8a3553c4", - "0b0002e77d3e97faeb73a5c2eecb84cd3f0e4669d97b4a66014a3acef9d4f33d6129dacaf702b9c865b4bb9ec52fe776f563b779a37e64daf6d39bb7dc4ec5cc49", - "0a04ba87a413537e9977a96b86e8accfc05e0341f746f53f1320b549165ca0b2c4261bb9aa5680de9cef1582e21468f0269105e3dac587df8c35cbbb703190a068", - "0b04833eca49b1b242d041e34219cc8f186e2d0139be5a47df67d9dd795b4d6ed8580e4746653fc64e7aa52a20218319b98a38531b81f3bf2d17a8fffae0037295", - "0b018b0d212175c1f66dd022afbfb95e8954f774a9a88c8f96c3ca03add18f60b9bb6cc2ce8c68d5caf7cf033e6decb7dc6394a35981f3e44e92ca7acfadd79cb7", - "0a0606f716bad2eec906400f878f249e0137751d9dd71bd8c634bc8f72b7b89de30a69edbaa4cc1a7b98a68c34640f17cac9a91947bdcac02c02b25b393ef53c4a", - "0b014847d8d36bb189b12617b92ec2b7baf77b8355a0de0e9fa4968229ea490c124bced2acf56f8667f644525f98126921476d9e131ae646e294a8ed5fbb6ec1e8", - "0a0732fff2be27140160e81deb8664b6269f6712e6f699610afda6814e3fe6f5115f32ba05c20fb8a1c44150e2e96e86015a501b54dfb1a3b0bab4fe955bd6c88f", - "0a03a94c64e23f69ab4f44d1855f94dc2304bf793374e362384cdb52dcb9844f78a34b7305a8e462f0e27b39d7e5b1d447b471fc9417dc214c4d4afa5493933c3c", - "0b002c6fa64f926c5e0d56b3d0e7c11ff85355aecf0b92af52d0c382ae769486088dd80819e657d5de85d2c88e44c6b9a0fdaf332d011902bfd3c73245ea18dbc3", - "0a0137e3564748c1095d28871fe604bfc9741dc5e625c08ba07d61658a59a6fa4a7e1c08679e8cdb46a3d662778c3eb61e5c57ccb68fd2a16d2170e6f7cf031100", - "0a0562529652057fd1f4d27ba20ecbce02a803f164344bb2f9b9b5820d83ea8753182653df29ac1bc29627365850d6c2b8d72c0807f1daba01696d96bd5889ebb1", - "0b026970ffbbec1c0f0e5d297e8bdd0a25eae8b4b92147b62afb5979d9bf6da101e73ed49a626be079a61d9f6bb2253aa40595b9a1d0b5489771c99a4808d3a610", - "0b0810a3a8d22059303462886ee97eb6e4218b5562976681e769f03f44fca258adaf44cdb95c3b395551921dc269cb3bda8b1a524287b927990e4a87450eb84c69", - "0b0339481be12df18bbab7f00686d12552b3100dcd3d6bdc89727b656ecbdc9e3109c6c1a0e9d47c5e3cc08ce4a432d2cd88a6e59df19146f571fbc9276e68aa90", - "0a08eb27d05b4fa23830deba13ffd31a48eb3c7314b36d08d9894cbc8d54ac6a9c590bf86a8ab69e321dc1206d754a0aa835502e3d7d2250f99d4f3ff8d31511c9", - "0a01950b359b1bb13a5ca223a203e725c3871c29f8cddc2564454134f440c13f8dbbeee00dbb267495df5ed598436a876eb8a5276a59313c9c5cf7cddb64a2bab0", - "0b050d108823cbaf7b4dbe9c0137155e282d6f9082d699ecb29fc2d7c05c40a7bd73bf10c011ce6d3830fc92cc4e28dfd7644d0bae057fda6cb6e7ca283bd9515d", - "0a0061149f796f842ce1c52aa44a660477ee3ef6f8faa2ff634676f2ca0b8558b9dd02097742acd5f31c94c96e0c565affbb01f9fa6732e3045c621e998d7f85a5", - "0b05c2a08dcd63f49fb2e5277adc171fcf5c753944347219e3b9b599c2f026e0ab43dd75657c5e4871de23cacecf639606bf46c76e5fd93ec7de8ef5551e9a34dd", - "0b05f5ef72d4a24f03c215920e750fb3ddc9ebb5b88499468b9eb721f9f9715f6f1b42b0f80c61548723d9667ddb50d6d7c9d5bbe6f4b944a441e9eac2f08a8358", - "0b00547e9ab33ce0a58eabca25d56f6f00a832ecd2427e4d7352a250f0e0a2ed14511f5895b5b528a6a8123dad2b8a450605a8c8b93523ccd29c9c27e869ea4955", - "0b05f89475a3f37908dab2b76382ce1a5563b3307d0e4a0f59248041ce99263a9ae60552c2dfeba53ba53399001928bf25b7a44b18991fc628882c616185dfd735", - "0a03213fefb56a80476279c864e79143cb1f4edb749eed8caada51128d3cb4cf6d196c259777ab0824dd8b40a75dc2c11894445294911661b2550fb0259664ea82", - "0b0355630598e54dcb3647b2576f71764c9a0c1879929f63da0c42d1a8929deb2c9fe5a427cd8c22d353f4aa3e2644f46993cfe9d6b57065fb1a1a25d389a36ef0", - "0a0815e33da6cdb0ac31ab8bd91e1027d7967b58f5573e5fa494ab3e57641fe23a611aff8598ef9daf5e7e85a95b5fadbab39c3d8b1c1dd19315acb59d0348ca6b", - "0a009a831e1a150695064fbf9a7038a37db3bd36333e6d5a9db6e82345513ce05fcf4ca65735d019f4c1e08684a09c56b9b665954866ba5374656a37708b26abe9", - "0b02683f0fe3542aa61e6d3edd4293ab370799ddd1c9309a6e4da773834761545e85ca17e072f523f105f40c2be139e32ebe59cae300d1a6b96f316950379663f1", - "0b065f60439552b0c8c75bf8a4a3e3a88c588fb072e2e80126536b412d8291ed9078c6570feadc7c42a9da8b7db636496795548cdfb4b1c53cbcace0ccf77c2dc9", - "0a025bb8bfaf9133e3556b941aed5a8a085c368381c08ca2135e0e2740952c785e4f9a20e324a924a0b4260d948f11855afac9ca7dd0c6f02afdef067561e882a4", - "0a05296cbc76d09c2998f860406d4188e6fcb6a0fb64394347735fc536c13ca260652ae22eed359db8fd3f2acd2087bbd97a9055625cd55f32dc7fc4c2755918e4", - "0a028cf85ae45b631bf90cc5345eb384e078c08dc3137394729d43c19a434481f284440e0fb58233e63926a1115198a122e1da2f60beaf5872f8e01f606289ee6a", - "0a04e9c9ccd556eb497827730b490ebca842a38d54263d168859117c32aeb0d148c7feacb2676a08075546f07c8f899d35d0d5cd1d4f15cfb31852a9a1e08c38ab", - "0a02c286b1c0b9e2f6c135b3059370c6477a856b8c2d5f6553106d4af71b7e0f4851f9f6308066d21feed0d32f830abf7af595f4e0a217e17b9881a45f12d61aed", - "0a071f1efa4f9f8ab77c22a2fd75e34ae53cc204677f39030ba6fdb46d19df847daddd6e7b5a7f2fbb3c125a0293ca5d47b81b002d08378938f13175757be61e57", - "0a07ed5f9caf57d54e751f3463ab53e1773cf3d2bbcd68b826d72f19c9b1411ab767fef43a80425c667cdd198bea3a05cbb560690a703bdd702bcc84f7bb9701a3", - "0b03a112b8c1e2bce6fd5fa8e4fdf7b1ed98f5bcbbaa00c4fc6a72bd1de58b073521bb1958550a55b15c43186c855cfe3e48a6cf1209c8983724110e693b799494", - "0b056cb4fd08874ca20d924bc5b49596048745138126ee9f9294c760966dc106fd0ae06bb5f6271ab93fa818abe9b892889219dce98854b608f43dfbff53eb8267", - "0b032a4715ff5da7fc8c68cecc1a0205e04a1409db4c145e47cf44c0117adef82456120665c770d2debae38f465e1e172b08cf7e51190528a465de66b6db824cb7", - "0b07894ba5f273cc7eff4adf950ef78e65069bca1748d9ffcf1e2e6b26f0be058bb18a4977260a9fbd6fa7664ebe14d16c5e0138d56d9c0ad6ac75092b91ef5e15", - "0a00331728ba735b6534d354c2bc838080f2faf8fc2ad0a725f78cd97b82c98fa04d5b646603aa9ab4d9e3414dce7bc4f79ac256ea4bb83a6871c92feb2bb85ce2", - "0a00910fc2ec737af7ae0351a5eeeb23609eae1c49f49d6abb11521fe053bf76b9723120e96def17eebf1235c4d20c8da08545156dce2c021d3004ee94eb1fec49", - "0b030d890dd78e7cd2af75dec73b98906c005623a28c10e93a127930565165eaff210418b12ed39de54ca67ceb6db6891b504c95c196378cf3aa6e0da43f2e530f", - "0b0332d854f9ae6f9bfba1687ae115ebe8ce4a6431d6279cdd1b6fa888418b54b7e1bc47da44cbecadac90edb23313157d3ae844a53a10eb5222b95cffb6b0d95f", - "0a06e58a81f21abcb589fb9251a8f4c7f31951f6991fb1232fc6c647355dc2c02ab7be698094fa2e6891319ebdb4b7e79b6ec587da037dc1772c09f61189b1c7f8", - "0b07706c92c3e62d3d7e3fabe557ae61c97d3bbb8cac1ef79b6cd8102d9c490085567007ba1a656fd254904226d7ce8c981d2db58525b0b6edfe59db455d29b18e", - "0b0760dfb3619999c904c899bef3066f51cb291c6b80255ac2f5017fc65a398c5ea76986b8b96769155e0f67b9e6409425f39b310750109278e17b7bf800c2d84c", - "0a0904fc3edf542b829cb126caaa741905bc0055a9a8e95f0ab7c6a2a7704ea8f938273d022938b47c01ca1e9509bf7baa3eb9e1bf26dc01b20c11386f4aa498cb", - "0b0484b304eaaea41109164b3fd23e9765e3718a2c01afebe074c8d2221ac9bea7488eab1d0026348bc32a888eda649c867ab8bb891f379eb11d5a233469f0b37e", - "0b0681d8af5e11ad60e3200ba55a9764f725dc7b9f2e5c84c378eae49283570efdfc284970ddc6ce72e439731a72724459825bbbc66db9ea20290d06be0d430013", - "0b04a6d974929d7bb47aa37c7c95c46b212b7a9b13e5fc4008781b7c6fd77fc0bb8efaa03f236ad2316efb3c8d37bd3aba686fc97f444a638aa921fcbd3a246bc5", - "0b0015af0548e8d1acbf860ab073d84e7396480697c92f169f67c9a74b3990d402e3280f9422725d7234876c16a387a248a2861007f442c2ad7008d2b5988e654f", - "0a022628335dc2dbccc25aa1eba632b7ba8ac8e8aba2228f8778c586813ab0431074b9f3eb9ddb58a807b12044eda9c90648f1bc0603f7536beb7edc06e42e2984", - "0a01c09096afc1e9b0e3748eab49d40ec8e597da3b133f0224871ff6a63e3a25753bf6d319b4f9bcc43fd3a65a9a84c3a728e727b97977b8733e82c25c908aca43", - "0a00bddd81744b57ec7d535d41ebbb4d4b4c1ed713ab35dd9cdfd6dace5f931b331da6df7970889e2b43321894c857c87c97fe15fab6984206136d6b9c8a3648ac", - "0b01939b15afd7fc2e40c0b0e04a1e37798dc3fff0365e7adae7826838efd72d587d1833b07ec970b7816e6bb7b5c41049ad77ced17cb34f0c65163ac692d2860b", - "0b0773e14d3b9915f82937ddafe6cfb6e6f772149ae3925d9676e417266afc5cafab5461782a6dfda4da3342982b8d620295b3d7c1316fabd98bcd539d0ac89680", - "0b0549e403d83cdf2cf1c47fc1210c4b0710400883e3490b3fd5d6ea27b9c7e3e7c42e7e385bcc8e3fd3f06013cefb15c8a8f6d450d88effa6b985f7df55b3ee44", - "0a007b638e365328a60e6426a980ee5738c780625c337d83997f749c8a89e676f5e327421973c5282b1f2798fde9571066aea0ec75fa1285b54c80d6c6395255a0", - "0a04b37fb7a3ad2d5d739f37604f88d65167f5d4982ce7a253638c5d4b7535fbad38fa5dacf386bd567f547057c17534ae70da529fa8dd039178fc4ff17d46e8b9", - "0a003fbc0f38ae0f291ffb947d8d9ef6cd783933255671e46aaae0201255ddc9da83f2bb4e7ea76e7251b777bfa9c6cb3d956d53ee270fb92fb6e84099fde6b79e", - "0a05ae00064292d2d0e15b67a455b3798fd6821599f00c55a16f64b9b37fc6af071bf1ef7d668098d3940546ad42c3e4b0254a70aa70bf44b3e2b04e5b190a2103", - "0b0074bf82593b6197dc56d671447a6b45104abeca739a21bc7b7d61a6716ae12b7ebc72fc0a4fe2edde6e7ebe785736793b94f1e08586a86e4ce260f07c0b4213", - "0a045c7c3aa04a6829c90ce5ad21a12c089b003c8ef49909528029ded639ac241ad69c48ca847309cc006922f3fb93698962ca1a63ad4f7d305a51d8d339105a90", - "0a08b21bd7223ed012aa6eebfd845c5fde8ee1ebde4c8ebace8c56d9494d99f455f26077c64cdb98f70f7d72520b2623fd13cc1fccc8a47a2065d489cf0c5dab01", - "0b060e58b7e4272624a5fdc5d91959f6068d6ff07b61ac32196b84fc9d16d92b48a7b2dd1f36eaf09f9f794468a060c11a4d2c0b638dd32cad5e0077a82893dfbf", - "0b0275bf2e5690de3db707b70759fc9e02db2023292f66031556891c8996547699f3c3f725a89b076c8b3a2598d27a5c60801e0432d641fe534745ab77b0491308", - "0a0382a2ab584855efd163e303d4d365168cafaa7170c6525a1ac2ad69d181d3ff4707e08d3d98527a5665b3f84fd509cc24caf8f43d847aa8535c568c351a278e", - "0a023bb6cd7fdbbe2c4cd5919e6488caf2f9fcc6d010eb0f5f3b253d6943462d7ba291d4d971e5023deba204977f87bc48421c1f276994d17dc1799cea1b44904e", - "0a08be285b358b8ebceb58fde0a7a58279883360d1d7f1c3e6af1448a1d8e08f7c1ecd05062f43bf9b1a0b73b4ce1d1340f66865a6f877e81a9aad24dd06232ce8", - "0a0047f71f77850ef9b48284bdbdea0098b2d89156e92ad497cd3abcf79685a86f5a5a08ba69d30dfed720d6316ea3229f3cf2276ba3e2b6bd64daae48235a43fa", - "0b04d2ffa29bcc7c26a514a4dbcff62368a57215f02d6ead9564cb6114853e3fff82f947428b66769fc2c74509e9972949554ca65fd31f16cb935f6c106954c649", - "0a053311506ae9528598fead431746bbdc928ddae2f71e0641032a3314c6dd443c7a2b5d9fc612e0976933cd3f8ba2ea6895fd65a4aa2a7ff304eead01011f7659", - "0b03a480bbd831263a157680cf2dafac0c890cfeda90c97eb2773fa21cb1e5f015eab367ff231f754a184ca82f38d6276db5a61358d18dedc9254add88dae8f20f", - "0a000bb90c619b62ec043407a946b7152840e537bc49167807b7a3a4f69ed93b641d70432b9cd2241a935010c43dda4f76ffd7068525867c575ad74cd9cd8db316", - "0b01944ffe95d31a2edc1b62e4b833ad4f251a4fe8017d4560493c1bc273f75ec408cc6657274b661119ed4b2f42218adc77d2e01206d1d9190ac8c0e373f7aca6", - "0a00777dffcf2ba0d6a395f600730726dc72f8fef636bc279df0060f21046e4f2e25d00952668ae7812bfda8315a4fa89e5f29d78e192da824fc0c8ccfd2547861", - "0b01ee827cfd09e0099f3b986ae0989602ba3a21471eaaec95db7c1eae28f409d299949c464038ecda2ffd21a060775113eb8f95062dbf3963dd77857f3060aa37", - "0a01aa32e02cb011d51d10f2add424ff5507dc9ebb795e3378519abd61df111c13b57d77d2a79dc88ad6ca9277de2ebc86718999c980bfeb50f077949fdbcd042c", - "0b019efda74630c4100803270c79186cce048263e5f421b97c9857a6aa6156ec4dde19a033aacc59c500fd71590313ff59ed61a011ef7d1c44e52ddfb78d9a9602", - "0b074d048ec2c198a3f612a0805d3fe854bcc3b2c601af99709f6d1ae9554366b1c224dddedf7eaf405935a355d7a2b58aafc3389e402325174c2eb7df4b2f6673", - "0b0572a372413cfe36626300d6b478776089c1cd4a48d49d6b5f0015b96997e8fc7d2015f6085be01cd26f3ed07b44b89cf0419677663d93bc68e14be44b528f6c", - "0a03b14d14b77d2d62b5aed410d2ad54892c73f029b48b4f6bf598e105b66abb0b2b731b1abd3ca568dbbea65455828228aa94ad2823330d782bc14762de2eb394", - "0b047603c5f9ba6a766f002025f3838ae8ac942a08761bb7c607b789e3c05a814c69e4620e37932df6cd4e3c11f0665c7df54cb88475c748bcdd704bb35183667f", - "0b06fcd571d3a8480a63d64c3a72f7b710cc774c75522e292cfb063428eb9828cdbd7dbc3063374ae6c9e38583d1bfcc2da044764f38922d2ea1d1c928db56b283", - "0b08f212da8f8ad42e050b0a9b87485f968a3c5293e2764ded604352f2bae080316a39dce043cebef37770b28d10b8a1ccfaa2562e426f2383212a06665b943d42", - "0a07362e4afa3708cd648ef58f7237f8bd9832814002a553c5bf97dbbf5dff3fcd47d79993246d9b9da128609b979f6da252a7c5304ae08a70b847948536b24f03", - "0a0647f37645b89dc021bbdfbbd90d42ae43cf5fedb42e786b6692792a1079f8a53f2846e012343f71a1a9027c532620fb025beddeb5dacb766422bd850f86f0ce", - "0b04901997eed3dd0c53d2d207d7aaf61d3e80e794a88c97104a6c936d0e15b780aad80ec130243fe6edcc0827cdc645e721b676193e5ec49f2675d207a22c8431", - "0a00f37cbe7237d391c56d669361e6d7b3a6a6f77474a6967fc16d000d68c3cd5024b2e9a96199407fd4846c14ad75c7ea1cec19c00f6747e20d87fdf166ca53bd", - "0a02042662184e0ec946fe57b092be185c4f3c39aae780560501c8b37e1b18704a95c037ab2b3e1df2094bf1c36e66b0469af0f938c3083f2b19cdc9b422916d03", - "0a01becf9264b2a631398cef9ec82690dd2ff92364d543e881174e7de51d100f93f0acbb8741890c9fd3ccd1bfe81b3b97ff8065c54a939072b2754c1dce07e4e0", - "0b072e46a5fb1d860727f838159c80fab4c0498bca14c809c3d677b47b8ce76351c932baf5624a2200d63cc436da95a4c5fd2eadc9968efa9448aadcafc13f799d", - "0a001bb7d70be34c042460a83d67549b23e69fbe59ab352502f182915b81897a44beb04e18979609c4cace3adbdf425207f71f4d572959bbd4e21163dd84c00333", - "0b07fbc389903613744ba2f54e173edd6e98d170f0725727fdb1f4539ad650243416896eeb9db50d07bc883866a8d887af2ee831caaef396dd5be0f6437982cceb", - "0a08f3fe2a5ee311ba50298ebf009f7d1e3047cc0a9ec14662cbec9b627a359076f9593e0f155dcf9facda9cf8d6acd9f26978e66ffc3a6c1867400c46e7f20dac", - "0b0203c11f850c56be6932c025c599b7087412591fe1898df0be3ece4c5d90901618c4fdc8875168fba08f8b2cf8391bae515b08763bacfc50c5f54be738428f9a", - "0a02436ac451e926cb5fcb9754ccef2637a2b8c6781c522ce470c98e5d9f2711998ab990d947001d4d7294d29ee642c53f1c350922c95adf5590e547f42c776709", - "0a0482f0b58465eec2974e04b8fc07521d6e0d40a0fb02da30c69122bf60e7816ea38b8d5228145bbf1ad5d6745ca6d8e0b241e3434c376f02842d323e9395cf7f", - "0a057608bd49adb8c899efb326a2fce77a4f55e75c61f119259040b17c5f7cc186250035fa2f1931919efb53ec8a57c00ac5af8670e44b5cdceaec3dbbffd269d2", - "0b01d7e214a513080a2bd9ae574d09f76fcd074ef6e12b78a9f4cc9bb9640d7c894034f0ba672e27ed8ac5868fde0f4f0d05466206212c9d51df0e52df21dece44", - "0b017e4b8d7b22235ea6e2d5ea229dd51cf863c8cdf82fc4adda9a3325cfd23c1336262c3b1227f3574d8a81899cb4412e1fd9aa1a38ba6df00a0cc648ffcd3327", - "0a05ef9f510b1e08974ea43a616874534ea8abd8570604edfa163ed5bec2f1eb29c24061bf32e34d00dc6fc9be1238a20de16651f508164aed11cb038d6afd4614", - "0b0761c53f1dba6beb40c47786fda23cf25dd6e7241c846f54285d6c1ce5c6996d0ef108cb83529b410d067961095deead20e662830f76cbc1146a45e4c958132b", - "0a016018003436ad37633d1a560c082f25be92d37c571e4377afc4c3a71ec459dc15cde3c6dd9cf98c6c0e4698a758894034ba898e874a55bff5123d1aef2c6898", - "0b05212e2fe275a1ec0bfc057ba2a46911cd2954474e6376196164b1f6b6b091c78c43b37395f50dda3fcdcbb43f33761f544580ba935f81e695b43347fdd89410", - "0a01bfed740887e42ccbe2814a6781247674e276a41e55caf511929e3aba8c88e0da6b8ebed32c4b175b75b89d81ffd0a9e6aedf549d19fa6dcf4de4c43c3f9bc1", - "0b07ba0559166eb41893b377d57da1e0dce3d588ff136cf32db089d56c396645b4b27a4dfcd1259da25af9ce074ceba45942764434bc34a28840b232f8cb5f8106", - "0b06109137beceda4aa45f411a92f55429baf644e8eea29f6a3e9024b20f6342fea11e694a9b6e2c43d922d426f5a5f8ee0f47189a95b8681d8a8a94c7e1dcb035", - "0b00505aaef0a28aa7183eca8439e14f3c8179f900231cc2450824370f98ef6cb4ea2a01d02388d53bf717e7e01cfe91976bc172ec8323e51d10dcba53b18efade", - "0b05056f467886e0934df981a3e690efc42696f9338f3bed0b84d0dc44860a63c23863c94be17eeb140a0fdfdc03246b8c667c23cc64c29cd9ed366343d631293c", - "0b03c080a4a79f4d32e1d0fcd29e6963311c1f38d225869caacb9053f7fac84348e5896c2574fa1ef70d8ced9f9461a88310a2cbe0a5aad1cc2c8de29948b24258", - "0b044e99a6448da4b51d7bc6b7509785b845fd7c6ca230708b94937bd01df68ca4de9c2ba5b1a3fe55c40762a0ed88b4ac0091d2db1142189b9311309019d41e4b", - "0a039100adc3b9e13cf9cdd6100845b587c393236bd3367cc716634f357f76fe3628c53e3f8b4ff48906f8dbfe7361461e898c5074b51dfab9fb16c95abc34d027", - "0a05646ddda9f11b5f34e19a70de98bb1c0de835b95fac2ebabac4fafd678d3cdb046bec2a8853d696f453925e6e99678bfea68b86450f6e9ba7b5e46ecd0a2da8", - "0b05c5e291daa9b5b35a44c599ffea2ebb2dc9941347f7372e36ab0ecc0716d71551cc2e4ce16dd6fe4a38c92ae08fcbf88a3317cdf1dc0bebf9f344793bb6f2f9", - "0a05d76fda2d561a5b6ca2c240d76294fd96eceff5b620ceeabf5745d75fb8fffbcdef48825e0916fc353efa2f36be61a1fa730fac02737451907e4d0386a8af61", - "0b04b34a923c0d6ae3ceadbd291bb617fbbd6c986a628cb7a237e2bdcba12a40fe989abd12d39e2c149ccc0112fb0a2a7743c55480fdcab93149e42d8b12c5f5d5", - "0a04c71d42d59e9269cfc0c6cfd328c1d62ebb6403a5e0db3bff47e162789a018f81a1ccc245c6ee3c8a8f8bd3c216b4a6f574b75aa6e50de4292ec1fac902cd00", - "0a0859e2351933c3f119894249cc98b048d073ada424cb75ebe7250ba158b2ac9fba270d3f9fdfd1b34dfe930e06f16aa973f5ef80708a0c3dca1d6ff40f77ae1e", - "0b0525cd98a156dc0358039243db45442274872d268e5fdd638f154c8699c03400e38eeb5854d067cff2a6f548645c166ebb08990aa09bf4347f860df607d9c33b", - "0a089588642fb6a568a759c0927e7033aedf5d0f424a1506c84d846f3d254cdfcd1fec573e2c29ed5fe3369d4975a1b89dc13c7c4ed09453b23a49747dfae5b079", - "0b001ab1f29991310b644abdf7f29743c73a0368863216b5bbe00372b90d37424766665e97f33e1a8ec9642a6eeb75d0600c62c7c4c1446fa5cf7fec231a1acb0f", - "0a03b18dc5af70096916f5bed31e270b2986eb3b1bca85fd4e3758a8fbab1cddd98e1bc20f75db53513c6f3b6c75899279ce5f4d56c68805a8b158e9ea83ee05e7", - "0a05e65378755d4df4e6fdb0a3ed9c660ade59ca294b1fa924aa052cd3216ddd60898ebd1140031d69baa1e8561f195d9c0f69b2c4376dace04a7a5a322a3163ec", - "0a00ac26ee4211ab999010966189553215b000e2634a5e5c98b4923ee2632e7fa95217f28a1e39939d0c734a0d8f9c57c8779cf6d511cd99f33978d788c1d19415", - "0b05a2d7bed00330aedf565115edf98467b4df9249c85398d88923b2d282e23204846a8b0c4e09a5793a534b49b0982f443bf11efa8a47c16c413355ed70f856ff", - "0b053e656724329380b6c8dcf2476d8c01a0452abdb8541b800ae77a2bddcb3b69fdce577d7fa94fa8f2105f5bf8acb842892986d9f7fb15684124a12da743e0f1", - "0b050fb36facddb4aaf477d5588599f8709e6a0ee279b3aae4aadc86f973c3c1c22de4efbb1f4e5ed1656b2b3c874d1362159bf60cff92cf187f92b813166e3847", - "0a02d2bb39b7453d673826f72db74ace76660b6171f2293d083d662c456b5d27348e50c4d36647b3212d149c59032bf5e3f95b74da323517b8d3947128790f54f6", - "0a02bbd7e2fc1cc6cf39645bb36e974428e92ab5eeaf24ae1e0b3be8cd423edd6206495adbea088002c1db40b965e7d921b0ef7cd1bcef7afcccf751ae3275c4c5", - "0b0675398e4630dd7d2106f06d79fd01105ed80debbc90dac7a6df2dad0a0647c31bac2d943e798a830ebc000057953817b8e3da99f9d4c542f55d82a20f41ec5e", - "0a075b6ceb64dda7bb416af602e5b77e73bdab11dd6ba0067ca3b73aadef8fd463651aff0e856164296d7f16eceb9578b5edcafa4866cc9e9a2782487312ca41b5", - "0a02e92a005bb95f400772039f3141ce53c96547c88ee6537697ea210ef12879e1ad292cc9ca987c63c34948c5e5649872a8e71add80f8cdad2dac7a8d24979496", - "0a07d16b0a24e0af31e8913b1e7be554162266f4e7f1de595c35ce555a30f872972ba336bceb85b6a305ddac58b59900455a8bb21886de953e78cf1b05cdc7108d", - "0b00554658001220ffec4b780be180ff5610a43a17343a1ea57368d4662d2b730b1a13b5d4fcbbde0c9e04ec4acb2ecb23dfb3e067699697bf9f5bcd2fb2cddf42", - "0a072a427e3c97e5349a3d231601a99e2b11fa7b00e4ebaa9b3ffa3d5d4bc5680ff8220545f24ef7001bc7acbee493ac990c99fa2a1f182cda3c86373ed0a00856", - "0a023d6d920b89b12bbb3a5245f306be862df996affc9fb0c7d4adf4af3bd98d90c5419ddd08d65de6116a48d93f8e1e060f35b88e49e080db9323cbeb0b42be81", - "0a022a86c2d6e6e29af970113d709e81cba3d1cd6d42b335d4967d1b73e2d96d620fa365273a7f63bf19967020944d0d6d729dde809ed6c9b378fcfca849a13494", - "0a0493a6c76ae2f5f6122621f6dd13ccf28264cf1aaea48db293c543cede9cf967f2dd734d704f486962f1acbaca22bfaa9eda3a6c805e1cc0138c4e0a65b00671", - "0a036ae058165d165c4f9282c965bfac71a3556df7af231a4deb8b1328a2f7c1448e403b651e78fda02af5985c4f837d80df87c945519185e74c056adb5523bed4", - "0b00a0b44e805834a45fadb168a405fd7a4b15c5598c37f622d6e248b40d1ef951a1e3fd544abd215f8ac710c2b77198ec3146ba8b35116dcfc2436f296102ac81", - "0b0408ece6c8a020ae7e5c204c22792bd3d614f8a7480ee3b35df661756885fdf7cb916a25e48dd51641febaaf79d62b0481e19874cd1db7a76d5bc594b7f03e44", - "0a00ad487a6248fc13e9cd9c153fcbeeb2d4a0995284d82aa8e381a5b60880644316f6306f456eb225e07a7d29f45721164b9c4bf84a6710b54433f55c20e8f196", - "0a052c532af3d7918ff02aec880dbb17c968b650288c687e0da247e1e0c57e70c4832bf40823329c3d93785f7c23ec6cc9fa82a6ec34c95c854220d54a4ec2df67", - "0a069a0d04070b8d4bbdbbb4fb330fc97b2920fd41a091919b2ebd2eb709209483f1432788793928ab0199259f9b482242a5fca85e7994a52d3e6a580f9c686206", - "0a0839ec54b075887961cf03baad697893f25f6c6ec5bebe30b02634abfcc8abefdac34f4678a30fb61e20800144ad9a2957b36b74590db0c6ac9e78ddcc69f6c7", - "0b0282783e39bf9d5b717ec722f2652e974bef6c42ec97e7ccd475622a38ff8d219f92b44555e121a1e0ecd194275d4536fd2efe30dadafc20ed04623b58ed6ec7", - "0a02103e418ae48b59216578a780700fc8c3d0ae94c7065ac15d878588353a7b73f01d0a715ba12d470b04dc03df3fe89f1a26020bd48bdab39f9858090468f833", - "0a04ac483df961e8d15c0db089b6190946de962823fc9f369d8cbc63bbcdad3162b795876d4cc292db737aad31feb40f8e267192b6d6b1aecde516e156ff787be3", - "0a07ca266a0d5c7249d3e09d6623ea0802bd11bedf0eb97d1c57a4dd43b0704e402642ccca8bb30c53e8b99ca71984b0aa3c32cde3d2474220b19df29e04444b59", - "0b040d321215cdb31dd2f12986b562a4705ffdaa7ae3b9703adf8367498a9a76b689a3f30360aed5854434a36af51b0cbdff5d83fb57c5ee60fe97f028c70790e7", - "0a03386a6d060638236d6047a3291f684f2a693d1ed8b7240ee6b1466a7b558a8876436545096af3f4bfb36907e9b5f2ba36b9316c7afb0ce005dddc7038980aeb", - "0a08e8c216c0baf9b1db5213f94b03bbf099aa975008b9f1ad4f14845c72486dff5a9b7d6987956b898d2c820891ddb50470b67921fcc99cfa39f730977893dace", - "0b04a6e4fb60a381a3508b95e542d89636b8649195abc3a52f0f15bf1dc7cd7e0d1643cc52daf0106429270bc759e878c2d655f0f17065d354a2a922592225d8e7", - "0b021d3ac0fe7a8a7b906024efbf52f2e6e1c18e436d1ecf4bd66fd76c78fbc8ca68ff990cbcefa230e5691cb379559703d26bc23309f60b273ae6ccaa2cd1d6dd", - "0b028c98a16c6fab50a855a5e9196b21c502075481ef9144618dc2b652fa74da06a310ddd60bb3576f0aacd096f57d204e8902dabec105002b863a79ca3d9f89a7", - "0a015ed8f30ae425a0303b3a1e4943711b32b6e6583d2436cce7e4081f03f2a069e1ae8b6a41f21a5799bd3c6bbbaa6868b0d6e54af3d98bcb62c7d7564224b6ad", - "0b018903e4b4a521b767ae19bd47b93ba75682ac878fc2f2e9294156d740e3c191c56788ab7d0bdd31ee2c3b2dc9d818e2e8c2ec42b8af5c778691b8713013961e", - "0b034df517b4a17f55c831f54edf9612e7ccbc948b40282c49c3c5d23776a2781d8c77bf0f53060e240f6b9537004a983597338a24cfb6ea919602ef6ed5d5acef", - "0a07908cf1421fce9e1c6a38699b5bd1fd7e96bc9301e2ae0fd57f321c6bcbd7b478a19792183a7bd33a9f6dab29007488433151b939fa66183f0ea5f52914a3dc", - "0b0018785df8248f54b000b741dff7b1d3a68cf42caf85e9b2b7bbb195402e6442f5662eebd282d26183734f799a662190f64de05eca519440a704a35c6233887d", - "0a018b1fed1f0db9fa580d057f42c1b6650b8e948803da80aee62bb28ad7ddfb4286b4646be9c2a4b32d23b6581e5132f6ea02c481234d0922845012d6ae8c2156", - "0b00136089ac5efe1c7d9dfc6119da93c3ab514f2ac34110834d538267d4206451cdb3c8054e7513727a1f5121a8d8e1287d1b0e63a07d52736daf674120c863fa", - "0b05b801a20fa2720f78bb505580c92692f9c5acf5cfc875d86c68993ac99961d0f794c5e8448e1d9eca1de732bcd8cb0385cfc74d6a27cfc5a732fe418460be0c", - "0b082287b5c2c91aa44207c5df2d8732523bc61dc8bfe3cbf5052a4717b1891d08d4d8f06a1b5802c953325ebbd5dd9bd0480595d2d1e20901ddeee899d68f4d62", - "0a029c9dc1145ba4a15bb75dfac5158f7e15ec36060989fa18637a4ac21e595669685c8f972c706d8d8b18b610af70a024f6921bf8799a96a83196f0f6df52a086", - "0a039b3d312966e22c5f9e3c8a0ef6d2e93ae1d9310c40881993abcb2aa72c6f4badfd1e47f139fac1d70d4bcb65a48bcd9557a1ae1fcd477f67e936e1a0242c50", - "0a08e91510a4315154a4e961a3c61aad434675d8fdb601e626c48266191893559cfa5a3a4fd0f9bcd0160626ec566af89cc9e1edb566cad686f0803a03a2c73fe3", - "0b06653fd8d6de57251eeab21d285c1f2806ea82abb35f633690ff2c6ee2588e9b0687adcf4a3d892a075f7bde011b8bef3d59e13057d583d9c43d1c82a50d8c78", - "0a044ee36efa480d42ce285a57adb4d9810698cf1830739107ca14646654da54eb26aefb8102a23de9054eeccc0e2693e47cac6550465b30864e83c6637fe7ed22", - "0a0879dc9747b5f68c4f0bd8d70d645f3a247f290f070f77ffdf0ff99384a956e6c55054c6d65df94b43616c9f35da037ac528c3b8d00bf7718d97f12ee79f87a7", - "0a025beb684ff5b892ea25daf324bf1089bdea3bc7ebd0f48ee689518ae122723b23117df71f383ef529192ef5936df8065f6a811f35cb20749c74d716d9a10573", - "0b068098fe3a7037315ade1ad34801dc6de6c47d68ec9a264a6c34324c36903bd655e05fa3edf27bfdc5fc55101452c98bae52308b73baf652cda8006ed6722b6c", - "0a011a6a238b227fabd75f093d29a4bc6bede42969235127ccdbe789430c50b278c0c2ef607675a15041c7ea08be1e91df72af12cd6f881e4951260a57198209ff", - "0a052bc4f8852f3b93c2c7d309577d02804decca0af2588bfba4383d251c24e88aeae36c7b492d3ed173f6d6bca1a0d0ebf7d8f7b5dd77bd6ff3cd81b01f40c1b4", - "0a08ff99d9e9b152a674e8f86572538e904d3db514aad4f39597b2ee48e7f23b7585fd9575a178834fbef031b599a4ebd4689a6842af37b25f0d5e68cdf8c3f4a2", - "0b08b6bb40a042de082a6cdb06f325a8c1aaf1f5a314456f10747614d04151e9cb6191d0aedebe9b205ba2e57b5d999001ec1a894885cd3045de55920783ac253f", - "0b08edc1a7f7c49c0636c8d6163f974d8d686fd4c6a40688151fb87f1f0593ce6b94d75d07ef96d424f26d3b36812c7db452be5d138de7fa4fb074e0f54feb22fe", - "0a0323a97dc604cdb4f8f752ddbd131c9eb632028a408c9139f0727a6db0537b2171a459d03443e651065bb3cfcf11b531fa66bbda504a8ae76db007681efedc0b", - "0a02c2f2103fd1a5ba6b52f6faf6e06cdc95aa9be4035e958fd2083660aac8b1d23552a7de382e803cff953f52af33635eea4e20c0ab00f81178903c70864b0b5c", - "0b01ba95da51075741bd8ba9fab431bd1cc044b744edb11de912000d585bd576ec1fb6bc3ffb2ce9b651f8fbe689dbb3927dd34757ae8e948e21569b8ed055d2ca", - "0b08dd85ee69106f86ee561ba5111704840b33d1ef25077931303bcf7292e93ecedb668629ba34b3f398432c379dd124b71d664208a5407581479f135d770b0266", - "0b017a5c424fb472e496dcd506d26417d90510f9cbd18ea82201ab5f50ce57638295914160071f0f6c6aa8318e1f97e8bdb9c6160a6a3a77a4752ef5dbc62c735d", - "0a00dd5c8d64cc60c664abeb57e365123954c940f45d8c90b946543ff379c15b41381264783a403b7ac437bae3b8f5cbc733123b01f1c4e8ba70f331c87263c430", - "0a03d69ee1a7e7a1a3c0341d7ecd1ae7a451c790eff278c52b2b49053ee66a42da26053b5c354051235a65975868661adda3b2e2dd8d55ef669f3d7994d0e79820", - "0b0440f911bb171bc7d9f62b69417c31f3c3a318753f22522eb1c00c02f43533e03ee79070be9e21ddb9370d9a77e22fd246daade57126ccf1958fb9f681343e4a", - "0b05b8921b4deaf66f3cd73ba9469e4b38fb0d1efd38eb000ab0dad80993a0ddd3137f75e7462662a43690575af10c642ec85c131a1361131cdb6902e0de1a3c97", - "0a046ec9d0d845eb590536dd040e4a26146a61273ff9584cd5efc99125e969479f1a61e737a0c844015ead5d2eee6f26ba98a39127b9e91ace80ba39b3ce925f1f", - "0a045a5f3c2b09d3e91f845dd335d61ef4eaf96a1c2b12e6e38f63fb2216617cbc0c90a96cf19e975c639e07658560ea7c1de229900ac3ff251cc4637e20bcb20c", - "0a0052d454b5ef69b468b499ea44b110e6656cda9c080ad5430b99d6a9f6172c563c601c3ede5cfc52d304aff88f26de579ac195044da994ab9152633a56191ae1", - "0b086186fddd39bf7916e5a105f4e5b7525e2a596f3f9314bf89f465edd72755ea4923336a83215a9a5713f51458453cb527f5e736e273192f37ab790524dbd7be", - "0b08ed1ca99b3da2780aeb10642ebff0f988707d6dafa4b67f4b73951fb48fff234d9ecebc304655fba3a9a8faf27b8d756261c0cbb8517debe0c817a8414dbc27", - "0b05082848e03421b62d6764f0c2bf26544046ae123b261e1f02fa7ef6883a41a680ae7d9d946a5f6cd3311bf1c44c5a330b6ff4db8fbe1bc8a3939c95baf25daf", - "0b00321d5025b6ecc0147aa1cd1a28f9263a170a1180c8240d7f42785c36f785be80f566c65f875e8b28b2fccfcc90ae8c6f2ef84e69abf7b0868473ba8851a86e", - "0a002aaf26555be2ec16276ccb056afe5e404877648ec8d920650fcda23e5dfdaeff32a00eb855c7683c06d4b0ce919f84352619e5110778f1819fdf32d4e3f020", - "0b0012a24347f4f4607520a7e6e466453e2d25dc435c9e407314e4b7333082fbb5ec3de1d1684845c754dbf4e86b535dcb8662093bc7954e1825c4ad87ff7a3cf4", - "0b00e6a9a4b4a4aa75b1b83602b0ca51dc7fce0a6ce522d9e039dddef2ead88ebd633d4f448b3cfaf4763ff5d285f493648b135a87fb8887e5446019af73661497", - "0a01e97ade6b5335579b4515375983b0fcf05f3ac7d578a737b03b0b17a5448f821e16318acb7d26c6f63d39750cc43b955138d765d504a39b07113a3c35531243", - "0a04a712b58309113afebf03cad34681a9738e54175b2399eee60d45f5693a1f0a41c98fc005157f0e3c0ba349f550824da0ae3cf4d9c670666686d2097aebf257", - "0a0760b3c58123477672978215ff46136da30866e860c0ce5d2f6ca5f0f8bbc8bbdfb1b4c961df625658ad2351f625038c5590f410194f933145c5eda44275cd99", - "0a0569e8ba8f134317b7d41bd64ca6438011cae169bb2df9c9779b5cb5a4fe07f3b16612ba091aabe422639af73b4dc33f1ec56dfb0fbba41eb04e8c9741f742f6", - "0b0170b7fb3e418550d91c65cb0a1392431a87efbd325b72d075ed263dc346735a96433a92bd79092ae5a6b9a28a7c96b0c99a66afaf5518e92a5c06e0b32b2c81", - "0a03262120c601fb41743477c2ea9ffb70eee4c8f17710426c9a9e52ba0172017c31a6e38259949e70156634a9f9f0e15b8a138d3f74b9bd001e51b1924cbaca62", - "0a016908a56e6340a8f4eda4758afe24278fdf881046b377fff4036626f4d0536d63760fb5f90e6780ddfcf267e61dbf57c4b410e53c3dcdbd5847d8f9cd218f6d", - "0a02c4753f7823fd9f013958dbf0349df7386af23db75c06f438cfb75700ec55157c45bdd23b9e573a7f9c9d1634d0384208e5b1cab8ac66f38aa2a5e541a66d88", - "0a08f4bb1a450e63c372ffe72c85bf819454eeba96aaabf506fb126ff9423ac2f2eb674b3c9efe55c09bb235f632cafbb5c911ce3699ae163a1a44dd892c3a1c84", - "0a0328fb967ea1d7c073c7ca87b94b31e21220529ac7021c53d5bbc4148f52bf105e73881e41031560dd2f675cecf0071a049a4d2b8130856be8f0d6ab038ed0f6", - "0b08a43817e9ef61790d89de8d543282ad58d5387bc9aa0e47de8b7f712a8cb34c52ea02445163a30d5c88018074c0e93a46a001ac756d409c856a852fe9e45842", - "0a08f58f0a575ab23ad6f5fffd23ef69230cc5e423bd296d414cec9d9ef18d65519d2b24a02e5ffcdad1236b2f7be2c1630f67274b9afb2007415dd312e51f411f", - "0a024b4ac3e54dc5f328c4ce62d8afba3d03ad7967d6f5f7df2edbc5ff2cfbc9eba3b630d6c0e5a6d80d0812e9dfa1b3bb7646ed8498e7b1bf66a7d7ce9fae6363", - "0a018dcdb10cd85df304835146bd5e12535dddce803971dc0b66fae839e1194d8ad43ce28aeaf9a63ca89666fe834ab41bd983c18d4ef258726e4887a12a6c4fe9", - "0a014a4625fac04014edf74efc97ba18441744d9ee56046744c5679c1e0e74d1b42dbb3a2a50cef0ccbc977fcf401b4929066f2f55ca1683ece85c8d8741fd6257", - "0a01f103ee7142457df1a7eed2003bcf7d82f37df404462c2894bd8eeb4906ed1f28ec379e03fbb2e76042fa0d423e639aeca236afda5c7f126c9296b7587a8154", - "0a035140b0a69bad541341b23110d8e90cb2850cd43970c974675d35743d695a46227d8bfb3434d204c5214c5086fea9b54e8d48ead563f118e770766e50eaabcc", - "0a069a838eef9e856e2a31ac1658fcd745011d54fa9f9b0bfc7fc3d8b551e6a5ee09dc20b2af7c951ac1e707a772251d1cde67eef6f7e88b2436842ca4bf1c051e", - "0b0541ea70ff6908c15cfa3feac753bf06681cb43065ba5002c633c484ee56bf61c9fea38f6016788fee57542a5d4e58f6f260a364475992b0f95207e6a4dfbcf5", - "0b070a8f2ba11050ef568c323176e36cab189051e09179f25e8e18ec584d942e2030ad44ef70beacdcba3e134af7aa15584e65cb66d1b098147b0f9eb7e62f2256", - "0b0228b05bca5a1d76553e6603e5d8245731221cacef433bfec387bbf3621b9b64a7d710096888c05a432da279852f6f7f0ef0528bf4f4958e537ccbaf3ed219e6", - "0a0345dcdf14588ebabab85a49f8e3b1c0d26ce13fea5ac153969c8e542a3997ab7d669d9fe0e06484c6a12b77b0dfb7f94816c5c062c5c2d229d2ef94e5138f01", - "0a019e7d42a7927e20d3c2d5d3f5918bd328cac3dfece320be95e493ad2a2293a38c7f93950d537dce3073f9a5e5a84c0b4f606f3dcb7596aba5febdc947ff5b20", - "0b075ff9920d488193d0aec75095d85e6b27a3ab3e8a4825ab2b4cb22e08ee2572434ca4056910f4260ea62b7fd737c6ef10187f6a21a3682732a2efd1aedead44", - "0b08f9bb6b75c7ca9356d4bbb57441f43fbe2a69aaa69c03194790a12828a05fa51d1fc78dbcea1af151c2f284de1be32b0fed147de0a61db1029963bfa59f39a1", - "0b0304342605a753613000ef70b16cb09ad0c6cf7ec8b01641f0d55c41d0d6c585e01053f5f08bf8fec6459f188e4000ba2e111acbbc055c6e7275d917626053ff", - "0b012d86833208561baed6381df1b493dea9db45b76455cdbe2b632f4685863488e14caac6edd7b9cb57551f7215f211cca90d4c6a5540511c80b524cb51c592d0", - "0b0596fdce5e5c53109be9b0a27f6d4facb738bd909709932e2798ceffa093ee3f2e0c3521897ba3e05f0bf53f3206cc118ff1645e283140b3f801038a0aafdf32", - "0b00e895cfa10c5c57cfc41f83e0d12954728117ea9d70fa17f242818615c97a45a7bbad560dde97c8d05b5d58737a89fe0808a58c7e3a79ef686203b0e61af787", - "0b080a5e865b0d401a668cee3a61eb14e7e532be8c9267dff2a20a856ea5d92b14464f2eddb3bfdb8645823fce34b2550e5d18bfb3baf6f3247e436448097d684e", - "0b03cfe5f62849e976c2e701c37a6e220b44c6298604acccce8241ee97290449b0ef8d984dae2787bf048e8ed48a5241e5571bdacfb0890587d8c3c5ce08dd995f", - "0b02bd1fd5ea6fe29e5b03de7d9898f34648918315e69d8ceadfcbead41fb44bef25e10e53186034a090c0039a924dfa9d9a55f08e9e262f21df500d85cb00950d", - "0b026fccb415c74ae43ce8816b0a4eedbcb91226ca2627222ab13386fc7a5ad28c91a1b9d40334fb353624ff2ef5bf79e045c765f82588c1f6c9d270fa44725f24", - "0b04d4c5a6b303729c991176859dedff650bfcd8741cb2b65de9379a80c8d822410425422868ef7a8190d53731f3bed163c450b45733e6a017c0f88faa0d47880c", - "0a02c32d260310077c95d535b643e38c1d25ce2f85135221e85269200500e0eda688bb259bfd4920796875385e7e55c1f51c8347c8743cf3629264bb794e9688a1", - "0a087fbb45914092f13f8b2bd9b904c60caf1db95243066e7841002b355e9353e2bce2a72cad4d8bede9802872c8070ef15e742f21443e41e580f5060f9bfbcb16", - "0b090dc2b7c5a6abbbc49f2f091907899f0820066761722e2023553f56467c699f40d7ba117b5dcc9caa93468c048535418f2238d5ed9f44d61c5cdcb8b8fd0d4b", - "0a08a0503a06a422696b46bd13099f41dd36b57949f066c0f5437b93a244329e5a6380029b32c3a440bae7fc3790b9def72399fa94ef0a697259e8d4f1bc21f987", - "0b00de3cb21e159d649461101e596b3d3566aefd9c70d8dd386c096b627dc8dd5733bd0bfec4611561ebcf004584b5525a575f595dba307ca80948e6de153ac2f9", - "0b05c810ce5a691b893edd97319015e61a9e5eeefce7007676f23e58ff5a2eba637659d3269d0001253f8de2ddab66352926e734eef386b442c98e99d14d839ff6", - "0a06516ea2cb5169868f7101bd96bf8c168e3058d6e0827e51a6a0c6b06e6dfb8f66274b251602e2bf9cd36f522fe3ceb072d591f73cfada5fb90c29819349d206", - "0a063a8a4adcbe055b0115d8c8360256c6a6bdab043589cda55e4cf01ef04e60a90efe9a87e912a3efa5b08c9416b7c10a453452de46996267c0de5382d7f299e3", - "0b07500c0c726dcdcd9b905de484f147843cc26493d479081233fa71352cdc3efb08a4ccb84b54c5b92e51af3a0bcfd8c535d284e67e34f795b0d4ae8649843b90", - "0a0302886bcf846f7756b9807ab4e9dfb2f4a68370b3a1e145859d5478a1e1322dfb05b41d7915ad8c654b460ee6aef5b22553b9b81171a92561be8beaba05fad8", - "0a021ca2b98d5ff5a2b385aeca6327b84f4898f381bc4c1a3f2c90fb836ff8d4e2ba1cf9bf78c1f990f07f90187c9c509acd7bcfba11d4177c2e15b88e218f428f", - "0a0479845e5e844ad27551cb972fc4759e557af8807859fa24ef2fdcc13873aa94a7f9dac6c26c08c93f04f73295a6abddf7a317495f9349223d4c69646fa19756", - "0a0417b7bc87b1c46a047cdd8b302410df5466f0bb8dca7f65efd9ef3ae50de71b71b128cc0cf07e32d3fe5cdea0a4038ff93dfeccfdf648fa793418c0e34ecf97", - "0b03b51413c261427491b2f7f9bea59b71c3afd9003e960cc0be3a806139e409acacc114dc4e6292e01e5d83f6a7bbf1811704405883cd9ccbd3f61f5015355091", - "0a061ebee6a1b14eb89cf784c5e49a61da274e9bf0a51cc31054f8bcfe886e935e1efdab43feacc4916679918c69fdb875e2bf72ed0b63dc3ca6e7f873912b724c", - "0b00dfe1dc929f6d8c4cabf0bfb43412b78520835ccde9fdd38b00c9a00a3da0f7c9bbc841d32e6090bf07edea7d25af543121858ba94298845ab1cf78c869333d", - "0a04f329f94b54f68a9b9e34d97d6cc700455cd0a8f89c662e942ea141d931b7ec0c93e6255cf5f06215de920bdd56950887a125ff1d52c926561c7a7bf8d21d93", - "0a07b47bae38743a340e01c48c7f984994ca97cae2ec438881041192a2c1ff2ac876b00610586117047de07e2d194f8dc59d4520d04a8d22f1d010e346ba39b228", - "0b077782070feb4e373ee34b8d32a2c76b0c8ff316c647e589834d5c3cbac504712f5e68b232eafa04e6b0856f2e533aa0c35d00840269fb806bfa9c0822b300e2", - "0b06b6d96236908f5e59ad55caeb7d56ea2d57abdd7f88b661c6d73ed598c5b4518e197ca14415696852c52112ffe7f750a62af8f17e77a6c863100ff6758fc190", - "0a037d54a14e26d386ecfbee9a41d58fdbcfad4bd774f2500184b29d4202974f90fc650b40a2712263bdea178fda7d6c45d4134cc5e5607383849905ac51dc2151", - "0a00fcfb4d017b813a80f92a76d8ddcfd4f8ebda96d742689807bc510467a48b1d4d90c450516a2815b9e332f27ff79163756323941956b21701af1082e5ac8874", - "0b0453f7fff4be0d7a51eac3b02b7a2d865989bae551cc06ea05023f2d7b43671d13fdf88dff5b0f53518f18b52cbbd363806c0f9b6a7f4a35be0f5af4a0401f4c", - "0b00df26c42f75345611c66554b245c5735fc8994294673e070258ce2f6ac6ddd34f67ed73b54e7ab4a56bf3447eb25fdf3f159675f1060a0cf75aedd1725c1835", - "0b05342ece64ddd7d0c710a427effabf05d42efacd3847cf9896025c2ed2d91dda4f660aa164d15c974ef6e6e263bc5d1f2e6b76bcd57f903395c5788000e6ff73", - "0b01858e225806a2a8d59af12bdc34d42b3438badcf21d3569d8d4b86dbc92bd7ab0359c0a0a7c8215f4c658223677f8e275b46af27f4987f7f90a5a0e7469d07f", - "0a08aa48b1dae83030844f2e3d9822b02a132dadf19e5df4f4b20c714b07dc5b5be2578f3206b55e3cace99ffeca8d66f15cf135b4de928a6a2f96f669f1e2d8ac", - "0a08c462559cdb6116713eeb277f02763c1c12238cf172acadc70a5b06a99aa81d9b23d72bc892a2c3cca964f54e2e0476055dca42a04eb2f258a6f432779519fc", - "0a08cfb6beda9709656bcd9ec93f017cbeadb4c3ee6969b3f7c1765592b966dd809708f3f206808160e61c0da34789669bf0b51413454696af991f4a938cb8569f", - "0a0690036b95c55efc9f82c50e5fca58ee25966aa6039a930760ea6af827c4568f2d95877fe5bee41ba6949907008851ab3fa20b14b195e32f3dcc766d658b09e0", - "0a09090995f23b728599c64d96100b63c2b19581d03e9bbe9539665cf6b5d94ba68012d13daabb2d629c9fc259951557fa9d258c3d6ed8487c8fe8893465944ab6", - "0b008cbce55e03771c3017283b08419f2bb516302dc88c7fdff0195b76f2b79a794546eb69fb2dde3a4a93f4bf9b9344e99f11dbf02fb17ce5de39c9f4b6b1bbd1", - "0b062386b1adcc93dbd87670b70f6f12ba65f1d93cc8e734d3a46c5bb7c45aad9815f0169cc49199ffef38d6ed3e2f84b31973b61ebb0dfcb44ea493c59590e05a", - "0a020bee698b941c33b9b2dc75de543bfb22f9963412783a07c56c955f07eacffa0b695e8307280e6e2a5f5ba31f4e1f9be1704b892b27398ac7ecc5579e9241ec", - "0a05889e3ee267b14d16456a97a8bc179c9998729bbc69061029dba6f6b8b4608f990b63b8f69a7760c8e2bfb1b052b910b60d0335ee812d700b71ef57dd8c2c9d", - "0b0724ecedf635fab6f0bab230aa5f99798713637bcbcc1ed99203504a02e87ade4689da7eb203a08ada571240dac6719e588df8515a985d647b09ec3cc7835877", - "0a07b34e9d05d8b87e96dd8a1dac0d8952d11005a90a892de0793f09cb8d3bb237c0630e851ee90a77ce8ae3b71c18c815376897815a9152cef5198a2c1c6ca100", - "0a042832f13562915ba95723996f79e00e93102b930d1fde58074a8386229165c4dbdc31eb23127685edd9a67cfe379b9eaf2c97653a3c85dcb5b01afd9dcb9e9a", - "0a061c968f2a51fa8351605b6117abb7aa13f4b9610843e181aeeeba98e2703021e5596e61ec07bf9f7cbde3b369c6691c63d861fd4e91c5dca5e8a0d561947e5a", - "0b012df647767a1469755a51a90209237b50d602407c1236efbbbb04e544cf6aa4d9bb37ba214dc43c195703600f20a5a4a153bcd63dfb8a843c8196d128c13760", - "0a057c801f161cf2a25232f67307a676badf22323cbdf6396a6fcfb7ae28539f8f70ad26048f67a9587fbeee7a33bac1bda7ff924117c3cf83e8c14a7abcf03c47", - "0b0555000a1cfbf692aea40ef061db6056fde211369a0526a8e4d9f5b853f457567ea569be65fc4f5c46240416057b371acabd4a0e2bcbbfb624628b5fc764bd4c", - "0a0628723b57b9ec1e0a4c65c4ef547bdb6783108d6f0b11537842c41b698a74e3c139167129806eed2ebfbbf25b0dbfce7a1bceb9356e8cf069d8b3f9d8b5d650", - "0b049fff81f772fd5aea83e10256b380ce2ef5011b1bb2a5d435c53218cc5fa55cf6f6956b25571ae60b91bde915759013bb25c5f73eeb987afccb9a07bb5b76a1", - "0a086a2843f33dad5a918077efa4696846b6f22ea7edfd3d7903d35ca52768b1c6825d27d9548882300680a7bd0c1c08b606cc2286ea9a59be317d8f4a1494c679", - "0a02d1a2f6b37f137fd410d3e3ac9ab6dfafe5773a97b3a50951305d05402d59199626ad017913aedca50766aa5e01c9daa273e9a41318c04fa0ed456ec334fc8e", - "0a08c427a30af9834a241b5d81a386a69850d5e9fbcb6b22b12e3070002c1c17b10561d3584e90d1666dd04f446b0be323b90a074e7f31de6e48b0592fd579af2f", - "0b0356d591292124cc9aacb5030cc4d8bd329d823d3bd1e27ac00d41316520755e9e0a9944b1d2093aa24eef9863884c7ec7b181bf0e0eb83fcda383367c12dffb", - "0a08561c1db5d038c1c8ce564773830a1fb11cddf656830f7b8dd982bdea6b2c4d020c5dfa2109d1bce1c707c053268fd73ddac9ce47ba7cbc9ec3071852181bd1", - "0a06bd68a5df46794c949f75f579e2aa712f40f9b8d05d024eeddd3eba2ba34c1b0102a3fbe5355078337d8afcc17f3a02be369db5b513b221909eccac91151449", - "0a0544de8bc34aca38675e8e2777c482f6e59337baa03bf8c467a609979db654a062af8e173d3d74ca37a6e19cb5b8f2753757d58d5dc8a7dbecac17c326d05009", - "0a042ca13a561b2658a475cd9be16645ee8e8ee8ae71544e7819a15a7d8178335ce7598c23657ab95f858bee375f5946c6bf81714839a5c619297d3622c13e58ca", - "0a01aeabc0696f58e295d93f138d88ca22a60b97b2e5e96bc7e5360dc47e2ba6671066f4bb208e5601a4e95537782b5288c566a5738542c585afb405f243649b38", - "0b05ae4257e6ea6d0b3b030bf2ac7f41c66c4127ea0288e6aaf343e1e43eef6787ab411d640e9ec6b1c103ddbdb0d036bba835d093a3a58e6e4a74d49199f39f55", - "0b0915334f1d098808b7939e4474d6a30330a32579abf4136d20402999954c07bc10ec1c7b266a732789ea0cad38a728e8d94feedcddc517a36939d06ac1d025b3", - "0a03d9b9943f55bd4a7dde648e1e74051be7695bbc5059c6716efad0f6123fd7cf90ea81cfecb0fb39c5f15b39d7d2e4b38c6306fde417c5b76329d6b6c6d29ce0", - "0b0208a14bc608276c61a6a6963b03e2f91c0801b2a0b5efa5214c4d8091d6f2a0d9c84708b749519fc054f9ec4ff05a71262b2fdaf8b738e9e6d4ca3aa986979e", - "0a086d56c469c6e6c801dc83432156a05f0f134204266990d5eae8b58f9015619195794ded2c9176f124e82647bd51d1307858004f4dbabaf7abac66d0405a139a", - "0b047c0011a6896c3adce1c5ab1934178e034b3912fd4c719ffe455ad9bf96e39bfc7a433610cfedcf2b4c65b95faf85ca708e8c165579a9d8f088ef1956f6f491", - "0a08af8ab87e4e2da5c5e2661fdab020b1f2582380beef24d1d13eff8dd7dd6e4737a5a4d4dadde01cc850fc81e44ead388b43761b8c8ddc138da5a96cce189652", - "0a02d66c03fcf1ee33fb67ee82707940c8717d2d35842c30b0f19d6d1d14e7d8a11de3c1dfda5e7a1a8a3b7f93083304b549f8df538944af1ec38d66f12ceaf2d2", - "0a08ddcc2f17998dd2f4f4052e47f335b553c4592880177bf6f910325c4cc3217aa4caabef577f4eb5067b889a9153523c2f93567d20c444ddccb4ef0f7506d55f", - "0b08942fbff1ce796d7e1acd416d7a38b00b60dd3201aed0ff130fe8c4cca518411ea795eeeb4cb4d2929d20fb37f089d023c93b38cf16512c33ce57baa607d631", - "0a06767a4d2282728c58a48dc47d32b69efcbc638c868fe6684c1f588d991f5275de69cdaa3426175e6ba32369a58ad1f2c15907e689222a39075826e8e3515902", - "0a022957563066e2ffb4a73c5a065ea1ccc8866203b70cf432986c11b2d09394d041caa49882cdcbbb8335c5f691fc08ef3666ac4709c82fd2a55eadb62b3d7caf", - "0b02d86356c3a4fb27bd7148d71a1efc1a0f2db662ad9f72eeb35eece7e7baa05b09f6ee86038945e0492193f27c561c037d059e471dba6d72ce02bfebb412517c", - "0a07782f6d00090fe188965b35ce8a23d41496bb5511688d590179a368a150718462393e21df4b10367c28772543f788c50cb1c9c388eef9378b1d25e2922eed7a", - "0b04719638c2e282c0d1c6183b7ba4f14a332c77519117f6b460466ed464a162132d2b2d18ba5c412cfe19ca95dde4a6ba0ed8e2adf7418581144ac6c3a920e2a9", - "0a010b399d0a0af9ac4764286180b4731efe08451bc13473a2bd4a9e917dc618dca2557610b62cf4d16fef5692c336a0819ff0911700118084e7fda3555bfe60bd", - "0b065b2b81ab34844c500246e45d8b48e8eecdc1ccdaa07dcf758b01c0811d96ac2061781666da75afa40b0cfbc36a8b3ffbe79177387cc6dcfb6cd78c8ba091ea", - "0b05236bee1f28dfae0f7442961a4cbe905e9588ed3abe57a406e61747dd620c2768ac92108b75dadae570c5f410aa07bedd9e1387f4428d4e2ffa88829f1cb02d", - "0b014aad726f240fe755825b0037dab0a8e376550a0cb715b30a0755b16e71f816289ea1cdbb792621e66a5e413739f84acf989b35358311a3f6ff9e32754443b3", - "0b06bbdaa800b68234092cd332852f845b838068219c64bbd89e56fcb20bab93e06a867c223c5bb5e40504280711404f40c5ce67a57960f7de499e9a78531e0c3b", - "0b0438995dcb642e639407a3467faa777e4afa71c4c3a64af4b30153baca3bcb90996c490de769a50567df4088f416467f7d2564ca09dc8336feb51751e63bf142", - "0a0273462c5f2933e9381ac617cc8bba9b7daa077fcc23b70d56ae04de971383f1f272d7f5731b8d4ea2f6fe586ac2cd98f9d9c7e1738788df7d4143fcda4ebe0c", - "0b08839f11f879b29e0752d1714ecd91e71f777a4549bb7e4a532226c2f33e827d8d4eaecdb849afe4a1f7cd817c63292c88304a8c19f87898896f57312b3db9ab", - "0a02daa97ed92a7e780d92528078c90202e75cac8d88ac969f6460f51ffff3f8d6eee8ad6a159b7b20b66494fd21238c3ba5eddc2cb22b18bb4f3faa9c0400c49c", - "0b079e7bbe1af96171fca7c3628db3cc9e2e1c4ed1fe532db63c982a4e9042ba53e7e88cb142fecaeccd2e57e832626b8e25c036f301f24c005a52236dcc30225a", - "0a057a684695cb201aa1687604f02965610159f61d09a9ca677ba21768c47c2cfd5992d47ff1dace9b841602a226f4b46eea8c06e2a221962fb8fc6f0316ed79fa", - "0b029cc7cde9ee102399dfe447c1d7eef4bb05c5b0a8414ff174ede6c41736b5c79ae95ceae2625f39def1f5a41fc54c00dc1a2be0d00c82a9f3c15a07e386d9bd", - "0b074af89e58496288d4d95fe5319dabdd90c8026ee529299b8e99b5c34f964c509109b43093919e8016e8244251e00d808e163f26132e3d962ab9aaae291e52e9", - "0b08d1c2ac2943233d2355d1e353c4693e10f1ba3d0e0d8d031bfbd0c81f790eab3f521b088cb6969ac7225eb15253bc0e2aad5fef6f08e6114e6c18085186226d", - "0b05e5fba9535fcea2c48307f66735d1996331a1638274eea073bc48db84be883b1f06b772d649f7a50f74f57fca3d81e9391c21b490908f3a0af4c2ca001daa56", - "0a06492c60003d76414b99cce6dbf9e2ef6c995112eea521bd02d92894379c4ee93e4070276ef607c46a5546fd4791b6ad9ebad2ef09189eaa8adef4506b0e831f", - "0a02ff58d317dc4d734e342afd583e28e83bf625ede927373b35c98adea3879a4e63d0655ac7f4de4992bc5aae49b7504959c75c448c713df9e38b38d7f0fe5a41", - "0a0029f3eeaa2474b9e3ef07233505349f98c89fcf8999015ae3ec5c6c79dc0cac75a4e90021d62570ed11aaeba50d6536d2efef21c2669e325a410d076fc8f269", - "0b03e5a24318046c319e1ed8d706662a0d998d8781300532f695c34c43a3ed1d4ddaf7501f0a0a24923e0a65d5d4de3ae450dad690f7b288361fc9939c5e3f0638", - "0a0192cf0c998d83a91e0cb47ebf6cfedbb0c73ee4e3995dbd443de1c3bac134a9343219ae9a10383c9e6fe371835d25ec562015441a77b2029aa68d3cf9cd8963", - "0b03518bf86160ffa552b5309c87c2a561be00d2c9c7928b655718033478fdbe70265b01a6c9c87881af9defd818231dacafc5120caa3748d8c5ced4b461bb1115", - "0b05700025496775e537ba365a9b14ed4c40609e905b85e6a3bc07bcb696b5be7c521054385db235e31f0b11a122325424a3144c08d7b8bf0a2472c59785909ee2", - "0b0821f450f746b0aa44926aefd29e0fb58ed8608d710064e29b57da58fb9f80a2f47f2cf03ca5333fc48461700e02f3199a68c21db1d9bd146bed28632bf82e8a", - "0a039608411f8bd69f35a9b83b2840181ed75c909e97ddb24b88acf1b86c1686b89a9f43105df02ae2ce9f05b2da427f7848c31f15c61eaea8b7769c8d83d7eb0f", - "0a08367c5106fd202f6f594dc6b6b86208f4af85549d0e0ac320ce5f8f9e3b5e554471a4d6e066b65486c44e4cf38ee428776207494b636436a65fc8244f08a2c1", - "0b08cd3b68c72be61de8c9a2c49ecbe2dcead14c06cd41ae16a31e25b47b8c30c01a23d2249c255bc295edd2dd0c21b3dcddf29cd5b21098a7425b0ec8cf47126a", - "0a0000168b63e9e53c1ebe3b6cf42f381bfbf503c24428694ddeb7e8a9ce9f49a741c0f278abc9800b74e995a11b4b760d51d4747cfb8475d7cfb934bbdbadf909", - "0a080dc3ea6bb58f6c0ffd482f1405ef847c4702df69509d18dcda026b7a721a55718350f088c1fa0bf853e025370629b67ac56652d60ff379d0663488acf9ff22", - "0b010709da8ff8cd5383faaad6750b4f9e91a5f08d41964976bed17283e35ff92c4f955b383d6af2ee65dad6e4802a45bae3c2e39f7a0edf6096183821af0ff452", - "0a035b1839ae0693b39b26f81c39bd4a10d43c9ce0fc7e7ca2a5b47b7dd4175b2b8ddcb87bd29a65f9441fa356de5b9f99b08ba80b49a2524b29bf72de6361b82d", - "0b038ea71795ca80956e562b7e7d817de5cbae9d62799976dfd8482c5e28476c34c6da2d24f1bdf58d7348a7245ed44b648b7b8bdf20e8918cf8204b2c06507b01", - "0b0875b6db397c22589341a0de822263e0cc893a2711c6150bd6ca1bca7d906a7877742c38ab692ce4be3d0a0ebb0c017af3a647bccd231402f07e9bbe09069148", - "0b07e08605da5162128c4b707bde325e46e12f414b09a280b71fe54fbdb016068ccef0642eef6a5979dfa88185d80936e7afa4957b54f190bd9de5772499eee1b6", - "0b04515cb6f1fb2adbd1569c34073cad1cc039ebc6fcb9fb9d377bf88877d9e8cdaaf73ebd6a13e4ba196ed5148b738fb1d5adb9cac5f04a9edee6afa74441ca85", - "0b07a719bf6cd56bca4a76b78d37aab351180810ab3f1ebedf70bb2604e7f1e18723f166c69140440a89847c1828f3ee19f7b671de0644a6e8209408dcc8587891", - "0a02207c9dcc200bd82d6ddaa471ac7d8ee43f7419b5b64b25063a1a86c3013eccfea34cea9c2010dfd717338d5ffde810a8ec611d882bbab5a78d495f4d40e801", - "0a05ae8085e9b838e3d71e73184bd28ded16b5c0b2662c7b0063c1c66999d9337d734c1d95bc22897d1f0a57a99032a745d01277ce958c74774c6b0cd9ad87c4c4", - "0a07dcbeb9304f55d634a429e3ef01a77cfccb075e2afb4e95f2cd6f9a6d213dddad741c544c5e60a8a67bebbebbbc8213596712373fdfaf760de7601b09fa5859", - "0a041506966a240f7a59149400ef043fd90a8da003978b2385b01c2df53c965e74641916e3d25c0c81357e4890ec8e5631416d92dc8831d6c2187c32c3f2b4f26d", - "0a00b596b38f0b928f6de3560e88cd102db916bffaff206bff7d8bcb25519c8dfebbae0b31e1c63bb72bb234d67b622e3a5f2e21333bc199d1750873373ca2b582", - "0a02a20c3c0085708eb6fd939096051cacf5e35b1f03aa2d8d058e7d2cccc9c24ccde5d1c6b82b078775907f81ea7e86d06efd74c15285bac8f655c1b895a61f6c", - "0a025ed2e81002ad2ca3693d0edc1237b14e0c723273e31d4b6e5f98ac207508a638aa6f2f9d05f042c58425e906fd12e3dbdbdf16824edf880da8d67a0a46b0fd", - "0b04c24ceff96995d331112d931c0578f8f38553113ba7254f83d48b06c913983ad87671337667bb829192d7475d45ad690e707889c61ef3c6fa97db619f1c9a58", - "0a051daba1d6d818887cb5a8d82fc875944f205f669463f0550944c7f47717ebbfa3a1960b31c5d48138c5f2174a92cc593df4876827fab74d83c4b97aa3dfc201", - "0a06b95760945b440a5f18f185eb44aa37f5f110cdd57fa7f01f016fd3d70b873be5d6e5a94c28f6f31016b68cf917726fc179170680c5ec3c977b98bfc9b08b2c", - "0b04195e6881b214b1776c2dbd78535e19745c92a6886afa2790ebad9da1ced5f028e896f953f9ba6cadae26ed83db6a6daeca7f605c4fffb31fa2d9cb0dd097bf", - "0b05caa29f62a9c44bdfc2e13e668fdbd0f033fdc9901e18159dbfb9dc2a49508686504af65aca339fc358b1cc66f7bc35457c5d0e9901466dbf386fb0840fa076", - "0b08efcbd84670526c09106c88bdbaa8aaf95af432c8db29ac1a967135c6c4b8073ec38c788e8eb5521d66b55448b0edc97ae19fbee3d7cb1013baaaf58df17789", - "0a0473ae5a535398c292f29b1d5fcd900e92b50c924066c3d3a8b0afe0db86026de386a2fdb3fa432d8ce6cacbfacba20f34341e0b2df85fc1c5384b582293833c", - "0a0782cb1b0d057a0939910c8f7062ef1e65c83a48a1d871ad77efb733ec5795e0859dfd5046e43f75c9e08ecb2cb87545e21e2bd299e849469a11787d57ec9823", - "0b00aa0ac3dd4221fa1603088abd95fcb00674306795935c1a76fc5d8632212bf7962b1da3b60cb32bd9ce363c2e5831c6ba80a774e9e7a179643ea68d08a7845a", - "0b04715dd9132e6a6d523f4f51c77c839f3d60292163f1829357e262e57a4fa8111838adeb89c1b3c59ee5cc5cf8bfdbf594c14e5a0144e7924120662f06e1043f", - "0b070c05abd26412389903da4b3016f6cd096f8f4c119e40df07e8796f4b0df9a05312a8bae5288c58f08c22d4cf1dfdc3ff2ba492c9e421752dfa200efe279807", - "0a082393e09f7976076c1d63cb7a8bf3d75e5d3a6ee75b839931282f4284d4e5c8cb32a4c6ce2af50c8d8d135cbbf2a12971389ed8bafa28363b5ba7330dbc4710", - "0b04b7fecb95c02e514ff5722a3baf8d00a3092c3c71cba142fad98f8c5f8eea18918292074ddca69c3e4aed15e2ce2d60039fdde730a27e8c932b5a89c96a220e", - "0b022c2fa3f812b06022ac864a35dcbf391920b4f291b2cd19df186b2d419f41a14ab3dec87206bbf089c08dcbb2a69d2d8493ec08888f7dee84bc09003687550c", - "0a0572d64154c483929ef1ce58f77f68f1f69ada4b84c43e0ca86b4457f3dc31495dffb4e3e5475d4dc3637419d0c408258f0393807c189707b73fca8c86202df0", - "0a02148d19c15ae36ae3f8dcee98d3cf1c8025ed55d38bb8429794deba4979474fa12d46d1e04f5566716e670155ecc79747cae4d4ececdc987043a27964792e87", - "0b05b4b375a6707d3361c3568af16c2622c840653c2943b5e8415dd7435ec4bb95dee77102a0d3566de78adf540faa51124fd9ea7fc6d14b2751428d09fe1e27ca", - "0b02d0a66605673c3100c658a61bc353d9b105c157bf450d3720e42b82fcd8b8b6572ae45fd875b4d6ffd3d69ff825f758b1953aa0c4ae2230fe53deab1054cfe2", - "0b010e82c33e695c466c8478fdceefa617ea090910308871a88cb66eda8192175d13028ce0569e336784496d60b104c28239fa41f1048299c33313f4e1eacafe3e", - "0a07f72f898efa6c183d1b9ef66ea9099d5ef97db934a44f7a27a5208da0ecb30660c0dd80c45ea5e4c73d6b0cede5db3fa6a7d44e08f7198de939498c1e8705b4", - "0a073c3f7224dd85b222bdcd1a052d354ae29523074d4140d4ee5f43d2295304beac36984aeb737fccfe6374f1a3e0930b0d88816a2743ea4f6a033621a819de92", - "0a07c8fd0a3e1145f6b239d1c3a88553043121628beb924f044e953d440fc73ee4529b3d89d94446a3f85fdab476bee5bdd0f68a927a106d45062c80d5877abb37", - "0b08dbfe6d347589e398d60054e526397dcf719836b4d5ca3c018aaa0c29b89f3353ef3c864951846dc190b67a048ab416e2a4d1b8f6881b3f5edd05b0b7fff4ed", - "0a0903cfc89b1405cc4a66908dd744098e6edc632b3edf5c9dbf62f12420bfecef85d58246e4e00b047a837f27e18a4f1b4c91c062364ac231dd889df0fc36bf60", - "0a033091f730151d4178f8fb8f2d74a8159e1bbdc9530572db704125aa80050bdec0168de7549d6aa0eb69bdefcb3fe6d644a6e6d5430cc5b81c235385236cb2cd", - "0a08a2a715c0041e766bae6e2602cfd11ee8718ada335a3134563df37542e8364ff1c74d4c5d31f200de82808187ccac809d7f4ba8da7e65cb5b514c2390827fc9", - "0a059ec02e1f579b3309643857e976201a7f321e947f4237b104cfa758c13d8b3d446280bd809e04e6af39c1383a2441318daa9dfd59e3aeb9d5b8f0350e1e9e91", - "0a06c1c7bb547ff71887e872be6b198e027cf77a97857560e6915f1655cb006098f296c247a08abdb9fd6b50529d70d51ca40c99d55d7b537b60cdaf90e07869df", - "0a034e9e8b091f059460e2d88931f22d72b7d84351aa9a4f18ab62471a973968823eda158fed33a5498bb868d7d56de133dc18e72667bc21a5fc2c9263ad613738", - "0a0119b91beab0f8c365392e9a9f0764d4ed13e28724995857778e0e4c0ddc98a4b04d18ad91a5e220aaf635cba022f84bb6dc9fce53ba4a7861efbe62e07b9cc9", - "0b066d0d3bb46e5488c33c155f453cd6bd81c09a1502828a6d015509b78397d3a9315afef04183a67e42db24867d9beb346a0d7091b3667c0a2cf111f52a06eecd", - "0a08d5c39429f33d090a3bfb7b7f7fc1d69e934a5d0e5adb331459c3d4850165500fd1bf3531fe48581c636f40bedcf8593d447786df8a55cc9bb287d15739be0f", - "0a06cf0adb5ee6afd850e2fbcc1fbe672c420b440dc5c349247f894efb979e54647fd7e57f45a75d8f77f03cbeca79b1d326b57c584091e2910575484ccd88ec95", - "0a04a0506f5ad60141c586e674a56cf3478bc993299fb9ee2cf17a3f7b51ba336bcaa08f84a8c8830c420b482034d09b0ddb11eb6512655ce73f6cf8facc66e2fa", - "0b070bfb444e748ec3628b7b63249a7dfedc91ba822166c251936c3dbe01484753fc5a56622277ba35a75581426f3d38d5b825c4acf9c47a5e42112dfe08ddbfc5", - "0b013b25bdb7fa5a737ab4466d6e5156bd0ca82d929f6e3a7aa542c5dae12a087a2e240cad94b11ff62291611c0412f938931bad7b6fde1508782282c5eaca1708", - "0b04aa29781039ef370cfdc3a710e5a33e1b315cd291cc453b84313a9633de1243040bbf121cafdcd1d3bcc559988cddb18c390549e6c5af20e2960d8c491d3c94", - "0b02559339320c386298a159a6ea9161ccdbf7f793e12881c0357f61920925d6678ee8a2a5b373175ad2024fdaedd38e485996be81230333323cd7616edc30b22b", - "0a084c1a0df33f02022d1f5bda56947c6e9b57e11fb6f007963892029c9d66f9327808d28f4069b61bec14f91d6da09d4fbbc42f666421469afbfc8edf7b9ef16b", - "0a062188ac448440a8414079f7e5415ca9278bdf3bfac868c821802cf2e3ec2f38a138a6379710afe17891509fd3d13cec329a959671bc9b5598212ae78205c02c", - "0a02a6146e0e70ad1d945ea0fc69773b6a5e627d6c36a46471f638cd31e762d0e9ae8893199e29104621e9a38bb2cce3d09a6c8f5035e3cdad20bba0dc9727de9e", - "0b01d15ab72f5948468a74698f1cd44392986c1a6bb992e904bf341af1019f58fade71940e00ccfc11d125fc13d814b504332677f2a7fe359fd1a01850027d02b1", - "0a01c9722eed20ea2852d3a8fdcff434194d0cc1cabbb43f6037055af52acb27f76d7ce083b1f7995b4d53057094ba774504ce1c98d5bef604f4217155f125a128", - "0a031a71de44395ad762723feeba0f064fba56b993f45149c763cd0716e094591f69418b6ad40c7b5b1e864cdad0b955486d3b2a85bb1ca8953652ab913e0e7558", - "0a006ada902b85ba93256315f23aac46ddb73abfb94e03ad1611191c9cee8d9475172bb3514489300a296fd5226cf62e6e78c5d01494e512c35d0cb2972555fcaa", - "0a0764369daec840b0c4ab7a76daebfa607264e6b39ea31dc7611ca9ce83ba6c9c6d875ad43c00f8f505f2e4275cf0bce4a578013b83726a681cab2ad5ca77394e", - "0a055aa5e07c65a0b20e088482eae52a9ddc9cc94adfd130ec8857aa5d0ae86641b8c801049d02f7b5c860a217717e55046301ab9427af508554f4db624ee42dea", - "0a0793c85d0e7ac8889f60064289855ac78a6b1051f207a4e56dac4fa8565613e81e39b8baf865bfbbec4db0f2ebad70cf918cdaef3acaef023ecef9acad582eb7", - "0b08133834d4285e09c261bcb6790cee2a1874dca158695b745248d671821b51c234f28204f9cf79ae1c28d216603e4715762e66ffca81a2e94809cf979ebd97bc", - "0b03ce668de29dfaffe8986ed9f8a3fac54fbf31554dd92b585624e4c7a1f539065b8e6a3c8a7bc4431f2ea6e4d6257b503b888bb1cb0e29d32e19978139f10f26", - "0a065efd78f2b437997b7d7529b206f85b77f848caf845e86d15f0c3e7c0bfa8c961a6c9e990b7eee1389a7d4fc719b30e20d31cf8731e80bd5630ac49738a9d01", - "0b009f5996d4b194d90ba79b222ce6916afbd0d1d1fb72ea79612574e9b74988fdcaae8affa1f81f40ea8ab838bd29e4c2dc788fff80485117ce76d5062edcb801", - "0a041316d13566df062cf4407769a98beb901dd3dd8e7102656c49d3b1019d926078e138da697dd5981726da1e4b397858704e9c2123288e5d00924bb653a9fc08", - "0a053bf6ae203271b6ae40c2a92c17416121335e563fe4ed6f79cbf4d5678d23796b335cfca7df02cf375a1e3fa688babedf5376d9787ce1d50cb0939e4f989369", - "0a014f305942004bd2d9b873cb03dd1c980485171fe71594026e07e3e42527103acd4759e927a4f37d1058f8037e3c1a3623c2dcb7e2ff4e32ca1c2581cde45ce7", - "0b07dfcd3c8c1828d195a98bec91ca1844490b47a02a86e70826fc133285b16e83e259f27911a4ef7455c944db29b802fa4ef51017d1e7b175b256ad79e1c44f5b", - "0b0467e8bf9470201e09c0ed749d7b6fd756206132d7cb0b09a23ae76e092cca1db45d667fd723536fd78ef9f3705a61277f9b5433727b2d723480745a20595276", - "0b054448305548c35ea0290821345b8c095eb6e0f591ae4d2532f6dc90b8c9a5a362dddeed055a888b0c2fc4672104841cedf3879932003edf43baf6ce6e0c14ce", - "0a06962d823f9c642cbd7f2f858cc1481b3cb73da359ffda5938cc3f0bd624561f8b133ce49c389f1d9187710f598bc0e40437fbf71456a86124cd0f1a09ce48a1", - "0a01116ee8f8db2101b7c7b661aaf963554640c1c7e4aca5d5c4312b11f060674b0adb0eb0d0627a95eab95bf554cab8d4bf94816e1cfadf021d1737d80c1a8d95", - "0b00da76da739bba8f6ab0569a07ca9d5d1b0b174f02ec54fe76e9ee0c493fc9af931a3d8bc8d8b64bf4ce27b2231ee6c7885a50fc7e6a69dd6ea714d5262f1da5", - "0a0304940c252b50a27db1a4095550c646efb814cbb64ec070bf4c19879fa5b2472686c645fb9be6d9f84bf6d2fcc0cd0bad6c184bbdf0183ab098054edfc1b0d8", - "0a05553da69d9bbac7cb3d800e994467cb63f639b4cb3624afeeb91335bebc4feff4357e09a427aeaa00f0618019eeb341010df5457049f4ec6feb38e752d4c5eb", - "0a01f23a0fa7b105b613bc4b808a3e47775473a0564b97dcb1fe9d5b84cb250c6063b1b2682c6a7459df6bdd470cfd2f3bf247ee0b00b3784033fc671c00855375", - "0a02b4bcff5035d0bbe126ecf67baa2c0756257afe8d703e05d6110d2ac9e2acb52cc0c453c17a4e6b658669c982ef8a87e0e9f9e66be949233cc63b391e8918bd", - "0a05b19fc8297e7c7e6d732d49bb18041095db6c69bc73dcc70e16bdc937b54ca5d8c2675e4170047e0e52deeb6b5f64b7f7698476ef418552283548d890f6a306", - "0a01d1b743c18269de05c0510bf12b9c6c86b3d5e84bf41afecac7495e69c4cbe704115a9fdec8269b45d068ea331404b0644b1a821dd8180c5cc74575ba22d237", - "0a02070b1e59573ce2f764d7d8c2c624dce04f8860426ba5cec18a4bdca1691624e7c9d83d134a6956e25cb20aa8c8be060c253048840ef7083a20d92307472852", - "0b04ef2cca9f68799949092e8f40360d12e4e45ee39525063221fc59a611e9b4b5255ea756d9f42ee707a8a5cd6775d037a4381da88e45f36441f2c01a669c8a4b", - "0b07a1d2e60e359c9d894b7017fd26f75c0bf6bfcd184fc77f1b304a397c0ea2c1127d72fb3c8ce1dde839d8ddeaba2a12480bd268a2fab0dde4054075456ccfb6", - "0b0778da09cc728445c08a590cb313b3f404ed73159a416a09ecd69667df5a042668b66d0538ea630cf8f6b031c685c351ba0149e2789d50b995f1a30b92457a5e", - "0b003dbb61ac6764150ebe9c02daae3504d922a15b3866fcab40ddb56eda1445e1ffde38d0c4f537e9a7929068e985d1702c3c5d0e7703ef16aedb4403a2952f1e", - "0a00b364a3e08f4ccdcae56adaa8f212c583c81caed163c1f05d77ac4cd5df58072f530c97e9d32f1cf3f5610fd9a0b83ac728cd60f2ddfd1cb24dfcdb4823c5e1", - "0b05b87fcfefdaa50d3df22a4d6b274dd368cf5a6230ed28dcf7227ea3ba058857072e1c1a0cc32b7969d8c6cba3010eb270360f6221e93bb588065cb9d2e47486", - "0a08eb2e2120a0f3a7a69ba19610b135b0d4062c3c3e274afbdb636947957a57c18cc849723827c502ef93a323cbba1c45a50390c91e81e02b9b16d69199c4f1aa", - "0b068ef57d84c95a5a85964ec60d8fedf4ecaf11fbfaf3f1a13fcafec7a0f937f98c804959b9b8993d06dbf0737a7ac28b4b659a3011b4aac7f0260a35ca1e3c28", - "0a035f306d4a4e6856729189f82e862a08322c6ee1e0b01f0e2a31a67a463c764340eac10c5098cb711192d601f3dedd29bb35c4489bec15e6733eb91e8104939f", - "0b08656460902e03022d039e55d779245dcb00522f721125f50e35eb2b64e2f8af6c9db1d34a59f9026e7c627f6e4097c1b9be05dcae6583870041bf43824716aa", - "0b076803c371f6d4404943021389b62ab6b24912f03aae619a2a56f9512b31dbbc0489a6900e58c7165f4f76734e1a3b8c4958f499ee0215b9e366a02bdc1bd01e", - "0a010eaecbc4cdf315c15e71857f899724d8fa6d727d54f5c43a763a32d3743598b87c370538bff7b325757b7272f2fc902910ddceb7670f614fb5eba0b8d11165", - "0a009b1e977be0edea44bd93fdfcf48be7bf67fe2660d90e00b73488e07526d9439bffc5bdbe67747007184a320df8bc569451920eb22a1856e4bae689f9ba4317", - "0a03ea47aa7d800aed393e37c02879908517389e2a0814b7bad7d3263818cf4a41fa71d8d62c392553c574db22027cf634587e49f3cd9f40ab4421a5f7695bc551", - "0a00d46e932c0fa3cbfbea3c975f4ac73fe3c2cf5c4c67afb877c399e046bd329e93a89ac4663574f5fb57d9917785d1bc94250cc5b262c511d9d6931b1a52fc1d", - "0a08bb8ef23d70575bf49a8062b72bf8280d35b7d9c5a1d325180fb4aba7580b1d45a96da0ee045883d109f313817afb5addb1f9ba8c42861ccaef7ebc02c7cd0b", - "0a0426682fa00c63c7b91d9b05a168b82bb70bda0bcad4a893b4b6c9c505cff87137ac1ebf4b86fae5385e50dce2100ac66892cbe87b323d6b6345792d66f54bf4", - "0a075d006e0d5958f27ab12971bb7fbb6940ca75347fbe2269d9337afca300873496bc8128d1112e06384324fc6052d715a330550fc83d7f94c8d10a5bd645f488", - "0a0480f2215c5cef6d3356f26805ad2ca9f7e6c6972879a299992096d26cfa01d1fe5f9a14e32f5a52a52a2281705852959052adcce9da7676dfe5efdfda3f47ea", - "0b0053920bd98fc32277b1ee6a2f50ad7ce6178f887a69dad1528af55d15ce40c1278966ec0a2464192ada99621cfc65f24afe68034284e151cef5209cc83766f5", - "0a044df7dc4f67e090d3d9f8e47e706eb1b7dfad012c499be06bcbfe0ee35518c898740daf41c69db72d56ec669bf29068ffde2633d1ffac1c6099edae54129ad5", - "0a08e8d6deb05a7b31909c43621c6a3b5a1ae29a33a2613f0ed2e5238018609a4a12b5b1e182860a8289b6000f5118fd685f83225700544d33978279884d5c7df2", - "0a03eb96e7b62748abbe933e1c6b7c02d0f8aec8c6a7a22b4d997bf90a8216429e1f918440de8bf94b94cad24f6f184384ba64ff190dfec0253c241ed707a12215", - "0b03c4f1529c429b0cea9c0a9aba2b1c7e9e100aec8927d80357e86ae69f2e23482d4217a6940cec0fbda64c16ea994dd1e9b0d2149456bc13dd154e8585571300", - "0a032104748ab10dcacea17e75f3273713e3c975047cea236256e556c466fd7708593819ec577f7b78d593dfcd83a1e496bdff0db27ed06262637ca4c6dba5af65", - "0b06df5137bdb4b7b23d62f2599bf6900238de5869e9cf36049f2886cef6478425e602bb109655b93bf151d0e335f1fa850ad24e4426f3f6ca774341ab800b225d", - "0a06c8dfa9afec88dbd57cdb6bbba179a734fbda86f204319919bd437d5c5f3f00c7cac20d85538885e28b73f68e8298d3539946020de5174a09b080c7f5b6d3b2", - "0a06261c73570f7d6de91839ca2d7932d19810935b80823a53a9de2b9d45daa23fa4269a44640d317e6ba179503e4c0c9f1e288cb638dda491b36d9be43d80a4f7", - "0a0161efd1e899feb6e9e1dda08862ea05dc3a5fd6cd89f869a2cf93440c8d7332e2806a7cf72d1727f9595eb070bc0437979701ead3d743f476805e0ab69ebd0e", - "0b068a9cfc2bfd95b14bf819783f5141f3874e8c947f3458136202d4f483c73188fa9dc521ccebe0a381d9991cb583934a8bd298b5fb5c207b5d9d968668a34c2c", - "0a04da2b6bd7ffeef0f725c92a90ac929724741c90c73b9ac3e15e79d1df31c969fef566a2ca5193f2c0ba821c315ce214c941993ed296b864580bbd43313293cd", - "0b01a9e5a98b02fcc04677cf36730a078de7f411b7f435c00c44ead7c81768f5e7ec8db72c3acdefbc1ec171ca5d43ec2151c110cda9a2c38fac21fdd4d6f361f8", - "0b05d0d5e9f364c5c3982d61971667292be6406b0aca664a712b05e2a9123cc0b2f39127c40d608694ebcf0f7fdae95272f9b6f93e05621223ccb1633c41f09265", - "0b03833cc0d1928d43857d0094987185a6d5672f4c1245393272bd021d42c842cc6b450860b546da2291abee09887622bdb81656e4857a9282a2d86a5ef4dc1677", - "0a0839f04d8e7a4095a894278cedf8ae9fd2d9e30b36cf703187bcfc1d8555f66dc06f6df44fc8ceac12447d0b370cee615cd6992e3bb665447144944369ec4340", - "0b0880d72f72d4034bc75136c464352c85d00cc9428bcaf49d0609f42d29abb371319a00b6aef968b510e1e14b9d7ee2ced0555eb47a97dd8ca12cf9496770b061", - "0b02b036d50692928bf18d7e180ca0f1b705b0a73b3c16db37b084e8a5cfe1802fc65ea3a96bc6c7f863e4c54458b94a2950e4b6c96654b6f92e972d5423d263aa", - "0b04f1babdb3f9d12ec2770543ab632949438d90033625cc19b83143418b58de6d82b076832f75c18560cab209ce42521630e4e8d6b0d51c62af954fb67cb8f200", - "0a08404f7d198304e38f56639f2086dc926279cb3693c20b18abc8f4a402eae667899bed6b2fbe1ea7d9681745ec26a244922cdae3b757c7f28f542bbed87dfc13", - "0a08b5f199cd03441d65ed67934f16250693ee1ec411dcb9f47265ce0e66815db4238a667ea53340eebc51374c65af67942e596740fc1d879d4080f3801d4e124c", - "0a062d7735be3b7df08d267492947cee5f9a70cc143e2bfd856530b563103768e609d6804d079567762bffcc74e30d62ee20ea358a0d5ffe6118ca9106fa85f924", - "0a017d10a5e9dc7fc3b07727912904f663812bf6afe3b1ca98aa5134e6b720685fed7733b16e68c45844d1232320f11069a65b66b21a3e8e15db07d06bcdd00439", - "0b0536e3377b33056294c874b3a06edbc65f761dd69f1a50b9e0acfd1a87d046ad791aed1bf1bd09d791225a81ed4147faba48bd16e2cd7861953fd2fead023acc", - "0b044010dad5d4e17d4f75eace15586980d47157c2449459a3ffd0836824d3207f14b4be1179228a73413cfcddb8cc704f0d9ab8184ac9fca9a613d9909d2061ab", - "0b0625344110389036390288c2a6a174b3aa1e9d561587274b41ec2871e02c05b23714a9635ca1b43885758c5332bea4b4f34bfde2d97a05ba5c673b11822a8301", - "0b031093b338414b501d6eff9eadbabd9cea79a3bd0345e2983e430ca258070e0eeba3c9a2d2cda3e978f85f448e17229be9796b5c690ff637c6ce34fc2222b6cf", - "0a001dfd3eec28cd4986d746f09f319ba68f860e68e46fb54d369e8d3bec2005460e56789331a6b5152a4a90f411a57bd9d56b292d30029350df2f0cd8941e0e91", - "0b070f8799b2ff2508a2ed5b13390e424a89d7e066f14ba520618a90f7cc06b0086e7ac5fe66dc4989c245c19745b9289636f248a1314c1258603f02a950a8c81b", - "0a05177feef8a96fb35e5fc77f932887832fb812138b035b4807aa83e38d83e45de940abbd36682a12924fe5375ba3a35925f63b3213d1b2542eab761ad9c8f1e5", - "0b02a843f09fc2501ba3b3e6f883ea9658a1a47ccb997cac3db2179bb5b388442b9adaaa0a058a120753d633fc5125396466e36cba79ca1af303674a9cd6d8d297", - "0b04e34c34124e7d855d4e8fe068f2246908559715a6676ebf0a0bd449825cad66b995fa54d7c14293f583116a59674e2d850dc7a46c0d1cbe6e0e85af89d66c68", - "0b02fdd4b6be52fb99e55031956cccca59be0b5e7036254b3b5d2d2312a45438f96f877b096a5b1e42ade61bf1c76c070dcadf850ee5a08a0c7183648bd2b4e9fa", - "0a004c44d6bb6333783f1b87573f7e00171d3ae6919a50be81368145db705085534d150ffacdc14d2ab127636a2dbafa7bb617851aac18d5f95d4f2050b0211906", - "0b05978416d861f886fd4b2caaa8e295419e515c6494be30d50019da3b42329e49f362abfc579d114487fdac2a054af3e8c761a4b52147f8cd47c652509e7fe4b8", - "0a027d831d4bfd65a6e2723cf57e1adaccdd96a7b0ec6a1a0350f2c9fcac2fb9f29559d5784869be6e45dcbe642e086ccb046f5c57353c2cf1aef834d216aaefdc", - "0a07c1e74164f5077e0ccbbb05cde9f9634d6d5722386c9bf859c703ea91023c72be324f03cc4099bf3561bbb7f4a61adc7f08bc96d4c9b7426ad48633168d985f", - "0b0483719c8af3ef996b0f78012a96770c0aed30175c5c39fbce26a01ba18edfd4dda2154126fccff0c9eb5bb3832bc8b1e87a1a32fd7a83cb592de1b5e4aa6b83", - "0a0204a5f0ec174ff0b70641cb3c157470dee704f211595688661797dad6759c5446db3cb68c01d4d580a43a92d559d2a69fd1b1e4cfe43d380496a839b9d5b4d4", - "0a00483a4b494d9231ad648638e74a4934822eb2e780835955b0f7158dd3fa1a0c497523ab4b4d6ad5825456902a6bf85dd219cf5a8ff7db97d78d152b988106d7", - "0b07f4be20660f7a70068fc9c758fc54e79654aa267cd960f5f96dc2334b76e3b704a0c787f290c4ef656a415d9b925450bf2b3bc534b3791f20cf2d2332d5c8b5", - "0a05f633ac120e72bc8c1c59115eeb6657ca463c9012d4aa1bdfe672068523117b9b11a8c0cbfe1c76fac47842fcffbfac0967e7813bdd91b65121e835e63801b4", - "0b047a08bdf8723ceb47d72407b6457fc6842b6880c0e45ae80d707b313e7fdc3d950d3fe377e5697933b5f594eb80dcda6460237d7085077e7d7844d29be9a6cf", - "0a00a354949f9e4f8473701759c783245e520ad9cc48e6741fe2d8d922001d5924df3fe9f69ab6513d405a1c0616094349748ea8f56179fbecedbe0d8dbb7e3411", - "0b03c04c26d965430f8500e806fee689013e0482dedbba0c94f066830f70ce7e2c0e5c7bdae11f763096987d28fe5bdd20277e43726cdbe41409a22902f6accf58", - "0a0664a6b79a11ea837025a7821a547a729f3f717660b5a677517526413a54400b4fa9de856282996724d020a68a53d512390f8301580566684609d8b21c4365b4", - "0a04d4eaf55b8071cae487309db1f219a9a13c8c7f2f23df05729fd88d734bfe8f027fd9aa72c82b2948880060d0b777aa3d17bd839cb395f919bb896ab310fb4b", - "0b02722a4555479bdf6cdbe90e54ed6d0644f95b37774135cee3bbbd3610d62ac4298161eee6e931cd2013040eacb6f9e6c0a4200bddff221e5e77c85edd394d47", - "0b06625810e97df1aba91505568a4453f29ed475f5072410aa81a958767090f66a0c5081bde811a2ac362537ed7d4a3c3128c2d7043023128a495a9d240a09845a", - "0a03e2c7c34fa8cb35b8bf16e1b53b177217ba0c0b0ee000fac7b18f82bdce7d31b915d6b0dfdabe9560d5537c340c964b19ad96c148673f44b1703c282f6a170a", - "0a00fc9c39f635494ee4e00ed9248a21dc71f021093780efaeedb0827ceac2f4f0c1ae3841b50d921df4e3f6ebced7e201ed27fccb6a514eb3435c1c4ddac7f1e2", - "0a0537ce66cc821907c8194a5a059c34c99036e1f2d89fa04696e06b1ece90e399fbc35e4774eaebbce31a7ba1517cda205cc7181f6002dd8c808ec3c6bb938880", - "0a01f3ea3e352016c2d1a1366d5a1fdb079bdf44e89e62dde7c94bf32321158c8e22e4db4316055f525a243bd9f47337e82cdffc8570ca8e21024ce4396a81a997", - "0a056d8773637e549212548f8464c2fd9319bf3cfa920bf5447e1799def5a21b06202d619c37c89f7b32f0ce3cbf969237d426f3161dd5465d05dc60a73586db85", - "0a072302aea2b499add6c1a1230efb6cd39a4e0e3bc380e4b5a5af6289854dc4c59172c19fcd5d8ded464034ad13e75447b914c0dd9a55e8d267fcab9ca6a6c672", - "0b05b341f5e18442797dd3817a431ed5e77f8e1cf7d8dd6be71bfab2fcb077655d55572936ad66b9c0927603abb6652756bd5f72390cb55ac0870fae4693d9dfb8", - "0a05e0dce6299053290484a565870fe83d6ab8d6e6a1da27c2ff4c67057b89c43a5ad341af9b73a34da9985679d1a1c3a628031d2583c270bc980fa4ca2a8ad47a", - "0a08b6ad1c9e6066dcd123a824bfad0e72e5486e548620ae0399167bc61b6e69f29243232e33e591e1d5c3ce98e59a28c8fe907d096819ff46e727f4ee3e693194", - "0a0345a6c2de3c002006a8b408d18cc01fceff2dda181a4bd1a4a2e0d715c0f54d64d692e59ae1342923d38ce3f669b8ceb3891bf8d39a0e5e220c51456555775b", - "0a033e82c7194f39c6c14058c60ba9b544a28f8a0e54479acc921ab778a64a2c7e9b18384dde06f4a1a2a36997b420599ac7668e4ab631dcf233e79ff5e506bfcc", - "0a081987455773d4684c9cc8a651deb961bdf7444ee61f38ffcbfa042b14ee626619e1683dd36bb6514b2d29b1fd522e506f7df8e784f9bc372f7fcb6797db1b4d", - "0a06fc75f9089f378e10eaee5cc1904f49df6870693c170000b75ff5cfe8ca50547f04e623befd6a5da67d92a5325457670c49ad323f5bc9ed1d093b5b0e048c6a", - "0a046a08083b815ef3d4aa43739cfd64c793e52bd0f9b3f9158f39349f6d002a089beba2582c8aa64f1593d6be71098ea23802068547b0a3a9e5329e6a63f9877e", - "0a0613a0ce18952db9628ec52b38e2087ccdb17150cfb90ba291eb547718aee1adfd6ceb19268901a0c010b6ac5f5e03bec2a980115aa978ffc3e35a44cc4fd4ea", - "0a06995406988e78b2c5b0ebc1cad94f0630bb91cf1e875f7c1a656eaa955caf15a1feb6598dd0a05993fbc9fe3bbd0dae6b592515a0a1662238fae5fa39c8347d", - "0b06ea285d5230e425ce3ad4acf1574493caaba8e399051efef973b8d77249d1136e39409d9648b66635bdbafb96827ec726d6ad0f347354f8f954782e8b59695b", - "0a08ee64f2c7e36b7439163fd092e000a053ebb6d3336accea8ec6f34ac6371f068f216a12a1a6ce065397306c0647175584295c8009919d83529743cb49ea25b3", - "0a04ce649cd0e85e9680b613c6e060df4805d735430f044ee4a143f144fa9b632978c8b0820e671906699330c8c201f9fb922af4ab893d2a15505e25b83dae14a1", - "0a01b0265a9e71816529c4759b49eeff8f15251e29c21dc6e7d2aaa5d717f60a50c5f7cf80c5038ae676be9c3504a1ecd752c77b2a06ed8e403c41d7392705755a", - "0b0614836334eab11a007b15bd6152b1e5ca78177455192eda1eb71423da408bc7ff70b289591d6845c63d2541d44ff41e68bd4987baeb9672cd50e06313ab852d", - "0b08e160c91226010e8b61b4d7c65c43235afafe377224c733ff1832435c7261ff37c40ed2ec27ac93aad4ae6008d8a221a9f2894eb057790cf53073a457af466f", - "0b0801d64ec9f56cd6f52ee2d0fdefab665bc82ede5fd463a72a572f927fca59ad025d614ee33dc4319c2f8ec3f200535d6e80965f92ea8295ffb6449edc293aab", - "0b00bab986cf2bca21a7555b29f2d2543e9c24a37114db68d8dd172947e0cb3efa1162373348a8d1c5fa7e8f541f6a2a4dc8dd2f715c591fa107ed76a71fb5a91a", - "0b03ead19088819050a80a36b4b9faecc9c01c5ab5265f90e58b4aa3019c1847f4a6a67d6db1a96a8ef54c3062443f1de3e8e6318829fd7760f53602a5c6417a70", - "0a067505333576ec6dd79b6d8d12856f65eeb7422e70750208b69f37ae55eb291b920c7635e90ec339832057768f7403308dcbd60de5f8045273fe6441931dd2c8", - "0a05b17e2dc6c0683ebdc7a1db53e0440ad516256480d3e5890b4423f5e7313dbba3f6e8ea85d221d5d1c4074d25f90b35a2a4a3a97f76b8e391eeaf52f76e1527", - "0b08da2681781993c753be9adffeb3eaef66ad1d9fdf8af66da7c81d1bf876782d3e5fd27bbc763cd8f6536d48908ad82daf64ae78b03e4ce9be0eb95f04996603", - "0b08843b61d9b9c8c2fb690b2ffe67b771c0e745e8468ce5f100aa4d6833f63bb1148aa6572b0fa81f7f575f07c74b4a5b1979df9dd16f3b98b26fa0f2d5f50a0a", - "0b05a930c1040d97e68bfe6055665b860812e4bb7a4a098ffa7371563ae84c0af6d265fcac27916cc26f7331801a0c9ad04b94bde0890a3dc9411e228e673880df", - "0a0861fe48f54adb2ab2e3ea69e9ddb95914e5bc11e95ced2b0311025454aa1e3d6d7d24557e57c45fb7e17896803e37af9f8e289d15d8114f0e3fa9f37e276ec0", - "0b03b8f5919407728fc49d58efa9161f02aaeb7d8f0f9114f6de914b1ca63c49d7dd878fe39f5df6fb66b827246ce012efb0b2badc6130feca219197bccae17526", - "0a03f56d2b37d3afece11523942d00175ff7ca0161ecbf0e5870feed5bfda997993c27d356fd391ce82cc02a4a123ccc6519973913893007b9da09a01feaf85055", - "0a0149ddeb3535ce511d628dd424083de77007c2e9a1a59a93a04c34efea9ea892931faeaf5e8ba4bc8e5fd313965eadb91c4823f5982d3aedf9a9fea1c509ccf0", - "0a00a02a1e006e13655281bed74855473bfa5a04331cb806baa33165ecf5452cac36f432e1f3aa4fdafee2decda4a068d7453f2ffb13256866d2013fe8b885c2d9", - "0a08f68053cf094c194ef78926253728d706e0157519c2ab7deda67d217f5eb7300b57686834dde31e7303337a36c4a2d822a5138c2a53c3740713aeb1fd2a18ff", - "0b0214674ee00e262c9b3e0cbaf4d0eb60495c911efd040aefb399c17b4b6219dca315e5d8eec7746bd723a04343d7e530a3cae10ac26f26c6dd60a135da877cdf", - "0a0718cfe15bf7d25b419f44af51f124c29029d0d3c5ca0e8cb27aae2ca91024035d26efe306be0b963140d00596e9d80b8c1ddae87f97f576de3425bded1f5514", - "0a0720a762ac8a611a2d9dc66fa134db25fc930404e3792c7c6addce1054c2045804ffd12ac19dd2a4124517806c254f763c587fdfcf16139613bcd238d3b69223", - "0a02d44a1a0f2bc7b8a3448f7a259de34b319bf93b47f7d49e9a50f5bbfc257e3330e91e71cd3152c86136132bb7e2188fbffdf6f7848e04d877f5c9d18cab0fc2", - "0a0531ae107f9835ca9be960d228de34d3bcfe4bf2304f58e6a3fcdc06929f5fb86706e416df23dd8fbda80adecfabb18505d38c2470f688375a9b15a688d7b26a", - "0b07c2719008b51bb8529dd584eaf573d47ac14f38ebc023834223fb49c18720cd3d7747ea3e188dcdd19420c0a69bbec0542e8b528c602b95d497f4603e18b5b4", - "0a067088bda4449f31f762e0f546b3916d7a30cda47a03724b9fcb9206ffc9fe17e5e70abf9ab620d41e45fa7ca81f9f151acb573d11a61119ab49ea1695231c61", - "0b08ad8225da525d43d457cb6f81d25cad20b1fe7346f0544e90a253680d4a7ebb01c909a2992ddc84f6f569d3f6fa5739124c2bcebb592ce631f1458be49759c7", - "0a02763b50e01fd9ac540d7164dccb0490bb9eb5eb7a8292842182ebb505d8daff5975088eec0020eb2b1ac305e7e1dca5a74be15d6b6b6a0c591d0df2a0eb346b", - "0a075982798bfb074aae1e25cd93fab1678ce7ea193c85d8c0acaba3873a0a140df3698603f18e2d63277ad9105eef9387bd94d45d302ab3b6b544e4b57f76c49d", - "0a031b84cda4faf8d2f92cd6196c4d44a798bab7a0fae8ffd66e9a861d2e771161cc4f549b9942147c79f7a92d863611a16cda6d5dcac4b857784f64da13d1212f", - "0b043762bd60c96d704d4290568000eb0b447cc37d24783d79314e0efd844f3cf1e1b20ad67d06162f636e432bba1f448a97b1b128a4bb5f993489456ececf0efa", - "0a026554944b23e3f5106e154653c0ba10dc92045c24718be4018bcacf9e53d4698c76736fb667c95496ab47ef3dba0f2917e0721211e25f0be7143cd66a099777", - "0b0076ff504c4529b0109bf643b616dd6035356343718713d6dc2af23cc820e94c0d10f0deec47d35552301777d2880ecab06c2b4aaf1889ad51f74ac9914abd70", - "0b0221ec22d3eb14d5402e362a6f30460e4d7b2bbbab4cf6e89ba33431f5ae7cb76f71b02e27c3ff12815f45388e72f363c4fa3c26d06c78666503930ad8e87d50", - "0b02b26950588725b58143613324a206b4a515a3ccc0ba3b4edbfea33072843dbb6a679c3c51f0cb0eba96a26c147d660eb75473778e970b8fe9d3d46a6a7cf4be", - "0a04c1bc096cab7096ba2ecb00de5f46c5a1fc92c67b8cf41b3f65034f1d930c9baddb2bc798ff6070ea6a4913e81e9399f2dba9417b17c7e660a17e5c0db73b42", - "0b0031e903003416cb9afb4909cf1c48680ccfe0a68aedcad533ccb37e0107ca8dad78ad1e6da4c55e97ac3d8b4852e305a7bf71ba8252cde652248ebe23dde110", - "0b04bf4e43287a3e00ffa1be5ef13fa013dc5e861641a896f552a39c7857c5ebabee4cc49c459f5d0da97dac8b3030ba513e1cec710f176d1cfc3faad5ea35c9dc", - "0a00c5f8e517e0a243a25e04b0e3081b8bb8c3e57dfadfc4c4afde821bf89fa0cf7a89ecc795591f23d66658d7f90de3452ee2149d449d4d8f1895db473a5e0d9d", - "0a07c6cedeb1fb88daa0e20b6ef0655e6582c966ab96f899f693d0a0927010e1f5107197260f44be3ec32b3cc0db53a7629d79cc144131edf5a1f7ac0d576342ae", - "0a00bd8d305e01f17ab50a2a802a65574e4bd7f9523b48cac15a9fb6f138e33eafeac13c87d4d50d998febe6eac2e1acf658674b09ec13a54ad558145a7fe426ec", - "0a02e933424586e58d951dcae85966351434942a8b46c8406a8517c02ee417699566a53fc3bb5dad2e4440843fce0809560ca6e28e99d11b1f2f63c3ad4bc0809e", - "0a05ecfc10930e00648c6edb8b805b0a47848a66ab631756e26e5293c73ecc013496ad726fbb2ea8f6ccb94dc62f56ac83bece350173830557898d711493f5c76a", - "0a0436d3bfa2842fd09bc7e08d45da61075c7d51af1c27cf84d6bc3a0414813d373c886a6580fc94d27e8fcfb7b674c267c021ee2bf784523953c9328d7736acda", - "0b0760b6fc333d07bf0c2df4edb33a0fd7e72e564ce842be1f9367197ca017f98b9705c3524a4cb7d460e9cc06047bb6e7211e2a8c5cd18fdffb3e9a62d2311031", - "0b045de378ac01cd62f6247dfcb9d5e33f054df82f5d08bc4868a77880fbae0310550741cd2fd3eeeefef6eff55185a0b73867afa694a9a20ca5d1b4d9dc074be7", - "0b01e96c8f5c6a622ab8c29406d12d7eae1bcaa05ea64b391cde073524b3150dfd4c2be92718182abe49e9f0dfe61af1d7bd40759d887fb9e3230d5a65e2574b92", - "0a08575cf9823395ab16280f7a8587b22e5408b208791c5b845bb1cc1b024bb92139ae106aa2f530a60aa8f4a3b6af31532ca3cba7709225296491817e3ba42cb4", - "0b0459f4a6f8f9b07d3a4d3b8e16bd7f98641809bdbe2e08a6569a9c55542d0b5139c251f2ee5e8b1492acb0c2def6338de73d392d8399a10dfb0bac5ec29a5ef8", - "0b0047e09db5dd255f4c51017400d9752befb377b21c5561b7e8b813b12bd9cd1cbfb004361fae78c1a29d69cd8c8977dbb49ce13f1e516014416a54a875b91c41", - "0a040f30b78b0e66c08d38ca0cf99533e9423673fd5286c4ef1d34be255351c82d79666ce470319db402b0909e42bb2d36480300954049a71f5c13f6b353ef51e3", - "0b0605d932f0a55213910f4f7b4556eb523e5bd42330b05973b3c7ac8a7666c8a9b4fea85f2cc2b0e2b3e108b60ce9d44dfaf03bf54a49d7a9dc618ca9c91ef1e9", - "0b0759e962c0517e0ed73622c42e45ff2107ec6e7fbe0851e6edabef6b0c04f68cd37cf7908a1dbd1f375750b431aa940e4d01f9be01efd494afaf90cce399ab0e", - "0a07ee0ecd11701c67dee7ed1eba90754673fae9529b4f4d27c35ca5f78a6cd67f12edf3f961503edbbf4da1a43a138a7897a4d1c0255bf3dd44f53ef9ece5e944", - "0a016f6907061bc3b06191851a7a0c8ec4154f8e369e46c295045abdb3fe678cc242255292f2ded090b743e93245345e6fe81f6da6ce136afe69242db965b9727c", - "0b00ba6ee7637df76badb07ea9a24725c3d2a2f9735639c8c4aff3d6f8e5a3eef8e0685bac6bf9fb884c72991066cee79957b37913f27fda07d2041bca17372716", - "0b083f85c9dc9eeac02cba7825ee034ac583ebea0765fe8f77a0820a8cd39b43269dc1963fee4223038372412fcf05b734fc8d0fc596ce19f08839aef63451bd17", - "0a021892213c4755782b4f75ff1aaae229dd6027257e60fc277b007113d7f050f8f6633f2adfbbcdcabaf1acbfa013fea2275bbcc4c50f6ba05bdff1d118835f31", - "0b02ca0847ee09ec0338d36afeb66e07fcbba4cf7653bd5699fccc7f9755914062d57574b1e176cdb79da50b2083372f7f1a0f8909712c43dbe8715829ea917ff3", - "0b00c72cf340203ad5230e2f85f3c5909f64c90c528640a4e8be63850c8d3a942baf76693c752629fd594a8124be8a3da32e83f9b4cacbb13c5d3c6f9896b7e37a", - "0b06095292e9929bf4a35e2ad392705964ba34281fe9f5c86b748cf958345adc0889ebda75d5f6d0537364ac32f56ec94b3112efa3568d8c1d8c1898aa495ef935", - "0b0456b277b2e0b2d0adb86c93baf1df672eeccceec1a57747fba45b119ea0d077e6fa1627ecef25e43c057cf4b759397dd80ef832061965a79c90c59e6e10aa17", - "0a022543bf84f1854e2882499fa020af95f352496f384881a1df50d3c0419f538cf335ec077f5309c7e708338dbd0f01a0f8a86ee0653d03fe8756e1ed58e96fe9", - "0a06ba0179d10f368b89c9b55114db617a2edf43618ef0dcc5ef7a834c8dbe6c3ac40cf43bca62bb38cef22f05d74a5950d331f106ed8fa550e55cf6afb08d572f", - "0b07ad1731a16bdea97b912762e90f37d0c85d22370d4d5bb22cc8e7f0f31e511586df5b8923d317b0a7d95f8b3f683375b772ec5f97303b034179b5699a91c5f4", - "0a0783fb5c9de40cb49992cbaf729f0c83ae235d648b01a50c9dd172a2ae193c988fdc921fc0483262a808edf93be66208d8e70fc54ed682370565b9705b1d2e07", - "0a02ee176656ed2995d1cdf72e2efddfe6df3321219a6ddf63cd343bebf6c2a258ffa089286248e09c0ff16cb7921693060891dd9969e25acb70f0415dcf654c74", - "0b027f8d3f4ebc5023ee2646eb412a3cf1293e3fc1c0419ef86c1b35777c2b3242223871be848205ad88706fb21a9c8496dc17af3be39ee00cd2030b80a0ed618e", - "0b03da44e62924c9b068d1c7e0bb6bf36f08dae30ea49fa7ce9106b3833a1eda03f7d3bca7b2787a040206c7370cc38876658bfe5d4a6a6e6360524921f66a909a", - "0b0169719fdc57a1da1ff8f4072ec308e5d9d17f80b5eac19bc2dac535aae716228fcadb295458fa457aa1af48453f71a7603b4dc804761221869b003fb894427d", - "0b01f292422b672e9078067d7f88af6f2d01fceae2e135574cc605e829b018f8d6cb975f242ff5d62e2ab56395da598a7fdf40e5be44ed13167fb29486fa92293f", - "0a02f3c84ebf03828cc791039df5bca4e3edb65aff6318b0337f805a0bff79f6a472e91fd4e777743127c4756276de9827d4f8268b1a719d4991cd892cf90fb7ed", - "0b017a911030a58a03c15362188ac4d69cc40945231f19ff9772429943c23d81c4b0eed8453c11f61c2d04ab7e6efcd79ec7f457c4a899412c91fb8c92206c9ea5", - "0b0064015ff72c437457177fe576f5f0a0eb27215b79c98ab8e67198c6eb25258c7e9ac0cde8d85c74f62c1de85fca415ad31b4fe1ba96131bd36471286e05883a", - "0a064c8bfe7bded34931dcd341f7392ecf02847ee0088c21831093c6adda4b4da3413aaaa6923c45c390b3a6e4ec627b80ab32a36824002a1b0a088ba0b852285f", - "0a03a6235e52a8d246c38fa65944490b4f1b814e5bd5c8b099962be736969a4a1069b2372a5247e5b5095ad95f6aa23c2194d92df8d8c0fde276bdbfc27e849878", - "0b078ea3b8a3c69040a529baba814fa3dbd1e56ec837a3ebfed0b179c92c5c61b1424467ff664069e1fb18a90df63348a578f0f50ee04e59a4460ed92621846ada", - "0a06f7c0c033531954882ed3ccd2eb6682b9d7ffd6b86ac997719b36a6023c653638452d1a6010829646070b49f4a1b3688147947fbd85cb8ccb239d5bfc7e1bb3", - "0b01f050991951115cc106ce78990e5a364c7cb53943a9ac8a1723b37d23918cb09c23cc3524f526169e90bd94299bb72b9b018adb262ae424c3d7f3108661eb8d", - "0a00dab85e2995041364ae750fe94bbef4def39659642e1143fb23673e9fdf9153421d22f4c6ddc5c038e4d66794729690441e5662c548cbeb16dcbcec0b8f3800", - "0b0018e1d4eacd81fb5cf18aa1678abfa303b85f92c678923a42a9942b99793619fe07ed40bbbc019ce71332946d333891c5ef1ae58a3e6166469a18c4400b6b03", - "0b0423c05a3377177bb8e1f7230409e16901843b4e1406909fb0b3e6df8753a35618d0fcf34c3629409dd3ba254d8ca1de99b71fac68cd2544c82c064a78005317", - "0a03a05cd5521a1218046f97364c65acc46653d8a9db8021b61491669a3b6d6c9e320521ac0532ed7e54c5a596dfb5925e6666e29e204c63fc10cd68d7c2c5060e", - "0a0589c1815a8131c85dc93215ea32634f46027f923228b5dfe767c677c01756f3cf86b1e61a6992f89839e9cfb38e6ea9682d7497b6c9599b5165c6d5f24834a0", - "0b024af0c22b26ed2f8c533e44ff9909f161e0e65bec65ac77571828ebcb6a7ec1b0d5f43cc4eb9a99d07e506a53d47780c26eec7c38005edd9ec40ec5dd541425", - "0a05dbee0fe694b6e302bfa0f7db6bbb3636ca0a7034596548b63c90afbc450e195eba9cafd1a6de9a2b24dec78d0b3ed3a3bac537fd459d3b5fa08318c91d5fed", - "0a03b86c8a2ac75b5f4ca7f250709a6b0b576bb8358497c26263170c2399975ed5b0562cbdc96f6a1480ea97654c600d559f71003d1583f57b22a743975620f860", - "0a02793b7d09d7f5142eb1f5f78906fe8740f43bee167a3dd0cbeb0c848e5a64c8764c6dffb240f3a0334b7746628bb84c2c1f5db65bdab5304de356281067d774", - "0a0594cba0c5b8279c158f0a985d8a09166b3191a081af1e2daad0f619cbea221aa18435b0dce5e060e18840ec39edcb77964296273373eaf902e3656077b28801", - "0b01bef55356e2df10047ea49a1a2428e3aadb36096bc9ddf5145648d4c39fc772731cf60e63081e70bf63e8b2674f53404813f88e7b5b9e9bcc36a564ebdbfd49", - "0b023c212fc391476e58f9c8b1858adf045f45757191a82891a795b04d42493587b08a36f24af29e9b2eb2da2f13fc27987afc7615abe7a2a003ca56d027e478a3", - "0b05f8a68842b9ca194392ca2c59867a93625bb03194d84d53743661c6d3b9d9342e11a1a57daa723603b006e359ae5a76fe5341b22e7d7ebd807b45a9b7ae2ba6", - "0a01356d384a914f003d81c7a03661d163ba0a3bcddc2bfdec781c36bfe6e405c82647d94920186b5f9b4bbedcfc628364cad0334740c7fe1dd64fdbab161963f6", - "0a054f760843f9b0cc25813592e35eb2b7b4244894eea9ac14ca1e57b31c901e1b3a5f1225ddb585ed330c489be14a31c7f6604bb7206341fda28f569e6e3933e9", - "0a03e966b81225ba2fa1a609c569af0978e9710c25cb3a50cc881e32cd5d706389e27f76e2c855dc7abe4a8a2912a090fbda332045449fc4977a4303f3ef767b7b", - "0a06cb655d29d276d7dddfaf888767cabdd3b302954eaf06c83c99237c0a418cf5834503eb55143eb55188884eeb41e26ff96483258f7cbb3a49b158ede3870edc", - "0a04790a3174a017b1ea852ad7b3918a66499aafeb519e722c9647704d661e4169e0c480567dcfbba08b45e9d7edcadd6024f10b5b78e352e6312f03f635939fff", - "0a060b105b8e6b699841ce2365704f3bbe96c9c414b659ab1760fce47a302b819147db38ec06dac3adaa8ed46ee0dcb3f69c40ef00a3e6339314d09f3e60955c31", - "0b0265e9a98d18cf00c8de236e838a0d9832aa6bc0bff0836e31bfdb63208b7f4355d5d7adcdf0b1c24d163fdaace670941a089f6afe62590944db4763f1e4e04a", - "0a05948e669319b32b0542cfd6986cfd561c3c547f07fa80f1f2ffc26cd0db9a8671da8cc5b43e59c19907b7708ec097666ce67e45568ac0e9553556a6f31f595c", - "0a02d44d004d2a56f0029227751d9671d868b45b540f8c0bc40c5dd051fb90b9c6593abfacfa8a4a6cc45ba05adc4273c7649ed8126b6dcb1f5fe80c8b977f3f28", - "0b00bedca8628bde12e626495854ae4ca8b21c2234359fa055787c1d414fa2421a3b552f1aa7c4f2ba25d347a90afdd177d44cc644598c5024efe07940c66c1d95", - "0a0370f69eb588dd009d1782d34395d6df095df7980305fdb6416f39edfe91a0eeaedd79e737636d49b4235cdcd5eb22ec0757546dd8ea7142033b95acfbab2fcc", - "0a07d3386e93227c36244134265ac3c474dc63656136f12837bb07fd53801351462937bd52fd938c325eae1a82e21e43f727f96ea9b4dce0d140ee9d73cbbaa2ed", - "0a02170f4b24a9127581e3624563045b29b7f6c1e1f96199ef026e6277367ca60e41719255f41903884eb2ccddf99f96fefaeb4e5773cf90e270f577fa011b00a3", - "0a043a642b647c0aee84713ff886dda7b401fe9d5503f32d0b62e8e550e4f1d5fc987b382c4f75ee63e5e710c1e9885460770ada4f22350d1a726604052c7b7fa3", - "0a074eb917bf92db0b753fe6acc93aab99243d6cb609dca3c27e2dd084725a39699978b0708f6734fdf3d5939ea697ef6d73920f0f767e91945b4cb848b94970ae", - "0a04c2bb608bc4ae49c24c3d49906a23b9f3ad492148f9871a4c64772fc9538d7dcb1a327827ba27ae42057c64929a2aaf62705f40b6fa27a259d6f43ea30f92f3", - "0a0094ad18393770b712343538ca3dcd0a955ba0e704883a2c9fa78b21296207c3e133bf97afb4510279b0b5914738051bbc715ffa74c7cb1e4904bb0e674ff34c", - "0b03185f355ae3c62fe616dc57dfd8a6ba442c323d685e6ed16b63aa91bb03bba94eb8b8d7d2304ca2582038a90e6d3d8710244a40d0165467344014c6def4988c", - "0a072f020af981a8d38364e074b9bc953fbd395cdb6b2b177c0811b7771d7d720368a8d84aec2497b0442a1d026610b46774012e24e8efb44c4ea9edb3783781d5", - "0a0136c05814f780806370acd3414d29b05ef2c639c14f235a390f4d6c2dbf35e77069cc5b0a1ad1a47d810e4f0ac30ed79f5c9b233981eb1c557a7d8c054e40dd", - "0a02cc93b47fe63eb0f7e4beff01dc209ef855c831753fd9b3121a075f14547c7be2f987f370777c57c84e23ce9ceb380de968f3acdcde4483acb2e776439a2c9e", - "0a0898ee0f405c7d28aac4f42f1e9b6bb010c7e3d7816be9974d93396a8f464c26994474ae435e770240ecaf786ccbd26cb8d0c26107cf0ec0e7ee5a3e2a219bd6", - "0b015781115713846a295d61381439abcb40e2383583465314505ed661d85ce96646744da6c7babb8b68d53ce233b3f1f238cd3960f38e331867161263b69d1545", - "0a00a37c53a4ccef6278a9d605d51cd0718e4063cba317d835d6577b4ce9b98588f64b46470161033e783380d4a8d582c0fc51c7b5d449c78a5ccbfe34a8ecc096", - "0b01d6dccb1e8ce22407bf429d8ceb9663f2f2e8fd408243386451de3d2242635fc26df47322e3fa78053566a0f8d9b6fc36bf43185a99ad9e87d4d05cf2969c26", - "0a05cab819af78d6200633ead4af7465222c7e0fbe7927bee78ae51a42cdbd3183080f1e04f2cd8c60cdda644effbc34f17c2b2281a287ff990788b058c4b8f5b1", - "0a07d4e67218877317456911ad84e2960d679fca6568280ba5b5e66088ce831410963ab67126f920b4dc30e7c7fc5a166fd01f24c1ea36dfbc897cde784aa6c087", - "0a04042cb6b0d2770c9709d95ce7c96bed1f3d0f35dfdfc377b3bc232d82da2d60432190c9da5d3faf5ae8ca4f572c25c546850fadad3e356b86365adabeaa7686", - "0b061d75d60f874038fc7f2c3e787bbe72f5e8e922a38d7100f7c150bbfe06df1d4d79503ffeba82a29c6eb1c1a5f799fe4212a8e1a797f7819341bf7c3aff5200", - "0a076243cc38f66fde38a889a80441e743ab62400a3745d8375792a7a0f0bf00cb059ba5bbf910925d965fc7bc55f0fcd4055a54deb90ba57b06f59306385207f6", - "0b051042e0dfd630ca5b007e72e281fd763d01ab2cef08d422f8cbc668b6b370158b7f20c27f873890f6eccfa3c7f2220ba26410ba73a79b83d35be1565d729317", - "0a04605927df1652f66296ec8f40d220e45675cb74594fadda97a133ce86be4524681a889d349506f71c9c113425c894e846d6eddc969f2b689356163d0763c78c", - "0b0170f2953f1fe058db796ab9f4135d2af32b647ae6c111e1d11bbeb9836bb66f0b0c737d895fe50c4a00043f38768d4c0a095f18be5628615be2cc18f976a614", - "0a0784d665cb66ab167318affa4b682f271d660e944b36146fce6f32742381970b4a84f5b3554ce9e83e4b1d8cc5338c157f4e49ee7a3c48ce3d20c32630068b2e", - "0b0294930cda5c960f0d4669ceaf15b7560cec98e6c75a2ed889696d2db22209bccde7bbfab6d0203617eae169d8ef515ecb22ea56ca96ef503c84fe097276d315", - "0a0126d6b93cd3b13be503c9e01d1ca59b322ce89d2d266dc49ae943da4f11071f50c607a554e04db6b562801edb4866181f86bea3f8e0ed25b76c0d436ef0ff93", - "0a06b638545b8f57abac3440b521f19d8bf7beab731b54357d7baf99c2e40c095fd670c32bbebb8f1e0a6a0a622fa2aec71171be498904cac017474297057ee453", - "0a0662e8339a9744d3bb854e6fee800518dc10a8ae92e4f6d1eef613291c9d7573fd3faab074abcae63323e2383959e8512d7d461dd807c25ec199893a9a5338be", - "0a03aab5e8cf9883fc3056f29c294713a9cebc104571aa7e8c308465211d5f9709874f36e83e303459b079457f0d656d7b2f98d816d9e3058070bac8cce8142673", - "0a06fb9e26759133417c62c46f9d55179ed7d873b4b2880e8401e704c7d035f0a38e7165ef78b9932216c5d4239cbe6f9202918efd19e98b9f7f495be125853990", - "0b05b855896082c53f17587a5b505b77676c225db524d4cbf9db83f75e934e51baf50975f31e63dbfab67b0ca20fd7c8b2a005870e94e90ac0395c1dda836fc97d", - "0a078a93ce385392d152ed5aba927300ba1f7a9e6fdc63897e0be51b79c1dfe272eb45f0422bc780dc7b342ff1f82a1619c3a2d32feec5b87ef588feadc70694f6", - "0b087c9fbb665f477b8c168d0eede724f8e8a361f28ce70d6bd97e4885c8f741eb61e3aa4010bb027feb73b29e1ddf377eb2df4294efdee0fa52be4cd0edf94f26", - "0a0519c9a06f3aa5fbb64b69881bc03da0cbcef228c29e125bca74b95575e0261a1409ecdc442946b4643a99d12b3e9290e526ba51860eb11380615c256b70b3e6", - "0b071026ee34639e667ad151d121da92fda92538859520fc3a5b1819553c9209c5b81be339ede61a0e23445ae0fb76e9832fcd9c6335a97b41d4d2ef4a7f2a8762", - "0a067750fb55bb44f7bdb86725ff647b28a8a0648f4d3c996045189ca230ecabb198410b7657d9171e4a0fcf602d5fe42ba5728dfac9b3744ab72135e5af37d673", - "0b046eb11f689ac1d3243299cc8ab2a0733e0f7a1a36b683b160a58ddbafa17f6012268cc997e51b7acad858d61ebb0595609540c9741a9a3464fb5dbab669aa27", - "0a01ebbdb35c5f13919f9a888672a864e069d9b79a849e034bf7b0fd3af71422330a39b3a5d727250648ad82f8e098d8472c20ebfe76bfdedb792e810ecfb79bc6", - "0a085aec86cb32d8bfb1bec987c7d1349da1d741183c7f24467d41b42af66ab6de80bf44d20acfe7028c083060a1237d0f156898183dd5ee4d865cca7ecef4cc54", - "0b01ecd6d6640db14de02a7c6c2f541ee089340aa46ddb6eef8cb84136af0dd94dc5092547dc4e970c81d0e636e9d2bc92005e2ca5c0bb98fd8ba5a915172a554f", - "0a01147fcb6d7a19fe1151e69dfe2db986e13b8f2af84161c7b756e7db10eea3c9e958d13eab94a1253c4cdebbff7f796dae2c4d1c5ab51360ffce3dbce1143220", - "0b080313a50bcf21eb845240f0e45c47cba3474ead98a06a22ab6b29ea19431c255fc41ad87416e536bb353527a445e5a010e49e4ec7b4103447403bef83df217a", - "0b01bb687e8ca2e6f87b05a959ca7c57d19b89041fcd26867a7673e3a46e89a7016971055663e94f466a5d7ddb37dbec524ac63e38ad51f3724b4a5e053dcd74be", - "0a07d4c9ff37f4815964e1864be9d30921520fa2c2520b499b52ff2f1ce1e7689a1b6651961f853b025bdc8be5b08cd587487be83375becf0eac92a2b66345e9fa", - "0b03f3fe42457347a4a7d94af380767ae53a45c3e19f45c2771cb8caecbf733d942be2a1651a80a00729d0f36f1864aecdbc559f378df327ee12cfc5e3657438db", - "0a00495dc9510d65d3223abe94002fc077f3c502f214585b880a8a9b7f28056aed27cda2bcf498988aee2f5f0966a00e3a7fa3f8e03c5b61d159a28cea10a3c222", - "0a00f368bd7d5290bd73597af84513e910246ad3ae8875fe33d5f625b9fbbebd10b94eb4e1b81930045a127753b712a88ca9c75203b05f2c2603e99b700e32f421", - "0a00833e2001b9221a12f1aee16ce5add05fa3686c9f98b54472e265469eeeebbacabf3ea62d0b87d89399921b8790225c7ca4810ddd6e74d27dee56e09e252423", - "0b0831112330250b3556460ff97ad0e0d2f12c3e042f9e0be9dcc1c0f3a324b7ccb7e68ac184ee1ace3685dc6e63d7ded3244fdbcd1990e61cf5c02cf2773ed07b", - "0b07183ae8c8a00fd13c8cc3e335ee0f9f5109e320d6cc940fcf50560fe995e6eaa2afbb3fc92a2c80ccafc31e1610110318db96a901a78c5e4244c3b5932bcc5c", - "0a05fae0cf5466147271ff52f6e589fd8a07076b0dc7b6a829ffbad4feb64e3ccc35ef86887a95d8da2b237c904d33debd691cf594f115bb6ccc730d6bd4f635c6", - "0a034a9684fadc0195c045b9eced33e16a14cc7a20315abef526aadbf4d7e0888e4ef20db3b2899b65ac127c7dec9d02e92bec2dee73ae9b8f3795a6d1ee688ae8", - "0b02a1c443a612bffb86cbf98051d49b543bc5e17d671a5becc1febabad0d768d0d3c60f0cce17c784e7f9f1d2b98fe693f8273de79c1d84a6ed70afc026d73f03", - "0a0086f911517927ee723c72223ab8b5c32e81cf30bb52db01eef1c674312b76684d1e5fe2e6382f46e7d38f7ca1e1f8c70c32f8df1863fb070e8ca7a99af134dd", - "0a0012ac25ed9861b2df9e15f5e88470406deac7295fe9b83de71b4f28047db5e1445572b57df4f883491d28c25e5ea3685aff37a4b347c0404c726ba1009e00d3", - "0a084b7d8878c7704eeb6c3e6bfbac651d01a6ebcacc5423a36d7b2f6d20ce55d7b8f2034c6e6054426efb7d56f04f9b49745f79301dc84fb3713d8b01a241b1be", - "0b0374839c4275c85371e99c6c8b6ccb15553a7c3fb34bf1aadf4dee7fe02ab9f475ffa7ff99b5e8137cf99a09c55d79d5f54b3fc734e5b9cd188193fd6806def9", - "0b01c53d712183e1b92a51abf0c0935d2f51e8552f3aaa742fe0487893bcda7941ce641f2a9e77a5e43a2c02694865da352d127b0015f2a415c20f4f7a656d15f2", - "0b047134406ed706801ae2f273301c886055f8312e0d30dc38d1ce88f264167f71bd6161847928ca2d8c2dc1d806225e3b491496d19ce6106fe4cdb3500de3d82a", - "0b0323eb5b0f1e3aa42e991d9826dbbe5c77949cc0289a060b78af68033e7a61b97629a373a9dc9aa49a8ffa1104b43f643ca91dc7661395eac89973d1e63effa8", - "0b00a424fc5fcb1120fdc2e6bf8536079b04d885931dba768c170335aca09a124e6bf9032672cd6ffe56067a5b8284442134be885882579d6158452390d82009d7", - "0a01b96d60c859b29ff588e9c421b2417e1707d7ee77b4f10ff671926f626cb6443fa4b804d128fd73f99e4efdc5ff77aeb2673a52d4866c787cd744570acbd694", - "0b06ef0befa951c59f863a41b3f066520dcaf358016c10cfbecd9c6e6fee5149ff22391ba3f5c81e2939912f012a680d13efdf9fd605d347b5f078f1c712eadd59", - "0a090977617117644728cc64c6e01dd1dc6374c202282872a27a32629b91f83fe46771a90a013574ebc1dd938f50f9f340edd697f64ce765776a3f2af6d903144d", - "0b0910adb874d6d8f173368ab46bc6626dc8c6b3de499125dd7c21bb9f647b7da3760a9ae6a0083c90f04a96074d2e3ab181fcfe8d5f72388f01de1182ca953b49", - "0b064dd361971ed0155202a95641c8f6d532c60649285f2b099af6e2bc2bb7d8251556d7641b06abdd67f6ab121140d9052e1114af0193c980c35518b4cd9289be", - "0b03c4d0ae6a540412e981d93deefa6af4e0bcf04559bc34215364645205d4811635403496a83e9a4fda800434fc0cb16c11cf76c3dd1d283d3eeaa0e207e78af2", - "0b027a4cbf5eb7c4ecd075604672cad7162c8ef88c9ef29cdbb086b740396c4dd5e5bc6a016ff57fecd7f91377e39506448a8b5fd2254b2832074fae9fec008853", - "0b04d450791a05ebae4b2c9a64aae839429d153c6ba39b6391b8fd9eab2733ec732ed623bce49af3d4136f0027b1d470e252f84e34aeb401e3ef9fb52ad8d377e8", - "0a032806e92ac6df2ccd46769c42abd8d95123dd47b6b8f116bd2f65b3d52344a61224d118898b7747177cbd4fa5f93fa517f19c313ad1389086771767bb91d77e", - "0b07920b57721007324913cfa30143d147eb9e9f965eee9374ab6267565382a7d26bd16f3338e70935775d532841304439fce0c2baceaa59ca081d6f4860a4f46f", - "0b019f8f17b116f58d335d0770fe4e4763b7cfd3801d32b54098543ca6794e367b5ca01b80ac35e43899e00c64804c3b5e9d3d895222cc5c0c04054ede08fd1619", - "0b03a48113d33faf8904b7902c1b7b1f3d4249d3d643b654806c048d8dfc756431e5714b5eba572e9721deada4f1b7c261b5cb048d8ec43666f9ed9132805cecd8", - "0a064e80850450143159b1b7d52f42f0c9300d9e64b749fe0544b896cfdba2bf6e7bc885f9ceb82781be19b83aefd0eb82abb195a87376893639db78a042cbcd71", - "0a07b23337d0a2cda780efbd2ee9c1ce8fa09312d9cf2cf6e272479ce0972178e4927bbb1ec3a1b11e00f30a1f95c13b853bd63be2dd738fc99668fb3e6f3656d3", - "0a0535ad68699b86ce6c568dfd439ba603936f0cf4c4e585634d2f50087b5e0b10f548e60ba5ea9790a9094f5facf8dd211f6b0e52a83a4544df7cafb1c4014c87", - "0b070d6fceddf7633a873de6e9793063fa90953fae58e8a445baf16162f55989ac01cea65e409490fab190922605bf305cc88c6f69bfe87482d8e7a189d82023a2", - "0a05d42118a2cc644d3d68192e3eb5fef34bd798cb6c63bea74b5d79e502e9955e87d7520b80f8dc1f07ba20f4a2cd07aa42445c083b118b77248f16110d58b6b0", - "0b0039b8f7d1c743f8bc8b76a7c815d05428cc1093e89af7f31cf3f64274430bebc23b8f9c99d68c7ec994cba6332ef9a0f492c3025b98c0dcc5a9930de1b0a04d", - "0a065fa70dd9d78cf683d341f9a429e4688953cb019c5ee99954640973e8b2534f369509c705c0c3d375c33ca2ad7696f6e5b821bfa37337d39b9f6d0c7a20fc1a", - "0b081132115e7ac1cacd8427f882181af5bb0c8042925964586f50b29863238c5aa7d05ab29e641fabf4cdac171e643f3b562586fe3e60697ae0a6c8104fb69479", - "0b007b46af4e3e605190919c94ac1ca7f60c103bfc3f8939fad0d138fa1e5fe0148b58691499a6a2b38ea0569d2e5afba3472cb63106727a69083a44c8ea8f5e15", - "0a06109ed68a4cc3511ff2df0bef95c86fe8368b754cc418d8ba07e385749686010ef990dd7f4dd26e2cf5a7de52b180e9e44237d4836de925e182919e64bb3067", - "0a02862ba7afbec259bbb85b1d2671d424a82fbb30ee70f2fc98bb5bd68c77f8b21036b0aa84d9c7775b29e9aec4045a43e03f82e3beee68bb990f8fc8af4f42e9", - "0a017aa863995f0b07071c5371a9537d63687bbf85632a3066fe5aa0e1b0557cc11f6ede38177b820e579bc29db3c5413e62533ba299320845a7887151a320a6c1", - "0b021e4985fbfa3621eee5774ffb705594b801cee054d62015e206ad0e422668f3edd50e01fc94067d3902c644d6508d96317faf2700bd4c9774a347cf8e4cf9c2", - "0a020722622833821097860ddf50f46807ca6b9feb05725e05d74e675c64c871a41fe8c46cb9e23a7fe1b75e3f7864a785ae21b0170d9fd6ee5a9ca1abeceb7e8e", - "0b08be3ae58cc08651364eda1b3f6d815cb524959b4dc174d13aaff5351793735e8dfb33fe8355068ca5ab4d237c8f55a213304333e9173a48e34fc987272196e8", - "0a03f66a5747da66e63870f4240b3128c9138e392f964b846fd943f8c30bc38493945baa5a9711390882fd1bbdd8283090d9efdde004d48c2b2a5908521757e08a", - "0b029f588a2377d89cdb8afe67adfce80b721c6c79b5cf0fec5b9b9b2675394479233bd34c68d7ea2d430514ea5fb2ec7790be58cf1a58231b49843dd2ad3ecb8a", - "0a003dc67c276faedc0cd07a40a2efa11502121facb014af39dc84a0de15397069aac7ae9e0e8a48b52c7446221e558b5b027f03492aa7719ed632d8c4e6bdd072", - "0a00f181563f755548e5095d5a33fae6153295f38fcd3072930247072eae5493ed49717daecb455135af5f19a4f33c6e9badc38b6a39308c4b37d1f75889866296", - "0b06bc6e9c14fab88c6c945dc566740088234e900dda8974e12bbdabc51b0c6a4873049e64593da945d48a49b7c31f86afd0c9183114e0ce220c33a8d6cdcc1a80", - "0b043bf81ac6bb38169a39e0fff38b1e07557acc054ec73349f140e888720deb1faf4a5907dbe23348a86e5b144901c9f52643669ebbe68311798c7512a67bb580", - "0a015d793a8932c5c83f3618546f61173c1de1771c51bc4a35fab66d21eab43dd0297933071ee6fed44c7bb46b7d51a1bc055d243851c609a252d7c2bf0b4d7297", - "0b05029ef6dee369a7035d817930158d3de12acbd7af0b25ec063b602c6d8377f283e927ca46c74323cede3f6797c60a4e618761b47b43c1aed6ef5d24aca2714a", - "0b02ce3196f657142f7d0b15ffd9f6ff587658f362cc7b0f10d8b85677505e71ecf28b655bc96d9436d5458c75fd340414b6b54cc888fd62ebe88fe0b8eb104267", - "0a077162e1c638b5a72c8853eaa8dab6671a6b06603e055e208a708d1897557924c80c295190f8d81d4a3a1bade62c1f6163385b0209d0f628fec30090772cea91", - "0b04ec68a823529863840dd707621a9d075514389ad1fb361739eab5a0b922fe63b267cdf37bdee470199b76875e4cc3307b2327a7b66ba937615d6c878f3fc9d8", - "0b02388b8d6d08fc65846b4249007e81104274bc699f2bcacbdc271aa8af781356f2b6144c5ac39ad14ecaf1b78bb8609cdc8e97f37f5f22a4b638ab4b4a40d5a0", - "0a0118711e819749ccf3a8827374143f692d05427a12cedf748fe5313cc05dab38d43b74dc56e85995cba9026983d37123916840731aacaa8e250d2d25b9225ddf", - "0a08da8d067f04265cffc3dc062602ad18d88cd1b002a0d2551267ce0c24601c81eb89007d7202190d69761624541e7a3135f4daa7995ee959c21f82f0898321c3", - "0b00c95b5c04ae90f4d60ec68467e95005c23c8bca252f03cc6b1bffcbb5d5b327bc8f4a776a905c92db3a5d2c4d84b47d5dc728503a45fd89e8452ed2483e337a", - "0a086d215ea7a79b02d032508be176fe9801cd990109c6e814c6bb6c49062ba64af684d6fd76dc92e295c07a98528d32c8f56d39b61a17039ffd5083751f327331", - "0a00e00e177f6aaac8bac993f5a9b46a995284191bd9cc41f8b527ccfe846ef371df2827f0dad011b4695b91d472603c25fea8c5efc72ecf0dc4090b1c4d31683a", - "0a064ad01fe1dfc39bfc10d3793f02f14f4f24882b66fdeeb7502f61c3357a8170a1d11465edff8f4d2f7c7c52db170ea61a616d75a376b9e1d537ce1abe11a6df", - "0a0026fc91675214e8a2a2784d3cdd97ef84d57ad65adede503741201cbcdfcac870c24a642847a8cf8f0e28a46ebc63946c4524921a5003274c282f30424a1cac", - "0a04ce6657f3d93108cbe5ec0abffc55af71ac15e76539ddd207a3c16b978a503d96ab933e7e3e432d6d873145018182fdc3cb6c15e3c27399f4725b624dc76900", - "0b0641d84cc45e1619674f0d8fcbda520bb2fa9fd38cfd96f2899279f382ffdeba96a9df68b5a567526d3aa006473c5208667c1091971a722dc7ee17896b54c46b", - "0b03c0d0413f58d17a820b271d73f82c8d5d31470149199df2aaaefad5249782b3a5ed6c20fc359ea1bb717bef74a8c0ce393b02bb8453671875470f7958ea57a2", - "0a0535e00a75f82effcd8df872ccfab0ef4b105cb25b7ccce47f283bc1149dc69017d6ec0fb7b62feb854d52c07b628f5619211b0b263050338136106477c0e13e", - "0b02f6964b8f6ecabfbc02c44f6deab1a231085c0c16dbdd62d5abd70fa685d41a2f61d45fd4e564e7b1c6c959940f19d9d57c1cc48bce84983fff35e25aaa12ea", - "0b054f627a54de44ea66c2ff442ff7b5e1334553a72bc94b329e4016066c7a95907e44b62dcbaa7727cd47c04ced2d99d7cde2f82523712d7e1734dbdf20da8bbc", - "0a0201395e0168c5c4a1e64f17333602b7a8c56bef4eeadf195027f6472b701c794a142b69c82f4117c02c98cf515f76dcd1ff77cdf0f4cfa0fc0090ecd2fa3d88", - "0b040c620a1950da0e7f9123942847be9b1e69b6d7d9a176eefadf0863f875f415806ef479554538dc735e12e863ec15e044a81f06cb04d2bcfb0e7c0795b6c61f", - "0b087fbf2a2ab0ba03f58d5dc338efb46448af5e90cc2bbba7bdc2f494acb77f13bf7dfa2f72b7ce72cad4d69b353615a321a4914d550f44db8a916660ac3bbe48", - "0a05d848b45f048fc3e89e895c4f36e3069bcec3913c07ab638a92600021f2e2d5b51710d7addda1f22c36759e282647812330b1fc9c6764a5350bdfc3ca4d5183", - "0b0918680ad88b6c5916c6808a6654a93d4d091adcc90643c362eb98e8a2240eba0ead32aa483b642015051f20975cc9cafd31490a75d74e17db8a47006163fcb3", - "0b0107518e56604dcc1a1faad3f3e94c2d87e2a1c47ffc530f2bb99eaa11a2677c67ab11042d7f63c6556eeaf2397fab943fdb34c0de6d26a3f7c9de8a92b4465a", - "0b0436216b6509c5d92ce032838e965f8e673673a56637b087c2f96d78f0ada6823b7260ea64f3809e446136285147323a0029a410eefd98532ae316eae014c5f7", - "0b0025023e4e344b21ff9f841350aa5668dc7a2fb18b8d3ab4365d8bf51f0af2e92c01a21f64992cf384ef75d93f32885c6870cd3d98e4d620983ee5fa5bab572d", - "0a03c1b43470e01de331e3b00e89208d6374808a6bb79f8d5825f88a43c82512fe94e0fb6647a60b315fb4991416807bab44761832444586c1eb687fea5397b2a3", - "0b02d5640070d340271388d4bca79b694b64d3ae69f47ae303b118fd1db0fca1ad934b8e143b0baca47fc80eb1d1bfc5678e25fc795199971b219042da03037384", - "0a0334fa33b2ed22bef8779fd1cde4e8228cd77b9c92fe6800075082c89a4575e633a370dcca32357069c7edb0a4468aac02131186558936332afd10305949e6f4", - "0a01fdc1d061f102430f237ccb0be2d373ddefc5450281702c77b98d0df1792859d6f53e51e88bd015f7e9a86785b09ea01dfcd79159445ffa655fec78cdd21e6d", - "0b00a053324973b81fde7ce7b20c1f388910fcd13541ed630e23142a2f72c1789e0bf3d55f88de0e6953c21afbcf8f2e334275e2236b23c52c7d8869d0b20b2a24", - "0b016b4f1d96eca09ae68cf5886faf8b3479ede21802da3eeebe6f810d7d9811b1ff93cb931995fea095eb2f0a86c02106a7bcc70017596f23416eab95645605fb", - "0a030c2592757a2a97bf96ce7773b881d2661a2d8926cf66e7ccaf0e166bb0cb2ce8a673e3dd903d9f0c0a90b0055d537edcb1434b355b6ea55ed5f278eb36909a", - "0a023570868ed7275e564fe6c6c28ab5b743b82da2983dbe0ba5d70ebda89cdbea13e16a55aa6258d2c5b71d7d27e4e2b4c9182ea922d9f7221dd1d6856e815e6a", - "0a08657ceb858244eabfb94ed930a8f3fb41d839f004c928930efba58f64db2fcfacad56276e34eaac1f858c00586f3250f7ff6536ef04a39376c7fd36b96f3adf", - "0a0684a1a82adfb964f9f1f57b21d33e2d5aafb82001cc89cab0b3aea32c19ed70fb1619c323ece373751005b891a81b7c5cfaa80927263fce3290c7a539cff690", - "0b027fd612b23a7cfc8aa116479835efd0d3120aae74cd45da98b2df3cbdeada88e571216fe6eb1031582e7aab59e4071df7a7393b82732aa584cab4f0970c182a", - "0a017174967523f62a61346a13c49acb1ca37c176eaaca724c39fb51a8b8bab6fab98ebcf559c6a7f64f5d149a6eff4b757f980ee65ff33d11a6215109b6293cb1", - "0a00ffb62cc0c1c2c4f2e787824034f15e8d53157c9a3c1383fa89c764cb3b9fa834087ab3273588625688e1b1bd8f337f6c84455b6b05675c04a90c1b7765844b", - "0b02c35ed797af1816c73e27101ae20c60381dfe9f26ac7a5afc46cd5fe2806d7d3d11bbc9f4e727bad68f6af3e64e2d766a708a5bd3e7e706b75b64ba1bd021cb", - "0a05ec533db9261ee91fe34e45b691927fafe0ca7a69c95f50707bb85e771147993634c89c0b2ae196c8a3bf3fde6b67e55e1f229698719c4f51ece08fb6241415", - "0a05ddfa438125d59469ee0af40fd182ef25ae7d17568d9b6329ee1fa13ea1e448b08acb96c78b5b400290fb99ebbc9773f0deca92190149d393616069b725fc26", - "0b02c76dc0e471006dca31ba90ae69be76f28d262cd733200c2fa55d116c7383f3b5538f69dfd6ddd503bc801b81708254481f85c3db3d37f5a4cb7ce357c6b796", - "0a07c1fe75af9f481f98c41ad2f19d19f3d65e165f19012e107b40f78a8db679e86ded395d6536cd4e075afa6c061270a2bf4d4150fef97f2cee1df8e7b1c60f68", - "0b00055d14cae36b207b0c1d4077c898ef452459eaa6aa449ace0a00184fb1b557a8c8addabcf4379beb17b0dad40655f5059849edc1f75638074d74df28984511", - "0b08dd7fd59f095b1832706e7106746d51b5aea43607086e7e5c917715c9b60c82f5ad978f84c837cc82d55d909f8e6901f00a70b074f0facd3c29983a483939f1", - "0b071e2ddcef96c56b57220e5ecfe4dd851f8c9d81bce3ea8e3f0410fbf74c3403aac8275cbd4ff2561656f5fe5c3e37373b48b2113789ea0fcb17a77795a031e6", - "0b02ee968dead2bc999a507518f2c3a76cca0c345a51aabfbb579d020ed195e820ca070bb714f347d402bbdf40451c56592e0483949addcd64a373f1cc6da649cf", - "0b0040f4f500f32d6c96cf7ade822ffd5377955c94c4507fb14ac9275bb16f1c4987d16a4aa10eed16e64c5b4e5c6e3a364ea2ffb67bf68c3f0a68f94d0939c9ad", - "0a061de0f2f7f67cb1a47f9f6887a8599eec0590f9b205a1765c383044a21199f3eb34e21cbd78db482541142dd470134bb0ecad0b215042f7a56dc8673c2dd2e4", - "0a05c707e8a22f4ce7288d6677a5af6cc8682938e94c9ca68f032343dc1299c7e83c980ce175b746c185fa9f8e0eb11fa31ab49bb8b7c372d710cbfcfdd6aaf646", - "0a081870e6caa0d9ead6da659c3f87715559c85ae55a7022e42405a731538f53eb708334f206068e176d11762efba081f63fa6ec5c183910098279fe5ab1684e7b", - "0a046eb0571756d97dcf9c8dbf11ef7d4f4d9c9a4f9b4088e9b1b48f43170c2e902faa061ac2d13c076e626d20c59934a11ab7761700b2b16cb56e2e6a2949c413", - "0a00667ee91c6154a9fb093292261068b18ede666a5532ec856327bf9a3d1b3eda20888f5c5b86c776ab9126ce4d023082fee54937754ddb8af4711c8e38d3b7db", - "0b030439e6eb29a6af833e2eb8b1e148c7135714fec436ae0faae2a8d392f0a1d9e6bdcee78ceb5dc493fefb9d301e6093b4e59b31c7672a39119f01909e16e470", - "0a084aacff683e1a444e7a1ce9141528f2f60a9d81710351f7b052fdd62f6a68ecc290da6e96e80d932c7588f446ca612b6eb9ab6d2852de8cf81c87078b3f9a86", - "0b027f2407ca14e65267493f399669a98cf9c462d5d8777850a163acd76e6871df9f34a01a13c74000e881386637538e93f079780cae9954250a6cfa9da43b41f2", - "0a00636f26cb72c6fb7e8c7b6cbbe03c3b183511f4fb7e7a2e344b6351e5d49c2ee6a7909e446f4efc483d9dcd21d6359789e9d1baf6114bc4b24a0277e584b1bb", - "0b002af3bfc31085a26e05b619e10c4e3a21b53ceeca94614d8fca0854e4d38a001409cd29b053c6da1a91a572853f19d026fe78e0227ba4991433ee23cee434de", - "0a080af81e666871b7790f206ea4e1aac032877b14602a53c4b764baa14b9f4699d6fc438dc620765fcdce416d67581dde152a5de20b5b580ec37e1f0faeef205d", - "0b084a1f191dc559f9fb4c0ae52dab8973fc7257ddb323ef3b969a7c3115f86176f7b10a9c3abe7eda98c1f93adca42468d29870f6bc5d906d1255cb235e2f0884", - "0b038329ea64368112713ec98fcb7ee94e4cbde30561f13df111f5dd82f146c6a1f8535f409ca4df541ff6f00811e26d28e5fc36ec0f67eb7bfbc0556b6453581e", - "0a04f1d7db4ef5cb98c9011a3eac88eb37fc3718fa071bda17fc9417e24b4fbe2bc858c307028d28de200c0b7ffcc21258af7d2b7d85a65f6b9787545d718cacbc", - "0b06fce2ea0870af878ce5f3b5afdac9d442a889c30feddcf7430d306e403d34db67382dae3d7c67e4dab3946549822e9ad3559006e8a9847eebbc99a6fa08efce", - "0b00dc07a57a8dc151d8f8cfb17cec610e82a886d20a6f00112cc2a243418c9b3d47d13a8a1eff89f03ed3bd05f034e47a0e69cbd4e6deb3725c21ef9ba405ca90", - "0a073be934550bf07399cbffda9cb9d2fddd0ddee30e88bd427e92919e0141f80e41a1cae79f8bfbdc99436acc0b5b1f62546343f9d561e36f391afdd2cdad166e", - "0a05287fed1a677b962e612c3730b102f5c43c447889f4fb0d9a3b7236f4faafe038c5147cb42f0a7ebf36009e437947ded4168c9709f12312963da522eae916cc", - "0a0341533e754faecb252d888f57919e3846fa3327893724f9116ba3f6d8db4d39a7c2cf7a34bfbaf4c8eda6703e593958b5cb4ef4a9213be34e6c6207775d1d15", - "0b06375ff39a303f1ed4ed4202e3b3508251da07a972bb88f841984b4ee8d5b25330951baec598b739f6ea98ac8e75f28d61035229405e328afc9a6acfb36cdd11", - "0a044cc3b0488b6f8e032b64b32937ad0c5020ba8424bfdc9931019c3cf0adfff7eeb74a5c6d44ca3da7dbbd28aae1e7487b092b34f57edc0d8a42d972e3cdc2e1", - "0a022b1de5433ace3791307a274d6ef209719786c3fb4a52ee5bd03b9d2aebc00d9593fa03e639d8bc1588055b30e87c2b0f145678287c600d954ff1c2f9c79c76", - "0b017c3e19a5282c35aa8ec5bdc4c07cfa39e193cbce5be32b7e9f0d4fc4ee5b99702f5d8cf62e5e857322229729831353a35f958d2a29eff2ed659b2778124de4", - "0b02d11529afea0bb7ba3cd99c0ff3f675cdd96672dfebaf1f4713b37f215813fed59935594f9936b4a95411057234c3f4793ab1a0d185556a11907c9b527bc834", - "0a052018d981886141bc8f16c448287c463d43dd47b90d52439b8ae998033137e667de893ce8c0bbfe5c7bfed7e99bbfe82618c099f5528e1ad94e36212f4ab4b3", - "0a049c6c1504d5f74b169231628a3eaa558d404894beb77925171cc56c1e992a4e129508ecaf33a442ff7f083d95ea353d518727f35a76d818f27141a84d95736b", - "0b07dd58a4b999b9dbdd7d5dfc2a644e8e6e85a5c1d2998c9574cd6087921b27464e0d93e48fb9a4bda7c0c045c0528cda8e66e94d9c1bd4716852a40b1facb77a", - "0b00725f97cbffa696e96103462aa0009f2aeb3c9a0e08aa9d03c3856a0a1bda2a5ea9e1cbcd8145d433bf51e819d4cbf9f7c1542bc6aa6fa61431c650e99b9787", - "0a04cd7588f8d24f2af5a15407088ce857396f3de7916cf2e2d02f7d952adb22b586ff914eae8b383439837693380293f94704c1fa33c5739f3d75d16dad2d54fd", - "0a070734c5f39c29ab0407254addde4b8234c99fc1f583fdca98c0297b08b3048b9e4403a05e3aa5184bf234863cf074745dcfe52b63cfcc9d02c44e9d15747f1e", - "0b06aeaaa3b611b04ff42494635f61a786685cd97e6dc3caf53c0ff0c5c136e59d0f71c96640e69599a97bc0965b43441ece882dae6054bac4cf1cc4fc14136512", - "0b04053165853dfad8055456815197b3414c685cdf0d3ab4f2aae48d374ec24099d4fc6bad8024559f2c834b45e554938c3203783ac74c991e611fcee38c915e85", - "0a066d6dbdae460c6fa1e2ba9b3eccf26bc9e54592466104ca70a1a6fca208d70400d7da97d50b1c1da9ad2fc5c8194dd810c5ef4322573a93fb4fb15e7299a333", - "0b04773669991ead848bc27bdc07405910122435dea86ded49d2583ef9d0cdaac5cf939e23d4eecd641a6168a8da3827b9c72d3ddd355864871e5f7b01737c2012", - "0b06c57add551b9d8b23b790ba8b67aa7f16cf09e267bd5d2b48070d73dd4485fd11a10717ea2a048433633b4f94bb50583214289ce7090f35c98dd4f1901838bd", - "0a004d6b6a838a1f68b4d6b33f6e7ad1e03ef3c6fbb76e3e4f4cb09966c2b3002b7a6e5804936ba9364dd035addecb476083dc37b2485c57cc0f5912c5ad39d5ff", - "0b07f405e4526847b15d59a8a78c04b9bb18d9799ffcc5fc5753dce06f99eaf337d1f77130182b2773b778449c4ae1ed38aab24717ac381d293143790fe58ccdc6", - "0b01990638a5fd2b0ea70982c56ac726901c417ff1165c9ca5aef3a1082b6da1be4343b994c662074347d55d06b00052f9cbae061da6ebba317ca0330ac2a09845", - "0b02ab869039ddc7b61b9e065214ff4cdc1cba383885df71c8a16387c4934e739312e8f432913418dbf127da5783f47d4fbb3b68ea2155b50e179e7f3274a06604", - "0b05c8b7a4350afd37fb31be0426cea0a42416481d1c3dfbea014c605cb0dc2113bf9d914cdeca4e6d098f880912c52401615768bc1166cc1e143ba25d70b42a66", - "0b043b96a2faa3dc890a029e11eb9e5eeb9ee1e446f613290538a10cd66149a299cd65ab73f0554c34256882ddf0e25025aa95668fdabd2067bdc763129a667b23", - "0b082ac40acf0d4d93ec3fed8df2621e0fb2c2ae12236ee7094464f19d81a11608f3611099ab0e0fee161e6c45833e5aacb914279bbd7d2c8f08f4e239273cdd08", - "0b016cda4f27f54542e93f45198702a3ea32fefe1b7e509eee446f9a600364237ed251cf973c7377e1805e75c4245a62706bd2012e3fab3fbfcd0152b190fbe59a", - "0a073b6beddb9c2cdd724dd54488577b299e96cc1ac4c88171b82982c55385ef735af7ad0a3d149dadef01854613d904d3f77480be8b0fd81dbab86c13a994544e", - "0b04eb36925055ae4324ddaf50da7c646ff65a97d7a1da79489533f06bd4b758e30221bab6a944ca9bddd2b33894a18bdebfe62228de74985ef9657dab0b332872", - "0a00421bbc67a643814318a8a111099c619cea5ef69c28c9e7cc7dd78175ff66b5e13fccdbf91635769e4de087d50c0f88e0b0a0da4cb92900058a5d8eefdcbeb6", - "0b0790eb86a2efe7f022ae2c6f65b2b8aedd89fffe439b31f0b77e400bc0503f1456c23534bb0abfa3643c4650f2ec588bc40fcc217746fa337274c001cca5295f", - "0b01acce106b1585c6941a32c43ce2fc4a4ced8a13ddb7660f0b193128c6717e9c4d62726c14e552a4b05c8f5551a8fae681efeb017cfd174212dd04974b497381", - "0b0007b401ab320430bd6fb75dec99d9ead2be41688acc43535c1d4db2c79ecc9abe66f2708655d60de9b2092290eb2fcd6ea1e0a09785de1bb3745f7af2f89bdc", - "0b054ecccddc1f163f45315bfc64d56588c5ee1ef6f381614871b8905c8e6740858c2c3c3c3c5176515ec9acddd482f39aec974922b5e67763bf4ebb6d7b2f5e16", - "0a077321200d7b176b0da1824b31c3ee2ac98bef497e829d980683391e8518dfbf654915a221fa997e632fa8d7c02b5dd0bdaba92dd3606e6cfdfe336d3feb057d", - "0b03d6505aaf812a3277a860fcf3dd498b23cf4eaba14ce00a0ae183f5b1da31a76e861ac416d042a6b472c598b43d289d84921ae4e3422a56b84f05b68ece2c53", - "0a05e222ef0364d5c5f6c78d3d7d1eff4bbb8a883cc09a8f9b092543056238ec83543a827c5836d47678fe2a64d7fd54c548ce3eee2ee3a32424e92c68f1a19317", - "0b034d0546d9937b392f5223e495eb7f1da1097493ace6f52c1ccde0db08c85db6247e0fff3bc64c9665422cc3e1282f1d2ae274aa3f1b8ea16b8928263b143dd0", - "0a08801499a17d0dfe9a39c1bf3a5452df7befe053975a44e5702dea32661a5ba70abccb0dc01917278c858aa0c3ea62430d2974e22af3182d25f8688b276550dc", - "0b03b81718cabce8cbaf808836ff4e60abd87cb441f99ac42e7ab90fc4290f575707ee7c06291b41d88fe73af921885846486761ef472ce76689bec90232aa7928", - "0b03e8dc126931d7771dcfd38f7bcc38e7a3b070e39c956d616f4566664c118624e79b5a76600f78c38b17ebef37bb0b4557ff6e956ef47e9f40fedbee63c6cb59", - "0a07202a7aec06edfe680b3d899b8633e34632b3d47620f64569b9e384088d9cc1b90240e4e7999c5b01f8da690d3a68fa6627b36d808223f954d942358e600bfb", - "0a00aadb3d173ffccc3a6e7fbf57ea977abc886f71289df21191bc67caed18e5953c7adab0db20a58cdb5916e06e3a0a7101f638f8f9c6c07720ce0edb40d24ca4", - "0a0316eeb86300d6d35cb8af46067d84d3c3bdfb41d4c8550ca0e89221a192643a280e8d16cfef31fa83b7161f2256bcc0cb8b588bd4e83d95ef923a1248fa46f0", - "0a085ae9081c5465db3715e067f53bb3b275ed4d4d04c94c20d467e8985d993fc026c54ba2bdd310f074ff8f930337a717a69192cf2c943bd9b82c83ccfcf3b9d7", - "0b0170664f8759281ccc8d1b89e8e1d6ffd3c4f775f5b350d87f330352e33fc21b70d7560f5e77262d7268a471d73d7831ca7fedee07fb312d73352753b8496852", - "0b03ac54f726b3f5bb7e7a407ff996606cee1c94c295407f2534f2a991e2ce2f6f9e4ac5aa4bb50d88f3cd126eb23b88cb17f03d487ff7f2f6b2cc64fbaa24e199", - "0b0036202b12207acdba3adb4159c1e4e553edac8e765377a8679e2fbcdf651749b415949b6d052c54ea60e3db9f1dc45a3bd87682276bd2f0aae4a4914e3a44f6", - "0b0016ad0d17091209553adeb251001ceca804ae84e14f3e49a7889612486c1be95b8213a5e933ea797c19b1065a2c5a9099247a2dfe6270ddfb0ec3bd6915748d", - "0b023dc7ac18f09c8affcf511a4bea63c9e8f90a36f87c93936141d4d62569080ae750c625ba4462f18946c09bbd51c47b3b57afe6d5384b8463ab8cc5e3cf769b", - "0b05f165d28921d2cb1aaf4d0e14726012edc4b1efd7ad5876ea816b1e14919ec47035fd1a799dd9fbc0f75b9d80a1d2bf7bff91f62b2ef9d19bfac4909e1c1173", - "0a04bee43b7c2fc2c7a6c29ec00012cb4e8ba355e4d56e28ecf6f17ac5e115757a82703fee6e819ffe956647a6965e96aa28a4de075e86c4ea246062af44b96023", - "0b0492b67a848e70b62ba6464f717ddf937189f9e9580714d7d1bdd3d86e6f1b9fcd34a19b700c12917c1fa5543931611abe05bfc362fd20fc2ff166ff6c723bef", - "0a03a20fdd3da48b7ca00483657fb761820df86c30ce3b2a9a9b488738c1bea0040bb30f8991f8f50144b3685dd5c77dabe3addba829d2e7dc6dbad0c324508214", - "0b025d2681471ca421b7052e4e8b03a570f814834fb2ea8c3e44fd549fffdd726eaf0190a528a247c457efa4196c3f2b94cf1ad9d4b7d7ce9e0c0c1712f72501f6", - "0b0013860bc0dda0375e4d33210c2f8e6171e1f87537bb760651c35e1d25a9aeceb0eece51bac6ec50b6e50295c06a6732d28d14bf79e03b5b38e5d98ae3ccaf7d", - "0a0478ef8bb4241addc15a645d1227a0cdaa4dd05081b34d3b839985f8487fdfdadcce58b5860203f8251a97f908ca215744a7f70f1b2f0960a691b53a692f29ee", - "0a0902d9e4cac7480276e964de728d586cfd402f9c5904a88a08d2bf5a78b44f58a7d8e47686da90648df3ce0ca854edfe1291c64c3f3f9ba2e5c1a397cfce79a1", - "0a0464b871390e3f9496e13a066a82f6a18125df0f3c6c61d1d583cbc1744c806e426095ab6731d7f268186c67610b3ec705169ba48b9411bbaaef6ba674479541", - "0a0117a0e24f93f0b7005ca2f105fd632b4e5322989757e11aee836148cefb9c218059bc2dd2658ce66dd47f1679a6cdc48b3d17539a2d2afc1bd57afb55f884f3", - "0b00403ffeec02075d07f67f39a8fbbce2d5a6c4018b81d733850953824eabfb25cba312bad68e3da958035c3e474a6ccee7b3d0dea518b1bf9cc3526ed400f8a7", - "0a059e04ff2d5b63ac612f2b0021a5a436073b15b6373859d5931bc1c68ec2ad6599f74a406e8ed1455ec203ed829161ac8ee69fb92944a8753e6e5216b7a92797", - "0a02f5c4c81287d9e3287dc7b5a854b96ce4cfc330e9e701844b75ad380289fbea08ccbd46e6f68dd0dd01f2e1b7051b2bc103cebd704fb1bb2b869e8c576fa8f7", - "0b01f34aeb4a0ef55d3a47529cdc60513a5398f5722c3ba3297ddc3fc4157a2e012218c05bd3cb81dba7b4099f881bc536fce73ef2ba11b59b25c8fd80f8ef306a", - "0b037a05cc88e5a3f81ab1ada82acf91ad39b8b07a1702f045829fa4918c1cb14af1b62e234beafde7da220e629b752d6bac83fc049081a105ad2bb6b3a983752d", - "0a05e575ecf24a23891f584c3b1cc2f2ae96b8949d384b16e930c469f55ea43fa0d6e872025ffae24eca25a63e44a8fe9675b0f7212e6208fdc0d43e9685291d2a", - "0b0765595ebcb0c17cccb5b7c81e9091eeed659b3921be96756021b3c5e83de107f22856e7c3592b867ffd7f3ce7307a8a25cc1484aef902106f04ec477b5e860b", - "0b0323324ca5a6c1a204adc6035c53e7d41a0570058958b5b9742b99b6f4aaf0158d7b727a6167907b8812d692391cf45babbdec712dab025f5f1b88032531e7a8", - "0b003a7729e7d3afe70d2f3d4f3f9622767eaf5ea95df8161be30f96724e6e3e57b08134b4dae71c6a0509db239f998e1807a913f250e10944a40ba1ded63311cf", - "0b0579dbc374f4527380dc7ce4fa7f4433bb5d5a4b10f4657a800afcd9352162be213fde6ac3b386fb20e0cf1b2bf875b17b638574935f16624ace4cb821d21d13", - "0a00f18638c951ca952ea951dc527500a49273d2fb77c7e759309a76a9f4915abcf13c421cef49a33bf55d943525c28377173cfd052dc39d052395c2f3616270a6", - "0a0280e90b62ace55fa275d4a69b4b4c53a598374a42593873465d5ca3c49197113ed4b61cb6947cfa99e9c34f266fd3bc77544f6ca1c2ca5b68a3dc55f5aecf3a", - "0a06d1f51101566ad9db61959b2bc9da1b92c89db0490d79ca082ecea3e02d00a4636feae9befd5a09d46f925ee7737927fa69c73774edcd72926671c192b4e6f4", - "0a012524b83007e3e93f02de5d334a51ac4568126d00a597c3ee0acba7df3a3268ec10800d5a319e730384d86a04a5cc61d32c4110c6723e8fe8107c92ca5bd62d", - "0a06726147d9849a422e7825dd899518f74173a7796fbe9596cb2790303a0f38ac0bce3ef62f23d3b0fc1db54ca5a326fd353683feb6369bbe0d107d99e95f47e8", - "0a01fef6aa2a6cb12151196251057c4b09e46dda9a0ac8c2e00d3f8728d0662163f7f5c3b6a4775d1261906d582bbfa7fa035f3dbc3236f6ec42728d7703b842d5", - "0b07c659765276693b526b12f752f6a6c84b577123e0ef2fcc2cd0c30ad2876312bc12f96bb0e2319c02df948ccd0dd16146a983239e6a8afbdca6ffe2a9ec735c", - "0b014390c2f93f2f50b016d1e029d7a1bc3da5f0ea194f568155c51bf055872df58bd6aaf1c5c437c29c9905ac4aa1c3d364bbead5141a9d66fa5526c37df6ab19", - "0a089b5af2751cb74d740013e0366aa68e4397638fbc09b04f76a9ed5567d46ed33e5cfa458959ee51307ecbd8289b975896ba145215402940bcceaac1aea94c1c", - "0a0492d8bd1df2c56351a9fdf657a6719a7f4c94672da5957fca7c956e1291e01001dc2aaf27395a98ff32d4054456a5150bd8145f437a29b4f2c320da23233ab2", - "0a05d6b5ee2508a4166cd5f4cea707fe7bdee6f7ee68847f16c2653a823a4aab8ffa47c019c75e54809f104446037866969e659ff506988e4e2581fdad2de7ad61", - "0b0506d666ebe558904b2453d4b19c1627f383bb8aeeec07511a08635b5ef8a2ba28ad3d1178d6053d485e3215d77db88dba1c348242f5f3cd5c36108842a3b7bd", - "0a0422c41aae1c80b71d4a9aa6d8b716d3f429e737dec9dcde39c64a29befb8ff0523d6af72415e240f7ce84ff3c51286d6913f271cb2dc5daca536c5c1b4d65f4", - "0a004b58ddf3f2ee615a7f4019c56ed60e8cd66aabc1a51194c82d5c9f722cdad3eb40615be11240ac5151ed62cdca6cfe2a62e8da5a6c7e861cbb9873683ee665", - "0a05dbea35b56e87e085067013f8a70f07d631dc6ee68aac745a64361751064e2d42a74a9034b8eb830442cd8295258b4f4dc933f966a124b2ea867adee30f9885", - "0b04f2ac2776dc4763f41f6cbba0168c1d6153ed733722eea61f4f24c3766d0f0c230035764c0cad813ff3c28cb0048f59f7952474b6520cae13e32d2b5d241e01", - "0a08f4a874e95fcf25ac41f3ab58411d5bf0be2033ad78893c27878fc87354d427c49ddda638e998b06200d71a517e033733077eee97e0f3674d1628ae018c94c0", - "0a080b5c4c3233991a75a35984df9a162fb14ab21f61335009685e3e984833f02a9d8b16f0ca8dbe0fa260b113a92cfe0cf1c153a30b58faaf36617fd1eb7e01e0", - "0b04b86d0242fca279fc1097465b8dce18b4e66d2dca8ed6d80763fbd60823813b0fc44e991ed21054290565ec088c0db58c783aa24fb6ffc43b52d7363040b9eb", - "0a02939faa5e43fde66fea8a031e6803e0cc3bc6eba042dec6b1d51820ef050383f15e96b37cee6b613482498f4c129ea819f28aee41d323f9f94149552bf6e6ee", - "0b02aa9c44c11544b86a8ebe7b250f52805075a99c6fe70cb0e8152a390a890ea518771ec208fad9da9dafc43eb665de21acceef21c93013548971b81cfdf757de", - "0b0068243026ece526633c69ef6793e0d711fc845c281cc4c67d1a2611f66191bb28ea374c55a366c61b2e45c4bf7aeb1b4a17c8fba0894d551110ef8c2f54b621", - "0b0521039dcfb3a00d854a2a50ecd24a263095a7499177caccbc6b03e80219f2dd4e8a9f0f852c0eeb10d9f836ce0305b14176f9b6bdc9b9c89522f8136ccb98dc", - "0a06ec2227e0186199264a76d1f26a86ba2cb561dbe9ce8684963c55879e17fe1ed38fca0a4791c3f08ef0a65a1fdd9efba71f74721303b8ce155c11f44479d07f", - "0a088da02874d02305b2f8df5df472eb6c6c9b1dc6b75ac69c4b5eb2cc469089ec85c621f6a1389bc9115a75d1b26f6b46fbc685fb1074c9b550c41a22d7f7f025", - "0b0124a26d1a4a4afd6c5ca12cb558fab8d84d9dfd4c112e16e3d009683e203728e853cbc28d951eee8b2c1127fb642fc5b4959cc5cab30f4e83df9d4e0c9fdc6b", - "0a041f35837c6e59f74694a632cae8a6299838fc78a6238b134b939290ffb5bb1dadad94589e034f53ff5286757e77f73a09c2f086d3068c37bae3245cee612889", - "0a0438a4dcd66347c8ace338f5e66db9fb1e7d40b37612c9be3550b562cde925f96e7e1fa78f7d568c3bb68df9592c0d11ae524a7647486b05645fbf462f0f0a38", - "0b08551fa2dd4716cfbc6667d9d9aa9d9a41457dd335253f8d028e881f23acc12d94ea0377e358021c7137dbd6fe5a369862e3edc65ce2332bc12b7a6352ca9fc9", - "0a045c889c601f1f85381b71f5eda1930a80fbacd4828f233207f0bb7cbf23f0f591ea70f9b671acadf325a2cf49369b46e5e38ae50c01eda3f082818deddb0860", - "0a025dc60ed85c56aa26cbc2fd68a8f361837b23237df501c4ad2658b5d3c718bd0d48c3f94d1cb4c4b82ac03733c87557f310588d8a94e8b222f53837aba8da35", - "0a069fb171a511f5d1e76a59147cfc52828d6cdce4b724b343b0823df95572358525237f51c7be6a93b67af65501f34f8ffae5aa84c67dde96dd22c442a3e2c1af", - "0b0242184b8bfbaa3fc47c632093b8a22056286d6245b61921b9c1121f0882212334f1180b73908225f52359f578eae9173b13c233afd76f4bd1ec1aca29b08e2d", - "0b01c7cc62442b661c6a44ceda8234c678e97524dd89a788e9aed2fa63eae8f90114bbca10620f43965aac116431f43d4a61b33d05f66d8ede8b379e2e014b00d5", - "0b0621952d9c3576e968f473b65afdf7d331e74928de403ac9f9feb7dc4c5562838045822be10d5ffa1a2db601ec403b7a046be1038b2dabf43937f3d0a0bbe2fa", - "0a044a78d01d7d6d49f74181b1ae379a0ed659c1a371d029dfa89bbbf950b49c55bdc795d1b583e5137fbf2714b24827f807c37a69224a91dcbf06d7bf19df0a26", - "0a00c466e6cef31d40ba47bdbefa2851660928666d5bfdcfa430e692d4b45ca19e913edaa56de4a63f65b43fdeebd74b142699ef396ed48846d606f73f27ac5fb3", - "0b06f7aa87729f26b57c1967657ed1aec9d3b479650e959d43913c3fe0b0b435aa7a46ccbe7ace8477dacb1f8c5e3534fc6b49e7e680cd62434ca536e89d65af27", - "0a074caa5d1898a14282a47ab0e981005c86bdbb7b6bcb23dad86785d59c00ab4ebdaaeb0fb6dd6a07e6d5cddcf4a65512649598875f033499adc90a4563ebc4bb", - "0b0052b46af5568405fb1a41b7c6afc0884d5a41e9f890ef3e56f00be9723cbd6a75b4bff778efbcdb02bd5103e15ae163e9a11964900e01d6130bc2d8b41b68b9", - "0a030cbcbea5a13e51c1e0ab7d1810ab40cec575dc246d2482160b3ae24531d5cf9a4d484e32162a5d49a8d99e7ff628ee789719b49d9c2e69d44c3354bcca2e07", - "0a0438cfd27022c0648610121b41770f9fabf37f55def431edf21d2fee20c7a8ab6e44200416648dc0fe4ceb1ae25059df35d75075cd04fb675c90eb56f8492988", - "0a04752de42b7f80d7b9bd31be1ab9be89ab9c5d214c24738606611fa5244d7f1696f5a921e647247682915573ab438ee8ce1c28ee9f596f4e289416497bfc6f83", - "0a08a0f7f6701b60570dc5e8916116ab94feba8896286e94e8a3a2e34a7fd23b1b4d08ffe14261b5cb6580416a8f44d7816d1e77785798c2741e43df5a76970c65", - "0b08c5a9ac34e411edd49b8e0bbcc4451b136f36d65483b9dfc92f0394428e55b90b696dfa8d0a62da130a64fb08c7613fac2fd7196ab4b6ee13ff51766d198560", - "0b07a0d2962a35665e1e3fd02726324744460597f0bebf9c78ed5fa2d04128d301027b6acb3f285d2f8bf880fa42189eff9acd9edeb77946397f19d1af6a4a5bf3", - "0b03ea497a294d08d13e14a9fb7002d081247b9c8b0a55c0f8cdfe2b9ddf15f5259f22f4c868abfa78728e2d6a3a1c936c62b862f7496fc3ff06c7eaa38ed7f0a0", - "0a02f7b86ba135c69902c21d1c1dcba336cbaa1e09bd749e344c9889f3fb307d4aa78bce24bd51972bfc69e4f0acb43aa54f793a6615bd8ea54cbadbf3d67cda6b", - "0a03d9396edb07522d1fb6c59aecc6c2f58809da82fbf3958fc31883ee65c27cee50c08e74b6ee96de5419f174573e1127b0b16c5dbffa8d315808d06727881c5a", - "0a048b2b6a51b0b8d28f053300a8ea670c3f960d1044b2b8c7cc0ae122b006954e5c4d3f9e75a9b43c39734671f847d5a7eac21a8ba855d03d0489ef80d2e89f29", - "0a0757c676dce4a7b3b3b17744b315acfe954b53c7b6fa36d8fc991b10f06b3436c3d078695cc102382c6636b3eb69020fd1cedf72b8670a84edd86483b1a434ea", - "0b007c23c4de22cb3dddd7d3017fbaae87271ccdbead2b2d7d782f8db45272dfcf9fc66c236d9ab1deb2bd7f179efd3b34834557fe7cf0b418ef3664f20c960d6c", - "0a04da6e0c93f15610d29377356b8655d73e2277659ea0ee23156345e009b5653f3712dcb3f2ca3fe209db9e4bf63d7be312c293f124289aff6e2f33dc0c4a6d1f", - "0a05d24de9ced96c36611f4124116085db3f3d93555265ae3fc59cfc93a49bedbcd1244765d6a12c45e18de39c1ac8bff90d59fcaecee5af010b46948c4971fde1", - "0b02217e6ed1dcb288dbf08151a7db627b8f4c769d7c244664f1e1c0e70243a02f0c625d140ed3d4ba656ffb625898ecff6b0a4189dd51d3554c3cb795b4d52fd7", - "0a011f97d870be89c4b1b9d930da06e090cad266f5789be352a88fe003ce1d881b41169e53c064c58b814bda1cf6b9ec10b18eadcb9995120a6bb799da8e5e7da0", - "0a03c74140dda05aed3ac77549adf16219272af1c3a31ba848419e2da352a3642ff6c02b9567e1c7c06ac8c2a9950851e340781d2395bbb5a8331689cebd24604b", - "0a0458584a661c7db0281e60f587067356a84aaae09c30e5391eb7452d66e106bebe8edd1f3377790cb13deea03535c653db71894035549d354fe364dff00f407a", - "0b076e59949df16dda1e44ecff6fbcf1d83b39d089b6d7828d21f7386be5807d56272c6200f061d37d23b898ff80ac1f3a4099466e2c29c889e7acd3092213560f", - "0a0825379af169cc94c38210b20f0fdbb5ba57cb899ce50d63aeac092157de48dfec7e44150c2a6ea3b3e1be291822c8d12b346bbc37a0827ea6ef24960451ebb7", - "0a0163246cb7c123ca27606dd45f2433f14eba99b2fcfd1732328c4770d4aef7945050a1edc1f57f792134dc5d4bfa331c9f2e2ff2cebc8aafda98da9e186c9f65", - "0b06c27ee8fd09b60517362aafe315700291d67fd2486d0eee777b3fe65dce80761a61c512a9e2f302e0df9c927ac6acf05b322ebe503e05c73fd6b174bc15215d", - "0b088d02e6bda881fe0e0aa4264df80a42aac6ed6aa7f87b76ffa1e8b66feb1da46ee4eab77c3c6f72da0ffd3a76fef53e54f9d55a9f8f9df1546a662b7b2c7313", - "0b07576aa300c34e479fe7c77ee48b0a97032d1bd95c701fb730da579a044e26df6bd93caf9932802b4dcc3b687d42f7d3c7079d25438e2f597d041f5f9d7ddac8", - "0b08c61169a08ae7bf110b0e348e199b7dbf699399501ea9f44090eeb2648b13669d1b07d6de6e53d94827e83017c290d3eb746fbc080c5165c69dc05726cc765b", - "0a002ba2a7b4971209cb5da536a87064ba02e14569e77ea9b5ed899497671a354ce1bd45afea6fdf80aa5a6444b0dfa8850a8777f7025af46e6244f662e890665f", - "0b06cb98e77869fc5992a8eb216d455cb61cac3f7eb857d13d3afa25a5c6b3a91a3a0ca167323011bfb1f0b14a3477b4ed4731c7a0c894e1a30b721885c7a53c89", - "0a01ce2f8146661ad2fd9e8182c00daa94adfb74bf5118aa5df22b68faf316f10c13397b0cb7fa27cf67f08d15e5cd407adbcfe8bca8b6eb4151c47663f6179acb", - "0b00daa8aa6f07a8655e086c3b15424eb14200d66dea257bff9d96f98c6378c1a10d809e8590123028b9579232f24a250878f44b6a6ce0853f8f4b5406efe99dc2", - "0b05ac20ebedf14faa4529622353116d58cb4c4f787d60311ba78791fbd6c6c6193430bba5dd4fca58c28b81e8379e340158e4cad040128603c8458efa25a16ff6", - "0a0584b78efdeab02290c580e5c6ea771187449bba5434307fa8c857cbc0d898f14ed77e1eb4b9619019d97a2cff525b460c917e29b547ee34f13fd41e97618286", - "0b0869e43c86a17050f9251fc659364368e6615ffd86173c799ea0bed38dcc077e43aac22e344eaccf365af2018fd80ba42ae296cef2e08a963c32008ab14b741b", - "0b019d572c9eada52d4521b5dcf006f2eb4c9b0ab67c9ed9ab61158115554ed3aafd267ad8bf8481603290c8c7da2eec154f48f805d69ac194ed2c4c39a22db02d", - "0b01e0a9c39cc6d99e11f67e0bd3acc6b5e29649033a93e92cb5c96104c1e71d04454c99975ec61d31109c642462d31b40b2a6a77b903d7d5f8045406e18759af0", - "0b043970340804df00037c827c5d097d6a8cc7e27f9600a0fb16456eefd20684c1a8fa3511a44c29e822db0bd9f3156c581ec70963c941a2a2fc04ab405ee87b1b", - "0a02dd9221c55d27c53bdbb29a4aed5375021fd556555848aaffb73cc432cbfb2855d514562a4bcf1a3accac9ea1930d379ab77d0e56ad5de052479780656cb283", - "0a042625c8bd76a2c660fca957966d5a54d6fadd684666c04010098123f1c6478b786f1c1cf4534f6a0200b5126afe5a83939c9774c2af57804a78e0b45e02f88e", - "0b0750a489b4db9f762e3308427ac987ef62b79a0e3f37e95b6f79d587102156687cc0eeb856447f4a1d7b34bf1b8d174ee26198e9cc2de19bfe02573ae49fd227", - "0b088c9000952e958a6242eb7186bddae2cb57595d9b95696291e8e63fa1037f5c1ad8574156c85a56350dc67f71a44c9fc60a8e4430342d8fadc0ea2dd1e37800", - "0a06a82d04ca3ac5ea2b54d7da0be537e761ea4f84c2071e6136a0c0b90c7d4246bffa05272df34622b3bb8bc3f656517feb73e475a8365008e613be48d20775ac", - "0b078f4042459e748ce8c7566bdf77a94c8723de3081866f333c3defb8aa48f657505f67d6ebd1126e908b7d19caf3f6c8eb7fc0cd5ea0ccac6e7db5fe4ba61936", - "0b01d11f7d740661e972529697a9e066749946ec4edae5e72822c7db80a1442b2c8f21fc40292cf9de9545be3fe50de5585f33e6a4c008b9b42ca798dddba05146", - "0b00fd1401a41c86199873d1851ad41ed3acbedf0f2728ffac89a37e12d4217d1d525861fc30e2de3d48ca0371968ea0955762a31f2fa2dbccf413b4074f841648", - "0b0468a0835aeff93a48ab9c91b35322741fe8135869fcf0c19dfa1e75560e9a9f29ce74674efd75611a5b2d4062a0113767225cd6c966095e28c9620fce946955", - "0b0210dd086cb71b486cd69f39aafe5015d4550889341067d79d9ad05776051db976625c0039666a184b70a498bae0747d5886f3799e8ce67f381d6d1db4c98473", - "0a00bff8d908200df2d5574c00f9bdf4b8895df0542c60962b3b9fcb3871bdea451438f96fea876c89663650f3e959fe1ee598464d5b43f7aba18f78ad7c0be73b", - "0b0391edc18a6dd2c707e3aa1f234a47745bce5ac2b8b97e30e57be64a179d3bc05eaf3a50ae36f898abb43448f309a66b28f7702f03fa6a54a5ffea79df852f63", - "0a0877041be9182eedb0e128a5cf5f2a56222e064e026a9a5fc32afec571c38f530e1da75fb3e327b1a02e6e0c05a013ee9552797e968ad4b956d9bc129421aaf7", - "0a08fdc70d2b58f360fe99462145a7577f720dd155d871906628f2fffc7abf3d77b15eff89bf75b0cf6e14fdf6a0bc8d112ef48cfb064a81d46e00a286f29ab71c", - "0b008e7760c9bb6742183703e58ceb3d3bd14f68f85921b694c1b94fd04835198dde866eb2ba25e4841becacfd241519e1432bebf5038d890310b835ca0107317e", - "0a003242f51507de565cd1d697e5bc891cd46d1e9789571b97fa2d33cd58f45949f274cdba3c5a560c49961e5045b95ae8ef9cd0fbf82eb803b21f132dea72dc64", - "0b07debc58c0f3aeb0b1dca2cca6b7a85ce2d6e83e12141ed4bc36c7aeaed0e25d57f4f9235086af17fca8686ac0a0a485dc6c1161d45d47f2f1cfcfbbf28e394f", - "0a018f45e8168472c15d520360d1cabe542dd3b73a298d67302ae0cd96b4f78fbb1f1b5dcf2ba102bb10f8882ce27f9b4975f76e4f02449d2e9537fcb3583ca5ba", - "0a04022a9f713436451eed82e576c497f725d14b9efcc194116ac1bd7bd7d2d259cbf54e1068efec1acea579f1774a3ab22a0789a0bebd796ea6876620ffb7b935", - "0a05a0d4129cffdbf2534ea41bcb3d1694def8324b37236a7db291b6b8d7086fad02ae9437858f8ff5a279c66fe68576983a5a64158a330d8c2add414bac39061d", - "0b04d4e309d37fa3cb1157c9f4182ca05117cd9d33c7b57d506b2f2c8599195dd495ff0e4b985c66de5769e1d3f56ab8d0a5c805979d6852b91c8b8c14fd12bbeb", - "0b035ab20caaac55fe99c5c398ec098278f9af180aa9f75a4651b57a10e9eabdaab2dee40a9b6fc861f7a1488b6b8009fd7faef15518df5523e464ba13ee0ca3db", - "0b011fc0b6e160eb29ac3037c1101a225fe76b5fbda22f5d7de73d307afa94b85530dacecfd6043e94356563984851ff5f1c30dfed1b203fb24a6c0fe72fbeeef9", - "0a06d3303047edee1b85ee06ab8e05f2ed58e8424a7b2b64b2ce35a801f9fee8bcaf9485c97beb0af13af2f5f00d9874abdfa8c5b8aa5433037d4ce60d4db801c7", - "0b03ca2fc432ec8b8e9e0c58b2cead14a112c6234e4dd3dceb234dc11cdfe222887ce1ee270c192d90ca4a369b7b6adfd31ce93b86f181e9e25281b4e8e9535bae", - "0b071247c02accbfc6b2ae3c54720ce9bf4d98926b754a3d5ff054a1911606fc5268bb1839fdc99070b10ff288b192b793a6d31cd2b75e7c479efc418deb9fa3d4", - "0a015aa659a499382f4496e63c92f6f17c2451b3e59383dcad60cb1ccbfa707587f9a2fbffc601d4cdc34ed17a29b3c33be802211f1d91eafe3379209f9c0c0352", - "0a07294da971ee6a1859c15e7799b1a6bf71a94f4c0784d38f3093edf3d20fc855b3f7b3b3668fa9bd77a46e38e44d30dc95b74a02689e7265ef774ac0feaeedc4", - "0b0309dd29d7f2ad8a1bcc5472dfd7810e1c6e0912d484ca598084c735c6c43d16eb53649dbc0756c81f963e37a78b15f414a5fcf02874cfbc9eaf24c9cee24d2e", - "0b091878f0e9a6508174f0f4794d4c599b09c84f108f63ad3af522d47011bd86f0c9f3c4803d377f25294b80e177a75dcafe01eaaa098210de07a0b9149eabf4dd", - "0a06c75b6cbfc76c909ea2db22d6d0d0bc315026129c114db36d409c180f8e8be7162f348122fc6340a9876f4e9a1b96794809b2de415b2661e4e8a9752fd6cfc0", - "0b070748733d069780be944e9c76ce8ce5171aecc2e6a49847e50e8f470c17286a7c3274b7b7b493067b876f7adec77ec6113700693e1d956923f36216b568598e", - "0b010383321edac8401ae08b04f065ad264521757017465784c3f9f5175d62a750754ef6550d77ff40758dec249291e49153d3f0a89a44c1e9fc13b6c0aed2d63a", - "0b005130549cd01ed05f6ffa6a8bc56113f2ab8b0724b06e7598121c167ab8316b8a9b04e49a7ce02f8349ce3d8cc85659c1142821e739fb027f0961a691539c4b", - "0b0261abb9809eb7627efbace9914a195585191b830bc421d30ba48e3aa19bc25ab273d35bb10c3a8815377240a00fd6d26f3c5e308f831cfb3a21cc616c7d1bdf", - "0b00dd16662f6d49b5d1ef7878a70b6426d1dde42c1c94e8e6e680e5e2229a9ee53ba0857bf227aee3c74a4e623d4d209b6f0e911bb115bdc9a262a474c28e834b", - "0b070c27c83ef33a5447dfce9bf3ed519c9af8ad5d4faecca1b8a10ed60fbd7807359dbf0c9d1807eec7051589a5e8bf5120edfcb3ff4d6f6a5807012672071abb", - "0b030fa61f243eee47a256740d326ebaaba1725b5a0d14b3132c45ad9bb5c75f2d138d4adeaf2fa406f6a9524c7147fcb8d52908324c54417be92bd5c1560165b0", - "0b03858ebf70aac0c096eb0b98ad4726c1344e897742452a3750b2b72abee989b47b9d8d16290893b1bd313bed4c2a3ffd7d3b634cf58553b5565fe6b5fd68efee", - "0b0647ff43e7ec21ae1e39f7c6bd74cda7c97a77d16c3a71ddf83d648004199ba479b708028669b39d6c7974209dea2a819c3a7168b23d0588d6c2e96235db59c4", - "0a0479054d26025cf024e124ad0a869eae72224db27a7c402e367086274c523a1ace22589af50eb71b6d162aceb7b6f9d87fc61d6b95445f77d91a6bc3b2d4d8d5", - "0b031e3b2d9ded0f9be078c0894ac3154bcb7c60b057be02eaf85971d7da297138adba94006d1a1d75b58f43f54dd0ffd33ce2161a3d110a40f5d480f9d6995863", - "0b02e1386d2adac1da1f2740114e4a349ad63cde3a86c0490dc8def4ee8a37411a274e933219d540099a0c2506947c324293c45a666f1e1b089f459cf692534a22", - "0a0758d278d5382b0f5535ecdcdc3cb3badf2948fe4492c928adcce0b74e286948f5e65ecb9739237b64617c1872a313fbd3cd53ec959783bf1ab9fc128afcde2d", - "0b04c4be7ac83c3d84ef05008350238dee6a9b6cccd66d890e1183e0e0d632fff241fc3da66722b76404d348ec6801327888a8a970b290039dd5c1778c36c143d9", - "0b02283aab369f47b692585e202b1c517c5383579d1b6b6c88808523bae2d389fc5f17b46fcf35b3d7b44a9ac1b4256d78d7d7af8d1c88bcd10dd8ff5deb69bd66", - "0b0616d5060a6a9716c19523d97f33c9c30c75510450aa7a1d966bfde1a0a85817d586d583fa854da3f9fc36ae5d90f0cf1ea0ff6e71f1e0d409e9168f8065b880", - "0a0064696b334822153377676ca59d4935fb38dd2fba02bd30e20d5614a7b6e751c92c847f109f15d2d27e0f627e4de10808b152d884abc938a37153510d5e68d7", - "0a010c367fc19c1941029ee757cd123239d8fa927317054fa72be7c10358196e9927312f0ca1d6bf01110e8fc61c38d0124e3e9d414afd9a1d964592cb8bc8352b", - "0b040d87ac88dffc28a7b2688202675accf4329f236d2472f9eecaaa032b3b2d6f296414d9b97385876c24fa973649de80ac74717747986ac2c6642cc52ecf5558", - "0b05a573d576950b1d6a99cfc2ae6347bb527df91d4b5b0a372ea014c71b6d56c720246da6505d15f1c011c0a77b554206e4674af28884b2c8354672012211ede0", - "0a038f33eb96f1f88d084d9cb7c7a7227c9f15e5fb0f01aed5c911cd22254331baad33b0dd51b7d13d20652d99c24f3b071a692a2ee9bc7a9959be6acdd6b265d3", - "0a058793c4e108402ba0278f2cccdbbec202633ec147252f2002b058e19cf62d10d72e7e54f6ef5d7a716b6a2591ae92812e27866a9ba44aeec4a1d2f4385ad8f7", - "0a03f3db8fa6f2cbca0c16d9170af0c3db4f514225a8b47bcde359d76d7ef1b99178d68e66c70a35cfba15b0480328c8441b0e1788c4ca5c9cb5b3bd8b6fc6cbb8", - "0a03d3ce1892bbb9a14f713a1b688159a80487ee999aef1310e7f84b70d428e10414e360caac5d5cc9ecf4e467836264c9fa67d86a6c00d1c57d50e09f89d6d5e8", - "0b03facfdd697d36d0899b0f41e4598621717d024825b98afb878ba1908ed40dcd50501b3ddebaf07f8d39b3494e105c89cc2402a6d237550b8147a947d6627b13", - "0b047210cd097e7c8bd710adb41e49ca63d8ec646b2305332df4c8978f9f8bfaaca553568e8df9dafb70f2f46ab0f447fd1b65aea5b592fde790488649d528adca", - "0a00a86d336fd8e810b7a259dd43de3e3316f8d2340d4dfaa45a457e76712d76d0fd3942c7f1f05e82689aa10a86da0a201f715f54f4c61e5412565948b5916bbf", - "0a021dc8f4e343d15ed22ddae094c866508c0e581125596c6f59a8d3e1f210ad2fda8c86b2764879c33c7e5ad3d3c4c1389f3c4180521e37c7da6827720aacd0bd", - "0a02b7a0bc8347f80110f72d834a1e7ac3bf44c35f4e5c028b73d094ebbfbb215ee7e6dbecf40637ea3965007d1a953bb427d676e9d74c67a417af0b36aebb7f75", - "0a05e08b25da60b62a46f77c0c3818a8e59b58a154114a7e0e0de800ff3730c7647f13a288a06c86da9e1ce9196f3151d73059b4a1a8f50cfc5991c6d9510e4456", - "0b0781291a70b747b75b69a766ce3af10e06fe467f05bf47b3224fb1fbf3e75b62a38a711912d5549113cde9380521fa580a9135864972873a9e3f7f0afd7a7591", - "0b077f8eea042b1a4c0ee3679be2e1eed9e3460087ea3f28b064b88492f5b78279cd05d517f5aee91c73c08fe18e8a081641ee5868900879a4599daaf46c6c567c", - "0a0715ba620d84fa6999e9f4b1734f77ab7ac3bf128a37bdaea7dc12be4632794198f4e01480c6879d938667974436ddee08deedad4689fda56bc6a02e9b9ad55f", - "0a04a70436e3c8ef23773c7aa63c28f342fd85844bc2fe526d4e2ad6958bf9e2c808314ce19f54512daf393b61869de676285b068cd317399fcfcec4147ce14906", - "0b017a75da2d9de3d6b601a41e9f0ccf54ac46ae197c600a98920f3e89c0acb6b455c330bbfb0375ccd4e81197fd82d3535acaa40275e46cb0725621ee15341ff2", - "0a00dd58a08c8bcd52c96acbe88a04fa642711cd716a1fc815521d414c93035b228aae1be05e3030612389b171af9f3deb8366779ded3cdee33514acb1ca2cc901", - "0a0403c7e7ae695582d7b10cc41f125ed054e4c362aec3c578d22fa6bd4a3573cebaaedf67e18de0d8979abe9d581bbe597f4a022a997899f3c8842a225f22769a", - "0a01b38fdbbaca47b0eac30dca12d47ddca1a543a55c80ca8fb352d7451d3a208aa0d58cc483e756181df95375257f0acbed27ac79bdf2867eb67dd98229568133", - "0a00f3c3d942d612dee0ce9bef52b057107b66734a3e2b0f13ece65edbef3730fbf4b7557a223a92a2f0a277d937093c5ad9ee2bf2d5427eea7cb2028f494c0a9a", - "0a07bb7a8b70475662f3c4c41fdc4cd63c614e9f01b1a1924f2fee395392b4665b4f0e447b83c73c3cb19e69b77113153170c40416771fc5157c6ac6d05f0bd8d3", - "0a037f7eb11dd8c181974f01890e7471a027da1c7ef70cef7284585cc862d5e5f68a161ed9e760bbcc4274074d1f94f0e6a4d5c9e31188b7dd96b776da1332d61f", - "0b02df3d8ce896f295802d03dec1d32258691be550c8060844495427ae5fce4531ef2428683c6b68786acefb4e0a2eb897efdec93ae262b24d8e2c28b785049ab9", - "0a01489d1e64a1fa7a43579689a5f175ab482ebd8fa348d3330e17434e995ee7c655b03a8c53c283dbf661e4fc18d3b3829aa177250a16d10034831c8c0f70a252", - "0a02b0a473b28dbd921c95f7bdf9cfadb2e5ae4741f38a22d75944c3190998b40042f9c792930648f242e6204de82a7e0bbba8a43bf216617fabd63baac4b98fa5", - "0a0716148e133a38f989893a9e0124373629d2ff5fdcdbf2e7e989fe17f16b1a46868ef95ebe04d45e67309623fde6a1654c87f6e0a4244aac3a72fc1c409b838a", - "0b060dd6f2702593d35465649a390af6df38f307f25170fd53f32a0faf6bb1d6883f58569faf6e935d35cc8a68e6b1168e23fc3b296af813a1e8babb6cd9bcce9e", - "0a05daf6de352a927dd53b4b95b2c86a4702c4008b25b5b017241a0e0a0cb806fdc485b38cf489bb64e083d39d2afd95c0ca2bdd9be0815dd237f6fb20c6cdefb4", - "0a059672a514a3df0e18f907ade1cce92c1a0678c4eb8be1a671e78eebd5be0abd352add1bd5796187042d22d3d8fe5bda66fa6acaad1f643b63b5a6b34b1baf01", - "0a05c6bf8457b1f21863991dbbbc92efdef6d4f55f5d1046dd9180da92c95881d452bd65184da28fdc490466a82377e8a15b5837c54dd89ce04aee27942d5074cd", - "0a059217ca06a8cb9fd566caf54b9d79388378ab024eec4db58386081e1069b6b5caa82acabec813768c84cb86221ba8f115713af7231e757fb80c189faabc30a9", - "0b08e5d885fa9797c47b0542bfb7d83cfde6d0580b01f405ed98a6fa16feb7feddaa5dc559adc815f083446c2acb2af7b5f98fc4723a4f3a0e1fbf17d4bfa47a49", - "0b077255d523555ffb48b8b5af65361bb8790f543810f3a9db84c5cce6433bba2a1690d1806137d7934fadf16eef5196b6f3b9b015805b98bbe815d1229c7692a3", - "0b038440a4da8aaf232e1888b1a58edfa826ded84573925ece2ca131d2dd6529d9a5b7e3d0eb45f63b90d91c844f6552e178e2ee9350538c305a9326778f988a58", - "0a015f35b0528d688a5d3d03066b049aae24527321b6d474411f96f9eb7a3443cb864e4919f173be28263ef63d6bc1023a0115aad717d53a2162d5e8c7b72de0c3", - "0a013be57a4cf95c23a06a95df940f9f6393e1d316743eabd840d15049b5512b281e2c8926f1df55798c91cfd08524cf27f26bc35d7e99912ebbee09889affc1f8", - "0b08af79a2e53b0235bd4ae818f54957911517154df8a93e0268132aaba9f48c6d90904adb5e0d6bd6efcef2f564749ebe5a8775aed16611ff4a0695795572b35b", - "0b00bc66a5d99a9e606976392e91a3f2f7845a220a9196400abbe85e40ddd10a99235e4ece42b1a102378333192d5fe35b8226b6405cb21b223f460a4ffebc0b4a", - "0b085aed4b380641dac72d0e9d76f10e8644d71b20e705d1a6070fecee87a7613359dfaf73c3a7ba614f21d8989d86bdaab4aae6dca3bc83c6bb3fb8e378b01789", - "0a07c231e7efea21435267d4b416be25ff9aadf5b5a77ee5e1d7ce9bb846adb493400a9737451372d8d14167bc7d36783796455381326605e565d962aff552f95d", - "0b021f124739feb08ee940f7c80b63f8ceb96a0e740d1d36c8f9c47141b7ae23f1e64aba3cf40de26577bf22e2236eb865ebd7ce1354a37e5dcc50ff177b301dfb", - "0b066ec6c6b2a9a6c26bd3204134a029472c97ca125c90318b7fbb9930f0e35bfb0cb83663a009d7334792af9e4a5eded62a49eefc6b14cbb6294334772107f61c", - "0a0534c19ea4981c055540efdddbaef2c34ea8e0e9e2ddebf3f6d08239fb9cdd00d375217bac370e2467faad38d086d85462b1348337f6bb57372b24a296e64612", - "0b04a6665ed0dd6d385ad145a4cb4be587f069a7e95bed6d9ebf70dddd7d9c8ac5ea7df86510f65f3fcd3d723793124642d4e5ff6aa5190479fcb51df3eecf4116", - "0b00e16463602196bc3c1d2151ae9d9545f4af1ef1128d65a0da0b76cb4cd0b6337267926c646acf0a1435aa96f7340b41b12d3172ae65922858cd1fe98ae5bc9a", - "0a047ed9e6136a070cca78fcaae818e4090672cf52cf05794efbf25a4e9186f087e51f5fd5f5f5e36a16edfa7bcb5a706db578a1c6e7850f1f6fbe8104b9958c6d", - "0b036f732d4fe347e9c6d9477b0addbe9d0bd657cdd2602c43dc9045d16851d4c0566c9f162c3727b6e470f74e9a213c3f7eb7b11903c11e62b89b228bb24c4b14", - "0b0407ccf17ade91ce179e6970462ed25ed81279c94e952d2991dcab46ec48e6d888bb554c29434eb61a1b911625d865d4000d88428e52f7fdae1e16aae54bfd50", - "0b04edfa4c3d30bed4f51908cc57c771bb393b9135ff6140aa9c6f91efb959dcbb0b09ad15a07f1086ec014ed402f9dde68b4e6e07aaafbde53f435b150cd792f5", - "0b00ae2882d9d6732f44be5fbe8d360d8f6a2dcc907e090561f491e527c591197661d1a454881b2790ed5fa04c504aa507ec2006e99bb8330b4477b5658fea0f64", - "0a02cfbde0ce009bd26176553ab91b37df0ed4190ce88c9106a19dc584a1f81def72c82dd3a1488931b6cb51db5100fa8fe587f410fcfdb9199edd4af6d778920e", - "0b034f15344fd468e4614c6c34867195079ab7232f259a1b07848a654eedd998ae0a874660abab34b2a699501ac9edfb7d90b5592dca64f83a4a71ef1081eb7e16", - "0a03166f7999faac1a7dd60f5795e88619a8dec23b4124d82fd3e6fd49627b61426dd759df9215853f78f182392c5fc93cfd4fbacf42b6c83ffa6410567d2ccf08", - "0b07a0c667df77fc7a382193425212dbe67dc44900452c92325e37ee7ff8dbbd14b9aca15b5f5ed548e1d6460ae34fbde953acfe4302368a2542c9a0cbd82f16ea", - "0b043dbd0ba0e693d728ff36bc458ec64f9a51e3aa1eef641b40786f1dbfef97284daca8efe5a65952ebba9a88eed754fe85cb9c401af1058dba60f5c8d30e7a88", - "0a0223fe20266682faa5c34b431eb3506e8cb6cffd2831002c774b04115cdf5392972ee38e9f4590d0257e4a7e3cf0a3c2d851c43175a0e32c51cc5a26ac3b40d7", - "0b0086e081a2665fe6b9c7826ecc29241ff9bbc67083dbe3bb5dd3dab5e3179812cd00a8bd0abc12559e2d8bc900256e717d938227cc4758f6e064b335ba13d857", - "0a03f13b5ed7c025648cdb0d1e44adb0fcd4869247941354b1605086101f9ec4fe6b6c62d212ce2a2f71e212572b1dbb3b8f23bbb192051e3ee4ee2c2017029dc4", - "0a01e24870363e873e01428576212534788889a0f05f40123fcb163162d948b63d8ace0da57ea0fda18c4d1b9d692bbd3122551935830e35eaecde06a9a68aa049", - "0b005d9e882b68e656b273b1561a94cd8aca364c7d6bcbf732acf231729149f9a4ad70bd47e6d775c8004b8ecc110bbcf8c57b9c31b724f88d560f8521cc4171da", - "0b03d28bf84c04e3c136baa3340fa28b5e5a423e42d048a1fa772fda32271af5bfdb3f67a61c65005231b5dc2d7cf0f42f1b2232b59d67033e5f9ae34f60d8d719", - "0b0491ff72ce169b0a657bb57a025af659cdc180a7c2eae43d7538a57df7888c3d77cba910b31898dbcf00c3c8c2ce3d3428c70379b2cb95cd566dcbd93902c022", - "0b024e15572c906bddc4a1ff54b516738d0934399c11abb464ec363687cfc4aa67fa42cf30c14dd4bd55f044a15ea16966377065c223c2ee49c2c5baf3bf3c9193", - "0a058e162d7acee78587ac576b5480f6b8278dc754df37f80ca9e7b3c55abb32983cf230bba977db8268f22be97dc31e4b5e777a8a8406a1c356e89441379c8bdf", - "0a07c8418cd7123ae40916e5cb080cddceafd1674898e1c411dc3043a00231e28777bf678fc56488578ada06a7d14100ce317fd1d933bc58384c9b664ff626bd33", - "0a03cd20fb10a42ac7c63c05d4bbded1d4bf833f7a7047e79f15a5b70cded9cdb2e081df0b95e409d7266b964b0a7ba15c557d5117f8f1571c1dbe43838f728c37", - "0b0189b03d3c0d43d2bd290dfe39753d41a3e28eee386356bb787216cf94bb90127d7be444df33a8c1f6b3ec668efdabbfe696b7c94904a7f052adb55c7f6ffbe5", - "0a04972bcc4fa5d731d05aa42aa3fcdc11be6e20b27638dd2c578f17ab6709934aa1bdbb99c5cff57c0ed28cb5bfd51e2c756b3e27f904f9758f96e556de1febfa", - "0b0893b2097e85db9edf9ea4cc1f706c4ae71798a952910c615787b32f5747ab67c39e95f07f190f64cb29b7b883eda44df6eb0a1d805650e7f92b5fbaf8801394", - "0a000147483a1177c773a132174c35726b125e6c1f7012b0991d594ec4d85b69bc7ff549a09df0db16bd6c0535740a9a7a3a7ebf64ab41cecac9651a1f1ad0ac04", - "0b0453e69b21ab30162df6a615add988cd61e6233c6c7dcda2dd98deda3f9d71e783e80ff279f8b3d760b9472ba1b2b46d8ccdfa9c4b4217fbb880cafaa38dbb6b", - "0b07046313b94b4b3c4d1519dadda554a15492dcc9a682f758771ff2b73b56587e479ba4d48a5db87b642a1826f4abfb8b968f4b6dd32abaa26e5e7ce520ca1314", - "0a074d1cdf5687ae79ca404824c5ad074e58ee8699c67125df574fde20530567b166d91e150b257c037f8ece0e3bc0866dc8b6c1a7dc476d4f3f9bb7ae4ca62683", - "0a01191071646ddb0584f3f0fc707f392f048e2a76d84f8d724c9b9fa4bc448cd50a25ffcfc8c895df5e518e46114fa3432e76c0098c518563af03df23e41fbecb", - "0b032433171cbae6ccb41920a99b90cf765ca3631c5585982fab2599bc90e8e057b654b3a6d5d2eee6273fe6ece7b7c660a6b10f1404da59ef9ac1fd203b59d225", - "0a08b9cfee7fb85c9c52c29640a4c2b5f80c75442544919d2b43f8ae315e529598d2c7ec6a10111db547c29a9fe48ea35f3fa76308596a8484a9e0a504bfeceb74", - "0a04fdb3142831338d84abca450616b45a1399878dac29e1c43727562a6b6da88b860ac43e5ff461c1d373aa306df61c83ee3d4f4be275d731598213dd3ad5cb81", - "0b057e649e91c1abe62511aeb07682a06640f1300539e9e123b4ed1d127e38665351aa3f9b26472d1e27c92a5cc99d98b934e0a08a3f354f9aea862ba1a5e276a3", - "0b0902ee18c4c59cd11c392af3d8e2374d394c2e018c94c14d60166638d5e217c7210733133b05e0817286e9d29c5877347e55478b7857ada558d6832ad2e7886a", - "0b079f150e4b68934da4023c396c65b39a4d5a1d16fc24b67397476b93a6ee71fbe75c3d5a51caea89c75039c84d5509214f6e6ba4a3ab076b506c5fbf307c3427", - "0a08292ed79230d59232f11e262b21e66164744b51d34d33097c80d1e13637619a23515144d59b99ece71e5cce8b81035347f73a8a363a7ef805b84a5d3ff0927b", - "0b05ddcfb57ce44326ce5a7c65886ba5b5dc589a04d4c6e1157149252933ad14105f48204ab43488f97c340a454aa567a11e670037a015523a5be5d30c4946b689", - "0b03265649f75c8e0e93343dc91ce70ff46b77f2ea70b5a9f2b4d00ad43262cda00bd408ce071d2c45a2f87d33b70ba1ed870649adb7d9709c2dd900c1718ade4e", - "0a015d61520bd061b3a2b308b0c64c9d66c24c444e816bfa3be4d04b32464dbb1354262b97e11f1a45f2b6012a462c8795b398e4659c0dfbac63024722d839973b", - "0a073d89b4b4eabf11d1276db4055bafb0a3ec0455f3f99c32ed831e03458f35e70f1a14182cbf5e78181eff6ea643937b5680f8df1de19bce2f8e0574dc98f63b", - "0a04a579ae0682994312b63732af32f42845c05dc5d80d2a3fce4dfe40b1846ae9c066aff52a6fc40cda8cc4150696fa97599101c2c126750b880a98df28bc95a1", - "0b0905757dd9aaee8c074877cbb49be8be903df84fcbdb07ed17f727c8d5f79bb1367a0a20204341b50da4aaa14637c87bf353b5c65a5352736a7d9db93ea39aa6", - "0b062c02b9938709a8165756e0eb712e14cd2e41692454901385de407c6d8f5f402d5bb7789d0c1c3eba56caaa07058817db31dcd619e52de707c82f9cdd8cca73", - "0a068ef7eb39e6b77fc6792fec2ec5383d1a4f215ce196172deab559645c6740da454de6b7b50c41c058797ea92c16948ce21754eca7dea5b66fba9b8da4956da2", - "0b071e832944acdbb9bd603f66f5ce106cf941242db8b92aab2fbffda049489b4d24ebfe59a4b3c83ad874e0036b01b46215b4262651f561cd8a8e4de4b668d75e", - "0a02170b6d276a4fe4bffe82b1547069da2f936f503250396a96b740b5b4b1ba4d7f1bc0fc151d1d2b9508c929f0fe0f9b2855b7f2b777ad0ed03af30f1ff3f4f1", - "0a0044e6e22b1ec18aab682b09c24adcb736610f947c07dbd0ba9982b7a788c1d5b048396a1b49f334e2a5585f0eb243698a0b7d32b3d693ff4600ec732caa292b", - "0b033f66cea4da2c367d1fe080be0d864ab5142ec941322aa678cdf8553093f5148382d9797130e12ef064c206e05c9298806d959b7213a863e6ea04b0d7141340", - "0b037b70fd3b6ad9a45f08fe6036c244185d48545e5f0256cf3d17aad48976fb8dac778be2790f30603be16c29d25e0572f40622de3038c2e70b89e948b52f0035", - "0a00e0b6dd0c25572227517fe40c80ab079d43c595fe4b7dcba8c17ed36af0034a1f4c10a7bc72eb79872a377f9ad98f8b448016104fa1ed79197e21fb75c77ad7", - "0b07550f5e7046047ca9f6aae86bbabf3f43b56922b7fda6c97442be000c41a4f93eb12147740965c8d0c6e6facfbd7a28839bb6e6aa7b28b8f1f5fb979e267299", - "0b07ad3775b1256da6bc61250ea53c177c4af34dee25f660c3e59ea1ae5dc94dcf795fc7baa2bb61faa1caaf4b3101fa13022b149de619ef5aaf921c27ddda69f3", - "0b016a8144ea69d3d8cdcce2eafad3581a0456b74010b4b9277e37a51f53dcff5b9d58738c3e59fb4e602e9d7d1fe2f404388e86237cb89a41b54ef568894221ab", - "0a04a166d3b7443058ad7ae99a6f50d3657222959fce06bc9cec937112ca9da55085342d1d4fe404e7af2e35dadad7afd9389d57ca246397f4902923e0e1dd49e4", - "0b07b97d8d14f2bba432ab10b64404ceaf4877e866c2153c2f37905c8a86849758d0e050d101530b5204642b3d84f75ee21b94c4067cff463e87a6e0fac319eb7d", - "0a035c4f7a0880fc449a515de925183b037480dd0fc995569f8d125ab5dbc3e4236a981a021af52ee522b31f29fc038175fe3f37f77006d5cf38605fab52138f25", - "0a004bb51936bf91f1fc58e911ece03a1472a57d698a99d594a4c9cc6a443bffe9eab37655bba60da51cc38cad27eaf4d816b7b2e52fa62a0973ae1196174a007b", - "0a06283f778798e5cd6404bc52887a7323df9f5267945f9ad8e34bc87d60fd5640049c2aa0e090768d6b1317442220398576f783d8a84a08c173728a7a0208b3bb", - "0a05da324e571de70f37e1d607307dc977abab7d09e52f15626661bab746e38c56dadf6278ca6dd6b6b205d4894727098a3b272fd877c38f6793ff9dbd5495c07c", - "0a04e84c306b0b225122c2e2dcab9464212bd6407c0e0a997bc83d9ae626af536a1cb1c20e5a5b0fee2f7257c72370a9c10d87497b539afdff60f35b50a81c27d3", - "0b03358aec79adf2cb6c4469e329bcdac81a041ec01e2531bcfb58e9663c970c8c37b1fa8e8e9a824e77fa60e793fc3b90d2d938e26bf45c6da9807a07c60f2b49", - "0a07161466be2fd215e512592641d18d81fa282ef42095cfccbd433c75ca36900d4e258165a9eda11eaaf98c27f81c84f42b3721d0766a9f8633b4e057014dac66", - "0a07b117d7f0f044f43a1c9256861f9d432a63a389926ff491891427cb86bccd614e33bdedf4fe0357c1d0eccaad736877fa199f84a756f6dbf2cf6f52d410094b", - "0b0013f9c93549bc369c1677a02e76d35408b6bf35d71e277672e5d27e039aa26e5a58412061e95c2fc5b89441fb77f96e45159e8f4d27d046f3eefb624c736f63", - "0b0373ef9b3deab5ae2a5c22d28cc7fd566474b8e6162bab34f6547c98d3536f90d28f2fc0bdbbfeb5ab340655205bd8fdd6c600262dc888b9c2112587475abda0", - "0b0794d93b102014a1ae9c9ff9253f8b37ddfa9764c73b8174d45e93cd67e92c26948998b17021e04ddb5b679b9546d27611bc4519e83856528a6c9274a2a36e52", - "0b0152ec5278b95c90bb3fc81b3210451f9cc7e0efa331646afa4b019d67eaa1148f582c9017d65b08eb2ca88c18d0ec5c19a8133250db802c88deeedc7d8cc2f0", - "0b05f4e3b7b6feec68d4cb252de78dda60c218e6b1c9eaa1d7db60f57ea7d3c420e128ca1e663fc3f9107655039e6671c0863eb8cf28cee63ba32f2f82b8eff58d", - "0b03682739b645a260d02f599aa241a700dc6b000c2ce2eacf19e59ecff174802d8a0d5958d4d679e68a1b3b5207aee4598a7b416e322f58b86bd23677ce5746f5", - "0b073ab6e5a5389cbe9c12bc2de7c2ebfaadab41da1212c0bac856daa8da856f54bd0310c40ef0d233f2b37df5e702383bbee4f03a4596e4fa7b2a97c921976669", - "0a00891d35110726c599265bddd4b18a4912b1a5ccd66dcb6911b19ec3d0882fa5b0436740a17b420c23688f82ef3a9185d49fa0f4ba067810d4a721a103358fe2", - "0b06d52c0f0a30667d781ece107779af3fd990005b4876ceab0120e1d053001224c147a5bc7ff4c4574966de0849ee6dcd9d6fade815435de4c4a7f3fb7b645d49", - "0b02b5234bda48db196370c80977443d8bcaa141b4eec03477a33417bbf3df6470dacea34f91217ec923c69794fa71ba8a54e0b6c1533935a5286cd828824b1e9c", - "0b08279f70e73d25948923c9aa5a131eaf6a78b24c1c400a803fee124c80dea2e48b0c09e488d8ff1a51391549b7bbabc9f85bd75a33d6bad32295830525cb2aeb", - "0a01f65db3213b0785dfbd5e356e42de927abb55498158428c5458e37d40476d665eb802d00486d3941240d69f7fe904bc3423d1e472f217226d1f5b6c8339671b", - "0b04c6b1a7d3b27d0bfddaf0765c068378da17f79a65e1213249f630551004b83c1ed548f5ee3a0bc42949432cf6d7b40aee18a27a1071d39839f8c48fa8131011", - "0b03b0a206777826a496fb2e6ca803eb269bac786f047a3a2b3c059cd1df0315e53cc9bf51006af4b5e7961f96d6f24c245c24598c42078718a56aef32b4126fa4", - "0a08e0115b0936f7fbf54c0264ecfdcd49eda2e89673113cc911addcc9c129a27cdc15963bf6f2df8278988199059d17e2062a4231ce0b39fb306011e2b65373fa", - "0a053732922987f1d1e9f931437523ba229553c97c76f22a97e21af1c4e1fa90232e219520ab18603d0ce2a1ef40f3d20b5a22a95c3bfc8be9495edd246533293b", - "0b08a3cdc9738ef0f61378be3068c9a4f35d8a991d1115c15c3e86009623aa97877e290131055820b8c2cc9c81f4f6cf3516e442a2fc617d5b7dde464d2be2b2ae", - "0a065db045780eb6d1299ed10ba4275be64ff76bf226eb7b564b038cf84a235630eecda81a6b1300a95ac64628526634c6e8ebd693dea420799bf787bde22b0092", - "0b05c6fba9acd303f2580bd4318a5bd2904e6b520962c1ce68c08f609c72a15d0920dd53e2442cf43a7d14ba4a614b39aa1a9299949986a908a87a9dbb816aad79", - "0a01eed3f26ce8d13c2e41b2d3430bf16dc50c00c151e64ad01820c809553e44d62959bef94063cda13b67201703fa93b42e34718f1f509a663ffe25d16a172fda", - "0b06248cb81e0abfd1b7dc3b998e3d78ead8e326b3587f1ef361f21d8c77f94ff80212c23b3bbda1905aa9974f0cfaa540ec5aeab21a75476d8acf260849df06f4", - "0b0830567b67028ddd57f26babc4f5272c0e29db8cc61b38d820f0ba19408253726867ad4b522851796c2748054c916c07eab6ebf90180b965571b5417215f0dd2", - "0a08b8cc21d9e2ab650976bf2eb152b03842758a5435d24025481c4f6f180d57ca8fac69397b5aeb41bb6d3594b769d36847a04585e33fde8300ea3b4e28706d67", - "0b0667dc3c0077246ed45207a7213ca019bfc83f3d431fa5e990ea778b92b4e3884131a2467fa5f42fe1ec595efd3f3c5130d45b55528bba3da516e514479db7c5", - "0b075ecb67c573a096e83e6484730ed2b638bb746c6f3782d950eca7990e3dd604293f7d209161e3d459949a548c9338ba5a23e5b0dc524bb16314a127e8f5a8c0", - "0a084224bd2cbf4f0d0e0d2100b52e480f51e7a0ddf079dab6191554808db819347fb7d3173688b117f03f1a46250a2278aecff9c176b717ccd540e88e30032837", - "0b03f63abe52ff524235b65349a1d460336d66be802786e3d52933e8b0f7ecd61087f3ec294f4d3fc692accd8a9f6d1463a81ee956421bea58e5a056c4ecd7570c", - "0b02ffe3c65f9dc286683d98ae2cae173cb9d1e9853626fb60fac8b9853683a2b673d2054c6ed0507184750b3a0ee497dee5d2e3dc0491c3cc628182dc4c1b49d2", - "0b090ed0a6e82aea6d91a22b929445f445289d845967d1a0ec8f0af660f73aa22b1368e0176ea0897cac572d885c45dc98b7474c71f8f066192b41ac93be6bf905", - "0a06f9e406ee876b84d4194134c9d388c8e8e7f622b0dabdd9d5ee4e53ef11b791ba87ad060df1b6f6913ea8034e6719c23d5af2d0fea115d552bd12735ffb416e", - "0b032eaae985db869d59ba2b9a4ddfb7bec9449962340620698f420cfcb1e09ae3b8206d7fb6fc50fab8edd9333481dd5645a3a1202779ec2e5b7a16386d4c37a1", - "0a075df5d90c17f39da58b9ad6fa5b90f241f1a6b650d5d05f7e7ced49f70cdffc6a00e0660b246cd28327ee88193685047fbe0de911343558e23aaa189e5c23bb", - "0a047c01ed993b47ad1470e6247c3b72e1e680d6a3b5214e5b80524fd3347a76bac94a241d4e3ef5555d73e55361b26c8b6b98399117451f82e7991ad9fbf8a4c0", - "0a065faabb64511286e70302c65b30f74f7cdb361cde9ac5227bd42329b2c9ccd69d639c90d4748dd930fae4bcef6e871b53708cafdf375e7ad698f8d68430f041", - "0a011939b6cf3b368c42bf5f3a48110993240c0969dd4538084e6e43d737e14f9644c510e45a4d680ce41557bca735254a01cd25128946c4a677be8dce95c80e54", - "0b0645f41cddcabe9983181464e6ba19f292f3703e19cdd7a36789698a1988b6d6dfecacb24593bd0096bba3b92cf37ae9878265e3bb719b4e91548ec60e4f95fe", - "0a013dc5e9393ed0881f98a0639b81d3a45dbd24406dca47d2fc40e28cf24c3f43ea9c982d873766204aac0b70906a9dcb4d7fda4c8abfa02e69a9bab89ee02826", - "0b0132a5cc379581051151659210d797eff791253ddd30dfe5dc3d2a0b63da26ca60c49880a0142c0a8039f149472c743341cf3bf5f56b204ccd4acc9a38d1268b", - "0b047fad505b473e972f8039d04fefef7ef9cdee0164bc800d1019c7059bc2201089d77b15982425308d7b45a64604d7d06f93925f00ac4ff0c58baa7decb2cb99", - "0b005f21492023118a482c39d05670b0d4edc863704a8e6e5676041a3eb624c56ddf18534a0326ff419a4f1cbd050d723495a3971e6b3cbf540a245d11307949a3", - "0b01a5d3d76df938337951db9f530044928b40d84eab158a371bd9c64533463e2e7df4d6a04212f67ba3efd30c7d702ce8f7e4c17a3095ff0844856982108a138b", - "0a076fcf53118c2b71d44b11a8c5997673792519c828642b3bc79b5bdc4afa176afa15cfe06096f7e5f0fe657d60e3ef9d2903127113e20fb6273e7197d946477c", - "0b013b30aa7975f9a74f41b88f579878344454711cea8576903011bfc06193dcea840b010519dfd00a5c9cd30c2d2b2016780e88a7f6a7f26692c580a5a4490d5c", - "0a07a31df8dd344a78433ea794d9b0ace0e8ac771fb7eb003b0283beba5d2be50a73d4a974aaa6fd2bf4c0150676417a4dce204f72f7d66c5f463cd2997d04a741", - "0a06b5ed432def80e63c34f5e1583036f8a504c8b523f056722573b353b4e9e8b6d284b23671da918ede482fe80c40c3ca30abd809233c551cb9067a68f18e0eec", - "0a0602412f9a9b1560d8edc095ccd61d10e5411bea6dbe7da40976ac4febc433b12f3b10ae009ff542ee07f30b4895fb44e9c001810002f9618055dc05726f22b9", - "0a0382090d0e31dc9f2af2bba656cacb9a401d7192b6815d9d30968948f7d29b314cdac761b42c6ea5bb6d2ee12d1aaf3f62031b2ab31195a25bb45ed52773ebfb", - "0b06bc8822f38f8d13a3e4901404d915b9a63ce0d0564600ace61476b0c8fd76341c794a155a11b345c6fbb9a81cac75777808f1f8ef2aec2e669aaf953a2757e4", - "0b080cda0ad281d026473387932b5970eac4212b27ef52c4446332711e69ed3deba454900182345529aff864d91b908a0f4097723c80c32d54621155b9f7b2547d", - "0a0717d5e39d79bbc72dc4a70dc1b0cedf7997691c81dc258decc31112aa1a8daab4fb575877f01afb9c1854ea1b1263b17b5452936ee4c0f020ce4b3cf465a340", - "0a007708fcfc7cc595de6e95b269ff2237b939103e08744e9293054e4c9200a90153d6f609f1a14a4ae952be1751e07412d4ecd4db4b73c8d91bc94450b3ce443b", - "0b06aa66fdbf76ba1745be3ca7203c75afd823c03808050f18beac2b4426ad6ba6e623069f68df8c478fd6a09fd76bb160bcf8d79562f0470192cfe2f474860c93", - "0a0757a9977e27c1b3c03fee6c7116deadd4ba84880737fd265c3a23e54c06003a32d474cd7d8f3859e85b9e25e45a9d5f2200c1d67e699eae0feaa6af68bfa001", - "0b0490de4411344999939cb0d2fd20df80f964ca6825944639b45f6621c0b8f4a3d316f5395540c5b47457dfc540cb925735db21598b996dd32af7bd3cfe99bb41", - "0a087fd1aa50a631a91bcd049197237eb4774ab18621b48b34c3e93466c7f661f1f7c193b0f12e0e1eb5fae2f1e034b54b53e608910fe6703f7db29e1bf16013cd", - "0b06a50a21eee723a4460954dafb322352d0b52ed77e21bea6c99abd26a2b07c15986b83c69e70d58848f2db49430169c463c4cffc017e1a9d5d582ceb75b161fc", - "0b04a8b6b0b1bb375175447fc281ac1f9f074f19d48975f32be9ba3a3b79e75c56fbd648f4ad408c1516006825078263e92d6e50db2ee3de75b5ac739bf175bd6c", - "0b0754a091c32c3b4a77c3123aa8e915622f1b1a98c0c4dc124b519d29390b097acd21ab1914a224a390866d3abce9a475a91ad3e68c76987d72508aa1b7823f5e", - "0a04f5950a1aa2c01ddbbfde4ab5b6987e4e92f8dd99cc7bd5e22dc18771b5c40e47d9a4b48cf5ab4aeae2d7e685f2f1d27b482da947a336dc37d9ff7070db2f54", - "0b086b36a43315d45b775386fe8f545d757ffb6f3d4e62dd71ba48299377ecb6baa60b3cdc0d7c24f0c203d90562c693a1e0e50ccd2eb8d4f6e161996291ebe0f5", - "0a08a63199e99a5e4a6fd36d3c810b49f44c558a4008104067615201a06ef6498e1eac29eb98824fc73910807b08999c0ba50744bf4585f2e881b01969eaa06851", - "0a054b0aaea5977a2864f1fc144f6be36cc448f511e2766ed457c586ef5fbc070df8cabc1c328969f62986bc8d3bd1fe938ea3f0aaab6843bbb438cda0afc05939", - "0b021abf33534b3eabe72a3617fb630b0f71458040ae741736d6d83c69419cc818a97540fc48ee7d5fb2355a545b85e5f52b6810aa5076618f86cc0851d099db88", - "0a00be3c9cad4a14440e5960860d68c8c761694e5dea1635ea268aba84031caea435fe45532f76452fe1bbc6639c563d4c2b1cd2aa689b484b7636ce0bc4854f44", - "0b027dd9379be7134d3da65fbeece3cb4f8525025d2e542a0ccce477160469590e8a2911dee306b16dc6178b1702fa489e5fde26deab48fc7b5e95da6a05f97c30", - "0a0042eb1f8f52a83606000495f362eb70e75f16fa9a40d134bd6f65952d335bf6a8001763dfd6e1c67c053a1800fc31e23f534493b92763cb847984d14a9b8cf8", - "0b024993221be08b849670c049211345245a940dbbee62db678349d7b7c7651ab991752f7045f3349f0e35a5cca739d706b7cee4dc406e9cd4a5e96081ff7f9d6b", - "0a07a07e908151ef98f4f293c63ca5306c221f55e38dbd6b9775d9239901d9047640d441e55f27236d2c9e9659c17af58f34991891b9abab11d961822078f19442", - "0a02de66e52bdcb05536088ec7a13a45d6f6a66c504399b9af5aa0ba337dda325903c66a043c878f5bbe96f52b947ca72a4a2443f8b1786e89e55c36ac5911d98f", - "0b0586d27e3b599dbca392cf51e75f0aef4c73524fca2b61ced233dfb28c8e577325769df1a24df96adad3acb07c61bcbe477b7aa2252edd5d5f5664bc4f42ae34", - "0b08030e25f0b6a83b6f8453e50e430166eea1034b47e3434e9cc6951122143ea84c7ee327523613f833e326c34294a376c72aa1123160787a6df37d5a825ffb2a", - "0a004db2d592bec10ee8c534b70cda0387d9d9df8015c2b5deb17652eec635416f4a7d40dfa7784a7c438a879d74055d927a785700eb9365ff4f222aaa686191fa", - "0b087c8763833d58d6fa93eeb649501c01fd104ea41c2ca890e785b69b27a1ee4f7d783770b297ef8493bfb113113d8374d79290dd9eae784dfbc2cee8c70b06b3", - "0b08c56b50db8d1a07a40219ddedc32c824fb6296ffef6fb49f20152064e84a7c30e4d538ba80825bdcbcc58dcd7144e29a65999e9038e3f675ecb207075e04147", - "0a03a350e43349349fb0a0cd21f15de1a1766f91438bd76d80cce66a37e9dcaeea305b1137f4908f00c43525ba6c666729bbe63b73059fa7bd7c56bed2ce331e58", - "0b0327fddfa233fdb39a53c1144b804fc3e2cbc65134d7ce745c7bab72dd3a08387f47787db37019bc063496d28957d9084faf8158386d3b93d0851408085d96e7", - "0a0707579cba4182832b562576fd3e3ef0d08b9a8f31e155a708173294468b65a1e3e085fe0e8396a37cb76464d43b74720b3862c440cb12123be1508bffd20b91", - "0b08029d07c49ee071723fa31b2871227291668509f0b0093afa7454293f34920629e11ebd13b5472507350a2220ca09609ae9a5654fbfb3018a74ae3114c3f6ac", - "0a0702ecd17ba02deaafcd1db637b211070c7590e68cbf8e51f161b7df47f6c26e99de2d3dc7009b90e54bdb3fd12450a440c5d399b7bad072f8607b2bd73c0c24", - "0a06e67c1d0a981d42f1412e5e36b62fbc96363378d08456d46e605b272694e272eb62d9c210760605b46598ddfb64d64cf01c5fa927eec67e9d7192440327772b", - "0b03fa76526899b259a4163b2403794f9d26136d9160fbca4ef94583f4cb95e6fadfe9ef54629c65c04ac3755d15272d34740bba0c0d025f38f8f33f2020190de0", - "0b0136c5462e7ef146ee402c9489d6322ecd683be3b6c4ecca6279e1d99585ee601bbe026c5e814d1c69750563c230f94bf9430ab660d2cbd65b9bfd0b4d17b35d", - "0a06c6a50833340621628d581ab5421cd9889b41927289ca063dc2b2f4b694402bc5913c472d564a5328cf71b6963802fe8fcc490babae9c5ddce6d8390a028044", - "0a07abf8fb018ae9306debb5120f9e530bde0f30792952164e0415956c8cfde7e1fd97d1efd2814f57a207835e72d0eb7fecf857773592f0b1ec16c0d6755455f6", - "0b0132536400145b0d23b41544beb1b7692681c04b52222634ebf7b9f41c06df305c00b7593bbc49238c052198a846ab06dd12e2419f23958ef23e815755e22283", - "0b01b1194de08058ab29e3590c5ba33976449970e5de3775b7d3fc012ab17bab29d7cf14740d2366da239fb65dc9f910e32741bdffb9d52c4324caf0c0ff6f1332", - "0a060b9e4f6456606e38a6b44bb9abc6b31428b845d2aabdc51b523e79e8f1ccc24ba5674591c2ad1ccd692188684be73a9a0c7d1b3f5599283510b690022b4b25", - "0b02dd64fc8b288388dff79782fb707d50e234d726d5993d05a3c98b1bf1b1c382d5a1dfcd143b3ed7bca372c7764e8f7ff13331b22982143f5c47ec47cf6225f3", - "0b040ff0d4957ab8bdce9079ad692e11b831bdab85eb0338333f8ecf03cf6a54445f405639b561b37a55d95ed2173878e0797eaf0520ff7ea0f62fe7feaa97fa50", - "0a0756c4440f93126dadcd3cc2b0c33d0d4a4479cca6f8763f965fb803073a8b9742995588c6601adcf2cefba3aabcef12701dbc35f9b78c2a17f20670c5e53574", - "0b06cfd77ade0f3626d80ad95a2ed41c20d89b47f64bc7b46fda0789fc73c608ba29577afd744c4d98574e44b25cb566f0282b978e2552684034a00a654829d78f", - "0b022b75d17f8000abf8db8412969c0bb272c4abc176ac128fc7431ec0480ba248d4a360a77b377f3656e53f693ce181bbc3e9501541ecff336112799265958f24", - "0b041de99015f59bdcf1c32567b30110daa1b5fcefb7b8d676fb29840108ed0c5488494de22d6611ff73993ddfc8cf6f199ba5e5267fbeb7d554efbdd66f0dd46c", - "0a04bbc700bc9ac23e3962d519d5ba462eaf61ee0822107391e55635a5911d22c207b2042427be65576561293b0d3868dce54a0c2a1ea5174bfb9fd73faf01bcb3", - "0a0710ed5110557ec7af7efaf0b8a9e0db81ae40540c05d11b9ad45f3736e44da8ea0deb790e43c358bd47bba0ed9696efe7e9aa42adfcfbfd9bdb38607a77c1a5", - "0a073911a1c3f508e909765a9c9d501a8ffa28d27b31ee1eb8147f144fa0415eff33f34f9ed6dbadf456bcfd771e5fad099b1139fbfe259618e293cc5f03d0b2b4", - "0b07fd3cfb6aa31268e77aeaa3811b3ebe15ce0a212d21f91b864fcdeb1c9880f1bd7b896875dcfc5cf30e8798c750410545fcb6ac3c70dc7065a48b290fe6c985", - "0b0907ddb5bf10b769a9ca188d121edb2f0fe68bc278f24a5af7e370556456db6896767e6b899a71de9a6155d289762590c7659aa465995854eeeb25bde797fe63", - "0b03d0ecf5afb8c00eb2d97bc1b8240fdec635d250bc818d24f55f7da7ec9c755d5fd1e11063d9b39358f02e218c61220fa5b78a61a3c1ff66fe2cb61fa6f6f225", - "0a006b62271a15f169a059330d59952c40363c7892b7cf9755846481b24066fbea246d2baf059146ce6fa292c31f5184ac1c3ff472f2044ad380136e19f13a50bb", - "0a07dc34dcac6333a68bf49ecac9573243b43600cea14f4320442d2853ac1028182b5c176b4dda16edf2ee9764356397058da91140e42abc40c10f4b315bba2fe0", - "0a02bf380bdd726e780a56ae8009c7393e5cb81decf6b1d740bb55062e34005287f3c49f4d30872339df8e9ffde760e3a0d6edb588ebd433660a5e9fa7f0b69ad2", - "0a0318c7f6d76bd6487488625c7dcf259f0171d768de3b3b16487ecc01d6aa75a78d806e080b713bb3d3460049798df0fc8af353d537e6c678f306aa0b440cf05b", - "0a0619512ae453b88c214ba6f6aacbff6d3573130068be7b827baa88a36a48ec68a8a66473d0737bd5e1c0a91f547e0197fc74a1bacc3450a949ef4d978d1b3dc7", - "0a043dfe192aa0a2e17c5cb76bf005eff17cc8f317ebdb36bc915c3501b5fc79a4f05fa67c79d9b9a0a001205ccdcaed2a88b1c6c2dfb8222dfd2dd8036c5776ad", - "0a08ce67d4ed797b55f676d63f835e9d80fb09a0861ab48daccdc013fd08803181ed7dd31fd45f60d978ef5b459c0226945385e9513d3382c2a8e2fec22a76f6cd", - "0a000af28c499a948c0211f4e7807068dbe48788848cb8cf9eb780f255d9de0d50b92e46bcabee01157ace8c6a8f8225f25ae63307cc3300e8ff878254817b763b", - "0a0196d8cdd08f640ba8df321afb144abf4988106236b56dbebca5d486a3691fa6995a172c478c281d3da9d7c18ce70be11f40f244859486c20c7a4ebb5ce1462a", - "0a03b013c2904c41fd3e8b6941e62b90c3f3d7132e5e8891d4da1b0b18156a97b83fea0fd7b479132496a16b7a4985e1f7d52d71e403fc07a5260fe5104599a72e", - "0a024e4050fb89b99d06a800eea935a9d5ae9689a7b7f0582898b55a391d4780708a85b2828424a754cc31c4f90844bbd3b790dc98891cb7b0584b457f211faeee", - "0b0057c61efaa1eb7f3ec5b193872145ef359be20ee1871cadff59cba16e3b066631780366d67a85f64244aea7546f482d6315c9dc6e48a0c87160b39180fb5aa1", - "0b027567f1b0c6f7762897cfe39666d6420813ed811b3314781c7f4dafe137ba70ff5405efcbae2996b3ff20abcbb54b4e2fa7ee28d8c264efe98e758f907bca23", - "0a07a3a7cd81b753dd086002ef62b001efe44d1436b058240c893902029cadffc4a64cc0565bd6e687b67a5eac802877b7d9122ae8fcee923c885186d42e958904", - "0a041e274cba8d3abf45e9d603416472cb77da4656c0fa1bd3be11061f2c6d527021e3f79bf97814b78ccea289b421adc285b05f1a9608cf20db790351be676172", - "0b03dc702b38879573f537d46078de4df0fb1d550283753d2976c7f3bc73bf2cc5847b2092dad67555f732956d4528aad2b69c753785d2c058529b6ceba8d5dd31", - "0b087ff9b64718203346620c7bbb779f49937502eac87b46dee83cc708192b4453151ba3f8ed947c2467d810e6518589b7c0b8d5180934272ec8bc9a955ade69a2", - "0a072631e06eb247be15d6c2fb121679e3f289b89526c643f2a0999725773e2ff47e95264048816018a1045e4308b22a6add840ebee9845aa5aca5ae3c823cb63a", - "0a03bfe00d75ed0502b5e47c975ff4d47b2070821ca047e89001b23b692290f04ed5b75de97cea7c50699b5d742eb4089f122d10cea02e839a7e4c1aa0afeddec8", - "0a060006f3594b7de9f52ad31d4065d5f67845e581ab06a47bb70c4fdf49e909c2ea48ac03097986cd47ed5bc0f3347c03f9c4b68732a483534a11f54c7d7c5b25", - "0a06b753febb5d0c4e22e51c982d20949bba4e163a796d23d3333f85426ddfbf24652060d3914004a3e37f287def1da5218cfe044d5efc2c4237b09c1ff0db4552", - "0b0003f48936097093ea93743543802e742d5d698fa1b7b50b80da95d83f94d0a57e2c167cd6a967fd832a5b6b8ce13dfcee76997bf3b606d08f8aa6c7046102c5", - "0a03ad972ec76613d5f5c8151542fbffff0403ae520862c6b3f4004786664a5e2c89fbc2c6c21c70f13bbd8b7575f56a437d40fdb975d7e7f8386c5ce70649731f", - "0b02fcc02d79fc5d9e3f506eba1c5d62158b582b85356c09980c58651f679a5e4983fc813aac6d7293efac0fa012fe3e1457d01d21b073fbb7c7b1dda8524fc058", - "0b090fb60121f8afa7b53a7f36b850b55b233c594d43afbfee789d30aa22d17e2f22e5adcf9927d0dc29d206ff1920103c3eca47bcf043a82dcc78b2b5c676c208", - "0b015988667b3208a2b7389b5835058a4235f608cee6f1e469dd4471ee3fcfb66203600c969440b472309dce07b2adecec35c5a259acf094f37c99fdc9dd5a1b47", - "0a0046efca62529a6b0bcac0df0cd5e18f55e9e0116592f1f78542c3fddb1726563df5d3768544d8f564cb83a3405e5fab789225f60c320eb117c52da3d74a25be", - "0a047150aa9f4d26eb9e48603324bbf78a19e3ac4830e9a143fd4f7e728db6e377406476b32d13b154f8a85dceedf1e31c885e77f554ea864e5a5bc790770eff55", - "0b03a864f78d1470138467e1e92ea29f3091295f93e2598712284fdfb5e8ed88e81b05e89444c1fe618d18d0cb1e1d8e540afb4b43876960c53e8358849c37e7e0", - "0a08e862ef717d8ade6641797a99dac37a3d204d4047893460df83d6389d1bb9f815f2ab6dfb81826fc2498975a3ad067337d897696b8906410a2ab6d124c4f438", - "0b0600ed8138ff4a40d25e5e60d18b473846e45ec5cfdc5464e0f7fb74d9b8686068f1686b1696733339afca99e9ff0e09fde11c0c34e81792e1b33de89d1de28a", - "0a01c0cf776c7ac917fd210aaad9ca26568f90ac40b0c762af6d5112a80f2cd2636126d6631e1ffd6984c45b1dc31e28e77b8a537b4abcce2d3006a025499b30d4", - "0b02a5fe89fa8625a2257346950442ee75097620ae082be65ce8a711ebab57638da3d61c97f3ab528151da1ca5d1aae6f35504a165f945df5733911a4ea50d4b77", - "0b05a68667f9adc29ea16eb7cc59dab14871629c7ec8226dd20ae07e9c3232df628ae2b508664a21a4cde77a6c825ee11e7906cf1538f6a1d6e89a116130580297", - "0b03ea1c0897c96bdc41c6f5a18156349d93dd66b694251050968006ce08a4a450419002fc9b09ad1432ac079ff35af41545c2cfcf05143686830f937ee2fa282a", - "0a03a40e8e3d5e254c12e51d7bc97290ec5122ca43fbea238c1f4c29317b2c04b95a6427e1e977bf1d13d51e79c20894100238badf0c44223453466469687b303a", - "0a063a526e7f461b00b2d4ce9cb1f502c1281e246a44c312826acc6bc65bc5f3a3ce4fa078022e295af8ad70863c45e4eaf84d4ffc429f958f4358840fcca7c0ef", - "0a074a11902c683ab3c12e02b166ed3d6f9f93e248007807dce04b73bf0d8c5b00baf8e5cbc38c9ebbc43d8dd2f4c332409d69cb921c352b49eb3141b61c3cabab", - "0a0382ef5446c17268e710d8388f374226dba26537ab57ec12ac8993e2628b6ddd82e11a9ce8671b2122fc38b5c4c932eae60994a7d11cc5df53ddf24efda66953", - "0a03cee437d7c7f0263a8e81b44592f1b7a38cf570b3be5ee85f2b2d08d0b79462ea52247f7dc4bac3964fa135c4599003e5d951c7a0f2ec9e7af03b1da5ca6228", - "0b05b61659278b7e1f191acff414e2384f80ef41d12bda5f117c3b9b5020b2516b2d39f90ba834dbc6ef308645a6a6a3ecca6a5c8e2b647c69780d5847bdbd9f8d", - "0a067a81ec17d6fa8a8d8fcd520075699aecb84ca94012afb25d378656206900d04a86baa6633a114afc13727732a5443ff9fdbf9beebc59a68f1fd626ba5a976e", - "0a0377a7711f58f4c071cf0e95769a630c1fd7e068152175dbe715a14f5c014a8810edd570b93f48044b331971045ace5bebb121577228f7f01ea14e429a0c245e", - "0a087e341a29ee2bb715a2d6ebc1b2dfd6e9fa219a4b99fdbc31e48b4e30bd28f69cffdb2f2ab6a491cb27a4a8c0eddd7355db89dd8109c33c9dbf5b7b0db840e5", - "0a05863b0525bc2ab8842ca2e32fa8907ba66a66c2a21b30c33ffe561d70f0a629b5cc7753157b2dd078abe0d300fdfbd22bb799dc3b792b5983f519fb781c1f16", - "0a0264b225b434f328ee794d2a5f73016950422ca07bb8998fddb8a33c0728c3d08807eaa58b94d027c8d1ef68139a96e792064b94ca13abfeeace74eee69857b7", - "0b06886b927e1c7124bb01f83ecb56f62c3adf41f884f7280e4d4ed6f392f7bee61a7b4c901119940a8dff9dc7a84fca90f2153ad66c1fc28189fa1f3d7b2a5253", - "0a06ea6b62c05a1af5f105b8bd5a7a2006b186ec4566eb9a9fe6f67a756a0b68745f5a027ced89ee173d956f46b9354ba31afad09a4de3a17ad121dd11ee71dd55", - "0b02f516d0e925b1409627b0a87f1ec8605c8738821914d392275c7534e9cdbd6e8afcf0c11e43d372193422c98a97ca38188c8dcb1f3256f06c9890ff6302eb85", - "0b037d54edbd37b7375cb68ebf422d7ab833af7a310073879e29a0abc0175a32c06046d4f20fc5c4902a6e6d812b3d44bb25f3daa5e39bf4886a442253230755c9", - "0b07c2673fe0a975c4e9a506819789f666c16fb209391b6551af878f5942f4cacb9199ed726cad4ff9e80ed28ca5c184c8ac72b0b5a110018fe75adf437f693e3b", - "0a0235c55177b81af5a1b875f04ae20997697e9c1f5166f97a919680a9d9324bbc5e3063dcaffb2f25fb4ea4ba96a9248bc5002657894af3e403dba408b97860f7", - "0b06dd9261543834689f0bd76dee83e631300628b8e172ebca5cc009a8ea156cc012f367933fdba596231600f80c7893dc561f8b6f59616bba53e2cf9158b3e033", - "0a03cec6e66e417534ca33252dd3712de1d3f7726eb6ddab794cc574b0378ca162944a45e219e016980462e724b9740d341d6d1db8db8f91edba4381b943127026", - "0b088649f7268f21b97afd00137ea437f05d27bd51a4c68f1999ccaa1ac8e450c0f51cacd66f2869ce637576b02ff789b999b1585788eee771045128014f09cf7d", - "0b0429639afa11feef327c2d8355cc744d5240a07b0960c820d5c4c72105d3faee11d6c31f993f05fb93436622c9c011f220d8df2475d697c2bc763634beba1427", - "0a0542c9d4eec8963ff15d2e4884b59c29fd944531a9c435276ec2685981e5a016d3fafb2d6784d4f297a554252b462804e21102c9d10dbcbfe772fcbad23a361c", - "0a035b554aaadbacfce3cfabbbac5e0fadd767d4c51191f0f98d01625531667a09d6801785e13fa671cf509c13f906de52be510b40742dc00b333afdccaca5a364", - "0b0884d0803a62bb41ac86cf2ca9941b23430f0f1f9555ec394d3ffcc5f35dbcfd687028c7f2da4e25368b2356f80177070d2756ab1bdc96a6a2181e4dbce2d1f4", - "0a080dab531d14096b114405fab6b35fc9ed2435b0f9f57598c3fe38badbffe9749d0d9eec550330120bf28018d230a4cf0a4e5260ab9c006b9cfd1bbc36720f2c", - "0b03f6f4a46f3b541f4e660b28a351cb25168afd9a2421065e43673b9ddfb8f4e2b16497be74b3200519ccb0b20e3d281f669ac1c6d45e1850dd172177a4283003", - "0a031561d3aef21781fe8cb4a1057e3eff602a363d3af32bfd6bb926e78dfc7311f13c8efef73d5e551c2e8fbea23730e5152eea7cb16286ba1b035752b59257ea", - "0a06659067b27a38db42c5622ef1bb2dadfc57f3f6f3bd38dfeaffc9692da068e2a566856961cb3894d5556e035f273e1062cd5364a51e5f28e2d51e8f7f125c48", - "0a00884b138664e5ff2284f62f250379360548e40402be25496ca4295b429ffd560c9a2287342a689e2e305677f0ebd7eb7505e188a792119c689fb55186412c83", - "0a038b76a1cd2e1c3c7aeb101189d6895866c706098f1fc0f6583fe8bc26acc4a6e01b19040affb209a9531de9ebf491affd3a71b89a86b9cd176e20443c749619", - "0b0069a03479a2e72bab842f9fee1052fa5d8dc4dd358ab8860c9a42b0c43002c8f64d9729a88c637e7453b43679d55a0e2b716eec6d095a437eff8184148e9e15", - "0a05b60f09470832a3b84b82364411c06f2ddb71ce59d634d0cd63aab1aa791fb6582323d87476f240bee6927a554dd21dffce196cb810bca63efaa39935e44f97", - "0b02ffde33e05cf05e03779a0b4a5dcacf31a625ed203a0d228c829dbc9e123170128d9dd4e560106c0a656352687034ed449ea03055772919078a6077f928bb50", - "0a01c6de55642dadde9daac63fbd5e0f40af45c17a220b08d82b6a2d09cbf9d35ccff05187dd08cd1e768e47e6ef03feccc3bca830d7411f29fd57be9d6d20592f", - "0b0325f4d69f7edf450f217cd9cc555c5abaa615b065a0606463e8c3e213c43e7e6c9182d6ab7d4dede16622a5297adfc5168bee0f7afaadf88ebe9a74f46b7a9f", - "0b01c1da2372cdeed528110349d7e5f95f201bb06daa3db4194e2db376d1092c663bd46d6bf488a82b228a0a038a11559410c9d9d9bdbc3e4b58039a36cf05b714", - "0b01e96842457622a883036019d5a69ba7dffaf1e8de2e39cf86bb119033ba81d27cd83dc2a7dcff5b02119f21bb684dc9a07f93e7fcbdb9d71230873be29dcfc6", - "0a06164486063bd7609ef3e5bbec4854cb2f3fad6f893eba8ac5298b182b57fdb4985ce2382f6141a10c3b03f0364ce982097afd8b2b8af02dbbacd8eb5c52903b", - "0b00dd9f97023a151f3514668ed58dfe3332a409cdd96890893b889b0a8487d59698efe22e88aeed597b14579e7ab5a8293286ca4acd47d58d3d7947252c82ab1e", - "0a0060f13e366e1b91e1d06d40747102ca343ae93dc1d3a03ff0d4500913f9abbd66ab658be89532483297a72edf141968fb8b5af13aec6f231b2201c6f73db4b4", - "0b01e813045486b7506131f28ea07897b268f56f378f9d2a400d6ff46b3ff05edf41cce20be7e7f04c5540eb42b518f07a14afc5a68cc4469f85256614b4a49d4c", - "0a0287231c13642cb8033bd55dd5f91816b9bbae5f72259bb61dbde78cee32a0fc54b57d7ef0c4f18343d31786ff0fc8563eca8cc7254431e1241459f218fe3585", - "0a07f8d8dd70cb8627d31acc1cf96e364e89e01e74c1b7130cafb5bddd51043bc4bf7f073cd6666254e13460b8632852520e00fee262217dd06f8b45b4df192ed1", - "0b07db289280ef017b0eb3a885b8bd2607f1e1ea25e0597a2463379dc42c2508cb06ff4a83abe1e1ea84524943aa90ca88e3cc308863e5af34593f8e2b55c28148", - "0a0904b5e55bf376ce72154594b258deb69466b99753b150d0ab03da95878584665fc3fdf469412629a7a668190f65bc41dbf4d9cd3367d48f31b89a1fbaf87e5e", - "0a0557492fd65ca21d9843f878d8e38b84f3cb71b1726ef3147ba1b3b483343c1c1ccbee6fb45f6645af334e079feb37db10ec7729ed866934a7148b151e8abc84", - "0a070071afb1e789122c68dd5f6987f6e227308e4c17209215f00f812fc417e027002c537ba982092996b1c4a1ae0cae80082e03edf80db631a65325b01b2bf9a0", - "0b0300de44e1d980909792477596d767b542c09ae497f28462d1e6d9da26d23c8845140c8750a8e84c72dbd53faa8c92187247ae11516e498355d5e6fe0edded76", - "0b0373d9ab04651f2e83259f2a41c69e3a76c9d95609cb3c8ca88bd669d9736755635140111a89e42b56ea5139a57986997440b47d59d87b2c6b741cc9bc394914", - "0b00bb69fd9779475852fe0f64054b8bf16c8befffdcc7645a8dde29e192cdcfbbf026010e62d1e51d5c132528ad87a478145462f757545613f4f2e848e736d82a", - "0b00976cf641ea8a21b914df42642c96295a44e9fc08c9fbd8995ee4bbb5a65c03942805226418afbfab94e5dd18c7f1205e32769f028eac3b7bf3ea404a48512a", - "0b03845b44337eb95546f451c716344dc054fa242afb69b80fa41fc6480671d970fb39c89890b75a7615abd20b87333a295d88606e642748da0662ad5117dd73b9", - "0a04b8e87e782f98864ffa48912f9f07c17d8df68c4992c6c11603d6c8087b01eea3a5aa0f7a4a7870e44d32f1e29ef47b99014c0b6fe0c25fbe7155de94602503", - "0b018e4d17e7849fb2bb8bdb8c56db433fa8a6c1e1bbfd557111134618e132e9d41d96fbb3e67f27217d86f388322910d87079e132276933335725ef7d97f0ae6d", - "0b010b7d7313c663f2fe0e3d8bf4892819bff3df5772b05ead7bbd032d9486722d33fe0b7f08cb82bf4fe64149c0200220e3085c75984e52e3f933adaddf9fbecd", - "0a0104eb489efc7e5be0889009f1cf61d5efc6af4550870cd8b3ee921df62d8aeeb4ea0b7d8bf7af0f3c3ff05ce6a73a4f2e5e72298e1b4b686970e5d1b918d3ed", - "0b08d6f1b7fddc8a3d927819a4d153fa9ad234b721278eb8bc5084c1f2974aa6d22511f8e88e9082948be1fefc9897a112b7c7d99128eb524244d9dc507201701f", - "0b089a5e876762c5a65a881ccec1ea88a88c6109b257a95426e909b4bc18f164307b0cb49c25c01118572b214c92afb97ce05b35057f442cf93ada6a59b76f5721", - "0b00d0c70b79e6fe22aaa07fdf34d8574bc32cec25db9915c88e8df59f13f25d984ad450f51c5f70607c16a0ff5717137ee82b1c8fd007c1e56a4587ce214e215c", - "0b0382c553b2d4f6c6064a17906534b976161d7e2f1ffcab34b48c9ffee03e67ce78cfcd4ea02fb78b455874116f8435fa18ad7c5afa9aafef0557820751343009", - "0b03e435dffc5e82dd164a232a29fa9dbc979adfd48bf19eb3f9d4f7253a23c674203351fe1ac8e6941f1d5b5bf31af2512c6e63086177c3522a58c02c402e84e5", - "0a01d90d4bf9b3d30106ee71650f488ce8ef8177e23e5a8b725016c2bc7f338dd5121b96cb64acd9a24937afe8ba3eb28e81dc4afb6fbb791202c81282c9367731", - "0b03f6b8ac92277c94b5a2b1262f2e5ada6297bb91bc4b70c9013f2efea89e90000f78743755ca62390708fabd745f1ae01bd7be62438ee360cfeff319b42ebb8d", - "0a0359e3aec59816cc40e10cd32e544ed16029b652371e276d32741df49d151ad0feee097c2716df9e67908a421ed9153ff6dae83cb63c21a343079431c9ac3769", - "0a02c8216fb52f599012813c3f4a9f8e539c7dd7a691aceffdfaa3bd589708ce070f209b20d38f1f14bde73544e1349981968c172aea13c032546c54498a1b8563", - "0a006a67152639e6c6969eceb2a351a71214f8eea8d9e467be2b631f36cc441b724d9402131d1cc1a578490b2c026e4287fc132c0ba5f6b83935afa2fa7533ff2b", - "0a0142d3d7985553408cdea4946ad7c96cbbdbc4a39a256e442bda0e10c7c050aa0b96fe12bb52d0d38d23c546e1fcf602d4783565e28e614dcb5c2f8f7ccc49ce", - "0b04b3159bc1488a3ae5e1706b0b5ed56999d3992c09ed737d02e3be1d2f2685fc86969618a9aa7d4b2e38651e6cc5e0d32fb6bd502c06d18f8e3447b8902c1e48", - "0a064929f982a67732967255a631b7cd36fb49eb15470c8681354d1c5f8691e9f843bea11aa0cd268b9cd26a0cca9a4a0fed58775fd300c733bedd211b4a144c5f", - "0b06ba97165ae65268e38696d197a5487013bf6516f85b737f49c2fac47b9ca0061efea409d6ed64da8363e0c78c1cc79d633d0670a4cb787d23ab2f800bb91161", - "0a0209ce660dde1a2a05d7ee922dd5aaac2de004b06831b2027e8facdd36d6ada4c2d0173496f01b53f85147fd21f022713b9edeee86e518e07ad3d15b0ef9b76d", - "0a018615632f2e3dd46928628a7c25422fe68da4ab70a4b33ec4d774ccb04dd5f941b4ee133e4405da554f9925d8796fc625a851943c5a52377f79cd08ee989dc5", - "0a0164c8abb1038ab8304e79a7c661c48f2bbea1dc79b17108514c0291c494f7c63874f3469f8766ff9ab4391f942a316b300340f0710c0e9e869f05eb0e513db2", - "0b03f644ea70d57b8b1ac52eb5db806c0d57f1a2295ee85ecab402bcc02df241b650b164f3ca820bd84b47e2ec9dc87a4f653667a016a0fcd35993b6df957b0baf", - "0b06f6934bab569199de21b37082e7b2b0f17a8bf497395b9baf899fd6d6f834dc6689b8d6598d6f73a56e54a7a9c45a60ae4d3fa75b0d705c3b2116b9aea50c79", - "0a07ef0b0658ad909be85f2b48490572f8f2f2a36defae355930cf816b7247d92866a3adeb65117c0cc91a87844462069b9ae1a5ce386a59e335ee6b01a4470de9", - "0a0911da2338c4852ddd76ce9f1f9571c0edb5e191636d558890db3a5941cd4e164a71e262c1e22d87c8541e08e9ef211a775d28e8d5bdfda128ef22947f771f2e", - "0a027b86716956a7900b6d3348623c11c9022e5f5e47ecd6de6115de39e0cf256406c92e2278d59a9634b1d39c64f37ef558f221440af5e94689d596c1141b7a2d", - "0a03b55358ae009c4ca45770dd420e327ac23536b84fc9392c31745857af3bd9b0bc5557d4131b72ca456c025ddec9e6537c3bfae2801fa5640ad130435093831e", - "0b00b5fbac9c6d8440079cb778f6925dce7e9944ae9bae1a9cb1ab264e91670732462d7f25001c16d714ee92ae60d96591ef78a5b4deb058834fa0bc4d303323a7", - "0a056b41ffd03333f75793f807f9eb0d5da277108cf7981794d8ffd14599d69c66ecf51a67a1ca4e9d9ca52040d0f18d2ffb9104421e2d88f8277c9c8c8c6518f2", - "0a00e72427cd289e612527d58e34dd46c93dbf8325ec9e53177b6bd9bfdf5df5afdc685cd608b0908c4f8c78c10a80f12e99226f1fbc3ff4e7139124d0c3f2774d", - "0a027748e866756791773799cd3e71c1a327878cc836af20d62aa641ec46b642aeaf3525da152db0a216009aecc699cc9fb6d7e1f4e56b46a5f3a9560a18214f7c", - "0b090ad8a6a8499ff1e807fe3ca8c5cc5a76b0142b8607407375624b10e0df115bfbd0bd50c1d11687357f1f7d508ca35c6008331dd36bf3c0bb8c0c3a7120b83d", - "0b05cd6e8dd1c5cdd14cb667c0938c16418262fe1d3d0e33a2cc44c879e534ab030c7b4e337879b0f905e71b8e205a9890ed86bfdff175d4071bd7059b18831382", - "0a0397e558572594684298b3ba4804cb33b24ed941ddc16544ee17e6e4db1ccb4ddcdf17e34d17ef8c0404c7c0d7b78764d8702f49a8506cefabcd7c07e56e93ad", - "0b02b24a8a9be44aaf3041072ac29a1a013a2ac8523ab6c72f557a4164b8f4dd66fa9d838c7622677620658fd42ba1ff5a87fb88108d52ae5939198ceeaa4ad28c", - "0a042f05c36ff1e0599ed76abdf97e56d297548d6c693f1d78c676905863a946351a4f4de9fc4b37ff12e6dd313a81a75a940c24154724b40543c3531ef74556bf", - "0a069f79bd3f59f7ae60704443b8ab47ffbd43304ffdfd5c6a202c0eb4e23a5ac8b0e18630bc693d3ccc88daaaf3e3a8654031ee0b8933d0c356b4d7b1ff30028f", - "0b03f29cb0f382a565dad92f5af1e5b0bf26a140f1e1c0c694bce498730c14c51b9fe4ff79cf7b99e1c99d91a5aa83e709f50f820007ec435f5345cb74709056aa", - "0a006d7a6ab13fbcbd7ed7f262974fcfe0def51847425790fb5422ffa4ecd616b4fdd48f93e1793605a0075b0c9089cebea4ac2258652d4a6c8dcf8e0d6c6a0122", - "0b014fc1384ae170941731a739da21f7b07bcda17134ddb59c1430cb05bf8d190a8e77c948a5613589b6392dc015b2f81bb9c20b9e02d8a124871776c53043ddf8", - "0b05ebbb017c859c14c3ce151c8d3bb59ec6db60b0fdb9c014777f3635ad7f50ffe329054bbda8826641ddfb2b27fee6fa836746df50d8be9d889149646a869fa3", - "0a00e1d7a06a7f624aaff4c5abc8520770912fc40211eaefc3852c5966edd0e4ec7ab0515b7db5d36be50e9682e1cd8639ac397ec032987c67f8915c519b02c206", - "0a06476a98feef246c6953e2ec85f8e4990dea813a4cdcef887caf07419b060c87aa4d44906d40cf23c57cf57e962484c992919c3b0f425c2aebf962b9f33a495e", - "0a0002feb55414bb9605ee61c838b9cd5c816c1b9eb2627d18d3fa95d170d94b98f4dcaf97edcd8e86edef82b4d94e0822ecf5053fc5591a3e6eedb61060c80e78", - "0a04133d0b249ace15d1b0c961ce0f1fbfa6e517c0063c3fb06d695669e33f23a0c04cb109fb232435662743f60b66345d7bfc37355c3795b5a032f6db2e0f9b86", - "0b02e53010b53804d3f9b242cfc9fe08455b87ea2268467f9b492dc22bb35581c522f7acc62db4921fc683340ffdd107e4f999e9a71b3bd3936413b5b22da97d2c", - "0b0489210d5354af9776ebec815d288db216b11428fe21c2c09cb22a9ce43c7bc5c54874641e8858237114e0df03da329b079281b7f1f5f4a25be129526c988943", - "0b00c152e2aa2521d467205bba3cf4314cdae78fbb758b7287825aa9021bcd6423faa0fc0c132ad6331b454a5b1e7e99f83a79613072f29e69bbfed931a9b8e573", - "0a0558eda7592bf6e87234cc4c868e64df5279f994baeef11d87d942e60a8600fc0cad0b4cfd1e25a0cb1e426df3676913b8d42aaf909a9f2cf7e59ff2f8fe3f4f", - "0a0557591eb47163123a88674b5a53c19fa6cc47241b53e6c09af53ce8660354ef19440fcfc6398b02c59655ad89dc4ce8237bdcaf62b5b15763c251e42852bd81", - "0b01db54e99003196b568aaa0fc2e206f5ec83ad538e1ed85e4d2622985ca92457100bfd4ede42830e0916e16caad8642e7b170081f22e267c31f4162000a3115d", - "0b044b46576362bed2100541bf132d9330f894038c3099d71a3765c1c66318c5dfb57f5e90bbc8ffa66d053fa9c55eceb0c84da973f36e0a775b2724bb1843a23c", - "0b08beb5964e6ad3492cf7c11902d1f3e0143517522930f2e1090d8f37882ab5c947c3b35aebeaaeeeeb6bce924a072c805eba9b79ad501f085c8b61ecef2f5be4", - "0b056109b20248267c7144ab2050ce06ed292765a55598ced3eea344ba7ae2f9f9db00e447023b9381b4b8206ef6847f493f6fe3117c0f013d96e00e3c95cf993f", - "0b04424de4863893c59c504993b3a7005eb3a78f5901489582471a4c5d0ae844d2af0b550c300ce32241a7abd435ab7719b3c379af6e7130b6f4661010f101998f", - "0b00384360afb697133c9027310620d8601ed597ed5dc4f4f361bb7a8ba93733e525f392c839ea808a7a123650e019be6735519c56778282307308f0ba4771ee38", - "0a045799832a7d6b1858a2cce3a0caa538c894f78a464e9e9e1f32b9a51b1d8d209841380c6329a82e727ee763c88b4a012573a188ca37989edfbb84e395c53d4e", - "0a0141a087b09480e751c4def996b15a709014bff0c0f05131f8dfd941f6004e88e471c19b94ff11d1a8fc08f01f703ce9488eb558104cebaa3459c969b9f2e93b", - "0b014202f118d0f3909d5af891340a1fdf7a71074d746fcd1dbc7ca5b907aa5279e1099a274fb549ff25121524b3f96908eff3bdb4bc443cc5323772945cc9e42e", - "0a083d1ff813d7e22368cfdd81fa4d152a9bf7546058cf63c6f1ece9c3f89400d7c09a546408e3a3ed2658523450559e7cc006d98b5f63390e103309f1c5a6d69f", - "0a035cd002dced0b8bc22c7820d07fa59753f1630a9a67d524141de404a9ebf7acc4c037b2d5d5525c6af05599e1a55695efbc058b4edf13ee150f20b32b163c81", - "0b040e4cdce99493ca2ff16117bb46fe5ce4bb963f65b487e04f286f85b9be6ea183a53420c05d15a7405e6c46098db90cae5bd46809f9dbd612badcc20d3c1caa", - "0b01487637d21f20a8650d76aff586ce755bc72d65c5d0dc7d8784e4f370d705cdf55b38e48fca6c6c91a780c2bea46e7508ae97acfe81c1745e168632e07fc314", - "0a03a9f095464dc6725714cf64ff6d724f00373d4668cbad9903103d71d411c19faa0f114702a94ef721ffbc9ef06a48de4c0e7e7829618f5cb5199e281e3fcb28", - "0a070e089858b414fead6ca40973a914c5217dd7d21f2134d612066152d977a1f78ca6c934c5e3b10873fcd7f4e6f86a60a979634cb9de6aa65b0e6a057e4eed0d", - "0b0836dca24a283622a433e0788bbc3878f2b4beb6ef5c90e38eaa0db9f45b8fae8d259e44d92a11ad2172c3bc9efebe298f99c05d7c4ce47337c67d6cb1170500", - "0a0565521f73d0f1429e42dd174c066f095149998b4a4626ef0d4b70dccbf32c5a5b2b2f67de663005aaf92cfc30570730bbf85640e7c223e5944ff611fbd56865", - "0b032eae94432b1fbe0c4e09db676914cf139f6819131033b41dc79f3fd2e26a4c09c694a4e8580d115d86e3eb9db9829c0d5763c0ca719e40087df1acdb97029c", - "0b0626ca03ff7bb5e8fe56d3e96472468a2928c1828c3a46fdb9ed2b42816c595a77b1c09ddd03f3f9b330eb09deafd01dafd661d22120a9b87579513f081d546b", - "0a0618570d20dfffa2f8b12c7772843ff649bd81d0ed3925bae28945c207f26c16afa12b1dbafc8a36efce41a4dd01f7db162785160a607fd723d9d1095cb96c2a", - "0a05081df2f61e7ba0ef7d353edacbe375ec68394f6dda1880c0c6ae00b08422a35531fad071665190fe67987b5dd3f3f140454da5fad309e4d508e92f7db04f70", - "0b03c5f56e95ae8d682a07ac7d35265b5e175bb2a38133487cd9298d28f2974121aefd4e9de2da538d833a88147fcb2b9ba94ee699c639ba2c70503c69a511663e", - "0b0052bcf93d54e89a4969bc8d73d38e76480cad6ef10e8e97f1e1900b2ba1e524f465f529ff9f1cadc1d375120ebe38a5f108c560286f45721c5becc9f8c31b0d", - "0a0001c7aff9f36db0de5e11c8d72a83b12843ad0a8db8d2881de88b2a87bf5a4cd61a05b63107d3bb40196cc4054443feee587fa30ec38c28704fafc31623fb2a", - "0a07b34bda3f490f089ff7df8a2592fcf74e5ecbf9aa07e2f41eb4496ebc8c4bf971239d2478676447188d1b0cf01742ee9a6611f07ef05f895a25ddb865655638", - "0b06c75b6631b48fecf08f4bc18c3f01365936c8b9a8b0f215b0676b60bbf5940bd15dad344bdc87e748fbfac71b608cb1586135ec05ddf6cd1a27bea968409a4d", - "0a04ad3b034d449d9c75922c8fe8db88b462379a3e1424297c8d9cdfae68e5bbd851f13d6fb93327e1569a0574fe31100259218aa57636cd97eef6ef037c8a310a", - "0a01eed145b4ff75598373e14b38713a8245ce70485ad2af2dc5460a4a301999211f2f835c0eac47ff10ec28e0f3e5a8ec49bd8a552eb3b576ed1db4340a7a6bb5", - "0b034b038aa1294197b8124669d575bfd89e8f359930d8412b80ac3c27ace99612128f5b534ba4723be3d8e7869adc210b9e2b169fdcec40fc9f96c1c4c59cac82", - "0b05fdd26d2ede35dca7a3f4721be004aea7fd4d2de0684ac7e25e9152720eecaf6b8d5fd0a97d44f67cc06a480cc5ca966be7be85fa1bf8865a432fe692d00531", - "0b03a7a13a7ad9878102b589fe703d98e3a7b980b10548e24345fe7823d3ca5ffc2f8410bec1ab755045b159abaaf729de2fb1bbabf554c0a30bce5032206ed9bf", - "0a08bb01bb35efeaeed238742032010d952c4399e9955c12daa55b274e798dbbb995feec7e4bbcc02c2bca14dc628d7a3a1eb965fd850a05a8a641ae05ce8972ba", - "0b0487ce4f2911cdb33383c028f3aa7553542a93ed1738a2bedbbbaf96158adbfbee7ba7560ffd7cd35c317e94073377138f960f9448d7752ab0189026370fa6b1", - "0b01e74b4bd8d3cdbe2fd9e94b7098068c85e65d256af96d7762f72420264f83e7ed6e9068e4bf6aaebe4116a2982032393674002116cc3cda15da1107c04a3e8b", - "0b07eb216f01273dd7efca79d8e2f2480641cfea6fc2c1faf4068fecf57331d7f1495c6247598bb94b113f12df49749e29ff785cde715ea899c4352d5c699aa69b", - "0b016fee2b2cea1a90e3f954d9e1c47b0de8de3607fbb282e3993c3adaa980c71e23fa8b16764a4ec09383e5050d8491c798c3eae7eadb245b3cd1bd84e8653dd8", - "0a0235edde8d59e29a3bc175ee96b36daa4fc63cfdc1e04cd7d5a6b0bbd181069f6e58126fa2377f82f32df1dd2a467d02b502fa507d8cc4d6aeaf49c0a8f3ac92", - "0b001970898982ce8fe51a4fed6530b4ec06ec966890e8ecd8b30b2012f6a90ae5d146aad2a48751d8507c636879464bc68f88c69007dc8f1aeb982ea8d5ec3b61", - "0b01e531b066e030a5f401d38fcd30b8e02b461235783282295f71577288f652a5cb7c1ce1dc19467df3c694afc6b023ceb4eb68df317efeb71fc0035183b812d6", - "0a083dbdee236f62ab1f60889880ba7d889fbfc41895b1a865444a02eb56e8f4f46f5deb13f0ba09dc5e28593f9e1643655f498e361e8783816fdbc348949838d4", - "0a0807e56b9b8a6660b1e5856a89bbcac91cff5042ead5918d4f71f983fb74bf67788e9fae794e342503db3eb4908ad8ec8256eb794f667c2ee95bfab998de55fa", - "0b01422ffa4bbde629eae73265f7f4d4aba6a25b56eb9fb57a2d6e28ef231ee2e0e3f797bfba803e90419793277e8eff2e884e5c68faa9775ce26ef32a6b0a1917", - "0b035bd3d50e280153d24bea2d3eb169f0a842efdf5a44b9ea2c863b84abeb496c2a64e87d3767c9d4882158b8b154dd79eb41d86594f11e13ceb2fa29b6db8533", - "0b00d5d06ab87a4015e405503b00fbb796245d2851eb4b5be8804173a2fafe99f1a5635d41964c440fd1c7318f5717d05f7ac9f485bbb32e70d0c67ddf9d0754e1", - "0b08c3afffb14056cfbd39243572d358bcf858c3e68680cd811d302e6a0e96c92c68956bd74af7f55e3809647fa7db68ec5d545ce999e5382e4635ddd99963f865", - "0a03d385a5551dd4dae6c55c1222e5713a7768426ecdb30b3ee6afa680e42e533a6965a07f0b7fe6cc574edde7595264fc481de3b3c91721ad96407cf48920c7b0", - "0a05caf5d3f6a4adc44cd603953101527645b0fe46dee5ca09178de1b5905263692822c5addc0371e6560d2f4705f1a09651245154f83bd31379b0846b0cba9c75", - "0a03fdbc8aa388628fdf1950d3bf9e4473923b73c615720e49a730e2c1cd8e98e7bb008644275916e385cfe2219980c68ade95625c52e6344f59bc2d130dc5c652", - "0b07e67846cae37450b4cde44c3b014869e3fe35409e55c5d02c22082dd882256703c990d78a69d5c5d9ffcc32f1f5ce34a8b669a84862e7a0335cd87b514eaf93", - "0a04f4214a0885a92e73dfcd635fbaa7a77c0070192758de1750f0ed4e01fef3e3936c285adcb4494505bddbebe87304bf49ad6c47b5b9d5191925b69a5e3d5f8b", - "0b02fb49ab6b913a1371edd058ed0206c63c494d8a3bbac2b804f141106c4ea868b1bd50fa81ca9c025326a198bb8db58320225804173a10aab0276651dd88acc1", - "0b017496583e31908525f8421117fe1b1ba6fe9b0a621f581c6a2e801bb31145108cbaafd02d99dd84e13ae23fbbc356a3cfbb440c8c259cdcd44d2a651318b17c", - "0b0051b07267e002f1911fa6304ef00d9ac8155343cb1e0afb057718e8c97c18bdbc6250c492db95c33c46b8cb0de5170fa1cd022161b334b25f9517106bc1de47", - "0a0372bfb17fe3b22088279ad5fb3339b73113b583e59921195b03e7ad75ee4096b52ff45ae854975f902b1ce19186420eecec5b152fa9d05904551290e6dc88ab", - "0b02a9c78cafcdc58fa0ccead03c9102bcc091ed94f7825f051d4b43c99097ca75ff12499ff69bcfa2cd09b69e97fee1d96d6a9afeb3242140300c42f8dd61fa60", - "0b030174641a7c4925fcacca3a6dc823912ae929337441d766041f8c173efb03ce715f8307493bbd6dba72c400f10907055bdcb38c0c91d0379fa89696734dacae", - "0b043b1cad05ef52fb67d4d956de549085e8a45cf7aa1b55744a15d7dfb870cb4acf97860370757bd285efa1b37fee3bebeeabe3d29ff2b6aea1fb4d2d7f5e6517", - "0b068a0cca4c2a6b7227deb15bfb511ad8e15df8d59313471e12f50fbf24eab226de1826a5c569ff32f278f21713be4d32f278a0668e2fdf1c72f6406112fcd8c8", - "0b08f31d4be1034458c1500b53475c711f8e427d6070369e348c14ec95fdef8d043d1346b22b6582ea0aa64cc2435d15c5b1bd58cb4f6d660e3a48d6914e55a938", - "0b003024df90a3598eaf5bb246af0cac6c8d60715e0025de692a470e4afc53f50e687e506832849806ac1633bd77b0065574dc01ce8a1f451894de0ece3280a618", - "0b00768ac645e88d7335035ea3482bfa5624d0ec434252f6fffd0a2a041c2f846c77f76c2779a16016372254a7035911597b2d76d1a3f2e1ece49d37c60b0522e5", - "0a061a7c8a107ce4d5d4a1e8e03d54f242c515c865886a8dbf36b31dc626864a41f16daa763b651bc86d7d55e7e9a6f696632b98192d3349a5f8baec905d463eaf", - "0a068ac9ab95cfe0f116f9af4e717fc4b7b14d7f665d8a70348411edf80835b0ebfd314b32a6d5f4cfb66a48640b7f32fe2375540b68e41cfe72c42db9421ec642", - "0b04f0a2c274063803e5feebbae351f4c7ea020a1753a370c542756901c88fd96afa57724c1aa877deae6745e6e576449ada8d88914b29a2d869636ce323f6a36d", - "0a0532c189d5bf6609e080847d4b076247b5fa3731353f355f5f9ef56f7fa38640a3102a8c55c972d87de23eafc72394520a875920845a99fb822bcdd1cf523bb1", - "0a016515930baed07f384f660c92a64ca758f8895495998aaa201786733eee454ac6b33b884143c217820610fdd0f0c64f4d1b8cad16ff1a9c79e6c4c1ddaf851c", - "0b08700a26c90a8a73772ab763705e6fa0415542cd4e27d07358a5e1b34c16fb41cfb04f1913744942497af4a868935e6010799a215f9255565257b69f4d4ed9cb", - "0b042bb92333f9964f09bfeee6bfcf40c396c54a0d0f3113a670a6e74fc75a5cdc4b21f9391ee9d967c7235f57831eb4f6c7f6684a0e1c35727e4bd29c12b0569c", - "0a00a0ebdfd8378718da70ef1be32e455c18b36679928a9f46064cc132df6ac5509aa8c474dca6c237266ca9cc25099646938c085e771cf52cc2371f5c3c3c47ef", - "0a008d872ed2cb31e1fa6182896889496347553c01b2b2bd14d194b2dfd0c373e5f8a4b86ed4d6cf80122407108d189545b479e7420765f3809b19ad539eb23973", - "0b08c6dd37a9efc1b50fc8677b683b6f7244c50a35acabdb09085f9c601fe77108961bed4006a0f546727fea692e7cd3991c5e5d8d6dc33ed35b48045b60316d4b", - "0b058434f5142d0fd5880ae054947d2deedc74793d42caf679b460d619fbdf91c4da4f23cd0f75abbd4dfa88d79b402b0d2bb5ac40c332777b547425491286e387", - "0a078def1450b879bb42ea31ea61ea5926b3412d231bba81e331b3efffa4a6f57571a907af70295b8ddf84e27bcf587d9ed4f2777424276d998fc54aa763fe5795", - "0b049ef4508ab25ff46819edaeb1e97f12ae1ad10fadf301ddffe949d0be27bc1c249cae5f0d10120e338ed6ad90881d4494b6f6073e5da5d4814d52c674d1f4a4", - "0b07114dc4793c9cc9f521fc352ded18c3dcfefa793fd0ee0271fba9bc5c5c61c583de325a2d3cb786fe2aa7b75e423f6a01ff087b936524c0453c45d440a7b98d", - "0a0787b2ec8ea46e073b7c8210778459be96e0defb8311851232d9f9202e03c3ec4e6b29ea5adfdc5b2057d655244d4d1dedbf3e54d8d2ddd9299638be7e56e393", - "0b003b54b738aa2fe340c5b9b4c3ab65d4865c88806b753b66afe758fdf34386a0fbd1f35d92b4b9c0cfbdddb5f8fe52e0137e3e424c71c3e6698010d340ec9cb9", - "0b05f03c5252498aabb544efb870ecb59d8195a847c0a2a841f588e7b344bf99725e3f7b0ef002cb00c066df2d4a47baad0af66f38dd41299d13164eec6922feb6", - "0b0147401a36dd52242bafa03f406eabfd0d4fbdd5e447ff5466ce3cd314aa530418c5b498a38eefacfb317a2d5cb2789cb4a7671a78b14369f40f6573f1e1bb93", - "0b03a2ee63be6f8abf5b30f69b2656822411621efa6125f94d4a6b9edae04aa5656951889be91cba549b64d5999bb8bb64d4559f78d95c5e94652047df4fbbb32e", - "0a0689ec04c85195dcb24ed155de8230758543e86004327802332e22b8e82edd52efc3cc85d6ce3f23c018d81b03aa2f0720c425cc136b893c6654a7b241583537", - "0b06710144ee84a3aac7fe392cf037ccd1ee1b6c7103bc31e0e1595b7486d5faf14e8eb716e7f399ef3269f9511f24fd7efc541b23b3d0335cca43e23ca604d15a", - "0b046cf170efd81aa2ac43d79677793fe13d51baa1aba4f25911a13d054aee6633cab3befb75ce743fa79f285194f3c7f0afa45c3027c3a9a9c992a0ca411caccf", - "0b007b23a6026350fb77dfe27965982098644df794e0d072b693448d186baa75ce2a13c7bfe419576bb87939487dc822219cf489a09779a9ca8a1c2b40a1791372", - "0b07bd4564dfe43146740580744d692ad39dc451dc83413b8de829096ff86c8439d4695b6d7141337a7fa95d1ba95223c09ee2f530c5250b4266751259d8fcfb19", - "0a03f424767a8149f16e639c4cb5278947bef16badee72d8287648fa0b11c11b1ffb4b4b7c2b77a9a276651ae44b3d9935f901370bc716e4b3b5042153e457b5a5", - "0b02348a163c757568fc19b82f032ca364a5be52d45aefba8af2d94048c01364161f58753ec531053e733e9ea0f03b9800a121f2253004d8c045618fe3c05dc615", - "0b0734d481347ee6720532312c4e71c58043a771dcd1157684575f4f905bb535c876cd2b3b5bb4c6472e7f755c6016fc6e4907bbacae9c0d51b5d0b3fb121d8f77", - "0a07db951081f9abe89d6a5b4f6d026e9b2c07315673c200fc02836bf4a46577a788f0dcdf2fa58af7783454961885a6c853ef6f51cf0623fe39277099b8a97c4a", - "0a024d21fd3ba853fcaf8723191cd0ad213b58c0778e399dc29dbce0c82b564dba13aaf304739ed8d94348e796610fd77e5dff821f8dfebc85359145c3e76ffc2a", - "0b023ec7ccd68618a9a99bed232cf55fd2de02dc9c16099a0c816c6a5e9e1429a9d911119288c930917ef1aed9a0378fd7b46a1e638022e078a2e6c8d4faa213b9", - "0b027e41d8d8fd3ca0a6ffd49577b2bde181e2cec4f08389d56dbc7bca461570baf338dc47edec180d61a5f3f8ddaec026c84ace6fdfb8842cb4fc78fbedc5b3e3", - "0a053f43c7bad75ff3dac5a92dc7843def3a11caa6298504e26393a50b29f7aaae255c05d8caa85d8d8f448c88916abb62b1513b444dca663c440eb1d743f68a9d", - "0b04bb1b344b315eecf4e7c7a1452d70c8c2cb66dd0c4e026cc01585281401b7bdb639243d04c665c3c6f7d1b0fcc7e24b5edede5c68f925adbef585261a3828e5", - "0a081a24b45b0b4115b7ca4e1143e3dbd9a67cf9d82533fb195f246d22714ae314f7c9d9bc31d8972c213cc33dac4246f83a3edfdbb56f4924a3ba1b13702321ca", - "0a02b169d307ed901a6c1a2965ce23793941de816fca7826fde56ff07b564729e9e50dbd6cd8eb5eb908a95cb7d73a1f495f181bc0c03b0e9e8d77d94dd0f149af", - "0b015a086163e321affe50a3010ad83680ccf952e16c442e662a4da1f91120bc09ce47221af9fa4b21f8b6bd9e58562158a0bbe2a31c1329e42699b105c7a795be", - "0a06cfc11b51619a64188dd5aa561478cc2e082ed4ebf9d370ec98e0373dce6907dc0de1d0d7f1e5e45cf4f3f44da89779fe0ce761bdfe62f74f6b574266a7f8f1", - "0b02f54a126c4e4b933c3dbc56c45103bcfd0577c8fbac9b16726a9126d2563bac7b0c46f5d77730949a600045629a1fbd8c6a2415cc5a1f6397ce0a02f4dc72e8", - "0a091f4e11019f4021e0219fc93c934c0cf3216ee0fb6339ff68903763b5cd4406cc9ff21d68386c49fa592dc1d9bcb4125f1ccae1df82823d5faba40cbba21ed1", - "0a0294fcd22c6bf18fa08143595d9a9e06a64b7cdc151e292e78b6f67c34be3d9955287ab10dd907ef6ef7d9ca5bd075b5bc658cc177267b46c0d5d4f9f1223116", - "0a0466fbf8f98f6b762cc8cd2eebb199688e42ffd4c533d7d5aa4c8fc8d630393037ad513343d617158fcf4ea31bfbeabf600b8961744a68ff0bcbaf677a4e4e60", - "0b02485be06f2a77bf429687b5f8a8251f9b721438f244619aa1665f48ead43c2b684da0e28c75ab7621f48b247a95262cd181e16aa77c1b4c1151794ba00aa8db", - "0b085d24e73787b60ac6583a0f1db8f9de9fa72a68a1be28288cd562090460e55fe7ba3e4e0c7eb0677daaf72830de25a966ef86f1429d846946a4bc8f5e83264c", - "0a071749d5fcec7b4c1f2359c06825456298d8d28f4719f530e751fcf4f453db8a44b1648790ab1c616aa0a20770eeb73ac90cef7717def5ba133e57360d8787d8", - "0a00967af9113acbd9e1c8b799fe8d92f5b50c45cf35ab40b2b54c16e4ecde6a85e6d92d9f8916afef19e7cf22fed308b9254fdf7a57b61913817594c67d165681", - "0b035e4d0a482637407f1e22233c363760966bd8fa7dfd6ff5d50fe795600be7c8e610b2fdbea2bc2e16bd20a0c07aa894ff30c1f3618cc2ced6f9d254484b5f26", - "0b073245982720082b8a07aaedcc05cde2ffd9a6a7fc9632bcdf87f4b7d24b9ad0d61c9e207bce9e5d7264dc4915c9a174433fb8d794eee724294e8df3c640f0a9", - "0a084db8ae33f1a6b7f66d0b5a8be2092a2ad2e3242df8e36ec6ae6419a189cf3eb68a02d5967bb754c46d89de4ab5f41cdfe6e4387ed7d3a7d7a366bc0aab85a6", - "0b054d94c17e3c61f0ddc2da7172524781f5eeea8d837514e2e3feb9b7b4876eaa454b423dc041e0bb9a0e2bc924807aa0dfd5ab2fea8c6a321791b45f6881fbea", - "0a00ba56dab6f50ada56bf77ce3aa097bdc9a8ad20b7b1dfbaa5887c6ef2e5f19f9478016a410efec74dc239fc2ab0ef51913d275153f6597cdb2044874b695245", - "0b03ac883faf88d3b8a1b1a7c603337aaaf5019300e4f8325437d1d1ee14038358eef3a660ae073addc7289bcfbe7956c65ca2119f0122f2902141e94e81e81f6a", - "0b013045ff0a2e0f20add7dae9f2ab1aea0fa0bbb3c2fba8c105f01f8084cc3c74280472a8c697e623a14e3b7fe3294da60d557dd81942ed9a3d20fedf7ea30ff1", - "0a01077e25f035aa58e7088179569c14c9dc080325a274711278be97902fe3dfd172a624b1910a5841b391a20583ee231f4a1346a8bcf41f01847f771108649d02", - "0b045bbf635999b8af29b15149cc02e6de920bc206c2ea276bcef6bd9541146cb22835e98de55d241f440ac8e5c069c085caa46a9e9b886818eb33bf32af90debe", - "0b05da7cc6b47fd7adc37ecf59eb5a1673ae643acb0c680ab1ae2a5e9c0d2d71bad9e1ebd179719235f969f6275bb83e69025767576c80ceef576d82a794fe78ab", - "0a00a6fadd8d66a56755c470ce770990d128ad9aa0cad399f00c84eaad5d1c67d5364269b6c1ce28c53ba14d89012425e8f29fb941f35740441292d996cbf1fbd4", - "0a08b55e7788b35753e2b7e78106ee5625c994bba56547711634fbb2cd50953959bcd19da9e54e8d7e6e074c13f721d2a4ec6b0dc399a2992343f28308f74d207d", - "0a02fbb10e0b7acab9f235373b90acf3d3ac8f6767787d7552a2edd566aed475b1f6d2cae59db324860c22dff96419c53d1653968755f813d0c25d61620b388310", - "0a01bc45229426cec28d6c526d90322cf1af9dcfe96867595de593c9bbce1621370b10f2e4bfb8a81805d8a843f9d7b93b20846c83296d87f54becbfbefa523e6b", - "0b00b11d6e43c39fe1bfb23c44f4bf22a63be82fec36b5530b3e0e2caf11f6cd3202b22225f48486ea83850f20f0e41f9d59bd932a520bfec752a2f93c0d6c5ea7", - "0b059dc59ebc129822dc650ffca61f24d6f9e0abf20b7fdd05d548250deb759e83152b4c16985dee3a3b807f18056a95bffe153cde6f083495934c7f8ae2c75cab", - "0b03d418bde5db6f724360bdbef86f38c30fb21e70b3aa7381bc65ab87792c144b584092241e07851dfdbe9c008e6bcf06befdb0386cff4ee350da566465489e8d", - "0a06c0b6b91aae718cb5033cf3035171471ce7ea4f13b2ec6396597af23a1c0c203d132d6754e6f5c75d22fbb33ab83675ff4decd6c9aaec15908a4e9f14ae9039", - "0b07b98b8f83b04fbd455d77e628484cfff24ca0a0a4d946b7bdfacf491fba2b084d6b8e978df6248747659564b888329a43d5bafcc2a9fff843a63721fd03fb85", - "0b015aa0e8259d9dde59f8d61ba8032d095281372be91f1d4d93f0be3ec3026f33e09da08a49fc11da65789caaae463eafebc369b84a155a0ccbaddbd6656a9b31", - "0a06715ccbd1e8407503f313e8629025c53972223bc90cc35e7c7d6a42bf103301a3abc82ee4c8729aa95f57a77b4092325ce02fb8816ee0f18fc3006bee6452a2", - "0b015359d6ddd56ded3d9c7399e9be31cc9602e68cbea8f1f6c03ca2ecb2e96bf2ed648ac1caa6241d3c1799dd117cc3640f8632ad6af3cae8249669fe4761aa8e", - "0b040f34aec861893c562cdf842279a3604493b9c7faf4e89462961b3804f8f1782cba94f36de58311fe1cfbb5ca3ef5e943be9a2804cdd49e46c857655bf29619", - "0b067837ecd7a10ad7207ec4a9571ac5b3db60f75b84286a91e92bac22347c2ca304501924d8b90fc8471745686446e58a0aeef8cd39697e0ca1a7a7bae323077e", - "0a040d0b906c324b7c10cf516cebb96e5ce5d15e3bd81cae3e52ed887b8c4098f8c9ff7efd4f0bd09cbb67bad0514c040ae11c77603e53286bb155123b9dfcee2a", - "0a01950e08654dad4d6898fb8c6f1665d1ccb6d1d9c18b4c73640ab6e65aa5db01a32c0cdb395a1963951842090fa5d33731c64dec082fa6fa7f35b5f95d1d67c5", - "0a00fe04e6bfee11498240068178d5600fcfa88f54168445946d20264655d144dafbfab4ab8bda10b0d4cbaebace4dfaba7971e0f8401132516345baf92c0dda93", - "0a0379a1f4511b4a9effe0669f6311f76968cc4e5a5f1e71a49cea957928bfd1a9b52b2e9918ebbf47f7978d9d18b8445710d6df5801d2651a373f62c6a52167d5", - "0a06cd168ac3eb6ea46b515f7f722377b7ea52cad2562bbe4efd9885f569d095c6630315e00f5f36245153ba1890f9d760c80a2bace857b8c42ccb7bfeedefc1d9", - "0b0584fc9857ed02d584c6f1399265aa1c0e2479b40a571201438ddf61653ba2381bbd1184ad82d99de06ebc90945b5f0fccd195a3c7beb52da9263274ac3b3905", - "0b0775bfaa619c0182af7dcad9fb5a45a1317d80435b73c144be4c5795a87564a44ada2b3e58a4b43d535d7e475bc95ac514762d1a88c9ba6f6c520150442c8b1b", - "0b04b3afba161b57130465ae341df69d36e22830c198a9fe726cd58b2234df7820f908bf3d9909ab66229fa7fd46d60277cb09abd239ef77c423028c3303242f49", - "0a05e14b07170163e2cc66f64c79ece57ab1856f8d05a767964d3c58b485de6512ea6520c0c91595afeb0b67441f233301546b2bdeab83d79afe8cf40770a4e163", - "0b04cf695903f97eb49981a9633b552b94bf289ae00e3620da26ad3efb775aa79927c119d5b59f856d8debaf2935e50e8b8b175fe5ecbb304734e95d7fcf55c700", - "0b003bd4ecac72984906521e29bb28353872b655c4b5258a7df3eaa638b91c267628d9b6dac5079aa6bd6051896399e9384097f5a8146c052e6cd1b94ffbf816bc", - "0a002d06948bcf06daf4a75f60158f72c82bd6a8318a1979e7c08a285f634434e678e6c48ebed5f455f5d326fc608e984d2255fd7015fb13704f56e1c4b261f8d0", - "0b05d09f01a72fdb368b7d27551b493f1f5a2fe5b0631aa30d75dbf076b4300a8ff30f7261b612147ae3e198c1199707af6aa7f7b5ed473fa666bf22f4d63e7474", - "0b0512070e9ded6e29294a697a011c135bc0c7699ae72887633e96c88518b08157fbb1a0cb4adcd58d3b7aa9831645db97f0fb032416eeab8c9eb913a505d53a88", - "0b02e7be28393dbe2bf2401810de7fee3cf0c9330d8769ffc9a71f318ec11b1eea54a596d5bc766dcd6fcb656bc3bba2d0d301bb225b1fed338b27014336f788e8", - "0b00c6d0905258833ca01d86065dd321d43b717ff2cf84b0bd0e4e20c2cd1605c86a9b0471a1db1ad4049014c1c851ce894edd9927eb19a23651e945a451819d0b", - "0b009f47a6a2398c4259b21783b7f9b0b13573471cff39755413b0e6eac7cca6fbdaa6e3f333d6ea61684aa7af3d90ed04d1d204a54891cee3a01a6347ab570668", - "0b017e323bdbfe1d0f7ec0ad73620ee4596d6f3eb19fc0c19fc4100003c57a2aea3ee04e56ef016a86b55a957a611eefd1e9ce5df8ac8ba97f1c7a4ceecfa82487", - "0b091dbaee922f1b9653fffb869635ab5f4e70d2e32144fe4755397aa0e5f1bf35c039eaae14d970564fbc7c83ffe7873f561ce352f4bfe133c40dadb56902491c", - "0a030cb2b23968e3c1091c5d8e87f65176abaa103fda3b95ce12d9e56d6301073f5b805140c0b49ac187ffa153554300a58d07ab99f83c133a879f38ca5af0a558", - "0a06579252797005135ad51fee935d21d8b3f9b9378b56aca9939ac11bbc7682ab63731ebb19f3d13057081588a9e46a6c5e86edb44e0cc708c304d154fe9538d4", - "0a06d6ed493a30e495b3fa71f23651efaa7c9065f911a4f884d189cd22960b9d22b85b9af16dbac1aafe2a77319d04218da538c8f8b61f974a47fd0b17473e2921", - "0b076c86589616e8fc2001309d88ecaf15c089888ae6a25da102f83028ac933de67fffaec80b534e7200ce54adaa61f5ca70dbe08edfec0df8c1e0526e7e99f748", - "0a01008a8e85f35e0ddfa02413da926bddd65cf6f2d6343465521350000fed63f7d0e03b67ba97960bba6c1f66dce0278019693edb51a9a88be020d76944f44cf6", - "0b00609ffe1d0c59fd671c57e91a14ff9d190c2aa10500c01341106f4caead77dc242096bff844747e12b700f43f6216ec03e7266f4d7ce756b82fd1a5e4d9064b", - "0b02e5d1b263af4b96e9deec7920f2454ab665dd670511d637a7d69073ba5d8b6735a6f540290643cd08b82332acadb5f6915488e60470867a038a823a616db282", - "0a0419989a574fe390617667f54dd8c79391437631ecd808c269529f1c5e48a6fc12623a3aa70a9689c96480de0f08a4cb33167d72676b9e10f671f672b648ae9b", - "0a04107a4c5046ed8c4772a9f95b0f46d79b954ecbcc868d433f4887dd5cd3f6a1a9e2f6ebb9f6395cdfe03bf0dcf9dec180fcc05abc124241113f2994c1aab510", - "0a00fb7997a7e4b0dcf36e39a45fbf4c34ad28fce6081cd14425cc24ce1f81c1dddfea3b4d39c6c87b6c71b8890f7b3014b0609139a7f31107934424ae9ecaa578", - "0b0753336e924a69835934fce973513fc4ef03ea4b6641622182c23b0d3651f2bc65f31a408bf5094e6a67df96328c11c31f446b4fff38afac5e62ab3719edc9c4", - "0b0499f20524f1b6f04b2d3755c1b740a1dd66914eb2250b6cacd9f31625092a104bb0c3132979f4bfbef972e788bbc46c61aff3f6b4f2db3f985f63731e85f3a7", - "0b0559d2e56b8dd600ea9628c2259a30ed8a1709d665ed25bf37e5d02d4cfdf02b19bd29bb2534e9a135dfaa737c727c887c245f92fc675fbfbf075c70bc0f7293", - "0a05a3c920e30c3733cc99f700b6688b73ba5045c76a7af78da184af372c53b99ee9f3f4ff6b29b811d1c60db216134aa96cd5682981bfd37a2fda1d122bd6aafa", - "0b05889df7685cff84637b05f4f9f3d515d48570f0e22ba64b6c16a8c2b24eca646638167547f801b1b387571b3a709da34df0f210112ce72bcc9075a769807e7c", - "0a03110b38dc227b4af99ebda90b121b8939470862e8f5e2b6a0d7b895f99bcdceb993a35a51017e617b3c73ec5aa9267bbb0295d6113d767579b52f18f965825f", - "0b012ffa24eb968da2701232d6f0815312b6118644347aeab03b41cc3ba1447970a39e39cb69cd515d6884a08faed9bb380126e3d95c8e0f3190805b0f2284b5a8", - "0a07b3297468f322510c2744c59c8e049372028256cfa08046d6390508e5329dc3102ccca86f84d89da5b6ac6ba292bd9b7c0a734847e15968eb64945a29510cc4", - "0b08982f6d0d20b4a389e3889d26d727123f2ed0dcfdfd0920b88bbef47a1ef763cce93848a17b5fee890efbd8b18abee87fcf3b031c2b897e79b26f481d518959", - "0a01fcc3dfd69c9c66639d7905b855174fd6cb064843da5eb4d2bfcd2444051646eb971c8034ed62598258e25e9c6492627343ecaf7f6a98ae4dac8e437914aab1", - "0a041b5c63cdff70bd7191ec58a5bf4e41f76ecbff3f9e53693a132c08fb96fa90a9f563d4e42228d4665af7e240f6f300b97934424fe36f146d0d7640634b91ff", - "0a06afd7ff8f6e298663a1c42de33b6e5a0d71eee54637b510e0230f3cec1c9c28d0dbb8896b640a59380597ebe0e5b8e808022bbca76942a1df8cd53c18dcc34f", - "0b085b1b17c41f735111d542a4f77be0d94ea80abd847608d6371f7e8223aed1ffb3f345296a45b556d981b11060efc98fbab63a6c8f1b079eca216fdffab4fa1b", - "0a00255bb6645143434ee4cdbffa7aeba239aa7b144fef834a52e6189b8724b708ec6a1d55304f4f104418e550022e7649cd49ac4d562b4af16c8ff60b19e1da63", - "0a03e2ce8711f7461c41301e95eca6f265fa89fa679ef490e62b103699b40ecab47abe3433b47fe97c7014d1811cd4339a8dcd3f1abaa08034431808a7ee95e6bd", - "0b01555e51afce886aeab8259f8fde56f3cabf89186a720af4777d33bd97893d3817ca8da50dd76f99991010c5681c959fde14c28a6af70faba2a8e7b002967016", - "0a04736054ca8a564bdf8ccbf764a9a4eeed20a7fb2dac4182c78efb571d07289b2b45080dc5dcfaf48b15a3ac03021dcdeb98f0cec76e8ac5988d06457f0c59a0", - "0a00970e332868fb5e5c736fb9951108c7528eb456b796e0c9530a5fc8280c341d401d9ef33de4336304cb0111fd3e4bfde173b7fe1e1fd4c9f716616f08416a7c", - "0b0421afb8b6229f8550331efd66cd073b62fafb09496757f5ab49df37c8a03e12a8136c51c89b087df4572c25dabba1485a17036d42b710dd5c3f5f1da19af974", - "0b037fc93a7a4d8ff3c3a890d0910c554ecfe888ca702921c0e57df9cd304296ccaa20c17c6ce73a69ade605a3730381693f260743159604c716a3f84a6d9abb22", - "0a0002419d5b3a8e0e3c153d25be075eb07a309eba8d909ded2fa72732b45e41e243010598457a347d5d73e3234103aae82ebd31f477b01125afe8cd5fd1443246", - "0b05e9141c12cc2f1fdd0bc31e21194b1a322a8d67038b8581e4bfa4479618d39807e710a4c68fb471606fa1380c7e3bf4ab15ef67621cb5e3fdd967759595da25", - "0b0171e083f2f07dc7f4423df263703d1dfdbb9a8909e6a6e8c3fa32eec7a9f543a6ecb7e5f28d7b0efb810b91c4b6b069ce4233019b6dd446b60bcc1dbe8dbdc3", - "0a00296fa2f0879c4e6a9626ab1550f1f0adb75a1ec5ecb7e0b4c05d75f284ae2ea56348831f13806bba55b0346ff654f39f43eac1c7b801b1ce27585d658ced3d", - "0b032d09bdbd17fd9bcb47c4cebcd13e809a44a344accaf4bc41291998c256c76e83f039701e8bdf4e2afa390968d3a5b88dabc64d56a93f69d181a323e9de58a3", - "0b083320731675088c8da110876951b36078757c198aeeeccf3fa63b7fd726d84d426326a31ba91fd6ab2323643a293330d08f0d459702622495674893ead656f6", - "0a0145a94c6fc2e2f50cd3b19bf1ad325db8a69ff23bbd60cb7c66f956898dd5c9ad7c65757cfe3e3c5574bc6ef2dbf366ffc4cc6898c12b4cfeb4d31ecfd10afa", - "0a066153cc8953478e0bb08bd2f240dac5056c12d3796d9d90f6df4660d45038ee0fcffa5bf93ffba0ac4e3ac23df9e9ad89bbd48abc7025c15dda5dbd7475c8fb", - "0b07bcfe1aa1fdae2144aaeec1590980bcfa5ea06f3b419661308d825cd3aa5b17615d3ad8fbd82e0cf5e82dde576307324213268ec8a22a4d3f7b71d7fad6dc3a", - "0a04e2e02d81fb3d933c1b4e5798db90d4de34789501edeff7f5247eedc1cb3a081303aee1653d52a9a22d61cc3c3cca8a6a1f7d1db74228a64da26afde9b8fdb7", - "0b008e8c72247a35db3745f1a191675f663709e4794e4fb0d1eac0f61825cfad40feb8b7340ca93afe72f83260cd97b4808364de3d3d932b746813540319319743", - "0b031ac72a9db9fc7f7db902bf3db0293e6238e57ae26ce626d444fb07e01d271688e0c317e99e5c40d38501e22b895d4690bdf6f3d19541f95e2c57b107705403", - "0a0873b70c0a5d99b7051bbfdd350f3ce7418878cfc269982319e65c2044a2393a3b5a76e56d1293abeda3d617b6fab9f2383c5884f83e909413d62730ffbb1ef9", - "0b05f0960211fabcf99ad0eb8a303fe8f12be9e77535ef85d7ef6fa291557baa693c7b42bf91db43e67c96f92f0ee7b2dca57d8c3302803bbac80b72ab02aa520a", - "0b01eaccbd70982e8dd81764429304d64c71132f91adc33c9fc77825bea9d534fcc70bd1d4e6e176adea8d89767c52b7cfd3bf4475f02247b867611fd29f210a63", - "0a085aa3027ba9ff5982481afeedf45fbbcdceb446005278aa610a31bb74b0c60315a917460a30d05ef6e4d13133dd40500036358e965ffb8840802810353678aa", - "0b03ac2eb51bf55d95d5626f08aedc1388196dbacc5ce4157134142aab66d5be3a67d75dc6e4b935f786b2a6bdf82cd93f2b72b2c4d60c867df4b413fd4c93523a", - "0b0460a287e31989dc1073d04230a0c54b3c29b2368c2573bac3bd1497bc03af4dad2569ec00b795ce394eca1718aaae090b213f40416e0e9361b531a228ba3515", - "0a078c2e6787e995ada49565555a52af0a876cbf745a95e83f8fc30962eb62643db2dd231696e5e2bfbdd893b2b648491a7bc549a4f82e307685442bbbe96cc0c3", - "0a00f1c2867d86c719a1506fa7113e354d558b1ea7002333e4c3b54a4c6d1d2872ab0129958c749a8ff2d5d9e8a77d979de2491cec6cb6063daf7a5a725e445dbe", - "0b005b1d26139f6d2206a0ea50b902b2cff56cb661a4c8b5c0213cc8ec8eec4932522a67b2856bfd4fa4fb89817efa96c3556be3489f59645cd4d5f98f23938c0b", - "0a02568e96c70b3a04900e67b00ba0afdd62f393ce7bbd6809ba54fd20d7aaa392cb7caac4e2013f5d9ed2ff3e42368a90a48bc19fd769239362583f5a7cb3d58c", - "0b03496006b584d9879affa31a17d835438d8a65d61343fa41cdf6c1a8358e2b37d8a85cbc1bbb27ccb17e664f1cbe2699c3b3364ae2fdb883846dfb024c465c24", - "0b041d909534cd111ce24551d3b03f19565025613a3acc724a00532beaa684414f5ccfae306eeed2f64a5fda5ec0712978597647ecfcb438a7de719bf49fc87793", - "0a07005317fae0b5a2d779e79aec30c18afe2b22e10020accecf77887854315eadc313f6ec8cf95015e46a8d16911d6b8f5b5499868fd449a7bbd36b535ebaa6e7", - "0a07db9b2b3f1df4a737c31c6e6d6d65cef33f20f9059a3191d5c37f20f4913808f6f0fb4224a98b1e8040ac33fe0459c3543bb2822d72543b9d10c30915ae117a", - "0a0707931815e5992a3defd9448265dd331c807ef7c8a243ae3184cb954ad4c4a57f8c946060f23f18339bd03055058b0a147969653fb853d9539f5d04a75dbce9", - "0a0707dd299e0f2eafed7b825b34e7a29fb30c46db3e83636f1f6ff27725fdf1e873b47ad2e2630aa63e5bfba44270790e3fc2ad4536154ca67c6d50e051f94ad6", - "0b04672537a0e9433aadb9aa815e709ff1f09121bbf78132af800ebf289c99438a2a43c03262cb867b458fb5eaabed8cdea232d5c32a9c198e91bdf6f02f12ab8e", - "0a04b4791d00b2333f74a546aa4d345595e4b22b0a63a9b103093c0eba67067cd0c04c01c697a73aa6643ac9e6192ecc7b0e67b4f2fce8f879877a21cbacadcf56", - "0a04d1e6ed79269f4b0037d9612a25d73e656eb8fd7e9212ee03a5f37268322c6f6ff45f0f01c666f975d4cd5f5e9d1aa561c8f0dec00b5d84213f0c409ab90756", - "0a066564f3ee4ceb523b3148dfb914dec7ca50c1c8ab4788d9c81a9c8fd966042d049388df0092829dc843aa66b640cc8a0d62c752059e24f8cbafbbc8b543fb8d", - "0b0882aa2723bcc8dbbbbc7873e9659865bc95bc47016cc37b27eb1707b8050b9174e49a6c4096313ff4d43fd64c376ea83f4036f4a47055ebb8b36df3f8bd4462", - "0a047baf3ce37c3f19b3f87a1022d66da82bb22695fcbceb67681d249121fb5cb770a06e5a7ba35d93547d9e2768e025062e0f87ede6bbfaccb604135d32b46c2e", - "0b0378a653fcd5f38021c0b3820167fa3449590642821d2b4fbb608ab44b2ed3e864fe89416acf6ba41af707f513e661ee9f45a95c09239ac73efd40f86e4347ab", - "0b0581c470b922f1e9b91bec3397bb668d88fe67d593588e552a697cb833fca6241b116506ed9eac0bdf53feccec210cca9068356e6f4ff4ea7ec964794aa753d9", - "0a02d5899d7b50427d3636b84f0055edd42d44c84ec3f9600aae281638f83c671e63b2a4a5f5a1906ea07dbb62a3e6eb417f0e39298ebb226ca514c92efe8d3b8c", - "0a01a9bda7cfa9a883858996f93c0ebe087912b351252f53df0036e72c0c4ce5b7b5ece27272fdcf3aeb5e6f07b9bbba9a5c3b815b2d8a8e309bcd9f29bc8cc9f8", - "0b0399b4472d5a344e03a77d7752d032d188bae9217db1696d9f28adaeeb4fd03b65b9e0fa8b0a605d2f7c7e67d4f2318797eb281c80641dd620cff3184e7addd0", - "0b05f8b4861efbfa56fcd71b965e5b111468f01377a1033f2ad36502b3e245fdbd0fcd81dc556e2c5b0d7b41717dc8427cb08651d6ca7eb2a4693f11a03d022932", - "0a06f9a524ae3b27db4ac62d7430a646c6dd9c5c19ade4cea5bfdb38c5c21395f2c5ad51598c500f7d9bc9bde4534245354a409165170c844fc1131422961c0e53", - "0a02ef1750fd8ca5ce81175a69bf1c223de868211451f98a09d8eab223ff6908ae0918f7078512dcdbe23221d6dd0a566ab853f1d2263b3ff93a09e51b5d41ee09", - "0a02c14f60d8924f38b1582d6c0a780657aa11a1a41c4cb0f0cc9ad3ae22269458daf7e208294daa128f0b1cea525d973c1da290a7484d9904aadf8022952b800b", - "0a032aa88d17a1f9fd607103d796d35a3ddf00c4da30337f4d170137977b093101b090660c8e880d8950948f5480ad837b05929c457b26a36d6e80ee05fa1b460c", - "0a0121dc6ffd0d75d976cf2b847e89be807bf5dbe2768799623da105bce1d1ff40fdaa40a064148d5163db67b4a494e3552002842d6d34383e36f97a838699910e", - "0b05f6c7016c4d10a6d33cfac19fbc5b999469d7f637d4b8f1e5b929270bed0aad8ff08e7d520b3c7869320f5a8af9bf2972c484d6b0de0f09d1d3ed4e9a0b11db", - "0a0364d896c00568d1fb3a27cf24a6491a4ebd0e21d2ae028cc8fe8b1dc1df9123d332c66cffcef79403ee76aa9a418362b7a79f4fbc65a8fdb9979b5a7b1f744d", - "0a013016b73daba5ce6bec26a2d14a12902df215a1543b152ecb3121371dcfa021c91a6df050c2484ac0c12058f80af7d20c30e440150f056f2d5f97e05abec50c", - "0a05040ace88011b791636b7f687f5c00716cb7676dccdd4ce3bc04fe10aaf00bf08e1748e5edca402e9993a5e291aa96d9cefc4933eca2d19f735bf5fab12234d", - "0a066350ebf673972c782863898dc69ab65c2c1657f6c6a46cac870b8224ef086bf60cd25b9f28edfb8acfe96ba13e0005d0b05b227bb0540bf1f0d2a96553d624", - "0b011a8058342b2a793837fdbbf58b232c3957c199bf26955736bab0e3ffe8d62559e3e1ac43698352a933576379a61c07fc67dcbfe7974cf28bb6e0b672dfca3b", - "0a057b5f37badcff57df92cc6cfd3c8e5545b2de6c1dae759a98870dfa5f547c2fa2c48a499b9163233e54f65e78379a9a4153155f0b067cf2a433fbc7aa580f19", - "0b02ad7887b542fa8c56cd06169b132df2b494bb29b497fbbaed0fba57826ca6a74de1aecce1ce677962ef0d0185cbe8349d7265adda480574402f7a95cc01af60", - "0b00addb47d6b4f95959a8a52ea25555be65fb0c81d3a89655369bd75f67cc50221552d778d0ba2dcc36f748ac8b677c9ea5f218eb6d31cc56f975343fb00d0329", - "0b03bb3a878e47a27b80a09218f71f055de35cc172a4beb35b344e1ead62c1ab131e446b05a7b2e920a5eb4cb06ccb7365a3d2e49fb713761a9e36c2e9fcd352dd", - "0a05a6172255b313e6781ac122ab1d92bdfae7c93ad88b62d39dfe2dd3c52e9980b98e9f4ab96510c493d5da0a4c701d6645c69d9b52c2af2b150f79fcde27407c", - "0b03ed11228fefe6ff276a48b5fbb5bde33877b183cedb632985b4875f2409040942d8f87715bec8b8aad85ebe5e5604edb6cefe4f21dbb043bb45209f988bd83b", - "0a0320faee8c4dc6c961adbb0eb4a43d3f9ce5577655fadcb331e251650da6c68d0efcd1ab41bf4bbcc464b31fdda35b1ffdfc690996cb651ea61143b0f7dd306e", - "0b025137adc17d1d66fb9d4b68b7f6ed349b1545038905ee335b1206f4bb2ae16df3fe5f0527f5cc9b8a0969c7979e9c84c439dd81d3a7e6c5b98a358f82ee9a7f", - "0b01531976afa799db3fd1855263b60a15f35b2da7e8d44c599a6a1befcbedf12c09c0fb20ccbaa96171ebf1c191f503a8d307015a71062c89e36ac5a9e2e5c49a", - "0a00a4ed73949da792b8e0c492f9186214741c845866e90e5b60cd18ad637651a4398e9d91f221a698e3522572049ec35cb11a5b30b37a879624c7eea6464eae4f", - "0a03e62ff5690fc38933225783ac4a189a46952cf2c2d5861a4cda158740efacd7427cfdaebf82cffd555dd7b80575dd21e5d7535b91a8c3db36d89af93fdf438d", - "0a08e2e6b12bf08c05de505822ac616989793515041d5f74219f2547fae3cea10ea5e635726ed112d3cf5fffcd06065f15ff43865cb003c701dd1b8f999e7cff0c", - "0b04b65c4825fbca44bc2167defe4c68adcba0c7bcf009315bf67c1c15cd3e5054432447ad765d28b57842801b3aa3bd62a3455253349c173d90d0829edbd11e16", - "0a0894712606c2e132107da923bb973183d9a061c4725de4199008cf00e710cfa05cf2f8d4c0f14efd0c460c77a498d482751fb1a5242b2024a9db32812bf9f248", - "0b05e1a0a3c81ddff0bec80a58ae9c04a4f85b326a60eb5374101277ad49e6fb235e572be242096abe1219795469a150f4d23efbe32fea52b550e33ef75d3af97c", - "0a0447df2e3908c4e246a8d27329a07f98b88b60ed5c73d19ace7e2c5475dcc990453ebe11e2f8a8d95501582f833da8b452eef75494f49fb4afcb14137f23a4b5", - "0a01331aa26aa4344fc72b624df24146a4f8e7a66329c5b114510f0b43b5bd8aa746d7a5afa96a8463b6210c0ba828f70544661ef2dae806c949cb0ea7871384bc", - "0a04ebbdd45c366fcce20c21f3ec0210bfc716aa42f938779abeedea61ace246eac7a63281668510a8144d7b7f04bff185334c6485e4552299717969c9368cc56f", - "0a079c9fd976fce4b5fc453fa1297d83864a385f26f50a188258bac10044483a0e76bb968d4334789f5b9f044f7523a9514ea9a3eeb18350e65bf82089e45f252f", - "0b05427a84f3d3a02459fae78951e14615b5c458da97a0178e4159b3eaa59bfab96a5a71262b8db3a2341f86294edc4dc5af521f8d25fe200832ac83f72860e8ac", - "0b034d7ce25b89c34c5b465fcf11a67ee49b671de02e3680c9e52a62380434c79661aeb91c0606ea5435c773d68f14a7065209e666132033134c5c7b8fe04baebd", - "0b014d007ee1133e0138ded5b3df6035a594a2682abae1e394d495d8de8eafb9bbb023448e4c5e24a8fd73bf5c107f94a7ae1887d5f13edad9314fd44fe3fa115b", - "0b07108e454ffeb78fd891160393759f53e49e49b41eb8556e8c643baa36124dade57543238e7c4ab3faf41e352638b407a6f401147ad02c63527fa706b21049aa", - "0a086f03bc1ba6b3d9ad737fd07e109d19dc4b21b1c7335c6e1aa8b78676c2caf0ea6b6fb3cd4507fda8876e5ac35ca8a0033daad9f32632d4db76f7d51cb761c1", - "0b0601b8904230a7b833028a8f2c8da47da39de6749b81ed062bd807b9cc9eb9abe2ab919e31e7b27f6dea77de3a9fdc7e5a559878f911603b79b704404e94faa8", - "0b0889bc8276cc5674f74e7d7ceb6bf7d0462c72b8107db96d1c3b0e1b64d021063f6586ecc6fc19536c1cb53f097eb86f2e340fe316765c9c3ad1cdbabc30082e", - "0b0483a752ab7ef7d6a06af7f9b55e99c2f3aed5e63963e32931e7b44532d15893e8e2d8abfe8a11837d92d437f626c11c7f95a9338a9f86bed9d80fcba587ec39", - "0a05212bc36c288d0508c8bb4ccbd5d6d5f48442c9e98807fe7e13fa62bf11a4edd4fb7c81c9e827945f784f47393070e3968562b093e175bedd58a4ea2b5b6e5f", - "0b06800a29a57697988e6f3b454f8f567642055ca79fe917d8933c1a18886186ede0edb6e3a579c29cfce191ce5880bd5e423c824ad07bb6d65fc16842fa8beb30", - "0b07691d996b4ed4cd2de22c55e393a3c47d770322a2022c28dbf1f7c5c9ee4e0eb23d1ba54ad053fcc5a2f5bf65d19c6d783a9d234902129fc788c11dca6b4fa0", - "0a01c9edaa9f2ef0a3a446d74b549167b81414133f70bf73d2c657e1129832c050eeeaa7be196a7b6d24e18d04b78bec32601b2c7cb43b515cc4117cb80dfc0d38", - "0b03651991935757cca67741145ffc448449d0163ffba37eee04eb25dbc218b088afe022d0ef305bd8175939fd8aa689da91f89059250ce54aeed618034b879c7c", - "0b03768f9be91c46e41c468dd85a30ec71de1fd2f3b205db258d5cebf6801c714c50c9b27ea32c3e9c351530cdf2a64abcdb14e1dd1b0cfc40ceb4317e4ae8844e", - "0b060b7272f23e8a702610b5e372573d1da10199a176b354341505113663d4a6898d9dcbafaa5d8e73629618f1bb090f0cee155bb9c36e7f0533d97d6a2f25aea3", - "0b0724b1381d28917424a6deece36a475cfd86aa6fab1c8b238baecc27422f3a1138bbd937ab6fba4f39cf1444adab69fae35d05c31e4e9bb6c3fab6293ca43053", - "0a02642a4e9dd2b380b5ca09077f80131b22e50f018db3c5bc8e700ec7236fe85fdeef8c01410a3203480d005c238bf30f4c17a3ea7b12b693aaac67897da9ec1b", - "0b04694b39072fd9aa3a7bcc4c378868db29b1c41fe21fb1cb7047d4c9141123d001cd2c83aca2a27135fadab1570808eac6967d8b40a36b14132298a8478d8c1f", - "0b02b0a325d2ad42ff24e158fc7a6ccdb54a84d37407e732e29560a1930204f0999c83d6fc8c3084e96adb7d7f1502e04e969ed037ef164ead860ae195cb8607dc", - "0a060e25a5461d26c670ebff5a4abdf08b19328da4eda328a836e86861ee195e1b02842b0c815972460cb6b71f4b7b41da13e6d1918dde35ccbe54f71e7b07685c", - "0b0696c66ae8fb0b3e8f34d350657f06baa19c53092e6d8bcbfd2b392a0b32d4370fec825bcc2e3c449416edb34b6bde8860386591a06f14f676c3a20b1365e401", - "0b02138c2d0c35db59a63cc0453aa40b7fafdaf94b1b6722484a682fd27ff2d633a032e0e2a7d37f5ea21d828a4386bb35a0ee471eae76adef9140c06c2c5d85b9", - "0b069a7713362c492f6c1dd2f773bd29d0331b570580b14552f10391153385b6e326a5326f39f0c3464c578f41fd3b682d7111d111bb9501a29ed486da62c7a944", - "0a06d03c65fd3a8267a366b15f8d9181ccfde456df64507ed9885fc56d54a7a5b2faa8be8477db7d3e4b6c259e2f76a16212edb93594b2b8dad05e3ae4f950d00f", - "0a0212e4168ad1eb08aae0f79dbbb9100f5e3232d0589b4b2398f55c197e1406e810211ad03ca4f9989fe2a25918dea9c745184e4e9b05df37501a9e98fa3613ac", - "0b03bb977ca1dc7d7b8ee7145619c2153a2144860c04b299e47ec171039f4be1f7a80f4c150295430bdadf2999536de404a621ddaf96e69263d95eec152b5ddee7", - "0b07d07711961f4d48667666bc2774c18adbdd3a9ceb75ce44bbdc8d3870c06e3510223ca2f308061fe04b76caf73efc5faf1be3dbe3e35891e2a3fbb22ca8cdea", - "0b06442f7b1281c7d0b6e8bb2ec4ae754a447d30c677fbe310e435aa107599955735657d304f0da8885ddae6e919f1a09cb16916a5eeb9d52da506cb96e469c790", - "0b06738568d03648c97feb6cbba76c7c1f5cd71b225fd050ffb458da2a5a4b00b82c40f8cb29bb216eb4d889416c783b71d352d23eaa8870a5d6790c653eb6950d", - "0a04dfa521e6e97fc7f8f87b7ab3580ed5171e591b392367ded698d1c3433d258cbc114a930b18c949e49fd2f6f16e54824e8881ed62ffed78e37cf49c1d5e30e6", - "0b051b2d5ab3fc8a1998ac88195bfe641c12ce72236ef7bd661fff46f31e9ac63ce0e11a86d10dc2d80c3d1a063b499bded8cf21be823ef4ecaea6f7a36b57f24a", - "0a009454d4f06dcbb79ed109e1b19ae18aad3df9fceedcd78c1753dd4786594dc8e93db11a22d5868fb0bbb130f10a7ebf61ca42b60e07170bdddeac0644f1c049", - "0b016b8c77147c7357ac71b2767c1ba98d85eaeca8dec8b0156fde23c73de1e06a293daf96565f07aec06494149c651b890eb58b2e5f5e2d15f00abc71e3ab81ba", - "0a01b683936f5e48e079d4048a8474fd9ce848f75b6c652f41d0913a545c9e4dfc1db7b1c54f933d25ad105bf27834ef55e4dc39066bc6a033df3e7466bac56e5e", - "0b0683101277e29a79b6ec2dd41d4b064983f714c033aaa9848464dd56e11a4d8014b8dd39f2ea6dec9b5ab9694b81097fb2757d03eb4cd87933edb2ac2a6b613e", - "0a00b72ae72d25576291a18b4c73ee6dec2c76a3454f69643b4dc85c47a9a9f0de3785f27fe567a5e746f0a77e8a7e19d3bd0384cb02cbbeb4b168cfadadc59e25", - "0b02a86a29b52c168220a23ed44d7414cab6c2c8588b869ae64ac4320509aa638ee57abcd77efb9b9004c28342ee96a1c099b2483666aa080d937274e9d2d26bac", - "0b0284c540ac5101cf08f9537e579a43f83f33eaf7a2642516a6766cab4283a1815e951912f480f189ba587704e223796f9c36e24d786137a3987eaea42c69016a", - "0a02d00e3fb9f1550fc1bafa3640440f4449df2d074f6a71bb52994606ba839b6a60910d6284a97cb4645157bc80aa4589ee13ee47fd1c9afe4ba90eba13361bb2", - "0b0359557f103d3ec4fd7a7a8af8159f0ca274d2a1caa83c4158f1f355c8cd793aca7813fff3fb129cd392a235d7b73ce8986d2b14c86c7bbc6bcca73173c872ec", - "0b04bfecf6f5153e74d62f7c03fb0a262582679748751c3f909211b1fc1d1db64dd42ea27f62b4c4d1532946fbc78443fb6c9a25a9d081ce6376b68bc68d0dd745", - "0a023999e9aa19265947cf378d34d2cfe7a541915e6f8318b1609003033b3b5e10113bcff35c14988f7337ed6ecf9e58b7de52099bbdba7eeb6ba23354df4b1fd8", - "0b06509391b109ed1a130a996c650713e50c7389698582f6f091f491b188afc0c4d319a69c241fb2c30350ddd650e9eb3c7734a7ba4aeab387fe26a64f4958b9f9", - "0a03a20900feefbcf7e57094f09fd5d50e0bc4e718276f1e6c0af78fe30251131d3bf951080f2b281d5ee214f5e1df159204c5ef34d8ac4ed7eae6249bf068d79f", - "0b0435f5ad9440c9e206456f2003ea98219a809b467ae9cc842014a5bfba62af34a2bd7ecc8d2bd65106ffea48f7d3dda38ac30df57ccc60dab5c9cecb7e93014e", - "0b049648e132dbb24a06cae748ff4990374d1ca94e6af588c8a22704a23d919219c66c219ce3739a8c7f9c734cf19fd0a1b7c1a09b421cff2271afd5842056e647", - "0b038d1a26c68946f2849f327aef29bd44935cfeee521d800121cf4a614781614d861a282e9b6a7d299dd13891900e075d13ec4a9988eb92f9eb10ba6b08a9c14b", - "0a03870ca214d007421e391a10f8beeea39e070a1d7876dfe704af9b970e3641b754862ff8e57236db2e3541f5c6e17d6e039d0be382de34f986d024a5b88382af", - "0b0108953e4414f0b4568ea6aed8aedd9ae192a3b819aa421507e5145e8b28e33027747870676a48f7fb4bf7f67dc66ed613fa6cc8c9fca41e2ed6287da09d1d14", - "0b010005f3545ed90aeda5bd11095b871d9f7a9e7129cf592be086c1b9be84d5589e4d7527c0f1a3f25d4335fb01f4cbfb47eaf81e57487a5ef61ed6b54ebc8610", - "0b0254c773a7926566772f78c727bc66adba6af543dbd108fb5c54aac0cd70cefd28c54247a0c1daf22f1a693e974547000e3aedc71325e817268b676aff962f95", - "0b0777c88de5c07c8f302b07138c135d347fcee1ef578095cac0e969aa47c959efe2a47fc5f983e4e54b478c4f8376ecc868930dee34bbe396633191ffc562f8c8", - "0b08d3a57caa602fd9091ceab1ccf50f2d9e797610d416097723fe2c8ce179a4910118dc815d0446182a0d60735a8aeca37b20d5dddbc75b10d77a942cc0a4a721", - "0a01c4c1a17160e6853b651c7a4ff6e0483d203e561b287a19ab7ae195010c26f531770867dc97d09331947f72efd4aa5ef2462ca17988b69c14e1b416918b5b61", - "0b013f0abd935c1ccda439a2cd2d9fab255f6ac703cd87bc1477bd0d1d5e92d5f559c596daa1c6835bd255d5a88239296e151bce811de25a793f854bb78238151c", - "0a03182d33a42c71f5f173cd97b1ea5ef6a8858c4191d1bfe89cf31a434c132256ea695452acf0330d8c9a27515beef788dba634af3a869144a5ebc5bfd588f33b", - "0b081b77784ff78d067ad317090a5e041ce268d625208109368fba2a0e2c0b8ca340f67a6da052bd27bc6cbb2e6d900b590109488773364c62ddea1a777d64abd4", - "0a00017b0554c5559b91f64f95a9e0dfd984f17859c74cb6ba236298e67b0f3044b022e1fe9afa397640c7bf74a7988617cc0fe8f350f1a52433e5871ddf4789c2", - "0a0615dca87aeb0b37e47d372adc6315ae318d38f7d0a19c9a75392fdb4a61b3e13b749b803a9c4a3b709a18a4b6a04b9b5da8cc6abfb172542849082f63be76eb", - "0a02a4868f1297fd292562a3dd40c693463440c37b710e63fefb7edf5d2f09526d641a00e00dcbe54c8bd173f4b57acbbf838d1ce0fa5043fc1e77b298890ad373", - "0a01d5f0b488be6756de947ec2bf1c1ca8e567acf4ed43ebbc16f298163d50701b18022ab507faabe01f159e16128158daefa2eedced347ac0a280f58562114c51", - "0b036d3c4fdede3a09fadbe818ff93b822d047070e98614f76a15908df97b05eb88651a1e7eeadc6ba124494af7a66b62b6eac3184804605d993e84d6367741c24", - "0a00be4e8c4e85ccaa1b2f85cb2e79a9be46f098a6b6ed75d4e726c05abd5c4a31de22c98913364306b60d78e743719dbe53685e47bf879579fd11e1ab3bac58a0", - "0b0267a2cb9c2ce06345bcfdd398cf0a5c9f7e5f41309f149ccf001888650a6c79df037c4efcaa09468d3015430e17942888ba5348e4e6f16e7996a86118909731", - "0b07953b1b032046b3b11cdb0fcd9d60b11d9edcf8ee24f1630a369693df76e0053c952ca34c4e57c83ddcce40976383152f6dfec12b3661bf570f45f00e4a6f66", - "0b00fc49165fb8703839dad18b09de2b934ab11cb1a62ecbd22e8062716042e65a36ea9e685eaa94bf01e156e923384831c6d1e66b1930b6eb2e45e11cf7847e42", - "0a0561723932064a4b3540d61b9f676113ee722ce3237f540254da6db835801276ebd5ac288e95c07d8497d4c03ad36f6ae111ff1f45fb0c6a5b5bfabfc6f5ab7c", - "0a02345cdad4ad76f0056a6062066274a3e4520b072c6250da562efe0d449dc65f112c869a18bbd60b9962017286996ce6c5f51ceb2d6b00bd771c85b3abe9a2d6", - "0b0118c61ee13d3e92f095e49c3cf807be9717868bf5c2a89949dc4f1de6d6fd07b1caf744866be3ddc4aa2afa81996aad6b76ad99d9d6873804c7aafc7ab09aff", - "0b04eee9bcccd3551e6d00a3027baf4f600c6d56fa1893bf0dd17f877cdfe5b6968b2fa73ae675dcdb8f33c5729f2fccdab79362b8fc2f848b58495f8493b434d2", - "0b0244c7fe454e7df7c2f23c9610c41580559d1738afa9d1eab7f1aca5f15212ee889cfcb483480dd565a5f0fa3f753a1d7bad52d7180ca65330a1bada9a2e51ae", - "0a082cc3306229327d3639c4dbb674094df8ee1251d1f7099fdbd6c22f5b18412a440e3ea01fa7355cd6d77be8b781153e1f691c0439121cfb11fdf4cabde7938f", - "0b03a6193df207107c0f4187185d2892292e9eb520711387f0c4e0ac924dc364576f3681bce0211267f40e50c87b54616c851845e022e6cd30026b06c848b09ede", - "0b034a888c21bddf9620f275403a06fff93e00bc53c66f591261a9f904e031a7c279b5e8554ac72e75ca99c09bb9a49e9b86b4e35ac0d95d9f292664fcec11c138", - "0b03fa7d418ffa4a555e10765206a895dfee5960f06c0704dfddd940a874cbe712ca7c4b3fdaebaf3ef99905864c5cf490a379b5f5f7ed76f2225746190018142b", - "0b0651e95634be71ec05a397f70b70c4009ca957fdb9ac82e587e73075fe272de55e22f7fc379e8c17a03c6be9a7e903724ea212674a7ea590e922930c9c653c48", - "0a04eb753ecc7fe3e02a26b3c7062e9631cae41d763f8b838f7332edbddf37e7fa520ecbda8abef88bd1bcde687331a231ff49f6bc9bfb497996e5f1c37a5808b7", - "0b00abab00a5832f28e4e9a72ad7e79193a06b509b22644506f4142c45086b106783365b6d0b185a6196053424bebcaec9bc5d7bd4bd6823ff58a50a805e2073e5", - "0a0826c53522b9f9369f4aef39c863cae406aad82ced9678fddae512456fb2a59545a3b5fa790370ae00c916da51c2f2c0b5ed54420d0186ca130fda9376f6bca3", - "0a006cee0bff39e7766aa027944ae4adc525a180eee3f4eb6b1697a4e06278e45c6fe630bd572c2f780a4edbd5967197a38f720a7772c44ef136fbc31ef3b424b0", - "0b00dfc9cee057b7676bc44ea5a322e148e3f21d226d166afda526ea7a0c996d3063d1e5d0a85b257a83187ece2edbf7de20419d81cc663625275a3399c2057096", - "0a01e1ac1ab627a05d16a04fa7f9b0a57589a83f0cb6a0acaf03ee370a3962b2206583ad57fb489a5245e4d23c1caa0aa156f16bbb187d53cf6d43dad0749b3f35", - "0a065ef4855009121eef29af59ca4fc931c8f722e7d82e78c180439a263eaa5947a885bcded53830f0bc5c44fef794cea903878ba21ffff80a51381850bc815aa4", - "0a069b29a6098f020dae2212f6db47bfd80b9f9f116c637981f62c2c02acd61248e0d12ce51fdffcad50d1cdb82b6807aea9177b8c10995291bed53e2e928d71a7", - "0a015968f8d49730161fd6a9ccf6061bd547a4aeb92edabe026dafae162ee320ccd796dfede3ee98080262cc4a2bf4474be8b6d089258b211be584ef74c4e07609", - "0b0550483c4760d38fb364e2c325f0776a10d99bfbd96a400876d77ddedb492ece55739be26ef5b5ba835e056e2dd3cc8cfe66f3750998354b2229c0aa9b2c0072", - "0a0779da14046a55f2db81580b29453bd68caee51e733759d260afa31e96cf31cd02e2d6f2a0c6b9e74bab4fc9aa233087d0fba95626df3fbe0efa4b86491b653e", - "0b0626e9f55e69b4f9da838e4c162dbbf638711cd2868f6e26644fbe776b9999404b4771f2a4488daf8d44ba06e7216fca102b3abcc4ebc571fbf1cdf541b9d30c", - "0a05696684efb6008874baddcfa8caa8d1df9c9bb3b67d7ae1730ce4eabefae6e0612ccea0ee8d3ffda465688d30e0c1825ae6b1e28efb9d7c3c0bb307a12d5e64", - "0b052dff3336a7046644d099801849354875a1a16ec13361fa8f9246ebd7762aca5da3bbf01e2e7c8036aee94db67b51a732d1e93d44093e37c0f5343b99620afc", - "0a03ba67004bb01f9f715a952b529be38142f71d7c33fa04c486689407421d7ca88ba218508cf7feee97748bcec515bc1b7f57ed746d277e31c981cbea6398e745", - "0b02968020766fefe599693b62180658805bd9f8c8cb349b62ee80d932200d95522fc2bf34a3d3e7494d0fab30ed1b7cf7ae745c519680dc4dbc9fe0fa8606baf6", - "0a030e23776855b8dad9ff379c67e036e3098dae793dd9d83ab21f8109b05662b3663ee250f3faa0854685f9908550d407c88f2744c0ac4eeb64bdf47b0e3bbd19", - "0b090611f669f07247b907a21ac76c35b1c9f6fa8d72bdcb07a71fffabc4d7e08cb5cab7809320154f242278df76621b83ff416213f88f6983a0e03f7dc01dc51c", - "0b05f9c99db32593177d9c108066bb30b6967b9857da97aef55e30968298d7d57c0ba402802ad4c4cf12ae77ebfbceec6d2a1d7edf4ae97a715a5c733d918278ee", - "0b08b6506befda706e6df00661dd5e5eb4353687d9891929ec05c9706f04d56502d45c4133659cb63e35cb025d4bbc12ccc48aecea60890ee08d8c7b77f7884594", - "0b08a29e2c54dffba0c2a40d5d0085dde735f089c665aebfdbae7ab9fc58d0f85254ee3230a9127ec6f861f1eb938267049e62f075420d31f1629b8fe21946d063", - "0a067ccc755718ab4db8b9da5b1e43f406c9638bf5797a2f7d5154e020a72464942d1619e9263a924610fb4e9d80b362f43f99c95059a8bfb95616498c07bdec5e", - "0a06194b840112c58f6ba57795b2360a62637ce6f49f996e78b50180a7a8f6025b33d0b6f90dc803538e7317e985f597a35d1dde22a45780f63242d033982d1317", - "0b0448dfa2122a58e2d7e3734b3410f5282c53972c905f2ceec598a9e45e811cb5dd4e8f54752d1b16781ba9eed7019688ce51425b179606d17706c86b2e3db2bf", - "0b0369c761d4b5fca7d080d9dcf056c555231cce13a4ba961a31782f0ec7632cadb2869e0d0e512b90d5c8a98ede0ffc9b9f3c161665b673eb2b4c714dc044b22c", - "0a012a6fb25fd206c0da248993848c6e28a8178c6a9b83902b8fd2c0b1bec16fc5b8b72d1cc9502c1d41aba649b7d1129be3a8c448f36f5c342551fbaba47e040d", - "0b016edb31c07ef29006ec992fef68166c4da430deb82421b5d4ae3d097892995662e42cf82a43f0e41a0b2cf92544a28db2e344ef0cb12d30002c8f9ca8828ba6", - "0a046fcee3b55549d714d1248ccef97db6800b07e7959c4a42d95c1b845c52381bf565db9c7a6da729e681e2b2c18fcbdd5d0957aa69cd0e4fb78787fc97ffa41c", - "0a00153bdf96a4b1e6581de39bc52a7c0e8982830d4aed561bc0297f5e4b8a5877b5b5d1689654995452a476387080f2e2da31d4ddc779b09ab586fafd0205d21d", - "0a04dbdc17234a8d42df11531eaf9029403654a926c7f6699f696ff464b52669f7f0d886a7e3862ea7e79e53563087df108c012851248db0220f17b0fe030cdd64", - "0a049b5c01ba6be97ee4c60bdb1a157a5a292fadf0da867fe86233d6d6b1b9f5b0800d95208622f909344c4ff4f1219e57b4becfc39e7177e38cb68d490097f7fa", - "0b03ec58b9697f1ba1c7cdd2596a2a6ec4ede83adae61af3a03ce634efb4db97f08d19873ea1c1d4392d934ee93cb2e5095132066333ea8422eaf6b9b2f1bc4117", - "0b0877789502dd2bd4bd0ac88e3b3a593cd48943e4631e6d18edda33c50a3ed03ec266ba1a3f64a013814b529cbdcadf370423556cf1489bff7442fbe8053ee477", - "0b037ddd4e58d2322103df574325a0656dfe5b8f08101cf83315db632acd26009367f3d6279b6444927a1ddd2f46449998d122e7f8c5f7b1e85c675aac371bdf7c", - "0a04a2f26f52a37277c38633035237977c6150153042a6a64e12469c177f06ea0b890ba137ca992c553d5fd0b9eafcd15dce98958fcdf257005c926ce74f427ebd", - "0b060f7aec3110ffa926431951ca5f70a7905fadee513d050e3bcd5b44974b960361dc3ff55ff36d3982ff4693c3ec518463cc5dfd619e82335b8b694f901215f5", - "0b045198c1c29f268a8b57df57702bb0b7c6a7960af8f7108edbf56d6abf1e2c465db729b2dd01253878bae3ad2cb537818585a13238bedf19cad34e981ce1465d", - "0b05d1ecbaec06741546ff04d06b24e0e53db611caa1f2b80e86636084d90f667b66cf95c81f0933655b0a7ae7262ff9fd32cf70c7869b140c6fdf4594c12cbe7a", - "0b036db55739ae2f96077268b2f9478465832405bf5c1b7fda31f4f6ca486a87dfcc6e6d21b0ebcc1a4e25ea0c45b11350035390e2c881b7a35bc0666915219324", - "0a001bbcc4ec1d939bd6377ec881529bd6701ee050bfcdc56991bc90e4423eb0ca447030def2b57311b7246244f16e807a73c1c2b806caf40770ddbdc5b0e9f50f", - "0a08910965968bd845e9573889430813be9353055bbac78f26028325b4d2c7dcabc3b36d7c7bd408e9754598a63451f6e1195cbd9fb7b4f0b9cfe1c1b8a16aa379", - "0a05f2cc752aa16ac038e15bd74d69305912cdb4b4e6456340ce59781594a6ab398285fa9906f6e0cd76b4039eddeb6d49e544cf5b428507dbeb21337c0725e9fd", - "0a04627fce4c0546c068b8dc9de0d470a8ee874444ee9b376fcfb5a6f065279532afdf0e4dec98912448d38b79ec185cbe23394928d9f033995bd8239b004f5108", - "0a07c0642ebe56b84e871ea53a3f5af3511f45d42cf043246ee404a10fd00d7871843be4fbb033f0fbd0482fce0b30cb1c6719d835938def2da69af740157d047e", - "0a07ce803b17f55b2bdfc9675f2f6bdb245ce36a03cb5495ae621989ae2dc7e800cd69d8dd9c8df56a763bc1fe1b3894e96b46589e9a554ababc7375cec3ed9937", - "0b01210d93711bcf5d83409f2ec0a44690b57e0fd2d6bdc3c2beb23da32fcd33a7b3ac54a647ac2c47b1de18d324475ae5501c0d5ebf4c596aa073c9f17e7e8e0b", - "0b08e88e1e7af081aac638fdd5dc18a532bbb686896428e147c7b91c0ea87911efa612e27725446b21424165d2dce35b8aa55b7132e1e0a5b216350eb82a6d7b73", - "0a07e66f7176016454b164e1ebc59dc02206da8d642b8537b078eff64345a5569f504fa73e5d91449fa88899009fbd2cac04ea838b6d1c483381d831d32dd32907", - "0b0103b518ebd3cb50a8df9499a99bf535130e973bf9e9cf59dab979496cc86f935061272ac5c599e8c0688690429a8dd2e8075ce046e6953e901dc92fc9c745f0", - "0a014e05b50bc977f666847c2c185caddd31a5a14d8df8847c3e9dc9b4c5feca4bea5ca2e277e9daa3bf237a22c0d6f78b1c3cad49b6fe1b0541c4816104690a27", - "0a06a63f5f83fffaa3551bd0c4226b117ddc0aaef4ffdbd7a1d744ff3023555c9b5f34aefb0efe9e2a722e24ceea4183cb4f3956b34969551617612adf1c47a5d0", - "0a0373c4020ef623534147529220de93ae899bb7d0132312fb0fb71aa0e857c9e26d708d9cf4a7ce4dfc810072825007eebf4ffdec323f5e2585c1aa297a82f519", - "0a046fc6ee105525454f62ae43949eaf87ffcf8bfd7e98f37685bf20bb7cdf33a1d26e2e45038688bc8d4aaefe1098bb6978ac3ec578bb1b6045df382d78232c0c", - "0a06bd9cc0b0ead5f49e02cc39d581270ac1b54dc5cdfbedd18003e380b510b8c0e585ca3c744962b53d3620265f20be13210a1d81ea09c3a1435b44544e2c43cd", - "0a0806dff1cc990de3e9acf4a027726b4a7561f3400406c191aaa72f5debf697612ddedd68d25ef0235a9909e2f3b423518025c0a4f66e10713b49744f80312a54", - "0a031289630a389aa79b53bf23685b3680e94fac0702a38e0dcf10a1af5e7c7a1f7c75b54a2f850859da0e422ad574c2a5a76338a9e788aab7b94213a17f067ea9", - "0b0815828a83a2e26c728cf5f5f60ab7ad147526be89322109cf5c5e308bafe680e8dda4cf1f146486b2510bd4a80f1b584b5cd6eb0121551a4a962124548c4fd0", - "0b0529bce17bd42cfc203492333b0a7aa3e3bb6dede1c937e85a2a413767545f9e7870aafb3922febc23ba7bf4efca92821c4308a886bf58f95368796d691eff61", - "0b0691e72020943c226c84b2ba2ec67f3405d6122351a301d787deb8e30b91e2d4603f0c3bb9ddecffccc9db93a3e53b3e440fea8aaa625db112e9571f40b712cd", - "0a04dd2fe34a211ced8fa4cde01db7fe77f62ca39da94ce40195c0c6390043249d19d6e66ca2bae0cd0087ede7a099cbe116f5eca777f2763b2f413fc5942f209b", - "0b00698392bc7cc6c103e5ddff30b394769ec2a8edd93cde6aa87b3774008691dba033196385e92325daf74ea62bcd57c78a446e8df30ebd424b5a7028d0092a83", - "0a0651a8f4390facab090a41e6e77ced2649947681f3b769f817f81df5cccc7f08f0434920862ae4b7d8e646caa309ec701eb373dbbe4a6f0157f67ad9c62df08c", - "0a0093d4a8f4e5a27baec290436aa9809d77ae44fad82587a3e168de68a6fdf0c4ea2889478e59d943e0a5175847cb73da461c4ab81daedf281282a9dbf82a1905", - "0a019a9ac8bd550a07cb0f3b59aae2a8f6129e081dbf469b807a4aa0b5f62716294de24628f2fd7f50de25d4367e58e6563a4ba789368df9367a0c6f1e52599b72", - "0b004f40094345abe944e7470ae16aa32207da4fdb9db93403e6cefde6afc9dd19e9bcf00c2a7b1b337491bb2b143abf9b799eb69191d6866deaafcf6a1b82d13a", - "0a051e6d41fdb61f97bd5bcf448cc9700f78566ae1133a4756efd3b53ebba1ddca8037e55c3844c9f11b6cbb3822f788f0797b685876e1a77086ee4e5b3f7ccaf1", - "0a080d7c6a88a4c584304e5b182b005235e6f90a65360f24f0819678b02abb573e3756b6494251a29859ed11463300e6ea17bedda6d075fa4cc81f77d4c34da53f", - "0b009050bf986aa4e31f4f8d2d0a92d14df0682d3db195fe6bbc74c6c5ef5be05de28e1721be8da7183c2084496a8b6522bf94d6a7b237e1ebc390f4482a7007fa", - "0a0783ec5e6a661b07171f37f0e836e2c8b41ad93ee47a012227d372b96931a99af20a6b030e5e01e1ccc19770a4cfbfa9565d1ad3b632c3f396da8f995d950bc8", - "0a03ae1ab93a759f0c9865cbf3730a75603813bb61449ecccc256b8900def8c4d009078a860d82229540be7256abf87fcdbb913d96482c3b54b7cad768e572fbec", - "0b0093a9c8d43bcd0b9e861cca7aa1a1873edc61ddce1aa83c8c287878fbd8fd46f851c2d47ab0631e6189719691b08f92e8c5813e24d9e86a82df4dba02336820", - "0b0748e964ef37d78b95ddf46d347bc7182a061b881cd3070ff6778c619e00fa40a83da1d01ee99c1017e409c709a529f712331e9dde9cafcffbf84efdbade7553", - "0a019c607233f0582457c9b77206d3696789351b155882e09ea2e64d1c3792768dc18b02f8347490f6bd9db14e8955ad8791be3e97f9d59bf6078ff8efa6abef07", - "0b05ef172ba4c852c8b1061cd548a732d62b3318cf40b076cc074997bbf801dcea5ac3b90740671a07370079320d94242cdcfb142e8466cac890d921b69bb60f18", - "0b0494295799b52faf0d728e7f4054296baf2c4ab46179378efbb3a632cb223e2ffd5bde376eab906cb3bb6d2f18d46825e9f90c6a6a7509efd3cd87857a90287a", - "0b08219c3ed18b8a6fc43e10e5bef2dc9f8923deaa1215887099d786afc355d6960a0fd3b134d590c76d2f173d027c389d06ce8df30f30183928e4da9378454564", - "0b053c26120e205c3fe63d1ff661df69eaeddf811dcdf30aa6cd00ef154ffd2f7caccec259e8e2e303066a2283d59d0907f5a26b63c25bace75f623ca5a237c75b", - "0a0568334e136761dff23415aa2221e72d17a9dce8c7cbdaaf30945147f20ac00bef1bca77d96066478de570b55ee34bcf328d874a0b7cd675944383dcfbfc30a3", - "0b0544ca034d9255dc95eb5690c156b7270375094461858bf39d7069cb60093447b1da1468b44500cfd51867fb149440dc6854390cd7e6a82fd05d211ec780b60e", - "0a05fcab9c4c39a4af5e8f6a425c985e58e7fba3454527aee57cf0381f6fa277f3cd94eff20ca0fa7637c5cf395c7c6ba811be8fd2de59879e43b6577333c9c932", - "0b04aa1864ff37f8d888bd01195e7492cbc80ee432c9e3c3e5731447d4842bc7472168f94b05402ab450927e72c50274d12c9ef45d5263526ff99e72df97afa3df", - "0a04e4eefbcd095729a826df00c99b141670da6df682a4a2943f7332805266ea68b73490bc4238262058876dcd61bcd80229ba45dcd1c2ff860adfb1b030df710d", - "0a05a5f9e4bc8edda14692e8a5bfb0707384b3f248ada5c6a790a73cea7d3e11b288835bcd8ad5b8b747a1cb724afc008563520a483a832f2058d48797efa9f282", - "0b0678cf34c7608b769a4d0cbe4879e56817d0738c22cc90587410125f721f7269a27996489a475beedd782a309ac2f4a081b51903b9bfd54c906f561f522b55fb", - "0b07fb161e6a7a5f27e99147219a86a59f6fb50a5d1cf5e3e6ff6e2f36d23b4190192173a2fb56cbd74a369ddee428213d88ef8fbbde474ce3e550bf59d076fe88", - "0b00c101df2f168bcda19c835b808972de8c9abb2d30502d9bfb3b36409962b27e445564a212cf4e12df9ef3fbdd5bfefad1ea25c3463658bcc9226298e794405e", - "0b08207905bcd0ca0c802aecef3f2e97d1fbef336867d23a92f116c7f920d11d04fb8bfb77b8e4b653e30c7be301099b156908320fd0ae224d829df80630b7958c", - "0b00d6b1c863f0894b35656a37682e7f2485a70c036b3dfe82f3ae1a858f3e85e283a6c52403efb01b74c10f33d3a03990d0d0e337a8727c9ad5765a54aeb47b71", - "0a07851e9c8fbadb3c859b78075f154857a9da90d55068c5643601f56a8120959d8a4a353578ecf6d72af6e20e2bc2586c35c260b6266e05637f98c3cb2610c774", - "0b090e44b7488a88a4b64cb419deb48f28847d1f8140b573a2716627b9517ad090d9d3c4b8c9c2fa0b94023293468533d6dd31dc97c5d56b1e74e29f5e346f0f4d", - "0a00c86b32f2d09342783951838c6679d465990357a9ebc8a1d0757f53bb3ebe3b80ce295f5e2ace43b47d87c688a29d6bd3d694476391e720efe97da7e1024da4", - "0b060017a22df048670f072374ee1960b8e4a47a7925e5de8a47b7a23dc0ed2c3e68a2358cf206c48008e9e9d69f421a6931ef315ccbfa9b045e0b22636c2a9541", - "0a0863d12efc8133d3a89614e08d4a22df543f5bdccd607ba616e3f3e442238d93b840e24b3b09caaee1ee1bac3e291ab2817dca75eb06364156db0f8406b01e0b", - "0a03c4ff951c3a5ecc725db0d56eb58ca46980793e83726fb0b1454fa0654a3b924841cf10cf5de71e05119a5e8a15bfba817c746f950fba57e5d02c750c8e9f63", - "0b0227e009f5fd9d909186cb75cf80f60db6b24fd4241cdcddd5bf6a1fb3d0817870f61dd9e2158e708a36c65ba3fe9f690dccde29bed9c45cfc6c9f34cd8bbf84", - "0b05172b39d301b55e01b0d3bbe9fc8781b828ee822db88db39ab6cdcd2559e40b843c271eb4d4e5569015d0eed1c24e2221ba47e5e82416c90ab27300b719efc5", - "0b068a218c520b66cbc2132f49e5fb895117c53ffd3d220fe48513acc7615e7fb75c7d50102a572b4414f8ba42286b249db9a623695b27a3cf3411574956832883", - "0a0193d0b110c7e25d0cde8729ed61cde8e03ab0f16a8df138d9efb5d283f4092f3b2a1c0b11df27ca4c73fc7c820703ceafe54b43029145195a3b91f5c6986fef", - "0b049633d961542c4b021c714b5e1de9e12ab85809c67be53194b2c9be9b9376580b9211d82001def50d3c698effdf23fce2852118f567736fe9f05bac0bb28ed6", - "0b047c3ef5c09869fc53c439b39ca5d3cb505101c7f9acc9ed0aed5f0607e9ea067353fc723aaa0611236c0f7e2ce93740f0654dca76766a1bba9c2d9474e94b66", - "0a043de4419fdc5d4ea9589e33c5f2ff460da6db7107c4969d27514c87f8effd097db7d02dc84ac81fedac28493008b8f024404bf67bb2775accee673d1ab71ec3", - "0b0910ce316d45aba143a047529af85d6d5a86c4b121a37731c67151e3ac92cd5fd281d7e8a48d82a425ebf9112cfe6c56abfa319824dd36b30ce84145068a402d", - "0b059305706fa58fe0ed5b1514d1e2caebaf3f9660647e4a753c9ce204535a0372d4dd6f1e6940b623c2e38ce164c2bf8edad9c25d55163dbecc0b09d1a998a56d", - "0b013acec8d681d0029b607d49dd4397f4598055e6dc9d97dce87d5957549d700503a3ee3f42219d1d1a2b8c996b3af27efc592987057decdf2811bbf4cbd211e6", - "0a0070b2b26ba57694a5030e8eb2a6a31538f6cb6a761a1841dd165566c77faabfb99402dcfd02c0842aa6ae49199f900dfe1f776cf39dd9e705636d013ed8b451", - "0b08bedfdade4270baff7608d2f80cc5f5b0bd45b77d5c13532fdfc19dfafc9fe2ea5b34a69e09f93f1afadc688007bce5d062030a608615c397129d74638dc626", - "0b07ce98be37f259607f337d6e808192490b4ea51e663c67005c16dcb1005bb8e1c52f68e8a16bf37a7b5462ad54d5dd790edcd58c5c3fa64b891af7798dd5842f", - "0b085c4f19d44e658c60471315f18b419a86d30f03dd12b045112f91192190e506a490887760f1718b7e057bd620b26f9dac678f8a9ab6988514a3d5d61b52f34c", - "0b0320b18470ccb30d769160d14aa52219899fb212fd70519d3aa5df9669f7d9fcaf7d220bd9fd2dd811bac3f00ebcefdbab21048304f71acf45c11edf245d8413", - "0a067c9602831d7689d576387fab37cd48eb755474a147349c476183f939ea4f59510e9794393b72af10f2f609be19b7397983f3fc05f7d4b6d5950bb8b719aa2c", - "0b04a0b1bbce5337f582b99c53b1f41211ba42b01cc6ac7c62edac6e97a626ede500dea56d1510af9414c6edee8d1d78b950bf3b46fcbd16ea05c476a4eddc65e9", - "0b04295a337e311aadcd6826fe43d4e3a2ba6c9ba0a94f9ab64232d748d346a75a4bb41463318a5b667b780856adc284ec0c92654a5b00e012b60a164457339d3c", - "0b081b8bd977b5b4efd4b983753a636b1a09c2e46ff066327ff463ff9139081f0b2a4ed3413fc9f5ff96b83630381da1f10c2ea90b21174c21e9f965e1ed555ab1", - "0b08c8c528ed39121b2e07f9f007cf4722a5c3a4df2a07fc4745cc7c47793083a4eeaf5369c51a5bf7f199734036af2edfe76f38ee040d22d7045abe21daa6b9ce", - "0b02c196654b6261a6e91c56628ad048c840e042aef8e55109378cd7c216bea61d95d8697df36c025f1657c07f34074ca34d8389e7fc6332e2f123efe1ca4e69e6", - "0a083ce077b4a462b53007a94fdb7ee0abfe4f9388042977930c0190a92c3c7a20a905ba87f2d54a09427c7c8b9c5ce89f4f8b44a7b277673b40e73cc083c8d9d0", - "0a03165bcc0ff4f0e95036fcfb9a8a06174fff0464abcacc29be2650ca1c855da5303a0311d6227990a5c72dcac13e59f1800c636c963b2e75e4382ca15667a085", - "0a01ac6bc23d4a7cfca2f4ac048312613d3693fe2418cc57f49e591277d5e8939f8dd7b53af7632c09fdbedaa828573c88fa44c096cc606a980496627e977d771e", - "0b05bcf2a08c2019bb6ba8c832bda90ee3ed403067edc3453729fa2df10b52c88e2d932169023cc3541b520b26fe8accbdd78803094fe427a6c53f3907f6ff69ab", - "0b03d96ecf4020d47a1d21775c8d5ed64ca78a51d6d0df9d4021a7f1881ab209708e6ecde0c0ac69665eacf1d2b3e0a9f71f9dbea1bcdbbf73320eaf4239482a7a", - "0a0108368d4cffc482857b75794c86406988782ac5697382e51d500c2940c64cbb7351633f07c29adb1f229c371a5a6f831ffaac4b7b230f96970284d3118096e2", - "0b0618d16ddcd70e476a2f62e4d8be6da5ef690afd20cf4c3447b5c4917743f5d38c9a53a886c83be3af51e39b15bd8bfa79c11bfa572350b4198653a40b75a047", - "0b0825d5fa84ab26ef200e10f84bc050c185e0a1f3ce9dad756872d45adfdaad56c5fd86c1452bd08831e035c61e45fe58ba696af85d479db3ea1da660067a9b8c", - "0a0297bc11204c5a21731c7cbe7d5fd56afad68fb383a904386e8ebe08de2d3dbe49f78d904618ef917e61fbffd9ef0b509646dad283795e9f163852c79d190212", - "0a083acbdfcaf627b07c36ecd86a16d088d111c9a0cd3669fda9dcd794ac47191ca4f4e8843604009c72261cd9a58ca5ad8a71a4c0b521a39e8524acb9b248a8cf", - "0b074219af31a294427c4a3d6657f3489ffdea9393d45e9135e61ba647ad6367e3c5e09a177b1a07291cebe8f3559b1ea30f24761d4f8262dcc9719c73fc52e44c", - "0a00c97deda3b7102573d98f3ba936e5e8c83e286d6c81a6abc38becb8c09cfac1a60c55770ee480d3674a0fa294a377b52b0b01cdb3d857be760f9c2c89e25313", - "0a07d790011bf2649f1d0f89c7074e2d28ed6f35760e9f005cf4d3557a76f99f3664ffc2e6f0fe45732c361cc1a075a91bf006b2ccf9dd066b4842dd716cacc6ea", - "0b0453858efc3537f9d2b8685e318e5c959b97d727ddc42b7015fdbc08e8b6eb4b46b30f609f0358c409a2d32f47c8005f9b74ed3f05a171044913b3ba39e6ecda", - "0a07d25007287cab01f768fd9badd14b6f2c99f1ce526fe31d2e436d69e9ea847149d3df5cbe05368c7620fc92c23f9f1416f0832902ada0c7063bb079076f2939", - "0b01de523e2849aa2b0e89a97eb2d4dfa4483fe3598b26ca6b01537ec56e5c72288e5e8de8fa9481b0c1d78374b95303cb46482c950609e423482465d76a6c30fb", - "0a01ee0fa6375205e720565c06ca497386a39b35800b363ea25abd7c13a02cfdf0f8cb48a16a8f860b0f85e3efb4f486854fd8d00a63abb520dbd32b31a988d405", - "0b017d438060798b84ddb00250b753570c41c868baea2d4e3cd8e697e8541c90976ee3f9ef74f207efc811abf8349b62a9c7c537f215e5a8320ca601786648d469", - "0b036121d9a01dc5bca2a4c7123b4a0842dfdbdde80346116cc3491c7e0ae2003f97fd3593de5d52e22a6bc76f8287f9bd0c345ee4047a7a10f1821d1918d375c6", - "0a0532bad9ed44a9e175983da85505be88008876842c104ed905755782948f583eb88daa4aa9b83a3117d22ae346075a420daf1d724d31711398e17bc8a4dd1667", - "0a055755e11cc4741223cb50dd4c716f20b41f2e476038bd5b0c08ebf51d68c9b0f1f5cf617500e576d048162324cbcef998b76692f379ad95009a80b41dc85ce2", - "0b033e8ed23fd78bc578b5e7794eb7da913a0b6f6e3cc13797a7ac6ed4c13aacc0e2060cd216a200ecb210370f49602c656cb6a1b83ded05eacc72ff52bc75cd71", - "0b07bfb7380fd7ebbc05c499f8b4d91d3e2b7d259ca2314b59431d7ffbc4561648f971d4f929636a2141d664adfd6aac908e8626d1f875493276ef27da042e2e61", - "0b07df70624fe0a6d2db372a8c6a36bc5dab6403bcd5f10ccdccae9afb76572e8b0a8f0180c7b75df6786245590fcb4f936aafc36222a3325a1f08ebb103897d6b", - "0a05c5ea1b043ef52f9be998cd64b2454944e397fb4c45494d003038d819e3814d6e699f2b81be1f4bdc82b132b23b14fe428c553eaea3f2bd66dbd6cda56e68f2", - "0a0212e23717195414bc8a53619943397bb00c744da8ec24e118a6876f4f99ce0f04565f07b75f6e087124c72aaa20466e8776c7012099e4ad47e838defc3885fa", - "0b044e2d7db68a7dbd86a207ed2a1f0d3c2607e6df4f479d3a82433c411061f8b88f2036f53de46a843cb57f371d32696b6c994a86677293e26db34b39e5d2124c", - "0b06d6b18982dbd8cb1979b6ceda97a6970b89aa2181e2e40686ffc0b7a040caf54185aea77738b77ca866c7a1eaff91325f43ae2c881b1c36ee2fcff0fb67ca03", - "0a0175e8c2bb0ac4d31ba5dc6867a7e218f881700d830f19703fcdcf3ce7ee6fcbc32268f4cf9009b41fbc0de636e1ad0a902735b662950950cb2f26d20289bfab", - "0a025160a16822e61dfcabc64962ead991f5643d014749e0ee3709f521ad248e286696c9355eba15223ce8b855106fd9a0ee92382f1ca00ad9b85ebdb04375b665", - "0a04aa3353a321d97ec5eca75c2c6f26a2226032f1eadd5487ee0ba1daf2ab203b0d4bf1284f6545e60a59155491ee7c4c22e172356d0743c1b38977d9a2f84a2d", - "0a010b4c3ec2f1909d7d6e277fc9c12bbb366ed941fe3c1a25f3d01ab3f8d1f7694f319809f84c47d1630dce185e7292b3fca12a9bbda80fa73fd3b22a08e9d742", - "0a0656c9b132864dc84249cbabdcca23ea8e65231d1bbd257308da8a2cdfdfd9b4ce334a2e36fe0d85b621d10ee6fc2577547ac5984a9a3d25069c2ef5c9387a84", - "0a03b7e8fc5e9904dc9a1d6bc21e6afc61ff066d18c84090b570953fedeac416c22ec5393e4291953097bd7cf9986e64bddfb863322706393c08f5a64c0ef47f47", - "0b0093731c2f5a4b2d63ea8466c4e46a0d6e0057231809ba7a4980ee8355778845f5e64ca545c6fe166caf07620bc2b1059a114de588e34242e0969eb625330438", - "0a0840481225fd8d98f0498a45f9450c26a5cfb9edbac44b4df45adcae63d79af19bd33ee55b7cf59fd7ca008e7436c237983e821898bf7a79908e7a2babb9499e", - "0a021f5d6ba218b1fac27c35d0548359fca227826a41445c9e301ca8642bcac1e6a7da8f483ced05ace123bd3175e73a631dc9d17d3f40b48071ab0c5fd57ec5cc", - "0b085b7b44c6fc23e61313220936257de094f1da8f4e6ebe8a285189cb7ecee52f2e4da3aa76e967a7d5471bb9d653a8f34544cf8d97dfbf75dcd03be6d165a57c", - "0b00c8b2c370f78d9e24bf0947bf2c1754354b9d526c6f53052e289d0f230145328702cc56fda57766d3665bdf141e20027b718bfc545e8425e606241ab74f0b68" -] diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index d56c3a80f02..fc91ea3e06e 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -167,7 +167,8 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle, uint32_t co tx.vShieldedOutput.push_back(odesc); } } - if (tx.nVersion >= 2) { + // We have removed pre-Sapling Sprout support. + if (tx.fOverwintered && tx.nVersion >= SAPLING_TX_VERSION) { for (int js = 0; js < joinsplits; js++) { JSDescription jsdesc; if (insecure_rand() % 2 == 0) { @@ -183,12 +184,10 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle, uint32_t co jsdesc.randomSeed = GetRandHash(); randombytes_buf(jsdesc.ciphertexts[0].begin(), jsdesc.ciphertexts[0].size()); randombytes_buf(jsdesc.ciphertexts[1].begin(), jsdesc.ciphertexts[1].size()); - if (tx.fOverwintered && tx.nVersion >= SAPLING_TX_VERSION) { + { libzcash::GrothProof zkproof; randombytes_buf(zkproof.begin(), zkproof.size()); jsdesc.proof = zkproof; - } else { - jsdesc.proof = libzcash::PHGRProof::random_invalid(); } jsdesc.macs[0] = GetRandHash(); jsdesc.macs[1] = GetRandHash(); diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 03f98870c43..02b6f8d3391 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -37,9 +37,7 @@ extern void noui_connect(); JoinSplitTestingSetup::JoinSplitTestingSetup() { - boost::filesystem::path pk_path = ZC_GetParamsDir() / "sprout-proving.key"; - boost::filesystem::path vk_path = ZC_GetParamsDir() / "sprout-verifying.key"; - pzcashParams = ZCJoinSplit::Prepared(vk_path.string(), pk_path.string()); + pzcashParams = ZCJoinSplit::Prepared(); boost::filesystem::path sapling_spend = ZC_GetParamsDir() / "sapling-spend.params"; boost::filesystem::path sapling_output = ZC_GetParamsDir() / "sapling-output.params"; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index fad4d027c31..436696ea592 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2745,7 +2745,7 @@ UniValue zc_benchmark(const UniValue& params, bool fHelp) if (benchmarktype == "sleep") { sample_times.push_back(benchmark_sleep()); } else if (benchmarktype == "parameterloading") { - sample_times.push_back(benchmark_parameter_loading()); + throw JSONRPCError(RPC_TYPE_ERROR, "Pre-Sapling Sprout parameters have been removed"); } else if (benchmarktype == "createjoinsplit") { if (params.size() < 3) { sample_times.push_back(benchmark_create_joinsplit()); diff --git a/src/zcash/JoinSplit.cpp b/src/zcash/JoinSplit.cpp index 287d2ebcca8..834ea76429b 100644 --- a/src/zcash/JoinSplit.cpp +++ b/src/zcash/JoinSplit.cpp @@ -10,10 +10,6 @@ #include #include #include -#include -#include -#include -#include #include "tinyformat.h" #include "sync.h" #include "amount.h" @@ -22,123 +18,16 @@ #include "streams.h" #include "version.h" -using namespace libsnark; - namespace libzcash { -#include "zcash/circuit/gadget.tcc" - static CCriticalSection cs_ParamsIO; -template -void saveToFile(const std::string path, T& obj) { - LOCK(cs_ParamsIO); - - std::stringstream ss; - ss << obj; - std::ofstream fh; - fh.open(path, std::ios::binary); - ss.rdbuf()->pubseekpos(0, std::ios_base::out); - fh << ss.rdbuf(); - fh.flush(); - fh.close(); -} - -template -void loadFromFile(const std::string path, T& objIn) { - LOCK(cs_ParamsIO); - - std::stringstream ss; - std::ifstream fh(path, std::ios::binary); - - if(!fh.is_open()) { - throw std::runtime_error(strprintf("could not load param file at %s", path)); - } - - ss << fh.rdbuf(); - fh.close(); - - ss.rdbuf()->pubseekpos(0, std::ios_base::in); - - T obj; - ss >> obj; - - objIn = std::move(obj); -} - template class JoinSplitCircuit : public JoinSplit { public: - typedef default_r1cs_ppzksnark_pp ppzksnark_ppT; - typedef Fr FieldT; - - r1cs_ppzksnark_verification_key vk; - r1cs_ppzksnark_processed_verification_key vk_precomp; - std::string pkPath; - - JoinSplitCircuit(const std::string vkPath, const std::string pkPath) : pkPath(pkPath) { - loadFromFile(vkPath, vk); - vk_precomp = r1cs_ppzksnark_verifier_process_vk(vk); - } + JoinSplitCircuit() {} ~JoinSplitCircuit() {} - static void generate(const std::string r1csPath, - const std::string vkPath, - const std::string pkPath) - { - protoboard pb; - - joinsplit_gadget g(pb); - g.generate_r1cs_constraints(); - - auto r1cs = pb.get_constraint_system(); - - saveToFile(r1csPath, r1cs); - - r1cs_ppzksnark_keypair keypair = r1cs_ppzksnark_generator(r1cs); - - saveToFile(vkPath, keypair.vk); - saveToFile(pkPath, keypair.pk); - } - - bool verify( - const PHGRProof& proof, - ProofVerifier& verifier, - const uint256& joinSplitPubKey, - const uint256& randomSeed, - const std::array& macs, - const std::array& nullifiers, - const std::array& commitments, - uint64_t vpub_old, - uint64_t vpub_new, - const uint256& rt - ) { - try { - auto r1cs_proof = proof.to_libsnark_proof>(); - - uint256 h_sig = this->h_sig(randomSeed, nullifiers, joinSplitPubKey); - - auto witness = joinsplit_gadget::witness_map( - rt, - h_sig, - macs, - nullifiers, - commitments, - vpub_old, - vpub_new - ); - - return verifier.check( - vk, - vk_precomp, - witness, - r1cs_proof - ); - } catch (...) { - return false; - } - } - SproutProof prove( bool makeGrothProof, const std::array& inputs, @@ -326,20 +215,9 @@ class JoinSplitCircuit : public JoinSplit { }; template -void JoinSplit::Generate(const std::string r1csPath, - const std::string vkPath, - const std::string pkPath) -{ - initialize_curve_params(); - JoinSplitCircuit::generate(r1csPath, vkPath, pkPath); -} - -template -JoinSplit* JoinSplit::Prepared(const std::string vkPath, - const std::string pkPath) +JoinSplit* JoinSplit::Prepared() { - initialize_curve_params(); - return new JoinSplitCircuit(vkPath, pkPath); + return new JoinSplitCircuit(); } template diff --git a/src/zcash/JoinSplit.hpp b/src/zcash/JoinSplit.hpp index c37926edeaf..98c8e30ddd5 100644 --- a/src/zcash/JoinSplit.hpp +++ b/src/zcash/JoinSplit.hpp @@ -56,11 +56,7 @@ class JoinSplit { public: virtual ~JoinSplit() {} - static void Generate(const std::string r1csPath, - const std::string vkPath, - const std::string pkPath); - static JoinSplit* Prepared(const std::string vkPath, - const std::string pkPath); + static JoinSplit* Prepared(); static uint256 h_sig(const uint256& randomSeed, const std::array& nullifiers, @@ -90,19 +86,6 @@ class JoinSplit { uint256 *out_esk = nullptr ) = 0; - virtual bool verify( - const PHGRProof& proof, - ProofVerifier& verifier, - const uint256& joinSplitPubKey, - const uint256& randomSeed, - const std::array& hmacs, - const std::array& nullifiers, - const std::array& commitments, - uint64_t vpub_old, - uint64_t vpub_new, - const uint256& rt - ) = 0; - protected: JoinSplit() {} }; diff --git a/src/zcash/Proof.cpp b/src/zcash/Proof.cpp index af87d1b8188..7ab1298a814 100644 --- a/src/zcash/Proof.cpp +++ b/src/zcash/Proof.cpp @@ -3,249 +3,16 @@ #include "crypto/common.h" #include -#include -#include #include -using namespace libsnark; - -typedef alt_bn128_pp curve_pp; -typedef alt_bn128_pp::G1_type curve_G1; -typedef alt_bn128_pp::G2_type curve_G2; -typedef alt_bn128_pp::GT_type curve_GT; -typedef alt_bn128_pp::Fp_type curve_Fr; -typedef alt_bn128_pp::Fq_type curve_Fq; -typedef alt_bn128_pp::Fqe_type curve_Fq2; - -BOOST_STATIC_ASSERT(sizeof(mp_limb_t) == 8); - namespace libzcash { -// FE2IP as defined in the protocol spec and IEEE Std 1363a-2004. -bigint<8> fq2_to_bigint(const curve_Fq2 &e) -{ - auto modq = curve_Fq::field_char(); - auto c0 = e.c0.as_bigint(); - auto c1 = e.c1.as_bigint(); - - bigint<8> temp = c1 * modq; - temp += c0; - return temp; -} - -// Writes a bigint in big endian -template -void write_bigint(base_blob<8 * LIMBS * sizeof(mp_limb_t)> &blob, const bigint &val) -{ - auto ptr = blob.begin(); - for (ssize_t i = LIMBS-1; i >= 0; i--, ptr += 8) { - WriteBE64(ptr, val.data[i]); - } -} - -// Reads a bigint from big endian -template -bigint read_bigint(const base_blob<8 * LIMBS * sizeof(mp_limb_t)> &blob) -{ - bigint ret; - - auto ptr = blob.begin(); - - for (ssize_t i = LIMBS-1; i >= 0; i--, ptr += 8) { - ret.data[i] = ReadBE64(ptr); - } - - return ret; -} - -template<> -Fq::Fq(curve_Fq element) : data() -{ - write_bigint<4>(data, element.as_bigint()); -} - -template<> -curve_Fq Fq::to_libsnark_fq() const -{ - auto element_bigint = read_bigint<4>(data); - - // Check that the integer is smaller than the modulus - auto modq = curve_Fq::field_char(); - element_bigint.limit(modq, "element is not in Fq"); - - return curve_Fq(element_bigint); -} - -template<> -Fq2::Fq2(curve_Fq2 element) : data() -{ - write_bigint<8>(data, fq2_to_bigint(element)); -} - -template<> -curve_Fq2 Fq2::to_libsnark_fq2() const -{ - bigint<4> modq = curve_Fq::field_char(); - bigint<8> combined = read_bigint<8>(data); - bigint<5> res; - bigint<4> c0; - bigint<8>::div_qr(res, c0, combined, modq); - bigint<4> c1 = res.shorten(modq, "element is not in Fq2"); - - return curve_Fq2(curve_Fq(c0), curve_Fq(c1)); -} - -template<> -CompressedG1::CompressedG1(curve_G1 point) -{ - if (point.is_zero()) { - throw std::domain_error("curve point is zero"); - } - - point.to_affine_coordinates(); - - x = Fq(point.X); - y_lsb = point.Y.as_bigint().data[0] & 1; -} - -template<> -curve_G1 CompressedG1::to_libsnark_g1() const -{ - curve_Fq x_coordinate = x.to_libsnark_fq(); - - // y = +/- sqrt(x^3 + b) - auto y_coordinate = ((x_coordinate.squared() * x_coordinate) + alt_bn128_coeff_b).sqrt(); - - if ((y_coordinate.as_bigint().data[0] & 1) != y_lsb) { - y_coordinate = -y_coordinate; - } - - curve_G1 r = curve_G1::one(); - r.X = x_coordinate; - r.Y = y_coordinate; - r.Z = curve_Fq::one(); - - assert(r.is_well_formed()); - - return r; -} - -template<> -CompressedG2::CompressedG2(curve_G2 point) -{ - if (point.is_zero()) { - throw std::domain_error("curve point is zero"); - } - - point.to_affine_coordinates(); - - x = Fq2(point.X); - y_gt = fq2_to_bigint(point.Y) > fq2_to_bigint(-(point.Y)); -} - -template<> -curve_G2 CompressedG2::to_libsnark_g2() const -{ - auto x_coordinate = x.to_libsnark_fq2(); - - // y = +/- sqrt(x^3 + b) - auto y_coordinate = ((x_coordinate.squared() * x_coordinate) + alt_bn128_twist_coeff_b).sqrt(); - auto y_coordinate_neg = -y_coordinate; - - if ((fq2_to_bigint(y_coordinate) > fq2_to_bigint(y_coordinate_neg)) != y_gt) { - y_coordinate = y_coordinate_neg; - } - - curve_G2 r = curve_G2::one(); - r.X = x_coordinate; - r.Y = y_coordinate; - r.Z = curve_Fq2::one(); - - assert(r.is_well_formed()); - - if (alt_bn128_modulus_r * r != curve_G2::zero()) { - throw std::runtime_error("point is not in G2"); - } - - return r; -} - -template<> -PHGRProof::PHGRProof(const r1cs_ppzksnark_proof &proof) -{ - g_A = CompressedG1(proof.g_A.g); - g_A_prime = CompressedG1(proof.g_A.h); - g_B = CompressedG2(proof.g_B.g); - g_B_prime = CompressedG1(proof.g_B.h); - g_C = CompressedG1(proof.g_C.g); - g_C_prime = CompressedG1(proof.g_C.h); - g_K = CompressedG1(proof.g_K); - g_H = CompressedG1(proof.g_H); -} - -template<> -r1cs_ppzksnark_proof PHGRProof::to_libsnark_proof() const -{ - r1cs_ppzksnark_proof proof; - - proof.g_A.g = g_A.to_libsnark_g1(); - proof.g_A.h = g_A_prime.to_libsnark_g1(); - proof.g_B.g = g_B.to_libsnark_g2(); - proof.g_B.h = g_B_prime.to_libsnark_g1(); - proof.g_C.g = g_C.to_libsnark_g1(); - proof.g_C.h = g_C_prime.to_libsnark_g1(); - proof.g_K = g_K.to_libsnark_g1(); - proof.g_H = g_H.to_libsnark_g1(); - - return proof; -} - -PHGRProof PHGRProof::random_invalid() -{ - PHGRProof p; - p.g_A = curve_G1::random_element(); - p.g_A_prime = curve_G1::random_element(); - p.g_B = curve_G2::random_element(); - p.g_B_prime = curve_G1::random_element(); - p.g_C = curve_G1::random_element(); - p.g_C_prime = curve_G1::random_element(); - - p.g_K = curve_G1::random_element(); - p.g_H = curve_G1::random_element(); - - return p; -} - -static std::once_flag init_public_params_once_flag; - -void initialize_curve_params() -{ - std::call_once (init_public_params_once_flag, curve_pp::init_public_params); -} - ProofVerifier ProofVerifier::Strict() { - initialize_curve_params(); return ProofVerifier(true); } ProofVerifier ProofVerifier::Disabled() { - initialize_curve_params(); return ProofVerifier(false); } -template<> -bool ProofVerifier::check( - const r1cs_ppzksnark_verification_key& vk, - const r1cs_ppzksnark_processed_verification_key& pvk, - const r1cs_primary_input& primary_input, - const r1cs_ppzksnark_proof& proof -) -{ - if (perform_verification) { - return r1cs_ppzksnark_online_verifier_strong_IC(pvk, primary_input, proof); - } else { - return true; - } -} - } diff --git a/src/zcash/Proof.hpp b/src/zcash/Proof.hpp index e06095d579a..7c9b7f7f5f1 100644 --- a/src/zcash/Proof.hpp +++ b/src/zcash/Proof.hpp @@ -16,12 +16,6 @@ class Fq { public: Fq() : data() { } - template - Fq(libsnark_Fq element); - - template - libsnark_Fq to_libsnark_fq() const; - ADD_SERIALIZE_METHODS; template @@ -49,12 +43,6 @@ class Fq2 { public: Fq2() : data() { } - template - Fq2(libsnark_Fq2 element); - - template - libsnark_Fq2 to_libsnark_fq2() const; - ADD_SERIALIZE_METHODS; template @@ -84,12 +72,6 @@ class CompressedG1 { public: CompressedG1() : y_lsb(false), x() { } - template - CompressedG1(libsnark_G1 point); - - template - libsnark_G1 to_libsnark_g1() const; - ADD_SERIALIZE_METHODS; template @@ -134,12 +116,6 @@ class CompressedG2 { public: CompressedG2() : y_gt(false), x() { } - template - CompressedG2(libsnark_G2 point); - - template - libsnark_G2 to_libsnark_g2() const; - ADD_SERIALIZE_METHODS; template @@ -190,17 +166,6 @@ class PHGRProof { public: PHGRProof() : g_A(), g_A_prime(), g_B(), g_B_prime(), g_C(), g_C_prime(), g_K(), g_H() { } - // Produces a compressed proof using a libsnark zkSNARK proof - template - PHGRProof(const libsnark_proof& proof); - - // Produces a libsnark zkSNARK proof out of this proof, - // or throws an exception if it is invalid. - template - libsnark_proof to_libsnark_proof() const; - - static PHGRProof random_invalid(); - ADD_SERIALIZE_METHODS; template diff --git a/src/zcbenchmarks.cpp b/src/zcbenchmarks.cpp index cb4cc181258..c6ff9da49da 100644 --- a/src/zcbenchmarks.cpp +++ b/src/zcbenchmarks.cpp @@ -91,24 +91,6 @@ double benchmark_sleep() return timer_stop(tv_start); } -double benchmark_parameter_loading() -{ - // FIXME: this is duplicated with the actual loading code - boost::filesystem::path pk_path = ZC_GetParamsDir() / "sprout-proving.key"; - boost::filesystem::path vk_path = ZC_GetParamsDir() / "sprout-verifying.key"; - - struct timeval tv_start; - timer_start(tv_start); - - auto newParams = ZCJoinSplit::Prepared(vk_path.string(), pk_path.string()); - - double ret = timer_stop(tv_start); - - delete newParams; - - return ret; -} - double benchmark_create_joinsplit() { uint256 joinSplitPubKey; diff --git a/src/zcbenchmarks.h b/src/zcbenchmarks.h index 721251eb58f..60ad5b282a4 100644 --- a/src/zcbenchmarks.h +++ b/src/zcbenchmarks.h @@ -5,7 +5,6 @@ #include extern double benchmark_sleep(); -extern double benchmark_parameter_loading(); extern double benchmark_create_joinsplit(); extern std::vector benchmark_create_joinsplit_threaded(int nThreads); extern double benchmark_solve_equihash(); From 8a638d5fd89098960ef16abd7e1a9a4957f41baf Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 25 Jun 2019 16:59:44 +0200 Subject: [PATCH 256/395] Remove pre-Sapling Sprout circuit --- src/Makefile.am | 8 +- src/zcash/circuit/commitment.tcc | 100 --------- src/zcash/circuit/gadget.tcc | 349 ------------------------------- src/zcash/circuit/merkle.tcc | 60 ------ src/zcash/circuit/note.tcc | 244 --------------------- src/zcash/circuit/prfs.tcc | 109 ---------- src/zcash/circuit/utils.tcc | 75 ------- 7 files changed, 1 insertion(+), 944 deletions(-) delete mode 100644 src/zcash/circuit/commitment.tcc delete mode 100644 src/zcash/circuit/gadget.tcc delete mode 100644 src/zcash/circuit/merkle.tcc delete mode 100644 src/zcash/circuit/note.tcc delete mode 100644 src/zcash/circuit/prfs.tcc delete mode 100644 src/zcash/circuit/utils.tcc diff --git a/src/Makefile.am b/src/Makefile.am index 5476239515a..e0ca82a6022 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -533,13 +533,7 @@ libzcash_a_SOURCES = \ zcash/Note.cpp \ zcash/prf.cpp \ zcash/util.cpp \ - zcash/zip32.cpp \ - zcash/circuit/commitment.tcc \ - zcash/circuit/gadget.tcc \ - zcash/circuit/merkle.tcc \ - zcash/circuit/note.tcc \ - zcash/circuit/prfs.tcc \ - zcash/circuit/utils.tcc + zcash/zip32.cpp libzcash_a_CPPFLAGS = $(AM_CPPFLAGS) $(PIC_FLAGS) -DBINARY_OUTPUT -DCURVE_ALT_BN128 -DBOOST_SPIRIT_THREADSAFE -fvisibility=hidden -DSTATIC $(BITCOIN_INCLUDES) libzcash_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) diff --git a/src/zcash/circuit/commitment.tcc b/src/zcash/circuit/commitment.tcc deleted file mode 100644 index d1b0b10fa70..00000000000 --- a/src/zcash/circuit/commitment.tcc +++ /dev/null @@ -1,100 +0,0 @@ -template -class note_commitment_gadget : gadget { -private: - std::shared_ptr> block1; - std::shared_ptr> block2; - std::shared_ptr> hasher1; - std::shared_ptr> intermediate_hash; - std::shared_ptr> hasher2; - -public: - note_commitment_gadget( - protoboard &pb, - pb_variable& ZERO, - pb_variable_array& a_pk, - pb_variable_array& v, - pb_variable_array& rho, - pb_variable_array& r, - std::shared_ptr> result - ) : gadget(pb) { - pb_variable_array leading_byte = - from_bits({1, 0, 1, 1, 0, 0, 0, 0}, ZERO); - - pb_variable_array first_of_rho(rho.begin(), rho.begin()+184); - pb_variable_array last_of_rho(rho.begin()+184, rho.end()); - - intermediate_hash.reset(new digest_variable(pb, 256, "")); - - // final padding - pb_variable_array length_padding = - from_bits({ - // padding - 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,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,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,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, - - // length of message (840 bits) - 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,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,1,1, - 0,1,0,0,1,0,0,0 - }, ZERO); - - block1.reset(new block_variable(pb, { - leading_byte, - a_pk, - v, - first_of_rho - }, "")); - - block2.reset(new block_variable(pb, { - last_of_rho, - r, - length_padding - }, "")); - - pb_linear_combination_array IV = SHA256_default_IV(pb); - - hasher1.reset(new sha256_compression_function_gadget( - pb, - IV, - block1->bits, - *intermediate_hash, - "")); - - pb_linear_combination_array IV2(intermediate_hash->bits); - - hasher2.reset(new sha256_compression_function_gadget( - pb, - IV2, - block2->bits, - *result, - "")); - } - - void generate_r1cs_constraints() { - hasher1->generate_r1cs_constraints(); - hasher2->generate_r1cs_constraints(); - } - - void generate_r1cs_witness() { - hasher1->generate_r1cs_witness(); - hasher2->generate_r1cs_witness(); - } -}; diff --git a/src/zcash/circuit/gadget.tcc b/src/zcash/circuit/gadget.tcc deleted file mode 100644 index 0a2ec77195f..00000000000 --- a/src/zcash/circuit/gadget.tcc +++ /dev/null @@ -1,349 +0,0 @@ -#include "zcash/circuit/utils.tcc" -#include "zcash/circuit/prfs.tcc" -#include "zcash/circuit/commitment.tcc" -#include "zcash/circuit/merkle.tcc" -#include "zcash/circuit/note.tcc" - -template -class joinsplit_gadget : gadget { -private: - // Verifier inputs - pb_variable_array zk_packed_inputs; - pb_variable_array zk_unpacked_inputs; - std::shared_ptr> unpacker; - - std::shared_ptr> zk_merkle_root; - std::shared_ptr> zk_h_sig; - std::array>, NumInputs> zk_input_nullifiers; - std::array>, NumInputs> zk_input_macs; - std::array>, NumOutputs> zk_output_commitments; - pb_variable_array zk_vpub_old; - pb_variable_array zk_vpub_new; - - // Aux inputs - pb_variable ZERO; - std::shared_ptr> zk_phi; - pb_variable_array zk_total_uint64; - - // Input note gadgets - std::array>, NumInputs> zk_input_notes; - std::array>, NumInputs> zk_mac_authentication; - - // Output note gadgets - std::array>, NumOutputs> zk_output_notes; - -public: - // PRF_pk only has a 1-bit domain separation "nonce" - // for different macs. - BOOST_STATIC_ASSERT(NumInputs <= 2); - - // PRF_rho only has a 1-bit domain separation "nonce" - // for different output `rho`. - BOOST_STATIC_ASSERT(NumOutputs <= 2); - - joinsplit_gadget(protoboard &pb) : gadget(pb) { - // Verification - { - // The verification inputs are all bit-strings of various - // lengths (256-bit digests and 64-bit integers) and so we - // pack them into as few field elements as possible. (The - // more verification inputs you have, the more expensive - // verification is.) - zk_packed_inputs.allocate(pb, verifying_field_element_size()); - pb.set_input_sizes(verifying_field_element_size()); - - alloc_uint256(zk_unpacked_inputs, zk_merkle_root); - alloc_uint256(zk_unpacked_inputs, zk_h_sig); - - for (size_t i = 0; i < NumInputs; i++) { - alloc_uint256(zk_unpacked_inputs, zk_input_nullifiers[i]); - alloc_uint256(zk_unpacked_inputs, zk_input_macs[i]); - } - - for (size_t i = 0; i < NumOutputs; i++) { - alloc_uint256(zk_unpacked_inputs, zk_output_commitments[i]); - } - - alloc_uint64(zk_unpacked_inputs, zk_vpub_old); - alloc_uint64(zk_unpacked_inputs, zk_vpub_new); - - assert(zk_unpacked_inputs.size() == verifying_input_bit_size()); - - // This gadget will ensure that all of the inputs we provide are - // boolean constrained. - unpacker.reset(new multipacking_gadget( - pb, - zk_unpacked_inputs, - zk_packed_inputs, - FieldT::capacity(), - "unpacker" - )); - } - - // We need a constant "zero" variable in some contexts. In theory - // it should never be necessary, but libsnark does not synthesize - // optimal circuits. - // - // The first variable of our constraint system is constrained - // to be one automatically for us, and is known as `ONE`. - ZERO.allocate(pb); - - zk_phi.reset(new digest_variable(pb, 252, "")); - - zk_total_uint64.allocate(pb, 64); - - for (size_t i = 0; i < NumInputs; i++) { - // Input note gadget for commitments, macs, nullifiers, - // and spend authority. - zk_input_notes[i].reset(new input_note_gadget( - pb, - ZERO, - zk_input_nullifiers[i], - *zk_merkle_root - )); - - // The input keys authenticate h_sig to prevent - // malleability. - zk_mac_authentication[i].reset(new PRF_pk_gadget( - pb, - ZERO, - zk_input_notes[i]->a_sk->bits, - zk_h_sig->bits, - i ? true : false, - zk_input_macs[i] - )); - } - - for (size_t i = 0; i < NumOutputs; i++) { - zk_output_notes[i].reset(new output_note_gadget( - pb, - ZERO, - zk_phi->bits, - zk_h_sig->bits, - i ? true : false, - zk_output_commitments[i] - )); - } - } - - void generate_r1cs_constraints() { - // The true passed here ensures all the inputs - // are boolean constrained. - unpacker->generate_r1cs_constraints(true); - - // Constrain `ZERO` - generate_r1cs_equals_const_constraint(this->pb, ZERO, FieldT::zero(), "ZERO"); - - // Constrain bitness of phi - zk_phi->generate_r1cs_constraints(); - - for (size_t i = 0; i < NumInputs; i++) { - // Constrain the JoinSplit input constraints. - zk_input_notes[i]->generate_r1cs_constraints(); - - // Authenticate h_sig with a_sk - zk_mac_authentication[i]->generate_r1cs_constraints(); - } - - for (size_t i = 0; i < NumOutputs; i++) { - // Constrain the JoinSplit output constraints. - zk_output_notes[i]->generate_r1cs_constraints(); - } - - // Value balance - { - linear_combination left_side = packed_addition(zk_vpub_old); - for (size_t i = 0; i < NumInputs; i++) { - left_side = left_side + packed_addition(zk_input_notes[i]->value); - } - - linear_combination right_side = packed_addition(zk_vpub_new); - for (size_t i = 0; i < NumOutputs; i++) { - right_side = right_side + packed_addition(zk_output_notes[i]->value); - } - - // Ensure that both sides are equal - this->pb.add_r1cs_constraint(r1cs_constraint( - 1, - left_side, - right_side - )); - - // #854: Ensure that left_side is a 64-bit integer. - for (size_t i = 0; i < 64; i++) { - generate_boolean_r1cs_constraint( - this->pb, - zk_total_uint64[i], - "" - ); - } - - this->pb.add_r1cs_constraint(r1cs_constraint( - 1, - left_side, - packed_addition(zk_total_uint64) - )); - } - } - - void generate_r1cs_witness( - const uint252& phi, - const uint256& rt, - const uint256& h_sig, - const std::array& inputs, - const std::array& outputs, - uint64_t vpub_old, - uint64_t vpub_new - ) { - // Witness `zero` - this->pb.val(ZERO) = FieldT::zero(); - - // Witness rt. This is not a sanity check. - // - // This ensures the read gadget constrains - // the intended root in the event that - // both inputs are zero-valued. - zk_merkle_root->bits.fill_with_bits( - this->pb, - uint256_to_bool_vector(rt) - ); - - // Witness public balance values - zk_vpub_old.fill_with_bits( - this->pb, - uint64_to_bool_vector(vpub_old) - ); - zk_vpub_new.fill_with_bits( - this->pb, - uint64_to_bool_vector(vpub_new) - ); - - { - // Witness total_uint64 bits - uint64_t left_side_acc = vpub_old; - for (size_t i = 0; i < NumInputs; i++) { - left_side_acc += inputs[i].note.value(); - } - - zk_total_uint64.fill_with_bits( - this->pb, - uint64_to_bool_vector(left_side_acc) - ); - } - - // Witness phi - zk_phi->bits.fill_with_bits( - this->pb, - uint252_to_bool_vector(phi) - ); - - // Witness h_sig - zk_h_sig->bits.fill_with_bits( - this->pb, - uint256_to_bool_vector(h_sig) - ); - - for (size_t i = 0; i < NumInputs; i++) { - // Witness the input information. - auto merkle_path = inputs[i].witness.path(); - zk_input_notes[i]->generate_r1cs_witness( - merkle_path, - inputs[i].key, - inputs[i].note - ); - - // Witness macs - zk_mac_authentication[i]->generate_r1cs_witness(); - } - - for (size_t i = 0; i < NumOutputs; i++) { - // Witness the output information. - zk_output_notes[i]->generate_r1cs_witness(outputs[i]); - } - - // [SANITY CHECK] Ensure that the intended root - // was witnessed by the inputs, even if the read - // gadget overwrote it. This allows the prover to - // fail instead of the verifier, in the event that - // the roots of the inputs do not match the - // treestate provided to the proving API. - zk_merkle_root->bits.fill_with_bits( - this->pb, - uint256_to_bool_vector(rt) - ); - - // This happens last, because only by now are all the - // verifier inputs resolved. - unpacker->generate_r1cs_witness_from_bits(); - } - - static r1cs_primary_input witness_map( - const uint256& rt, - const uint256& h_sig, - const std::array& macs, - const std::array& nullifiers, - const std::array& commitments, - uint64_t vpub_old, - uint64_t vpub_new - ) { - std::vector verify_inputs; - - insert_uint256(verify_inputs, rt); - insert_uint256(verify_inputs, h_sig); - - for (size_t i = 0; i < NumInputs; i++) { - insert_uint256(verify_inputs, nullifiers[i]); - insert_uint256(verify_inputs, macs[i]); - } - - for (size_t i = 0; i < NumOutputs; i++) { - insert_uint256(verify_inputs, commitments[i]); - } - - insert_uint64(verify_inputs, vpub_old); - insert_uint64(verify_inputs, vpub_new); - - assert(verify_inputs.size() == verifying_input_bit_size()); - auto verify_field_elements = pack_bit_vector_into_field_element_vector(verify_inputs); - assert(verify_field_elements.size() == verifying_field_element_size()); - return verify_field_elements; - } - - static size_t verifying_input_bit_size() { - size_t acc = 0; - - acc += 256; // the merkle root (anchor) - acc += 256; // h_sig - for (size_t i = 0; i < NumInputs; i++) { - acc += 256; // nullifier - acc += 256; // mac - } - for (size_t i = 0; i < NumOutputs; i++) { - acc += 256; // new commitment - } - acc += 64; // vpub_old - acc += 64; // vpub_new - - return acc; - } - - static size_t verifying_field_element_size() { - return div_ceil(verifying_input_bit_size(), FieldT::capacity()); - } - - void alloc_uint256( - pb_variable_array& packed_into, - std::shared_ptr>& var - ) { - var.reset(new digest_variable(this->pb, 256, "")); - packed_into.insert(packed_into.end(), var->bits.begin(), var->bits.end()); - } - - void alloc_uint64( - pb_variable_array& packed_into, - pb_variable_array& integer - ) { - integer.allocate(this->pb, 64, ""); - packed_into.insert(packed_into.end(), integer.begin(), integer.end()); - } -}; diff --git a/src/zcash/circuit/merkle.tcc b/src/zcash/circuit/merkle.tcc deleted file mode 100644 index 09f02ae9f2a..00000000000 --- a/src/zcash/circuit/merkle.tcc +++ /dev/null @@ -1,60 +0,0 @@ -template -class merkle_tree_gadget : gadget { -private: - typedef sha256_two_to_one_hash_gadget sha256_gadget; - - pb_variable_array positions; - std::shared_ptr> authvars; - std::shared_ptr> auth; - -public: - merkle_tree_gadget( - protoboard& pb, - digest_variable leaf, - digest_variable root, - pb_variable& enforce - ) : gadget(pb) { - positions.allocate(pb, INCREMENTAL_MERKLE_TREE_DEPTH); - authvars.reset(new merkle_authentication_path_variable( - pb, INCREMENTAL_MERKLE_TREE_DEPTH, "auth" - )); - auth.reset(new merkle_tree_check_read_gadget( - pb, - INCREMENTAL_MERKLE_TREE_DEPTH, - positions, - leaf, - root, - *authvars, - enforce, - "" - )); - } - - void generate_r1cs_constraints() { - for (size_t i = 0; i < INCREMENTAL_MERKLE_TREE_DEPTH; i++) { - // TODO: This might not be necessary, and doesn't - // appear to be done in libsnark's tests, but there - // is no documentation, so let's do it anyway to - // be safe. - generate_boolean_r1cs_constraint( - this->pb, - positions[i], - "boolean_positions" - ); - } - - authvars->generate_r1cs_constraints(); - auth->generate_r1cs_constraints(); - } - - void generate_r1cs_witness(const MerklePath& path) { - // TODO: Change libsnark so that it doesn't require this goofy - // number thing in its API. - size_t path_index = convertVectorToInt(path.index); - - positions.fill_with_bits_of_uint64(this->pb, path_index); - - authvars->generate_r1cs_witness(path_index, path.authentication_path); - auth->generate_r1cs_witness(); - } -}; diff --git a/src/zcash/circuit/note.tcc b/src/zcash/circuit/note.tcc deleted file mode 100644 index c598c62ee6a..00000000000 --- a/src/zcash/circuit/note.tcc +++ /dev/null @@ -1,244 +0,0 @@ -template -class note_gadget : public gadget { -public: - pb_variable_array value; - std::shared_ptr> r; - - note_gadget(protoboard &pb) : gadget(pb) { - value.allocate(pb, 64); - r.reset(new digest_variable(pb, 256, "")); - } - - void generate_r1cs_constraints() { - for (size_t i = 0; i < 64; i++) { - generate_boolean_r1cs_constraint( - this->pb, - value[i], - "boolean_value" - ); - } - - r->generate_r1cs_constraints(); - } - - void generate_r1cs_witness(const SproutNote& note) { - r->bits.fill_with_bits(this->pb, uint256_to_bool_vector(note.r)); - value.fill_with_bits(this->pb, uint64_to_bool_vector(note.value())); - } -}; - -template -class input_note_gadget : public note_gadget { -private: - std::shared_ptr> a_pk; - std::shared_ptr> rho; - - std::shared_ptr> commitment; - std::shared_ptr> commit_to_inputs; - - pb_variable value_enforce; - std::shared_ptr> witness_input; - - std::shared_ptr> spend_authority; - std::shared_ptr> expose_nullifiers; -public: - std::shared_ptr> a_sk; - - input_note_gadget( - protoboard& pb, - pb_variable& ZERO, - std::shared_ptr> nullifier, - digest_variable rt - ) : note_gadget(pb) { - a_sk.reset(new digest_variable(pb, 252, "")); - a_pk.reset(new digest_variable(pb, 256, "")); - rho.reset(new digest_variable(pb, 256, "")); - commitment.reset(new digest_variable(pb, 256, "")); - - spend_authority.reset(new PRF_addr_a_pk_gadget( - pb, - ZERO, - a_sk->bits, - a_pk - )); - - expose_nullifiers.reset(new PRF_nf_gadget( - pb, - ZERO, - a_sk->bits, - rho->bits, - nullifier - )); - - commit_to_inputs.reset(new note_commitment_gadget( - pb, - ZERO, - a_pk->bits, - this->value, - rho->bits, - this->r->bits, - commitment - )); - - value_enforce.allocate(pb); - - witness_input.reset(new merkle_tree_gadget( - pb, - *commitment, - rt, - value_enforce - )); - } - - void generate_r1cs_constraints() { - note_gadget::generate_r1cs_constraints(); - - a_sk->generate_r1cs_constraints(); - rho->generate_r1cs_constraints(); - - spend_authority->generate_r1cs_constraints(); - expose_nullifiers->generate_r1cs_constraints(); - - commit_to_inputs->generate_r1cs_constraints(); - - // value * (1 - enforce) = 0 - // Given `enforce` is boolean constrained: - // If `value` is zero, `enforce` _can_ be zero. - // If `value` is nonzero, `enforce` _must_ be one. - generate_boolean_r1cs_constraint(this->pb, value_enforce,""); - - this->pb.add_r1cs_constraint(r1cs_constraint( - packed_addition(this->value), - (1 - value_enforce), - 0 - ), ""); - - witness_input->generate_r1cs_constraints(); - } - - void generate_r1cs_witness( - const MerklePath& path, - const SproutSpendingKey& key, - const SproutNote& note - ) { - note_gadget::generate_r1cs_witness(note); - - // Witness a_sk for the input - a_sk->bits.fill_with_bits( - this->pb, - uint252_to_bool_vector(key) - ); - - // Witness a_pk for a_sk with PRF_addr - spend_authority->generate_r1cs_witness(); - - // [SANITY CHECK] Witness a_pk with note information - a_pk->bits.fill_with_bits( - this->pb, - uint256_to_bool_vector(note.a_pk) - ); - - // Witness rho for the input note - rho->bits.fill_with_bits( - this->pb, - uint256_to_bool_vector(note.rho) - ); - - // Witness the nullifier for the input note - expose_nullifiers->generate_r1cs_witness(); - - // Witness the commitment of the input note - commit_to_inputs->generate_r1cs_witness(); - - // [SANITY CHECK] Ensure the commitment is - // valid. - commitment->bits.fill_with_bits( - this->pb, - uint256_to_bool_vector(note.cm()) - ); - - // Set enforce flag for nonzero input value - this->pb.val(value_enforce) = (note.value() != 0) ? FieldT::one() : FieldT::zero(); - - // Witness merkle tree authentication path - witness_input->generate_r1cs_witness(path); - } -}; - -template -class output_note_gadget : public note_gadget { -private: - std::shared_ptr> rho; - std::shared_ptr> a_pk; - - std::shared_ptr> prevent_faerie_gold; - std::shared_ptr> commit_to_outputs; - -public: - output_note_gadget( - protoboard& pb, - pb_variable& ZERO, - pb_variable_array& phi, - pb_variable_array& h_sig, - bool nonce, - std::shared_ptr> commitment - ) : note_gadget(pb) { - rho.reset(new digest_variable(pb, 256, "")); - a_pk.reset(new digest_variable(pb, 256, "")); - - // Do not allow the caller to choose the same "rho" - // for any two valid notes in a given view of the - // blockchain. See protocol specification for more - // details. - prevent_faerie_gold.reset(new PRF_rho_gadget( - pb, - ZERO, - phi, - h_sig, - nonce, - rho - )); - - // Commit to the output notes publicly without - // disclosing them. - commit_to_outputs.reset(new note_commitment_gadget( - pb, - ZERO, - a_pk->bits, - this->value, - rho->bits, - this->r->bits, - commitment - )); - } - - void generate_r1cs_constraints() { - note_gadget::generate_r1cs_constraints(); - - a_pk->generate_r1cs_constraints(); - - prevent_faerie_gold->generate_r1cs_constraints(); - - commit_to_outputs->generate_r1cs_constraints(); - } - - void generate_r1cs_witness(const SproutNote& note) { - note_gadget::generate_r1cs_witness(note); - - prevent_faerie_gold->generate_r1cs_witness(); - - // [SANITY CHECK] Witness rho ourselves with the - // note information. - rho->bits.fill_with_bits( - this->pb, - uint256_to_bool_vector(note.rho) - ); - - a_pk->bits.fill_with_bits( - this->pb, - uint256_to_bool_vector(note.a_pk) - ); - - commit_to_outputs->generate_r1cs_witness(); - } -}; diff --git a/src/zcash/circuit/prfs.tcc b/src/zcash/circuit/prfs.tcc deleted file mode 100644 index 3f50ac9e5ff..00000000000 --- a/src/zcash/circuit/prfs.tcc +++ /dev/null @@ -1,109 +0,0 @@ -template -class PRF_gadget : gadget { -private: - std::shared_ptr> block; - std::shared_ptr> hasher; - std::shared_ptr> result; - -public: - PRF_gadget( - protoboard& pb, - pb_variable& ZERO, - bool a, - bool b, - bool c, - bool d, - pb_variable_array x, - pb_variable_array y, - std::shared_ptr> result - ) : gadget(pb), result(result) { - - pb_linear_combination_array IV = SHA256_default_IV(pb); - - pb_variable_array discriminants; - discriminants.emplace_back(a ? ONE : ZERO); - discriminants.emplace_back(b ? ONE : ZERO); - discriminants.emplace_back(c ? ONE : ZERO); - discriminants.emplace_back(d ? ONE : ZERO); - - block.reset(new block_variable(pb, { - discriminants, - x, - y - }, "PRF_block")); - - hasher.reset(new sha256_compression_function_gadget( - pb, - IV, - block->bits, - *result, - "PRF_hasher")); - } - - void generate_r1cs_constraints() { - hasher->generate_r1cs_constraints(); - } - - void generate_r1cs_witness() { - hasher->generate_r1cs_witness(); - } -}; - -template -pb_variable_array gen256zeroes(pb_variable& ZERO) { - pb_variable_array ret; - while (ret.size() < 256) { - ret.emplace_back(ZERO); - } - - return ret; -} - -template -class PRF_addr_a_pk_gadget : public PRF_gadget { -public: - PRF_addr_a_pk_gadget( - protoboard& pb, - pb_variable& ZERO, - pb_variable_array& a_sk, - std::shared_ptr> result - ) : PRF_gadget(pb, ZERO, 1, 1, 0, 0, a_sk, gen256zeroes(ZERO), result) {} -}; - -template -class PRF_nf_gadget : public PRF_gadget { -public: - PRF_nf_gadget( - protoboard& pb, - pb_variable& ZERO, - pb_variable_array& a_sk, - pb_variable_array& rho, - std::shared_ptr> result - ) : PRF_gadget(pb, ZERO, 1, 1, 1, 0, a_sk, rho, result) {} -}; - -template -class PRF_pk_gadget : public PRF_gadget { -public: - PRF_pk_gadget( - protoboard& pb, - pb_variable& ZERO, - pb_variable_array& a_sk, - pb_variable_array& h_sig, - bool nonce, - std::shared_ptr> result - ) : PRF_gadget(pb, ZERO, 0, nonce, 0, 0, a_sk, h_sig, result) {} -}; - -template -class PRF_rho_gadget : public PRF_gadget { -public: - PRF_rho_gadget( - protoboard& pb, - pb_variable& ZERO, - pb_variable_array& phi, - pb_variable_array& h_sig, - bool nonce, - std::shared_ptr> result - ) : PRF_gadget(pb, ZERO, 0, nonce, 1, 0, phi, h_sig, result) {} -}; diff --git a/src/zcash/circuit/utils.tcc b/src/zcash/circuit/utils.tcc deleted file mode 100644 index fa7ae324a9f..00000000000 --- a/src/zcash/circuit/utils.tcc +++ /dev/null @@ -1,75 +0,0 @@ -#include "uint252.h" - -template -pb_variable_array from_bits(std::vector bits, pb_variable& ZERO) { - pb_variable_array acc; - - BOOST_FOREACH(bool bit, bits) { - acc.emplace_back(bit ? ONE : ZERO); - } - - return acc; -} - -std::vector trailing252(std::vector input) { - if (input.size() != 256) { - throw std::length_error("trailing252 input invalid length"); - } - - return std::vector(input.begin() + 4, input.end()); -} - -template -std::vector to_bool_vector(T input) { - std::vector input_v(input.begin(), input.end()); - - return convertBytesVectorToVector(input_v); -} - -std::vector uint256_to_bool_vector(uint256 input) { - return to_bool_vector(input); -} - -std::vector uint252_to_bool_vector(uint252 input) { - return trailing252(to_bool_vector(input)); -} - -std::vector uint64_to_bool_vector(uint64_t input) { - auto num_bv = convertIntToVectorLE(input); - - return convertBytesVectorToVector(num_bv); -} - -void insert_uint256(std::vector& into, uint256 from) { - std::vector blob = uint256_to_bool_vector(from); - into.insert(into.end(), blob.begin(), blob.end()); -} - -void insert_uint64(std::vector& into, uint64_t from) { - std::vector num = uint64_to_bool_vector(from); - into.insert(into.end(), num.begin(), num.end()); -} - -template -T swap_endianness_u64(T v) { - if (v.size() != 64) { - throw std::length_error("invalid bit length for 64-bit unsigned integer"); - } - - for (size_t i = 0; i < 4; i++) { - for (size_t j = 0; j < 8; j++) { - std::swap(v[i*8 + j], v[((7-i)*8)+j]); - } - } - - return v; -} - -template -linear_combination packed_addition(pb_variable_array input) { - auto input_swapped = swap_endianness_u64(input); - - return pb_packing_sum(pb_variable_array( - input_swapped.rbegin(), input_swapped.rend() - )); -} From 9a0e2575269f192f99040a09fd6cab41b39a6da3 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 25 Jun 2019 17:07:41 +0200 Subject: [PATCH 257/395] Revert "configure: Guess -march for libsnark OPTFLAGS instead of hard-coding" This reverts commit 98cfe4228c376b9224f8f72085a4fcb2cdca9cc4. --- build-aux/m4/ax_compiler_vendor.m4 | 117 ------------- build-aux/m4/ax_gcc_archflag.m4 | 267 ----------------------------- build-aux/m4/ax_gcc_x86_cpuid.m4 | 89 ---------- configure.ac | 4 - src/Makefile.am | 4 +- 5 files changed, 2 insertions(+), 479 deletions(-) delete mode 100644 build-aux/m4/ax_compiler_vendor.m4 delete mode 100644 build-aux/m4/ax_gcc_archflag.m4 delete mode 100644 build-aux/m4/ax_gcc_x86_cpuid.m4 diff --git a/build-aux/m4/ax_compiler_vendor.m4 b/build-aux/m4/ax_compiler_vendor.m4 deleted file mode 100644 index f06e865405c..00000000000 --- a/build-aux/m4/ax_compiler_vendor.m4 +++ /dev/null @@ -1,117 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_compiler_vendor.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_COMPILER_VENDOR -# -# DESCRIPTION -# -# Determine the vendor of the C, C++ or Fortran compiler. The vendor is -# returned in the cache variable $ax_cv_c_compiler_vendor for C, -# $ax_cv_cxx_compiler_vendor for C++ or $ax_cv_fc_compiler_vendor for -# (modern) Fortran. The value is one of "intel", "ibm", "pathscale", -# "clang" (LLVM), "cray", "fujitsu", "sdcc", "sx", "portland" (PGI), "gnu" -# (GCC), "sun" (Oracle Developer Studio), "hp", "dec", "borland", -# "comeau", "kai", "lcc", "sgi", "microsoft", "metrowerks", "watcom", -# "tcc" (Tiny CC) or "unknown" (if the compiler cannot be determined). -# -# To check for a Fortran compiler, you must first call AC_FC_PP_SRCEXT -# with an appropriate preprocessor-enabled extension. For example: -# -# AC_LANG_PUSH([Fortran]) -# AC_PROG_FC -# AC_FC_PP_SRCEXT([F]) -# AX_COMPILER_VENDOR -# AC_LANG_POP([Fortran]) -# -# LICENSE -# -# Copyright (c) 2008 Steven G. Johnson -# Copyright (c) 2008 Matteo Frigo -# Copyright (c) 2018-19 John Zaitseff -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 30 - -AC_DEFUN([AX_COMPILER_VENDOR], [dnl - AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, [dnl - dnl If you modify this list of vendors, please add similar support - dnl to ax_compiler_version.m4 if at all possible. - dnl - dnl Note: Do NOT check for GCC first since some other compilers - dnl define __GNUC__ to remain compatible with it. Compilers that - dnl are very slow to start (such as Intel) are listed first. - - vendors=" - intel: __ICC,__ECC,__INTEL_COMPILER - ibm: __xlc__,__xlC__,__IBMC__,__IBMCPP__,__ibmxl__ - pathscale: __PATHCC__,__PATHSCALE__ - clang: __clang__ - cray: _CRAYC - fujitsu: __FUJITSU - sdcc: SDCC,__SDCC - sx: _SX - portland: __PGI - gnu: __GNUC__ - sun: __SUNPRO_C,__SUNPRO_CC,__SUNPRO_F90,__SUNPRO_F95 - hp: __HP_cc,__HP_aCC - dec: __DECC,__DECCXX,__DECC_VER,__DECCXX_VER - borland: __BORLANDC__,__CODEGEARC__,__TURBOC__ - comeau: __COMO__ - kai: __KCC - lcc: __LCC__ - sgi: __sgi,sgi - microsoft: _MSC_VER - metrowerks: __MWERKS__ - watcom: __WATCOMC__ - tcc: __TINYC__ - unknown: UNKNOWN - " - for ventest in $vendors; do - case $ventest in - *:) - vendor=$ventest - continue - ;; - *) - vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")" - ;; - esac - - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [[ -#if !($vencpp) - thisisanerror; -#endif - ]])], [break]) - done - - ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=`echo $vendor | cut -d: -f1` - ]) -])dnl diff --git a/build-aux/m4/ax_gcc_archflag.m4 b/build-aux/m4/ax_gcc_archflag.m4 deleted file mode 100644 index c52b9b296e9..00000000000 --- a/build-aux/m4/ax_gcc_archflag.m4 +++ /dev/null @@ -1,267 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_gcc_archflag.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_GCC_ARCHFLAG([PORTABLE?], [ACTION-SUCCESS], [ACTION-FAILURE]) -# -# DESCRIPTION -# -# This macro tries to guess the "native" arch corresponding to the target -# architecture for use with gcc's -march=arch or -mtune=arch flags. If -# found, the cache variable $ax_cv_gcc_archflag is set to this flag and -# ACTION-SUCCESS is executed; otherwise $ax_cv_gcc_archflag is set to -# "unknown" and ACTION-FAILURE is executed. The default ACTION-SUCCESS is -# to add $ax_cv_gcc_archflag to the end of $CFLAGS. -# -# PORTABLE? should be either [yes] (default) or [no]. In the former case, -# the flag is set to -mtune (or equivalent) so that the architecture is -# only used for tuning, but the instruction set used is still portable. In -# the latter case, the flag is set to -march (or equivalent) so that -# architecture-specific instructions are enabled. -# -# The user can specify --with-gcc-arch= in order to override the -# macro's choice of architecture, or --without-gcc-arch to disable this. -# -# When cross-compiling, or if $CC is not gcc, then ACTION-FAILURE is -# called unless the user specified --with-gcc-arch manually. -# -# Requires macros: AX_CHECK_COMPILE_FLAG, AX_GCC_X86_CPUID -# -# (The main emphasis here is on recent CPUs, on the principle that doing -# high-performance computing on old hardware is uncommon.) -# -# LICENSE -# -# Copyright (c) 2008 Steven G. Johnson -# Copyright (c) 2008 Matteo Frigo -# Copyright (c) 2014 Tsukasa Oi -# Copyright (c) 2017-2018 Alexey Kopytov -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 22 - -AC_DEFUN([AX_GCC_ARCHFLAG], -[AC_REQUIRE([AC_PROG_CC]) -AC_REQUIRE([AC_CANONICAL_HOST]) -AC_REQUIRE([AC_PROG_SED]) -AC_REQUIRE([AX_COMPILER_VENDOR]) - -AC_ARG_WITH(gcc-arch, [AS_HELP_STRING([--with-gcc-arch=], [use architecture for gcc -march/-mtune, instead of guessing])], - ax_gcc_arch=$withval, ax_gcc_arch=yes) - -AC_MSG_CHECKING([for gcc architecture flag]) -AC_MSG_RESULT([]) -AC_CACHE_VAL(ax_cv_gcc_archflag, -[ -ax_cv_gcc_archflag="unknown" - -if test "$GCC" = yes; then - -if test "x$ax_gcc_arch" = xyes; then -ax_gcc_arch="" -if test "$cross_compiling" = no; then -case $host_cpu in - i[[3456]]86*|x86_64*|amd64*) # use cpuid codes - AX_GCC_X86_CPUID(0) - AX_GCC_X86_CPUID(1) - case $ax_cv_gcc_x86_cpuid_0 in - *:756e6547:6c65746e:49656e69) # Intel - case $ax_cv_gcc_x86_cpuid_1 in - *5[[4578]]?:*:*:*) ax_gcc_arch="pentium-mmx pentium" ;; - *5[[123]]?:*:*:*) ax_gcc_arch=pentium ;; - *0?61?:*:*:*|?61?:*:*:*|61?:*:*:*) ax_gcc_arch=pentiumpro ;; - *0?6[[356]]?:*:*:*|?6[[356]]?:*:*:*|6[[356]]?:*:*:*) ax_gcc_arch="pentium2 pentiumpro" ;; - *0?6[[78ab]]?:*:*:*|?6[[78ab]]?:*:*:*|6[[78ab]]?:*:*:*) ax_gcc_arch="pentium3 pentiumpro" ;; - *0?6[[9d]]?:*:*:*|?6[[9d]]?:*:*:*|6[[9d]]?:*:*:*|*1?65?:*:*:*) ax_gcc_arch="pentium-m pentium3 pentiumpro" ;; - *0?6e?:*:*:*|?6e?:*:*:*|6e?:*:*:*) ax_gcc_arch="yonah pentium-m pentium3 pentiumpro" ;; - *0?6f?:*:*:*|?6f?:*:*:*|6f?:*:*:*|*1?66?:*:*:*) ax_gcc_arch="core2 pentium-m pentium3 pentiumpro" ;; - *1?6[[7d]]?:*:*:*) ax_gcc_arch="penryn core2 pentium-m pentium3 pentiumpro" ;; - *1?6[[aef]]?:*:*:*|*2?6e?:*:*:*) ax_gcc_arch="nehalem corei7 core2 pentium-m pentium3 pentiumpro" ;; - *2?6[[5cf]]?:*:*:*) ax_gcc_arch="westmere corei7 core2 pentium-m pentium3 pentiumpro" ;; - *2?6[[ad]]?:*:*:*) ax_gcc_arch="sandybridge corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;; - *3?6[[ae]]?:*:*:*) ax_gcc_arch="ivybridge core-avx-i corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;; - *3?6[[cf]]?:*:*:*|*4?6[[56]]?:*:*:*) ax_gcc_arch="haswell core-avx2 core-avx-i corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;; - *3?6d?:*:*:*|*4?6[[7f]]?:*:*:*|*5?66?:*:*:*) ax_gcc_arch="broadwell core-avx2 core-avx-i corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;; - *1?6c?:*:*:*|*2?6[[67]]?:*:*:*|*3?6[[56]]?:*:*:*) ax_gcc_arch="bonnell atom core2 pentium-m pentium3 pentiumpro" ;; - *3?67?:*:*:*|*[[45]]?6[[ad]]?:*:*:*) ax_gcc_arch="silvermont atom core2 pentium-m pentium3 pentiumpro" ;; - *000?f[[012]]?:*:*:*|?f[[012]]?:*:*:*|f[[012]]?:*:*:*) ax_gcc_arch="pentium4 pentiumpro" ;; - *000?f[[346]]?:*:*:*|?f[[346]]?:*:*:*|f[[346]]?:*:*:*) ax_gcc_arch="nocona prescott pentium4 pentiumpro" ;; - # fallback - *5??:*:*:*) ax_gcc_arch=pentium ;; - *??6??:*:*:*) ax_gcc_arch="core2 pentiumpro" ;; - *6??:*:*:*) ax_gcc_arch=pentiumpro ;; - *00??f??:*:*:*|??f??:*:*:*|?f??:*:*:*|f??:*:*:*) ax_gcc_arch="pentium4 pentiumpro" ;; - esac ;; - *:68747541:444d4163:69746e65) # AMD - case $ax_cv_gcc_x86_cpuid_1 in - *5[[67]]?:*:*:*) ax_gcc_arch=k6 ;; - *5[[8]]?:*:*:*) ax_gcc_arch="k6-2 k6" ;; - *5[[9d]]?:*:*:*) ax_gcc_arch="k6-3 k6" ;; - *6[[12]]?:*:*:*) ax_gcc_arch="athlon k7" ;; - *6[[34]]?:*:*:*) ax_gcc_arch="athlon-tbird k7" ;; - *6[[678a]]?:*:*:*) ax_gcc_arch="athlon-xp athlon-4 athlon k7" ;; - *000?f[[4578bcef]]?:*:*:*|?f[[4578bcef]]?:*:*:*|f[[4578bcef]]?:*:*:*|*001?f[[4578bcf]]?:*:*:*|1?f[[4578bcf]]?:*:*:*) ax_gcc_arch="athlon64 k8" ;; - *002?f[[13457bcf]]?:*:*:*|2?f[[13457bcf]]?:*:*:*|*004?f[[138bcf]]?:*:*:*|4?f[[138bcf]]?:*:*:*|*005?f[[df]]?:*:*:*|5?f[[df]]?:*:*:*|*006?f[[8bcf]]?:*:*:*|6?f[[8bcf]]?:*:*:*|*007?f[[cf]]?:*:*:*|7?f[[cf]]?:*:*:*|*00c?f1?:*:*:*|c?f1?:*:*:*|*020?f3?:*:*:*|20?f3?:*:*:*) ax_gcc_arch="athlon64-sse3 k8-sse3 athlon64 k8" ;; - *010?f[[245689a]]?:*:*:*|10?f[[245689a]]?:*:*:*|*030?f1?:*:*:*|30?f1?:*:*:*) ax_gcc_arch="barcelona amdfam10 k8" ;; - *050?f[[12]]?:*:*:*|50?f[[12]]?:*:*:*) ax_gcc_arch="btver1 amdfam10 k8" ;; - *060?f1?:*:*:*|60?f1?:*:*:*) ax_gcc_arch="bdver1 amdfam10 k8" ;; - *060?f2?:*:*:*|60?f2?:*:*:*|*061?f[[03]]?:*:*:*|61?f[[03]]?:*:*:*) ax_gcc_arch="bdver2 bdver1 amdfam10 k8" ;; - *063?f0?:*:*:*|63?f0?:*:*:*) ax_gcc_arch="bdver3 bdver2 bdver1 amdfam10 k8" ;; - *07[[03]]?f0?:*:*:*|7[[03]]?f0?:*:*:*) ax_gcc_arch="btver2 btver1 amdfam10 k8" ;; - # fallback - *0[[13]]??f??:*:*:*|[[13]]??f??:*:*:*) ax_gcc_arch="barcelona amdfam10 k8" ;; - *020?f??:*:*:*|20?f??:*:*:*) ax_gcc_arch="athlon64-sse3 k8-sse3 athlon64 k8" ;; - *05??f??:*:*:*|5??f??:*:*:*) ax_gcc_arch="btver1 amdfam10 k8" ;; - *060?f??:*:*:*|60?f??:*:*:*) ax_gcc_arch="bdver1 amdfam10 k8" ;; - *061?f??:*:*:*|61?f??:*:*:*) ax_gcc_arch="bdver2 bdver1 amdfam10 k8" ;; - *06??f??:*:*:*|6??f??:*:*:*) ax_gcc_arch="bdver3 bdver2 bdver1 amdfam10 k8" ;; - *070?f??:*:*:*|70?f??:*:*:*) ax_gcc_arch="btver2 btver1 amdfam10 k8" ;; - *???f??:*:*:*) ax_gcc_arch="amdfam10 k8" ;; - esac ;; - *:746e6543:736c7561:48727561) # IDT / VIA (Centaur) - case $ax_cv_gcc_x86_cpuid_1 in - *54?:*:*:*) ax_gcc_arch=winchip-c6 ;; - *5[[89]]?:*:*:*) ax_gcc_arch=winchip2 ;; - *66?:*:*:*) ax_gcc_arch=winchip2 ;; - *6[[78]]?:*:*:*) ax_gcc_arch=c3 ;; - *6[[9adf]]?:*:*:*) ax_gcc_arch="c3-2 c3" ;; - esac ;; - esac - if test x"$ax_gcc_arch" = x; then # fallback - case $host_cpu in - i586*) ax_gcc_arch=pentium ;; - i686*) ax_gcc_arch=pentiumpro ;; - esac - fi - ;; - - sparc*) - AC_PATH_PROG([PRTDIAG], [prtdiag], [prtdiag], [$PATH:/usr/platform/`uname -i`/sbin/:/usr/platform/`uname -m`/sbin/]) - cputype=`(((grep cpu /proc/cpuinfo | cut -d: -f2) ; ($PRTDIAG -v |grep -i sparc) ; grep -i cpu /var/run/dmesg.boot ) | head -n 1) 2> /dev/null` - cputype=`echo "$cputype" | tr -d ' -' | $SED 's/SPARCIIi/SPARCII/' |tr $as_cr_LETTERS $as_cr_letters` - case $cputype in - *ultrasparciv*) ax_gcc_arch="ultrasparc4 ultrasparc3 ultrasparc v9" ;; - *ultrasparciii*) ax_gcc_arch="ultrasparc3 ultrasparc v9" ;; - *ultrasparc*) ax_gcc_arch="ultrasparc v9" ;; - *supersparc*|*tms390z5[[05]]*) ax_gcc_arch="supersparc v8" ;; - *hypersparc*|*rt62[[056]]*) ax_gcc_arch="hypersparc v8" ;; - *cypress*) ax_gcc_arch=cypress ;; - esac ;; - - alphaev5) ax_gcc_arch=ev5 ;; - alphaev56) ax_gcc_arch=ev56 ;; - alphapca56) ax_gcc_arch="pca56 ev56" ;; - alphapca57) ax_gcc_arch="pca57 pca56 ev56" ;; - alphaev6) ax_gcc_arch=ev6 ;; - alphaev67) ax_gcc_arch=ev67 ;; - alphaev68) ax_gcc_arch="ev68 ev67" ;; - alphaev69) ax_gcc_arch="ev69 ev68 ev67" ;; - alphaev7) ax_gcc_arch="ev7 ev69 ev68 ev67" ;; - alphaev79) ax_gcc_arch="ev79 ev7 ev69 ev68 ev67" ;; - - powerpc*) - cputype=`((grep cpu /proc/cpuinfo | head -n 1 | cut -d: -f2 | cut -d, -f1 | $SED 's/ //g') ; /usr/bin/machine ; /bin/machine; grep CPU /var/run/dmesg.boot | head -n 1 | cut -d" " -f2) 2> /dev/null` - cputype=`echo $cputype | $SED -e 's/ppc//g;s/ *//g'` - case $cputype in - *750*) ax_gcc_arch="750 G3" ;; - *740[[0-9]]*) ax_gcc_arch="$cputype 7400 G4" ;; - *74[[4-5]][[0-9]]*) ax_gcc_arch="$cputype 7450 G4" ;; - *74[[0-9]][[0-9]]*) ax_gcc_arch="$cputype G4" ;; - *970*) ax_gcc_arch="970 G5 power4";; - *POWER4*|*power4*|*gq*) ax_gcc_arch="power4 970";; - *POWER5*|*power5*|*gr*|*gs*) ax_gcc_arch="power5 power4 970";; - 603ev|8240) ax_gcc_arch="$cputype 603e 603";; - *POWER7*) ax_gcc_arch="power7";; - *POWER8*) ax_gcc_arch="power8";; - *POWER9*) ax_gcc_arch="power9";; - *POWER10*) ax_gcc_arch="power10";; - *) ax_gcc_arch=$cputype ;; - esac - ax_gcc_arch="$ax_gcc_arch powerpc" - ;; - aarch64) - cpuimpl=`grep 'CPU implementer' /proc/cpuinfo 2> /dev/null | cut -d: -f2 | tr -d " " | head -n 1` - cpuarch=`grep 'CPU architecture' /proc/cpuinfo 2> /dev/null | cut -d: -f2 | tr -d " " | head -n 1` - cpuvar=`grep 'CPU variant' /proc/cpuinfo 2> /dev/null | cut -d: -f2 | tr -d " " | head -n 1` - case $cpuimpl in - 0x42) case $cpuarch in - 8) case $cpuvar in - 0x0) ax_gcc_arch="thunderx2t99 vulcan armv8.1-a armv8-a+lse armv8-a native" ;; - esac - ;; - esac - ;; - 0x43) case $cpuarch in - 8) case $cpuvar in - 0x0) ax_gcc_arch="thunderx armv8-a native" ;; - 0x1) ax_gcc_arch="thunderx+lse armv8.1-a armv8-a+lse armv8-a native" ;; - esac - ;; - esac - ;; - esac - ;; -esac -fi # not cross-compiling -fi # guess arch - -if test "x$ax_gcc_arch" != x -a "x$ax_gcc_arch" != xno; then -if test "x[]m4_default([$1],yes)" = xyes; then # if we require portable code - flag_prefixes="-mtune=" - if test "x$ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor" = xclang; then flag_prefixes="-march="; fi - # -mcpu=$arch and m$arch generate nonportable code on every arch except - # x86. And some other arches (e.g. Alpha) don't accept -mtune. Grrr. - case $host_cpu in i*86|x86_64*|amd64*) flag_prefixes="$flag_prefixes -mcpu= -m";; esac -else - flag_prefixes="-march= -mcpu= -m" -fi -for flag_prefix in $flag_prefixes; do - for arch in $ax_gcc_arch; do - flag="$flag_prefix$arch" - AX_CHECK_COMPILE_FLAG($flag, [if test "x$ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor" = xclang; then - if test "x[]m4_default([$1],yes)" = xyes; then - if test "x$flag" = "x-march=$arch"; then flag=-mtune=$arch; fi - fi - fi; ax_cv_gcc_archflag=$flag; break]) - done - test "x$ax_cv_gcc_archflag" = xunknown || break -done -fi - -fi # $GCC=yes -]) -AC_MSG_CHECKING([for gcc architecture flag]) -AC_MSG_RESULT($ax_cv_gcc_archflag) -if test "x$ax_cv_gcc_archflag" = xunknown; then - m4_default([$3],:) -else - m4_default([$2], [CFLAGS="$CFLAGS $ax_cv_gcc_archflag"]) -fi -]) diff --git a/build-aux/m4/ax_gcc_x86_cpuid.m4 b/build-aux/m4/ax_gcc_x86_cpuid.m4 deleted file mode 100644 index df954658ee1..00000000000 --- a/build-aux/m4/ax_gcc_x86_cpuid.m4 +++ /dev/null @@ -1,89 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_gcc_x86_cpuid.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_GCC_X86_CPUID(OP) -# AX_GCC_X86_CPUID_COUNT(OP, COUNT) -# -# DESCRIPTION -# -# On Pentium and later x86 processors, with gcc or a compiler that has a -# compatible syntax for inline assembly instructions, run a small program -# that executes the cpuid instruction with input OP. This can be used to -# detect the CPU type. AX_GCC_X86_CPUID_COUNT takes an additional COUNT -# parameter that gets passed into register ECX before calling cpuid. -# -# On output, the values of the eax, ebx, ecx, and edx registers are stored -# as hexadecimal strings as "eax:ebx:ecx:edx" in the cache variable -# ax_cv_gcc_x86_cpuid_OP. -# -# If the cpuid instruction fails (because you are running a -# cross-compiler, or because you are not using gcc, or because you are on -# a processor that doesn't have this instruction), ax_cv_gcc_x86_cpuid_OP -# is set to the string "unknown". -# -# This macro mainly exists to be used in AX_GCC_ARCHFLAG. -# -# LICENSE -# -# Copyright (c) 2008 Steven G. Johnson -# Copyright (c) 2008 Matteo Frigo -# Copyright (c) 2015 Michael Petch -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 10 - -AC_DEFUN([AX_GCC_X86_CPUID], -[AX_GCC_X86_CPUID_COUNT($1, 0) -]) - -AC_DEFUN([AX_GCC_X86_CPUID_COUNT], -[AC_REQUIRE([AC_PROG_CC]) -AC_LANG_PUSH([C]) -AC_CACHE_CHECK(for x86 cpuid $1 output, ax_cv_gcc_x86_cpuid_$1, - [AC_RUN_IFELSE([AC_LANG_PROGRAM([#include ], [ - int op = $1, level = $2, eax, ebx, ecx, edx; - FILE *f; - __asm__ __volatile__ ("xchg %%ebx, %1\n" - "cpuid\n" - "xchg %%ebx, %1\n" - : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx) - : "a" (op), "2" (level)); - - f = fopen("conftest_cpuid", "w"); if (!f) return 1; - fprintf(f, "%x:%x:%x:%x\n", eax, ebx, ecx, edx); - fclose(f); - return 0; -])], - [ax_cv_gcc_x86_cpuid_$1=`cat conftest_cpuid`; rm -f conftest_cpuid], - [ax_cv_gcc_x86_cpuid_$1=unknown; rm -f conftest_cpuid], - [ax_cv_gcc_x86_cpuid_$1=unknown])]) -AC_LANG_POP([C]) -]) diff --git a/configure.ac b/configure.ac index 90dd4e44500..890aea55715 100644 --- a/configure.ac +++ b/configure.ac @@ -768,9 +768,6 @@ else LIBSNARK_DEPINST="$prefix" fi -# Set optimization flags for libsnark -AX_GCC_ARCHFLAG([no], [LIBSNARK_OPTFLAGS="-O2 $ax_cv_gcc_archflag"], [LIBSNARK_OPTFLAGS="-O2"]) - # Additional Zcash flags AX_CHECK_COMPILE_FLAG([-fwrapv],[CXXFLAGS="$CXXFLAGS -fwrapv"]) AX_CHECK_COMPILE_FLAG([-fno-strict-aliasing],[CXXFLAGS="$CXXFLAGS -fno-strict-aliasing"]) @@ -909,7 +906,6 @@ AC_SUBST(ZMQ_LIBS) AC_SUBST(GMP_LIBS) AC_SUBST(GMPXX_LIBS) AC_SUBST(LIBSNARK_DEPINST) -AC_SUBST(LIBSNARK_OPTFLAGS) AC_SUBST(LIBZCASH_LIBS) AC_SUBST(PROTON_LIBS) AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile src/test/buildenv.py]) diff --git a/src/Makefile.am b/src/Makefile.am index e0ca82a6022..ad2521c1606 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -70,10 +70,10 @@ LIBSNARK_CONFIG_FLAGS += PLATFORM=darwin endif $(LIBSNARK): $(wildcard snark/src/*) - $(AM_V_at) CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="$(LIBSNARK_OPTFLAGS)" + $(AM_V_at) CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="-O2 -march=x86-64" libsnark-tests: $(wildcard snark/src/*) - $(AM_V_at) CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ check DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="$(LIBSNARK_OPTFLAGS)" + $(AM_V_at) CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ check DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="-O2 -march=x86-64" $(LIBUNIVALUE): $(wildcard univalue/lib/*) $(wildcard univalue/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) From 7bd700b1007f90635798339167310b1ad631880c Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 25 Jun 2019 17:10:00 +0200 Subject: [PATCH 258/395] Revert "Check if OpenMP is available before using it" This reverts commit daad2c273657233735a100e5011fcc2fd1a88b75. --- build-aux/m4/ax_openmp.m4 | 123 -------------------------------------- configure.ac | 10 ---- src/Makefile.am | 3 - 3 files changed, 136 deletions(-) delete mode 100644 build-aux/m4/ax_openmp.m4 diff --git a/build-aux/m4/ax_openmp.m4 b/build-aux/m4/ax_openmp.m4 deleted file mode 100644 index 866e1d66451..00000000000 --- a/build-aux/m4/ax_openmp.m4 +++ /dev/null @@ -1,123 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_openmp.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_OPENMP([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) -# -# DESCRIPTION -# -# This macro tries to find out how to compile programs that use OpenMP a -# standard API and set of compiler directives for parallel programming -# (see http://www-unix.mcs/) -# -# On success, it sets the OPENMP_CFLAGS/OPENMP_CXXFLAGS/OPENMP_F77FLAGS -# output variable to the flag (e.g. -omp) used both to compile *and* link -# OpenMP programs in the current language. -# -# NOTE: You are assumed to not only compile your program with these flags, -# but also link it with them as well. -# -# If you want to compile everything with OpenMP, you should set: -# -# CFLAGS="$CFLAGS $OPENMP_CFLAGS" -# #OR# CXXFLAGS="$CXXFLAGS $OPENMP_CXXFLAGS" -# #OR# FFLAGS="$FFLAGS $OPENMP_FFLAGS" -# -# (depending on the selected language). -# -# The user can override the default choice by setting the corresponding -# environment variable (e.g. OPENMP_CFLAGS). -# -# ACTION-IF-FOUND is a list of shell commands to run if an OpenMP flag is -# found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it is -# not found. If ACTION-IF-FOUND is not specified, the default action will -# define HAVE_OPENMP. -# -# LICENSE -# -# Copyright (c) 2008 Steven G. Johnson -# Copyright (c) 2015 John W. Peterson -# Copyright (c) 2016 Nick R. Papior -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 13 - -AC_DEFUN([AX_OPENMP], [ -AC_PREREQ([2.69]) dnl for _AC_LANG_PREFIX - -AC_CACHE_CHECK([for OpenMP flag of _AC_LANG compiler], ax_cv_[]_AC_LANG_ABBREV[]_openmp, [save[]_AC_LANG_PREFIX[]FLAGS=$[]_AC_LANG_PREFIX[]FLAGS -ax_cv_[]_AC_LANG_ABBREV[]_openmp=unknown -# Flags to try: -fopenmp (gcc), -mp (SGI & PGI), -# -qopenmp (icc>=15), -openmp (icc), -# -xopenmp (Sun), -omp (Tru64), -# -qsmp=omp (AIX), -# none -ax_openmp_flags="-fopenmp -openmp -qopenmp -mp -xopenmp -omp -qsmp=omp none" -if test "x$OPENMP_[]_AC_LANG_PREFIX[]FLAGS" != x; then - ax_openmp_flags="$OPENMP_[]_AC_LANG_PREFIX[]FLAGS $ax_openmp_flags" -fi -for ax_openmp_flag in $ax_openmp_flags; do - case $ax_openmp_flag in - none) []_AC_LANG_PREFIX[]FLAGS=$save[]_AC_LANG_PREFIX[] ;; - *) []_AC_LANG_PREFIX[]FLAGS="$save[]_AC_LANG_PREFIX[]FLAGS $ax_openmp_flag" ;; - esac - AC_LINK_IFELSE([AC_LANG_SOURCE([[ -@%:@include - -static void -parallel_fill(int * data, int n) -{ - int i; -@%:@pragma omp parallel for - for (i = 0; i < n; ++i) - data[i] = i; -} - -int -main() -{ - int arr[100000]; - omp_set_num_threads(2); - parallel_fill(arr, 100000); - return 0; -} -]])],[ax_cv_[]_AC_LANG_ABBREV[]_openmp=$ax_openmp_flag; break],[]) -done -[]_AC_LANG_PREFIX[]FLAGS=$save[]_AC_LANG_PREFIX[]FLAGS -]) -if test "x$ax_cv_[]_AC_LANG_ABBREV[]_openmp" = "xunknown"; then - m4_default([$2],:) -else - if test "x$ax_cv_[]_AC_LANG_ABBREV[]_openmp" != "xnone"; then - OPENMP_[]_AC_LANG_PREFIX[]FLAGS=$ax_cv_[]_AC_LANG_ABBREV[]_openmp - fi - m4_default([$1], [AC_DEFINE(HAVE_OPENMP,1,[Define if OpenMP is enabled])]) -fi -])dnl AX_OPENMP diff --git a/configure.ac b/configure.ac index 890aea55715..157e5e154c9 100644 --- a/configure.ac +++ b/configure.ac @@ -750,16 +750,6 @@ case $host in ;; esac -dnl Check for OpenMP support -AX_OPENMP( - [AC_DEFINE(HAVE_OPENMP, 1, [Define if OpenMP is enabled]) - AM_CONDITIONAL([HAVE_OPENMP], [true]) - CPPFLAGS="$CPPFLAGS -DMULTICORE" - CXXFLAGS="$CXXFLAGS $OPENMP_CXXFLAGS"], - [AC_MSG_WARN([OpenMP not supported, disabling multithreading]) - AC_DEFINE(HAVE_OPENMP, 0, [Define if OpenMP is enabled]) - AM_CONDITIONAL([HAVE_OPENMP], [false])]) - # Gitian uses a config.site that sets depends_prefix, and then sets --prefix=/ # build.sh just uses --prefix if test x$depends_prefix != x; then diff --git a/src/Makefile.am b/src/Makefile.am index ad2521c1606..e258541f568 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -62,9 +62,6 @@ $(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*) LIBSNARK_CXXFLAGS = $(AM_CXXFLAGS) $(PIC_FLAGS) -DBINARY_OUTPUT -DNO_PT_COMPRESSION=1 -fstack-protector-all LIBSNARK_CONFIG_FLAGS = CURVE=ALT_BN128 NO_PROCPS=1 NO_DOCS=1 STATIC=1 NO_SUPERCOP=1 FEATUREFLAGS=-DMONTGOMERY_OUTPUT NO_COPY_DEPINST=1 NO_COMPILE_LIBGTEST=1 -if HAVE_OPENMP -LIBSNARK_CONFIG_FLAGS += MULTICORE=1 -endif if TARGET_DARWIN LIBSNARK_CONFIG_FLAGS += PLATFORM=darwin endif From 6a4b8b77512c0236c13b15fd17d03b9408a0fdaf Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 25 Jun 2019 17:11:43 +0200 Subject: [PATCH 259/395] Remove libsnark from build system --- configure.ac | 11 +---------- src/Makefile.am | 23 ++--------------------- src/Makefile.gtest.include | 2 +- src/Makefile.test.include | 2 +- 4 files changed, 5 insertions(+), 33 deletions(-) diff --git a/configure.ac b/configure.ac index 157e5e154c9..d3aec4aa2d9 100644 --- a/configure.ac +++ b/configure.ac @@ -750,14 +750,6 @@ case $host in ;; esac -# Gitian uses a config.site that sets depends_prefix, and then sets --prefix=/ -# build.sh just uses --prefix -if test x$depends_prefix != x; then - LIBSNARK_DEPINST="$depends_prefix" -else - LIBSNARK_DEPINST="$prefix" -fi - # Additional Zcash flags AX_CHECK_COMPILE_FLAG([-fwrapv],[CXXFLAGS="$CXXFLAGS -fwrapv"]) AX_CHECK_COMPILE_FLAG([-fno-strict-aliasing],[CXXFLAGS="$CXXFLAGS -fno-strict-aliasing"]) @@ -895,7 +887,6 @@ AC_SUBST(EVENT_PTHREADS_LIBS) AC_SUBST(ZMQ_LIBS) AC_SUBST(GMP_LIBS) AC_SUBST(GMPXX_LIBS) -AC_SUBST(LIBSNARK_DEPINST) AC_SUBST(LIBZCASH_LIBS) AC_SUBST(PROTON_LIBS) AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile src/test/buildenv.py]) @@ -926,7 +917,7 @@ unset PKG_CONFIG_LIBDIR PKG_CONFIG_LIBDIR="$PKGCONFIG_LIBDIR_TEMP" ac_configure_args="${ac_configure_args} --disable-shared --with-pic --with-bignum=no --enable-module-recovery" -AC_CONFIG_SUBDIRS([src/secp256k1 src/snark src/univalue]) +AC_CONFIG_SUBDIRS([src/secp256k1 src/univalue]) AC_OUTPUT diff --git a/src/Makefile.am b/src/Makefile.am index e258541f568..f3f8de7061f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -30,8 +30,6 @@ BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS) BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include -BITCOIN_INCLUDES += -I$(srcdir)/snark -BITCOIN_INCLUDES += -I$(srcdir)/snark/libsnark BITCOIN_INCLUDES += -I$(srcdir)/univalue/include LIBBITCOIN_SERVER=libbitcoin_server.a @@ -40,7 +38,6 @@ LIBBITCOIN_CLI=libbitcoin_cli.a LIBBITCOIN_UTIL=libbitcoin_util.a LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a LIBSECP256K1=secp256k1/libsecp256k1.la -LIBSNARK=snark/libsnark.a LIBUNIVALUE=univalue/libunivalue.la LIBZCASH=libzcash.a @@ -60,18 +57,6 @@ endif $(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) -LIBSNARK_CXXFLAGS = $(AM_CXXFLAGS) $(PIC_FLAGS) -DBINARY_OUTPUT -DNO_PT_COMPRESSION=1 -fstack-protector-all -LIBSNARK_CONFIG_FLAGS = CURVE=ALT_BN128 NO_PROCPS=1 NO_DOCS=1 STATIC=1 NO_SUPERCOP=1 FEATUREFLAGS=-DMONTGOMERY_OUTPUT NO_COPY_DEPINST=1 NO_COMPILE_LIBGTEST=1 -if TARGET_DARWIN -LIBSNARK_CONFIG_FLAGS += PLATFORM=darwin -endif - -$(LIBSNARK): $(wildcard snark/src/*) - $(AM_V_at) CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="-O2 -march=x86-64" - -libsnark-tests: $(wildcard snark/src/*) - $(AM_V_at) CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ check DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="-O2 -march=x86-64" - $(LIBUNIVALUE): $(wildcard univalue/lib/*) $(wildcard univalue/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) @@ -114,7 +99,7 @@ LIBZCASH_H = \ zcash/Zcash.h \ zcash/zip32.h -.PHONY: FORCE collate-libsnark check-symbols check-security +.PHONY: FORCE check-symbols check-security # bitcoin core # BITCOIN_CORE_H = \ addressindex.h \ @@ -455,7 +440,6 @@ zcashd_LDADD = \ $(LIBBITCOIN_PROTON) \ $(LIBBITCOIN_CRYPTO) \ $(LIBZCASH) \ - $(LIBSNARK) \ $(LIBLEVELDB) \ $(LIBMEMENV) \ $(LIBSECP256K1) @@ -491,7 +475,6 @@ zcash_cli_LDADD = \ $(CRYPTO_LIBS) \ $(EVENT_LIBS) \ $(LIBZCASH) \ - $(LIBSNARK) \ $(LIBBITCOIN_CRYPTO) \ $(LIBZCASH_LIBS) # @@ -513,7 +496,6 @@ zcash_tx_LDADD = \ $(LIBBITCOIN_UTIL) \ $(LIBSECP256K1) \ $(LIBZCASH) \ - $(LIBSNARK) \ $(LIBBITCOIN_CRYPTO) \ $(LIBZCASH_LIBS) @@ -573,12 +555,11 @@ CLEANFILES = leveldb/libleveldb.a leveldb/libmemenv.a *.gcda *.gcno */*.gcno wal DISTCLEANFILES = obj/build.h -EXTRA_DIST = leveldb snark +EXTRA_DIST = leveldb clean-local: -$(MAKE) -C leveldb clean -$(MAKE) -C secp256k1 clean - -$(MAKE) -C snark clean -$(MAKE) -C univalue clean rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno -rm -f config.h diff --git a/src/Makefile.gtest.include b/src/Makefile.gtest.include index be593103389..474dd31e508 100644 --- a/src/Makefile.gtest.include +++ b/src/Makefile.gtest.include @@ -61,7 +61,7 @@ if ENABLE_WALLET zcash_gtest_LDADD += $(LIBBITCOIN_WALLET) endif -zcash_gtest_LDADD += $(LIBZCASH_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(LIBZCASH) $(LIBSNARK) $(LIBZCASH_LIBS) +zcash_gtest_LDADD += $(LIBZCASH_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(LIBZCASH) $(LIBZCASH_LIBS) if ENABLE_PROTON zcash_gtest_LDADD += $(LIBBITCOIN_PROTON) $(PROTON_LIBS) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index e65b35a45a8..42ca0d13875 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -124,7 +124,7 @@ test_test_bitcoin_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_C $(LIBLEVELDB) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS) test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -test_test_bitcoin_LDADD += $(LIBZCASH_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(LIBZCASH) $(LIBSNARK) $(LIBZCASH_LIBS) +test_test_bitcoin_LDADD += $(LIBZCASH_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(LIBZCASH) $(LIBZCASH_LIBS) test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static if ENABLE_ZMQ From 9ce0caf205dad06e8ee9fc782f75aa07c8248a31 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 25 Jun 2019 17:28:57 +0200 Subject: [PATCH 260/395] Remove libsnark --- src/snark/.gitignore | 51 - src/snark/AUTHORS | 19 - src/snark/LICENSE | 24 - src/snark/Makefile | 285 --- src/snark/README.md | 628 ------ src/snark/doxygen.conf | 1807 ----------------- .../algebra/curves/alt_bn128/alt_bn128_g1.cpp | 524 ----- .../algebra/curves/alt_bn128/alt_bn128_g1.hpp | 95 - .../algebra/curves/alt_bn128/alt_bn128_g2.cpp | 505 ----- .../algebra/curves/alt_bn128/alt_bn128_g2.hpp | 96 - .../curves/alt_bn128/alt_bn128_init.cpp | 273 --- .../curves/alt_bn128/alt_bn128_init.hpp | 57 - .../curves/alt_bn128/alt_bn128_pairing.cpp | 547 ----- .../curves/alt_bn128/alt_bn128_pairing.hpp | 92 - .../algebra/curves/alt_bn128/alt_bn128_pp.cpp | 58 - .../algebra/curves/alt_bn128/alt_bn128_pp.hpp | 50 - .../libsnark/algebra/curves/curve_utils.hpp | 22 - .../libsnark/algebra/curves/curve_utils.tcc | 37 - .../libsnark/algebra/curves/public_params.hpp | 103 - .../algebra/curves/tests/test_bilinearity.cpp | 121 -- .../algebra/curves/tests/test_groups.cpp | 153 -- .../domains/basic_radix2_domain.hpp | 45 - .../domains/basic_radix2_domain.tcc | 112 - .../domains/basic_radix2_domain_aux.hpp | 48 - .../domains/basic_radix2_domain_aux.tcc | 242 --- .../evaluation_domain/evaluation_domain.hpp | 125 -- .../evaluation_domain/evaluation_domain.tcc | 117 -- .../algebra/exponentiation/exponentiation.hpp | 31 - .../algebra/exponentiation/exponentiation.tcc | 53 - src/snark/libsnark/algebra/fields/bigint.hpp | 70 - src/snark/libsnark/algebra/fields/bigint.tcc | 279 --- .../libsnark/algebra/fields/field_utils.hpp | 51 - .../libsnark/algebra/fields/field_utils.tcc | 183 -- src/snark/libsnark/algebra/fields/fp.hpp | 182 -- src/snark/libsnark/algebra/fields/fp.tcc | 790 ------- .../algebra/fields/fp12_2over3over2.hpp | 116 -- .../algebra/fields/fp12_2over3over2.tcc | 412 ---- src/snark/libsnark/algebra/fields/fp2.hpp | 120 -- src/snark/libsnark/algebra/fields/fp2.tcc | 261 --- .../libsnark/algebra/fields/fp6_3over2.hpp | 104 - .../libsnark/algebra/fields/fp6_3over2.tcc | 216 -- src/snark/libsnark/algebra/fields/fp_aux.tcc | 389 ---- .../algebra/fields/tests/test_bigint.cpp | 96 - .../algebra/fields/tests/test_fields.cpp | 191 -- .../knowledge_commitment.hpp | 84 - .../knowledge_commitment.tcc | 111 - .../scalar_multiplication/kc_multiexp.hpp | 55 - .../scalar_multiplication/kc_multiexp.tcc | 274 --- .../scalar_multiplication/multiexp.hpp | 110 - .../scalar_multiplication/multiexp.tcc | 590 ------ .../algebra/scalar_multiplication/wnaf.hpp | 39 - .../algebra/scalar_multiplication/wnaf.tcc | 123 -- src/snark/libsnark/common/assert_except.hpp | 12 - .../data_structures/accumulation_vector.hpp | 74 - .../data_structures/accumulation_vector.tcc | 84 - .../common/data_structures/merkle_tree.hpp | 71 - .../common/data_structures/merkle_tree.tcc | 246 --- .../common/data_structures/sparse_vector.hpp | 79 - .../common/data_structures/sparse_vector.tcc | 316 --- .../libsnark/common/default_types/ec_pp.hpp | 53 - .../default_types/r1cs_ppzksnark_pp.hpp | 22 - src/snark/libsnark/common/profiling.cpp | 382 ---- src/snark/libsnark/common/profiling.hpp | 51 - src/snark/libsnark/common/serialization.hpp | 104 - src/snark/libsnark/common/serialization.tcc | 180 -- src/snark/libsnark/common/template_utils.hpp | 26 - src/snark/libsnark/common/utils.cpp | 102 - src/snark/libsnark/common/utils.hpp | 57 - src/snark/libsnark/common/utils.tcc | 23 - .../gadgetlib1/constraint_profiling.cpp | 48 - .../gadgetlib1/constraint_profiling.hpp | 42 - .../gadgetlib1/examples/simple_example.hpp | 23 - .../gadgetlib1/examples/simple_example.tcc | 54 - src/snark/libsnark/gadgetlib1/gadget.hpp | 27 - src/snark/libsnark/gadgetlib1/gadget.tcc | 23 - .../gadgetlib1/gadgets/basic_gadgets.hpp | 351 ---- .../gadgetlib1/gadgets/basic_gadgets.tcc | 705 ------- .../gadgetlib1/gadgets/gadget_from_r1cs.hpp | 45 - .../gadgetlib1/gadgets/gadget_from_r1cs.tcc | 123 -- .../gadgets/hashes/digest_selector_gadget.hpp | 42 - .../gadgets/hashes/digest_selector_gadget.tcc | 62 - .../gadgetlib1/gadgets/hashes/hash_io.hpp | 63 - .../gadgetlib1/gadgets/hashes/hash_io.tcc | 105 - .../gadgets/hashes/sha256/sha256_aux.hpp | 160 -- .../gadgets/hashes/sha256/sha256_aux.tcc | 297 --- .../hashes/sha256/sha256_components.hpp | 108 - .../hashes/sha256/sha256_components.tcc | 250 --- .../gadgets/hashes/sha256/sha256_gadget.hpp | 98 - .../gadgets/hashes/sha256/sha256_gadget.tcc | 230 --- .../tests/generate_sha256_gadget_tests.py | 55 - .../hashes/sha256/tests/pypy_sha256.py | 263 --- .../sha256/tests/test_sha256_gadget.cpp | 48 - .../merkle_authentication_path_variable.hpp | 38 - .../merkle_authentication_path_variable.tcc | 76 - .../merkle_tree_check_read_gadget.hpp | 73 - .../merkle_tree_check_read_gadget.tcc | 196 -- .../merkle_tree_check_update_gadget.hpp | 90 - .../merkle_tree_check_update_gadget.tcc | 265 --- .../tests/test_merkle_tree_gadgets.cpp | 40 - src/snark/libsnark/gadgetlib1/pb_variable.hpp | 144 -- src/snark/libsnark/gadgetlib1/pb_variable.tcc | 330 --- src/snark/libsnark/gadgetlib1/protoboard.hpp | 75 - src/snark/libsnark/gadgetlib1/protoboard.tcc | 189 -- src/snark/libsnark/gtests.cpp | 12 - .../reductions/r1cs_to_qap/r1cs_to_qap.hpp | 70 - .../reductions/r1cs_to_qap/r1cs_to_qap.tcc | 338 --- .../relations/arithmetic_programs/qap/qap.hpp | 193 -- .../relations/arithmetic_programs/qap/qap.tcc | 324 --- .../qap/tests/test_qap.cpp | 104 - .../r1cs/examples/r1cs_examples.hpp | 73 - .../r1cs/examples/r1cs_examples.tcc | 164 -- .../r1cs/r1cs.hpp | 153 -- .../r1cs/r1cs.tcc | 310 --- src/snark/libsnark/relations/variable.hpp | 213 -- src/snark/libsnark/relations/variable.tcc | 512 ----- .../examples/run_r1cs_ppzksnark.hpp | 35 - .../examples/run_r1cs_ppzksnark.tcc | 114 -- .../profiling/profile_r1cs_ppzksnark.cpp | 71 - .../r1cs_ppzksnark/r1cs_ppzksnark.hpp | 486 ----- .../r1cs_ppzksnark/r1cs_ppzksnark.tcc | 886 -------- .../r1cs_ppzksnark/r1cs_ppzksnark_params.hpp | 34 - .../tests/test_r1cs_ppzksnark.cpp | 44 - 122 files changed, 21922 deletions(-) delete mode 100644 src/snark/.gitignore delete mode 100644 src/snark/AUTHORS delete mode 100644 src/snark/LICENSE delete mode 100644 src/snark/Makefile delete mode 100644 src/snark/README.md delete mode 100644 src/snark/doxygen.conf delete mode 100644 src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g1.cpp delete mode 100644 src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g1.hpp delete mode 100644 src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g2.cpp delete mode 100644 src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g2.hpp delete mode 100644 src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_init.cpp delete mode 100644 src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_init.hpp delete mode 100644 src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pairing.cpp delete mode 100644 src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pairing.hpp delete mode 100644 src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pp.cpp delete mode 100644 src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pp.hpp delete mode 100644 src/snark/libsnark/algebra/curves/curve_utils.hpp delete mode 100644 src/snark/libsnark/algebra/curves/curve_utils.tcc delete mode 100644 src/snark/libsnark/algebra/curves/public_params.hpp delete mode 100644 src/snark/libsnark/algebra/curves/tests/test_bilinearity.cpp delete mode 100644 src/snark/libsnark/algebra/curves/tests/test_groups.cpp delete mode 100644 src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain.hpp delete mode 100644 src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain.tcc delete mode 100644 src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain_aux.hpp delete mode 100644 src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain_aux.tcc delete mode 100644 src/snark/libsnark/algebra/evaluation_domain/evaluation_domain.hpp delete mode 100644 src/snark/libsnark/algebra/evaluation_domain/evaluation_domain.tcc delete mode 100644 src/snark/libsnark/algebra/exponentiation/exponentiation.hpp delete mode 100644 src/snark/libsnark/algebra/exponentiation/exponentiation.tcc delete mode 100644 src/snark/libsnark/algebra/fields/bigint.hpp delete mode 100644 src/snark/libsnark/algebra/fields/bigint.tcc delete mode 100644 src/snark/libsnark/algebra/fields/field_utils.hpp delete mode 100644 src/snark/libsnark/algebra/fields/field_utils.tcc delete mode 100644 src/snark/libsnark/algebra/fields/fp.hpp delete mode 100644 src/snark/libsnark/algebra/fields/fp.tcc delete mode 100644 src/snark/libsnark/algebra/fields/fp12_2over3over2.hpp delete mode 100644 src/snark/libsnark/algebra/fields/fp12_2over3over2.tcc delete mode 100644 src/snark/libsnark/algebra/fields/fp2.hpp delete mode 100644 src/snark/libsnark/algebra/fields/fp2.tcc delete mode 100644 src/snark/libsnark/algebra/fields/fp6_3over2.hpp delete mode 100644 src/snark/libsnark/algebra/fields/fp6_3over2.tcc delete mode 100644 src/snark/libsnark/algebra/fields/fp_aux.tcc delete mode 100644 src/snark/libsnark/algebra/fields/tests/test_bigint.cpp delete mode 100644 src/snark/libsnark/algebra/fields/tests/test_fields.cpp delete mode 100644 src/snark/libsnark/algebra/knowledge_commitment/knowledge_commitment.hpp delete mode 100644 src/snark/libsnark/algebra/knowledge_commitment/knowledge_commitment.tcc delete mode 100644 src/snark/libsnark/algebra/scalar_multiplication/kc_multiexp.hpp delete mode 100644 src/snark/libsnark/algebra/scalar_multiplication/kc_multiexp.tcc delete mode 100644 src/snark/libsnark/algebra/scalar_multiplication/multiexp.hpp delete mode 100644 src/snark/libsnark/algebra/scalar_multiplication/multiexp.tcc delete mode 100644 src/snark/libsnark/algebra/scalar_multiplication/wnaf.hpp delete mode 100644 src/snark/libsnark/algebra/scalar_multiplication/wnaf.tcc delete mode 100644 src/snark/libsnark/common/assert_except.hpp delete mode 100644 src/snark/libsnark/common/data_structures/accumulation_vector.hpp delete mode 100644 src/snark/libsnark/common/data_structures/accumulation_vector.tcc delete mode 100644 src/snark/libsnark/common/data_structures/merkle_tree.hpp delete mode 100644 src/snark/libsnark/common/data_structures/merkle_tree.tcc delete mode 100644 src/snark/libsnark/common/data_structures/sparse_vector.hpp delete mode 100644 src/snark/libsnark/common/data_structures/sparse_vector.tcc delete mode 100644 src/snark/libsnark/common/default_types/ec_pp.hpp delete mode 100644 src/snark/libsnark/common/default_types/r1cs_ppzksnark_pp.hpp delete mode 100644 src/snark/libsnark/common/profiling.cpp delete mode 100644 src/snark/libsnark/common/profiling.hpp delete mode 100644 src/snark/libsnark/common/serialization.hpp delete mode 100644 src/snark/libsnark/common/serialization.tcc delete mode 100644 src/snark/libsnark/common/template_utils.hpp delete mode 100644 src/snark/libsnark/common/utils.cpp delete mode 100644 src/snark/libsnark/common/utils.hpp delete mode 100644 src/snark/libsnark/common/utils.tcc delete mode 100644 src/snark/libsnark/gadgetlib1/constraint_profiling.cpp delete mode 100644 src/snark/libsnark/gadgetlib1/constraint_profiling.hpp delete mode 100644 src/snark/libsnark/gadgetlib1/examples/simple_example.hpp delete mode 100644 src/snark/libsnark/gadgetlib1/examples/simple_example.tcc delete mode 100644 src/snark/libsnark/gadgetlib1/gadget.hpp delete mode 100644 src/snark/libsnark/gadgetlib1/gadget.tcc delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/basic_gadgets.hpp delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/basic_gadgets.tcc delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/gadget_from_r1cs.hpp delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/gadget_from_r1cs.tcc delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/hashes/digest_selector_gadget.hpp delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/hashes/digest_selector_gadget.tcc delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/hashes/hash_io.hpp delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/hashes/hash_io.tcc delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_aux.hpp delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_aux.tcc delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_components.hpp delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_components.tcc delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.tcc delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/tests/generate_sha256_gadget_tests.py delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/tests/pypy_sha256.py delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/tests/test_sha256_gadget.cpp delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.hpp delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.tcc delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.hpp delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.tcc delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.hpp delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.tcc delete mode 100644 src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/tests/test_merkle_tree_gadgets.cpp delete mode 100644 src/snark/libsnark/gadgetlib1/pb_variable.hpp delete mode 100644 src/snark/libsnark/gadgetlib1/pb_variable.tcc delete mode 100644 src/snark/libsnark/gadgetlib1/protoboard.hpp delete mode 100644 src/snark/libsnark/gadgetlib1/protoboard.tcc delete mode 100644 src/snark/libsnark/gtests.cpp delete mode 100644 src/snark/libsnark/reductions/r1cs_to_qap/r1cs_to_qap.hpp delete mode 100644 src/snark/libsnark/reductions/r1cs_to_qap/r1cs_to_qap.tcc delete mode 100644 src/snark/libsnark/relations/arithmetic_programs/qap/qap.hpp delete mode 100644 src/snark/libsnark/relations/arithmetic_programs/qap/qap.tcc delete mode 100644 src/snark/libsnark/relations/arithmetic_programs/qap/tests/test_qap.cpp delete mode 100644 src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.hpp delete mode 100644 src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.tcc delete mode 100644 src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/r1cs.hpp delete mode 100644 src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/r1cs.tcc delete mode 100644 src/snark/libsnark/relations/variable.hpp delete mode 100644 src/snark/libsnark/relations/variable.tcc delete mode 100644 src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.hpp delete mode 100644 src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.tcc delete mode 100644 src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/profiling/profile_r1cs_ppzksnark.cpp delete mode 100644 src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp delete mode 100644 src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.tcc delete mode 100644 src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark_params.hpp delete mode 100644 src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/tests/test_r1cs_ppzksnark.cpp diff --git a/src/snark/.gitignore b/src/snark/.gitignore deleted file mode 100644 index ea2a20f44a1..00000000000 --- a/src/snark/.gitignore +++ /dev/null @@ -1,51 +0,0 @@ -*.o -*.a -*.so -*.d -libsnark/gtests -depinst/ -depsrc/ -README.html -doxygen/ -libsnark/gtests -libsnark/gadgetlib2/examples/tutorial -libsnark/gadgetlib2/tests/gadgetlib2_test - -libsnark/algebra/curves/tests/test_bilinearity -libsnark/algebra/curves/tests/test_groups -libsnark/algebra/fields/tests/test_fields -libsnark/common/routing_algorithms/profiling/profile_routing_algorithms -libsnark/common/routing_algorithms/tests/test_routing_algorithms -libsnark/gadgetlib1/gadgets/cpu_checkers/fooram/examples/test_fooram -libsnark/gadgetlib1/gadgets/hashes/knapsack/tests/test_knapsack_gadget -libsnark/gadgetlib1/gadgets/hashes/sha256/tests/test_sha256_gadget -libsnark/gadgetlib1/gadgets/merkle_tree/tests/test_merkle_tree_gadgets -libsnark/gadgetlib1/gadgets/routing/profiling/profile_routing_gadgets -libsnark/gadgetlib1/gadgets/set_commitment/tests/test_set_commitment_gadget -libsnark/gadgetlib1/gadgets/verifiers/tests/test_r1cs_ppzksnark_verifier_gadget -libsnark/reductions/ram_to_r1cs/examples/demo_arithmetization -libsnark/relations/arithmetic_programs/qap/tests/test_qap -libsnark/relations/arithmetic_programs/ssp/tests/test_ssp -libsnark/zk_proof_systems/pcd/r1cs_pcd/r1cs_mp_ppzkpcd/profiling/profile_r1cs_mp_ppzkpcd -libsnark/zk_proof_systems/pcd/r1cs_pcd/r1cs_mp_ppzkpcd/tests/test_r1cs_mp_ppzkpcd -libsnark/zk_proof_systems/pcd/r1cs_pcd/r1cs_sp_ppzkpcd/profiling/profile_r1cs_sp_ppzkpcd -libsnark/zk_proof_systems/pcd/r1cs_pcd/r1cs_sp_ppzkpcd/tests/test_r1cs_sp_ppzkpcd -libsnark/zk_proof_systems/ppzkadsnark/r1cs_ppzkadsnark/examples/demo_r1cs_ppzkadsnark -libsnark/zk_proof_systems/ppzksnark/bacs_ppzksnark/profiling/profile_bacs_ppzksnark -libsnark/zk_proof_systems/ppzksnark/bacs_ppzksnark/tests/test_bacs_ppzksnark -libsnark/zk_proof_systems/ppzksnark/r1cs_gg_ppzksnark/profiling/profile_r1cs_gg_ppzksnark -libsnark/zk_proof_systems/ppzksnark/r1cs_gg_ppzksnark/tests/test_r1cs_gg_ppzksnark -libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/profiling/profile_r1cs_ppzksnark -libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/tests/test_r1cs_ppzksnark -libsnark/zk_proof_systems/ppzksnark/ram_ppzksnark/examples/demo_ram_ppzksnark -libsnark/zk_proof_systems/ppzksnark/ram_ppzksnark/examples/demo_ram_ppzksnark_generator -libsnark/zk_proof_systems/ppzksnark/ram_ppzksnark/examples/demo_ram_ppzksnark_prover -libsnark/zk_proof_systems/ppzksnark/ram_ppzksnark/examples/demo_ram_ppzksnark_verifier -libsnark/zk_proof_systems/ppzksnark/ram_ppzksnark/profiling/profile_ram_ppzksnark -libsnark/zk_proof_systems/ppzksnark/ram_ppzksnark/tests/test_ram_ppzksnark -libsnark/zk_proof_systems/ppzksnark/tbcs_ppzksnark/profiling/profile_tbcs_ppzksnark -libsnark/zk_proof_systems/ppzksnark/tbcs_ppzksnark/tests/test_tbcs_ppzksnark -libsnark/zk_proof_systems/ppzksnark/uscs_ppzksnark/profiling/profile_uscs_ppzksnark -libsnark/zk_proof_systems/ppzksnark/uscs_ppzksnark/tests/test_uscs_ppzksnark -libsnark/zk_proof_systems/zksnark/ram_zksnark/profiling/profile_ram_zksnark -libsnark/zk_proof_systems/zksnark/ram_zksnark/tests/test_ram_zksnark diff --git a/src/snark/AUTHORS b/src/snark/AUTHORS deleted file mode 100644 index 1b2d7a24703..00000000000 --- a/src/snark/AUTHORS +++ /dev/null @@ -1,19 +0,0 @@ -SCIPR Lab: - Eli Ben-Sasson - Alessandro Chiesa - Daniel Genkin - Shaul Kfir - Eran Tromer - Madars Virza - -External contributors: - Michael Backes - Manuel Barbosa - Dario Fiore - Jens Groth - Joshua A. Kroll - Shigeo MITSUNARI - Raphael Reischuk - Tadanori TERUYA - Sean Bowe - Daira Hopwood diff --git a/src/snark/LICENSE b/src/snark/LICENSE deleted file mode 100644 index 3eb759a5e07..00000000000 --- a/src/snark/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -The libsnark library is developed by SCIPR Lab (http://scipr-lab.org) -and contributors. - -Copyright (c) 2012-2019 SCIPR Lab and contributors (see AUTHORS file). - -All files, with the exceptions below, are released under the MIT License: - - 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/src/snark/Makefile b/src/snark/Makefile deleted file mode 100644 index aff19c603af..00000000000 --- a/src/snark/Makefile +++ /dev/null @@ -1,285 +0,0 @@ -#******************************************************************************** -# Makefile for the libsnark library. -#******************************************************************************** -#* @author This file is part of libsnark, developed by SCIPR Lab -#* and contributors (see AUTHORS). -#* @copyright MIT license (see LICENSE file) -#*******************************************************************************/ - -# To override these, use "make OPTFLAGS=..." etc. -CURVE = BN128 -OPTFLAGS = -O2 -march=native -mtune=native -FEATUREFLAGS = -DUSE_ASM -DMONTGOMERY_OUTPUT - -# Initialize this using "CXXFLAGS=... make". The makefile appends to that. -CXXFLAGS += -std=c++11 -Wall -Wextra -Wno-unused-parameter -Wno-comment -Wfatal-errors $(OPTFLAGS) $(FEATUREFLAGS) -DCURVE_$(CURVE) - -DEPSRC = depsrc -DEPINST = depinst - -CXXFLAGS += -I$(DEPINST)/include -Ilibsnark -LDFLAGS += -L$(DEPINST)/lib -Wl,-rpath,$(DEPINST)/lib -LDLIBS += -lgmpxx -lgmp -lboost_program_options -lsodium -# List of .a files to include within libsnark.a and libsnark.so: -AR_LIBS = -# List of library files to install: -INSTALL_LIBS = $(LIB_FILE) -# Sentinel file to check existence of this directory (since directories don't work as a Make dependency): -DEPINST_EXISTS = $(DEPINST)/.exists - -ifneq ($(NO_GTEST),1) - # Compile GTest from sourcecode if we can (e.g., Ubuntu). Otherwise use precompiled one (e.g., Fedora). - # See https://github.com/google/googletest/blob/master/googletest/docs/FAQ.md#why-is-it-not-recommended-to-install-a-pre-compiled-copy-of-google-test-for-example-into-usrlocal - ifneq ($(NO_COMPILE_LIBGTEST),1) - GTESTDIR=/usr/src/gtest - COMPILE_LIBGTEST = $(shell test -d $(GTESTDIR) && echo -n 1) - endif - GTEST_LDLIBS += -lgtest -lpthread -endif - -ifneq ($(NO_SUPERCOP),1) - SUPERCOP_LDLIBS += -lsupercop - INSTALL_LIBS += depinst/lib/libsupercop.a - # Would have been nicer to roll supercop into libsnark.a ("AR_LIBS += $(DEPINST)/lib/libsupercop.a"), but it doesn't support position-independent code (libsnark issue #20). -endif - -LIB_SRCS = \ - libsnark/algebra/curves/alt_bn128/alt_bn128_g1.cpp \ - libsnark/algebra/curves/alt_bn128/alt_bn128_g2.cpp \ - libsnark/algebra/curves/alt_bn128/alt_bn128_init.cpp \ - libsnark/algebra/curves/alt_bn128/alt_bn128_pairing.cpp \ - libsnark/algebra/curves/alt_bn128/alt_bn128_pp.cpp \ - libsnark/common/profiling.cpp \ - libsnark/common/utils.cpp \ - libsnark/gadgetlib1/constraint_profiling.cpp \ - -ifeq ($(CURVE),BN128) - LIB_SRCS += \ - libsnark/algebra/curves/bn128/bn128_g1.cpp \ - libsnark/algebra/curves/bn128/bn128_g2.cpp \ - libsnark/algebra/curves/bn128/bn128_gt.cpp \ - libsnark/algebra/curves/bn128/bn128_init.cpp \ - libsnark/algebra/curves/bn128/bn128_pairing.cpp \ - libsnark/algebra/curves/bn128/bn128_pp.cpp - - CXXFLAGS += -DBN_SUPPORT_SNARK - AR_LIBS += $(DEPINST)/lib/libzm.a -endif - -# FIXME: most of these are broken due to removed code. -DISABLED_EXECUTABLES = \ - libsnark/common/routing_algorithms/profiling/profile_routing_algorithms \ - libsnark/common/routing_algorithms/tests/test_routing_algorithms \ - libsnark/gadgetlib1/gadgets/cpu_checkers/fooram/examples/test_fooram \ - libsnark/gadgetlib1/gadgets/hashes/knapsack/tests/test_knapsack_gadget \ - libsnark/gadgetlib1/gadgets/routing/profiling/profile_routing_gadgets \ - libsnark/gadgetlib1/gadgets/set_commitment/tests/test_set_commitment_gadget \ - libsnark/gadgetlib1/gadgets/verifiers/tests/test_r1cs_ppzksnark_verifier_gadget \ - libsnark/reductions/ram_to_r1cs/examples/demo_arithmetization \ - libsnark/relations/arithmetic_programs/ssp/tests/test_ssp \ - libsnark/zk_proof_systems/pcd/r1cs_pcd/r1cs_mp_ppzkpcd/profiling/profile_r1cs_mp_ppzkpcd \ - libsnark/zk_proof_systems/pcd/r1cs_pcd/r1cs_mp_ppzkpcd/tests/test_r1cs_mp_ppzkpcd \ - libsnark/zk_proof_systems/pcd/r1cs_pcd/r1cs_sp_ppzkpcd/profiling/profile_r1cs_sp_ppzkpcd \ - libsnark/zk_proof_systems/pcd/r1cs_pcd/r1cs_sp_ppzkpcd/tests/test_r1cs_sp_ppzkpcd \ - libsnark/zk_proof_systems/ppzksnark/bacs_ppzksnark/profiling/profile_bacs_ppzksnark \ - libsnark/zk_proof_systems/ppzksnark/bacs_ppzksnark/tests/test_bacs_ppzksnark \ - libsnark/zk_proof_systems/ppzksnark/r1cs_gg_ppzksnark/profiling/profile_r1cs_gg_ppzksnark \ - libsnark/zk_proof_systems/ppzksnark/r1cs_gg_ppzksnark/tests/test_r1cs_gg_ppzksnark \ - libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/profiling/profile_r1cs_ppzksnark \ - libsnark/zk_proof_systems/ppzksnark/ram_ppzksnark/examples/demo_ram_ppzksnark \ - libsnark/zk_proof_systems/ppzksnark/ram_ppzksnark/examples/demo_ram_ppzksnark_generator \ - libsnark/zk_proof_systems/ppzksnark/ram_ppzksnark/examples/demo_ram_ppzksnark_prover \ - libsnark/zk_proof_systems/ppzksnark/ram_ppzksnark/examples/demo_ram_ppzksnark_verifier \ - libsnark/zk_proof_systems/ppzksnark/ram_ppzksnark/profiling/profile_ram_ppzksnark \ - libsnark/zk_proof_systems/ppzksnark/ram_ppzksnark/tests/test_ram_ppzksnark \ - libsnark/zk_proof_systems/ppzksnark/tbcs_ppzksnark/profiling/profile_tbcs_ppzksnark \ - libsnark/zk_proof_systems/ppzksnark/tbcs_ppzksnark/tests/test_tbcs_ppzksnark \ - libsnark/zk_proof_systems/ppzksnark/uscs_ppzksnark/profiling/profile_uscs_ppzksnark \ - libsnark/zk_proof_systems/ppzksnark/uscs_ppzksnark/tests/test_uscs_ppzksnark \ - libsnark/zk_proof_systems/zksnark/ram_zksnark/profiling/profile_ram_zksnark \ - libsnark/zk_proof_systems/zksnark/ram_zksnark/tests/test_ram_zksnark - -EXECUTABLES = - -EXECUTABLES_WITH_GTEST = - -EXECUTABLES_WITH_SUPERCOP = \ - libsnark/zk_proof_systems/ppzkadsnark/r1cs_ppzkadsnark/examples/demo_r1cs_ppzkadsnark - -GTEST_TESTS = libsnark/gtests - -GTEST_SRCS = \ - libsnark/algebra/curves/tests/test_bilinearity.cpp \ - libsnark/algebra/curves/tests/test_groups.cpp \ - libsnark/algebra/fields/tests/test_bigint.cpp \ - libsnark/algebra/fields/tests/test_fields.cpp \ - libsnark/gadgetlib1/gadgets/hashes/sha256/tests/test_sha256_gadget.cpp \ - libsnark/gadgetlib1/gadgets/merkle_tree/tests/test_merkle_tree_gadgets.cpp \ - libsnark/relations/arithmetic_programs/qap/tests/test_qap.cpp \ - libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/tests/test_r1cs_ppzksnark.cpp \ - libsnark/gtests.cpp - -DOCS = README.html - -LIBSNARK_A = libsnark.a - -# For documentation of the following options, see README.md . - -ifeq ($(NO_PROCPS),1) - CXXFLAGS += -DNO_PROCPS -else - LDLIBS += -lprocps -endif - -ifeq ($(LOWMEM),1) - CXXFLAGS += -DLOWMEM -endif - -ifeq ($(PROFILE_OP_COUNTS),1) - STATIC = 1 - CXXFLAGS += -DPROFILE_OP_COUNTS -endif - -ifeq ($(STATIC),1) -ifneq ($(PLATFORM),darwin) - CXXFLAGS += -static -endif - CXXFLAGS += -DSTATIC -else - CXXFLAGS += -fPIC -endif - -ifeq ($(MULTICORE),1) - CXXFLAGS += -DMULTICORE -fopenmp -endif - -ifeq ($(CPPDEBUG),1) - CXXFLAGS += -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC - DEBUG = 1 -endif - -ifeq ($(DEBUG),1) - CXXFLAGS += -DDEBUG -ggdb3 -endif - -ifeq ($(PERFORMANCE),1) - OPTFLAGS = -O3 -march=native -mtune=native - CXXFLAGS += -DNDEBUG - # Enable link-time optimization: - CXXFLAGS += -flto -fuse-linker-plugin - LDFLAGS += -flto -endif - -LIB_OBJS =$(patsubst %.cpp,%.o,$(LIB_SRCS)) -EXEC_OBJS =$(patsubst %,%.o,$(EXECUTABLES) $(EXECUTABLES_WITH_GTEST) $(EXECUTABLES_WITH_SUPERCOP)) -GTEST_OBJS =$(patsubst %.cpp,%.o,$(GTEST_SRCS)) - -all: \ - $(if $(NO_GTEST),,$(EXECUTABLES_WITH_GTEST) $(GTEST_TESTS)) \ - $(if $(NO_SUPERCOP),,$(EXECUTABLES_WITH_SUPERCOP)) \ - $(EXECUTABLES) \ - $(if $(NO_DOCS),,doc) - -doc: $(DOCS) - -$(DEPINST_EXISTS): - # Create placeholder directories for installed dependencies. Some make settings (including the default) require actually running ./prepare-depends.sh to populate this directory. - mkdir -p $(DEPINST)/lib $(DEPINST)/include - touch $@ - -# In order to detect changes to #include dependencies. -MMD below generates a .d file for each .o file. Include the .d file. --include $(patsubst %.o,%.d, $(LIB_OBJS) $(GTEST_OBJS) $(EXEC_OBJS) ) - -$(LIB_OBJS) $(if $(NO_GTEST),,$(GTEST_OBJS)) $(EXEC_OBJS): %.o: %.cpp - $(CXX) -o $@ $< -c -MMD $(CXXFLAGS) - -LIBGTEST_A = $(DEPINST)/lib/libgtest.a - -$(LIBGTEST_A): $(GTESTDIR)/libsnark/gtest-all.cc $(DEPINST_EXISTS) - $(CXX) -o $(DEPINST)/lib/gtest-all.o -I $(GTESTDIR) -c -isystem $(GTESTDIR)/include $< $(CXXFLAGS) - $(AR) -rv $(LIBGTEST_A) $(DEPINST)/lib/gtest-all.o - -# libsnark.a will contains all of our relevant object files, and we also mash in the .a files of relevant dependencies built by ./prepare-depends.sh -$(LIBSNARK_A): $(LIB_OBJS) $(AR_LIBS) - $(AR) q $(LIBSNARK_A) $(LIB_OBJS) - if [ -n "$(AR_LIBS)" ]; then mkdir -p tmp-ar; cd tmp-ar; for AR_LIB in $(AR_LIBS); do $(AR) x $$AR_LIB; done; $(AR) qc $(LIBSNARK_A) tmp-ar/*; cd ..; rm -r tmp-ar; fi; - $(AR) s $(LIBSNARK_A) - -libsnark.so: $(LIBSNARK_A) $(DEPINST_EXISTS) - $(CXX) -o $@ --shared -Wl,--whole-archive $(LIBSNARK_A) $(CXXFLAGS) $(LDFLAGS) -Wl,--no-whole-archive $(LDLIBS) - -libsnark/gadgetlib2/tests/gadgetlib2_test: \ - libsnark/gadgetlib2/tests/adapters_UTEST.cpp \ - libsnark/gadgetlib2/tests/constraint_UTEST.cpp \ - libsnark/gadgetlib2/tests/gadget_UTEST.cpp \ - libsnark/gadgetlib2/tests/integration_UTEST.cpp \ - libsnark/gadgetlib2/tests/protoboard_UTEST.cpp \ - libsnark/gadgetlib2/tests/variable_UTEST.cpp - -$(EXECUTABLES): %: %.o $(LIBSNARK_A) $(DEPINST_EXISTS) - $(CXX) -o $@ $@.o $(LIBSNARK_A) $(CXXFLAGS) $(LDFLAGS) $(LDLIBS) - -$(EXECUTABLES_WITH_GTEST): %: %.o $(LIBSNARK_A) $(if $(COMPILE_LIBGTEST),$(LIBGTEST_A)) $(DEPINST_EXISTS) - $(CXX) -o $@ $@.o $(LIBSNARK_A) $(CXXFLAGS) $(LDFLAGS) $(GTEST_LDLIBS) $(LDLIBS) - -$(EXECUTABLES_WITH_SUPERCOP): %: %.o $(LIBSNARK_A) $(DEPINST_EXISTS) - $(CXX) -o $@ $@.o $(LIBSNARK_A) $(CXXFLAGS) $(LDFLAGS) $(SUPERCOP_LDLIBS) $(LDLIBS) - -$(GTEST_TESTS): %: $(GTEST_OBJS) $(LIBSNARK_A) $(if $(COMPILE_LIBGTEST),$(LIBGTEST_A)) $(DEPINST_EXISTS) - $(CXX) -o $@ $(GTEST_OBJS) $(LIBSNARK_A) $(CXXFLAGS) $(LDFLAGS) $(GTEST_LDLIBS) $(LDLIBS) - - -ifeq ($(STATIC),1) -LIB_FILE = $(LIBSNARK_A) -else -LIB_FILE = libsnark.so -endif - -lib: $(LIB_FILE) - -$(DOCS): %.html: %.md - markdown_py -f $@ $^ -x toc -x extra --noisy -# TODO: Would be nice to enable "-x smartypants" but Ubuntu 12.04 doesn't support that. -# TODO: switch to redcarpet, to produce same output as GitHub's processing of README.md. But what about TOC? - -ifeq ($(PREFIX),) -install: - $(error Please provide PREFIX. E.g. make install PREFIX=/usr) -else -HEADERS_SRC=$(shell find libsnark -name '*.hpp' -o -name '*.tcc') -HEADERS_DEST=$(patsubst libsnark/%,$(PREFIX)/include/libsnark/%,$(HEADERS_SRC)) - -$(HEADERS_DEST): $(PREFIX)/include/libsnark/%: libsnark/% - mkdir -p $(shell dirname $@) - cp $< $@ - -install: $(INSTALL_LIBS) $(HEADERS_DEST) $(DEPINST_EXISTS) - mkdir -p $(PREFIX)/lib - cp -v $(INSTALL_LIBS) $(PREFIX)/lib/ -ifneq ($(NO_COPY_DEPINST),1) - cp -rv $(DEPINST)/include $(PREFIX) -endif -endif - -check: $(GTEST_TESTS) - $(GTEST_TESTS) - -doxy: - doxygen doxygen.conf - -# Clean generated files, except locally-compiled dependencies -clean: - $(RM) \ - $(LIB_OBJS) $(GTEST_OBJS) $(EXEC_OBJS) \ - $(EXECUTABLES) $(EXECUTABLES_WITH_GTEST) $(EXECUTABLES_WITH_SUPERCOP) $(GTEST_TESTS) \ - $(DOCS) \ - ${patsubst %.o,%.d,${LIB_OBJS} ${GTEST_OBJS} ${EXEC_OBJS}} \ - libsnark.so $(LIBSNARK_A) \ - $(RM) -fr doxygen/ \ - $(RM) $(LIBGTEST_A) $(DEPINST)/lib/gtest-all.o - -# Clean all, including locally-compiled dependencies -clean-all: clean - $(RM) -fr $(DEPSRC) $(DEPINST) - -.PHONY: all clean clean-all doc doxy lib install diff --git a/src/snark/README.md b/src/snark/README.md deleted file mode 100644 index 89183b43aa8..00000000000 --- a/src/snark/README.md +++ /dev/null @@ -1,628 +0,0 @@ -libsnark: a C++ library for zkSNARK proofs -================================================================================ - --------------------------------------------------------------------------------- -Authors --------------------------------------------------------------------------------- - -The libsnark library is developed by the [SCIPR Lab] project and contributors -and is released under the MIT License (see the [LICENSE] file). - -Copyright (c) 2012-2014 SCIPR Lab and contributors (see [AUTHORS] file). - --------------------------------------------------------------------------------- -[TOC] - - - --------------------------------------------------------------------------------- -Overview --------------------------------------------------------------------------------- - -This library implements __zkSNARK__ schemes, which are a cryptographic method -for proving/verifying, in zero knowledge, the integrity of computations. - -A computation can be expressed as an NP statement, in forms such as the following: - -- "The C program _foo_, when executed, returns exit code 0 if given the input _bar_ and some additional input _qux_." -- "The Boolean circuit _foo_ is satisfiable by some input _qux_." -- "The arithmetic circuit _foo_ accepts the partial assignment _bar_, when extended into some full assignment _qux_." -- "The set of constraints _foo_ is satisfiable by the partial assignment _bar_, when extended into some full assignment _qux_." - -A prover who knows the witness for the NP statement (i.e., a satisfying input/assignment) can produce a short proof attesting to the truth of the NP statement. This proof can be verified by anyone, and offers the following properties. - -- __Zero knowledge:__ - the verifier learns nothing from the proof beside the truth of the statement (i.e., the value _qux_, in the above examples, remains secret). -- __Succinctness:__ - the proof is short and easy to verify. -- __Non-interactivity:__ - the proof is a string (i.e. it does not require back-and-forth interaction between the prover and the verifier). -- __Soundness:__ - the proof is computationally sound (i.e., it is infeasible to fake a proof of a false NP statement). Such a proof system is also called an _argument_. -- __Proof of knowledge:__ - the proof attests not just that the NP statement is true, but also that the - prover knows why (e.g., knows a valid _qux_). - -These properties are summarized by the _zkSNARK_ acronym, which stands for _Zero-Knowledge Succinct Non-interactive ARgument of Knowledge_ (though zkSNARKs are also knows as -_succinct non-interactive computationally-sound zero-knowledge proofs of knowledge_). -For formal definitions and theoretical discussions about these, see -\[BCCT12], \[BCIOP13], and the references therein. - -The libsnark library currently provides a C++ implementation of: - -1. General-purpose proof systems: - 1. A preprocessing zkSNARK for the NP-complete language "R1CS" - (_Rank-1 Constraint Systems_), which is a language that is similar to arithmetic - circuit satisfiability. - 2. A preprocessing SNARK for a language of arithmetic circuits, "BACS" - (_Bilinear Arithmetic Circuit Satisfiability_). This simplifies the writing - of NP statements when the additional flexibility of R1CS is not needed. - Internally, it reduces to R1CS. - 3. A preprocessing SNARK for the language "USCS" - (_Unitary-Square Constraint Systems_). This abstracts and implements the core - contribution of \[DFGK14] - 4. A preprocessing SNARK for a language of Boolean circuits, "TBCS" - (_Two-input Boolean Circuit Satisfiability_). Internally, it reduces to USCS. - This is much more efficient than going through R1CS. - 5. ADSNARK, a preprocessing SNARKs for proving statements on authenticated - data, as described in \[BBFR15]. - 6. Proof-Carrying Data (PCD). This uses recursive composition of SNARKs, as - explained in \[BCCT13] and optimized in \[BCTV14b]. -2. Gadget libraries (gadgetlib1 and gadgetlib2) for constructing R1CS - instances out of modular "gadget" classes. -3. Examples of applications that use the above proof systems to prove - statements about: - 1. Several toy examples. - 2. Execution of TinyRAM machine code, as explained in \[BCTV14a] and - \[BCGTV13]. (Such machine code can be obtained, e.g., by compiling from C.) - This is easily adapted to any other Random Access Machine that satisfies a - simple load-store interface. - 3. A scalable for TinyRAM using Proof-Carrying Data, as explained in \[BCTV14b] - 4. Zero-knowledge cluster MapReduce, as explained in \[CTV15]. - -The zkSNARK construction implemented by libsnark follows, extends, and -optimizes the approach described in \[BCTV14], itself an extension of -\[BCGTV13], following the approach of \[BCIOP13] and \[GGPR13]. An alternative -implementation of the basic approach is the _Pinocchio_ system of \[PGHR13]. -See these references for discussions of efficiency aspects that arise in -practical use of such constructions, as well as security and trust -considerations. - -This scheme is a _preprocessing zkSNARK_ (_ppzkSNARK_): before proofs can be -created and verified, one needs to first decide on a size/circuit/system -representing the NP statements to be proved, and run a _generator_ algorithm to -create corresponding public parameters (a long proving key and a short -verification key). - -Using the library involves the following high-level steps: - -1. Express the statements to be proved as an R1CS (or any of the other - languages above, such as arithmetic circuits, Boolean circuits, or TinyRAM). - This is done by writing C++ code that constructs an R1CS, and linking this code - together with libsnark -2. Use libsnark's generator algorithm to create the public parameters for this - statement (once and for all). -3. Use libsnark's prover algorithm to create proofs of true statements about - the satisfiability of the R1CS. -4. Use libsnark's verifier algorithm to check proofs for alleged statements. - - --------------------------------------------------------------------------------- -The NP-complete language R1CS --------------------------------------------------------------------------------- - -The ppzkSNARK supports proving/verifying membership in a specific NP-complete -language: R1CS (*rank-1 constraint systems*). An instance of the language is -specified by a set of equations over a prime field F, and each equation looks like: - < A, (1,X) > * < B , (1,X) > = < C, (1,X) > -where A,B,C are vectors over F, and X is a vector of variables. - -In particular, arithmetic (as well as boolean) circuits are easily reducible to -this language by converting each gate into a rank-1 constraint. See \[BCGTV13] -Appendix E (and "System of Rank 1 Quadratic Equations") for more details about this. - - --------------------------------------------------------------------------------- -Elliptic curve choices --------------------------------------------------------------------------------- - -The ppzkSNARK can be instantiated with different parameter choices, depending on -which elliptic curve is used. The libsnark library currently provides three -options: - -* "edwards": - an instantiation based on an Edwards curve, providing 80 bits of security. - -* "bn128": - an instantiation based on a Barreto-Naehrig curve, providing 128 - bits of security. The underlying curve implementation is - \[ate-pairing], which has incorporated our patch that changes the - BN curve to one suitable for SNARK applications. - - * This implementation uses dynamically-generated machine code for the curve - arithmetic. Some modern systems disallow execution of code on the heap, and - will thus block this implementation. - - For example, on Fedora 20 at its default settings, you will get the error - `zmInit ERR:can't protect` when running this code. To solve this, - run `sudo setsebool -P allow_execheap 1` to allow execution, - or use `make CURVE=ALT_BN128` instead. - -* "alt_bn128": - an alternative to "bn128", somewhat slower but avoids dynamic code generation. - -Note that bn128 requires an x86-64 CPU while the other curve choices -should be architecture-independent; see [portability](#portability). - - --------------------------------------------------------------------------------- -Gadget libraries --------------------------------------------------------------------------------- - -The libsnark library currently provides two libraries for conveniently constructing -R1CS instances out of reusable "gadgets". Both libraries provide a way to construct -gadgets on other gadgets as well as additional explicit equations. In this way, -complex R1CS instances can be built bottom up. - -### gadgetlib1 - -This is a low-level library which expose all features of the preprocessing -zkSNARK for R1CS. Its design is based on templates (as does the ppzkSNARK code) -to efficiently support working on multiple elliptic curves simultaneously. This -library is used for most of the constraint-building in libsnark, both internal -(reductions and Proof-Carrying Data) and examples applications. - -### gadgetlib2 - -This is an alternative library for constructing systems of polynomial equations -and, in particular, also R1CS instances. It is better documented and easier to -use than gadgetlib1, and its interface does not use templates. However, fewer -useful gadgets are provided. - - --------------------------------------------------------------------------------- -Security --------------------------------------------------------------------------------- - -The theoretical security of the underlying mathematical constructions, and the -requisite assumptions, are analyzed in detailed in the aforementioned research -papers. - -** -This code is a research-quality proof of concept, and has not -yet undergone extensive review or testing. It is thus not suitable, -as is, for use in critical or production systems. -** - -Known issues include the following: - -* The ppzkSNARK's generator and prover exhibit data-dependent running times - and memory usage. These form timing and cache-contention side channels, - which may be an issue in some applications. - -* Randomness is retrieved from /dev/urandom, but this should be - changed to a carefully considered (depending on system and threat - model) external, high-quality randomness source when creating - long-term proving/verification keys. - - --------------------------------------------------------------------------------- -Build instructions --------------------------------------------------------------------------------- - -The libsnark library relies on the following: - -- C++ build environment -- GMP for certain bit-integer arithmetic -- libprocps for reporting memory usage -- GTest for some of the unit tests - -So far we have tested these only on Linux, though we have been able to make the library work, -with some features disabled (such as memory profiling or GTest tests), on Windows via Cygwin -and on Mac OS X. (If you succeed in achieving more complete ports of the library, please -let us know!) See also the notes on [portability](#portability) below. - -For example, on a fresh install of Ubuntu 14.04, install the following packages: - - $ sudo apt-get install build-essential git libgmp3-dev libprocps3-dev libgtest-dev python-markdown libboost-all-dev libssl-dev - -Or, on Fedora 20: - - $ sudo yum install gcc-c++ make git gmp-devel procps-ng-devel gtest-devel python-markdown - -Run the following, to fetch dependencies from their GitHub repos and compile them. -(Not required if you set `CURVE` to other than the default `BN128` and also set `NO_SUPERCOP=1`.) - - $ ./prepare-depends.sh - -Then, to compile the library, tests, profiling harness and documentation, run: - - $ make - -To create just the HTML documentation, run - - $ make doc - -and then view the resulting `README.html` (which contains the very text you are reading now). - -To create Doxygen documentation summarizing all files, classes and functions, -with some (currently sparse) comments, install the `doxygen` and `graphviz` packages, then run - - $ make doxy - -(this may take a few minutes). Then view the resulting [`doxygen/index.html`](doxygen/index.html). - -### Using libsnark as a library - -To develop an application that uses libsnark, you could add it within the libsnark directory tree and adjust the Makefile, but it is far better to build libsnark as a (shared or static) library. You can then write your code in a separate directory tree, and link it against libsnark. - - -To build just the shared object library `libsnark.so`, run: - - $ make lib - -To build just the static library `libsnark.a`, run: - - $ make lib STATIC=1 - -Note that static compilation requires static versions of all libraries it depends on. -It may help to minimize these dependencies by appending -`CURVE=ALT_BN128 NO_PROCPS=1 NO_GTEST=1 NO_SUPERCOP=1`. On Fedora 21, the requisite -library RPM dependencies are then: -`boost-static glibc-static gmp-static libstdc++-static openssl-static zlib-static - boost-devel glibc-devel gmp-devel gmp-devel libstdc++-devel openssl-devel openssl-devel`. - -To build *and install* the libsnark library: - - $ make install PREFIX=/install/path - -This will install `libsnark.so` into `/install/path/lib`; so your application should be linked using `-L/install/path/lib -lsnark`. It also installs the requisite headers into `/install/path/include`; so your application should be compiled using `-I/install/path/include`. - -In addition, unless you use `NO_SUPERCOP=1`, `libsupercop.a` will be installed and should be linked in using `-lsupercop`. - - -### Building on Windows using Cygwin -Install Cygwin using the graphical installer, including the `g++`, `libgmp` -and `git` packages. Then disable the dependencies not easily supported under CygWin, -using: - - $ make NO_PROCPS=1 NO_GTEST=1 NO_DOCS=1 - - -### Building on Mac OS X - -On Mac OS X, install GMP from MacPorts (`port install gmp`). Then disable the -dependencies not easily supported under CygWin, using: - - $ make NO_PROCPS=1 NO_GTEST=1 NO_DOCS=1 - -MacPorts does not write its libraries into standard system folders, so you -might need to explicitly provide the paths to the header files and libraries by -appending `CXXFLAGS=-I/opt/local/include LDFLAGS=-L/opt/local/lib` to the line -above. Similarly, to pass the paths to ate-pairing you would run -`INC_DIR=-I/opt/local/include LIB_DIR=-L/opt/local/lib ./prepare-depends.sh` -instead of `./prepare-depends.sh` above. - --------------------------------------------------------------------------------- -Tutorials --------------------------------------------------------------------------------- - -libsnark includes a tutorial, and some usage examples, for the high-level API. - -* `src/gadgetlib1/examples1` contains a simple example for constructing a - constraint system using gadgetlib1. - -* `src/gadgetlib2/examples` contains a tutorial for using gadgetlib2 to express - NP statements as constraint systems. It introduces basic terminology, design - overview, and recommended programming style. It also shows how to invoke - ppzkSNARKs on such constraint systems. The main file, `tutorial.cpp`, builds - into a standalone executable. - -* `src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/profiling/profile_r1cs_ppzksnark.cpp` - constructs a simple constraint system and runs the ppzksnark. See below for how to - run it. - - --------------------------------------------------------------------------------- -Executing profiling example --------------------------------------------------------------------------------- - -The command - - $ src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/profiling/profile_r1cs_ppzksnark 1000 10 Fr - -exercises the ppzkSNARK (first generator, then prover, then verifier) on an -R1CS instance with 1000 equations and an input consisting of 10 field elements. - -(If you get the error `zmInit ERR:can't protect`, see the discussion -[above](#elliptic-curve-choices).) - -The command - - $ src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/profiling/profile_r1cs_ppzksnark 1000 10 bytes - -does the same but now the input consists of 10 bytes. - - --------------------------------------------------------------------------------- -Build options --------------------------------------------------------------------------------- - -The following flags change the behavior of the compiled code. - -* `make FEATUREFLAGS='-Dname1 -Dname2 ...'` - - Override the active conditional #define names (you can see the default at the top of the Makefile). - The next bullets list the most important conditionally-#defined features. - For example, `make FEATUREFLAGS='-DBINARY_OUTPUT'` enables binary output and disables the default - assembly optimizations and Montgomery-representation output. - -* define `BINARY_OUTPUT` - - In serialization, output raw binary data (instead of decimal, when not set). - -* `make CURVE=choice` / define `CURVE_choice` (where `choice` is one of: - ALT_BN128, BN128, EDWARDS, MNT4, MNT6) - - Set the default curve to one of the above (see [elliptic curve choices](#elliptic-curve-choices)). - -* `make DEBUG=1` / define `DEBUG` - - Print additional information for debugging purposes. - -* `make LOWMEM=1` / define `LOWMEM` - - Limit the size of multi-exponentiation tables, for low-memory platforms. - -* `make NO_DOCS=1` - - Do not generate HTML documentation, e.g. on platforms where Markdown is not easily available. - -* `make NO_PROCPS=1` - - Do not link against libprocps. This disables memory profiling. - -* `make NO_GTEST=1` - - Do not link against GTest. The tutorial and test suite of gadgetlib2 tutorial won't be compiled. - -* `make NO_SUPERCOP=1` - - Do not link against SUPERCOP for optimized crypto. The ADSNARK executables will not be built. - -* `make MULTICORE=1` - - Enable parallelized execution of the ppzkSNARK generator and prover, using OpenMP. - This will utilize all cores on the CPU for heavyweight parallelizable operations such as - FFT and multiexponentiation. The default is single-core. - - To override the maximum number of cores used, set the environment variable `OMP_NUM_THREADS` - at runtime (not compile time), e.g., `OMP_NUM_THREADS=8 test_r1cs_sp_ppzkpc`. It defaults - to the autodetected number of cores, but on some devices, dynamic core management confused - OpenMP's autodetection, so setting `OMP_NUM_THREADS` is necessary for full utilization. - -* define `NO_PT_COMPRESSION` - - Do not use point compression. - This gives much faster serialization times, at the expense of ~2x larger - sizes for serialized keys and proofs. - -* define `MONTGOMERY_OUTPUT` (on by default) - - Serialize Fp elements as their Montgomery representations. If this - option is disabled then Fp elements are serialized as their - equivalence classes, which is slower but produces human-readable - output. - -* `make PROFILE_OP_COUNTS=1` / define `PROFILE_OP_COUNTS` - - Collect counts for field and curve operations inside static variables - of the corresponding algebraic objects. This option works for all - curves except bn128. - -* define `USE_ASM` (on by default) - - Use unrolled assembly routines for F[p] arithmetic and faster heap in - multi-exponentiation. (When not set, use GMP's `mpn_*` routines instead.) - -* define `USE_MIXED_ADDITION` - - Convert each element of the proving key and verification key to - affine coordinates. This allows using mixed addition formulas in - multiexponentiation and results in slightly faster prover and - verifier runtime at expense of increased proving time. - -* `make PERFORMANCE=1` - - Enables compiler optimizations such as link-time optimization, and disables debugging aids. - (On some distributions this causes a `plugin needed to handle lto object` link error and `undefined reference`s, which can be remedied by `AR=gcc-ar make ...`.) - -Not all combinations are tested together or supported by every part of the codebase. - - --------------------------------------------------------------------------------- -Portability --------------------------------------------------------------------------------- - -libsnark is written in fairly standard C++11. - -However, having been developed on Linux on x86-64 CPUs, libsnark has some limitations -with respect to portability. Specifically: - -1. libsnark's algebraic data structures assume little-endian byte order. - -2. Profiling routines use `clock_gettime` and `readproc` calls, which are Linux-specific. - -3. Random-number generation is done by reading from `/dev/urandom`, which is - specific to Unix-like systems. - -4. libsnark binary serialization routines (see `BINARY_OUTPUT` above) assume - a fixed machine word size (i.e. sizeof(mp_limb_t) for GMP's limb data type). - Objects serialized in binary on a 64-bit system cannot be de-serialized on - a 32-bit system, and vice versa. - (The decimal serialization routines have no such limitation.) - -5. libsnark requires a C++ compiler with good C++11 support. It has been - tested with g++ 4.7, g++ 4.8, and clang 3.4. - -6. On x86-64, we by default use highly optimized assembly implementations for some - operations (see `USE_ASM` above). On other architectures we fall back to a - portable C++ implementation, which is slower. - -Tested configurations include: - -* Debian jessie with g++ 4.7 on x86-64 -* Debian jessie with clang 3.4 on x86-64 -* Fedora 20/21 with g++ 4.8.2/4.9.2 on x86-64 and i686 -* Ubuntu 14.04 LTS with g++ 4.8 on x86-64 -* Ubuntu 14.04 LTS with g++ 4.8 on x86-32, for EDWARDS and ALT_BN128 curve choices -* Debian wheezy with g++ 4.7 on ARM little endian (Debian armel port) inside QEMU, for EDWARDS and ALT_BN128 curve choices -* Windows 7 with g++ 4.8.3 under Cygwin 1.7.30 on x86-64 with NO_PROCPS=1, NO_GTEST=1 and NO_DOCS=1, for EDWARDS and ALT_BN128 curve choices -* Mac OS X 10.9.4 (Mavericks) with Apple LLVM version 5.1 (based on LLVM 3.4svn) on x86-64 with NO_PROCPS=1, NO_GTEST=1 and NO_DOCS=1 - - --------------------------------------------------------------------------------- -Directory structure --------------------------------------------------------------------------------- - -The directory structure of the libsnark library is as follows: - -* src/ --- main C++ source code, containing the following modules: - * algebra/ --- fields and elliptic curve groups - * common/ --- miscellaneous utilities - * gadgetlib1/ --- gadgetlib1, a library to construct R1CS instances - * gadgets/ --- basic gadgets for gadgetlib1 - * gadgetlib2/ --- gadgetlib2, a library to construct R1CS instances - * qap/ --- quadratic arithmetic program - * domains/ --- support for fast interpolation/evaluation, by providing - FFTs and Lagrange-coefficient computations for various domains - * relations/ --- interfaces for expressing statement (relations between instances and witnesses) as various NP-complete languages - * constraint_satisfaction_problems/ --- R1CS and USCS languages - * circuit_satisfaction_problems/ --- Boolean and arithmetic circuit satisfiability languages - * ram_computations/ --- RAM computation languages - * zk_proof_systems --- interfaces and implementations of the proof systems - * reductions --- reductions between languages (used internally, but contains many examples of building constraints) - - Some of these module directories have the following subdirectories: - - * ... - * examples/ --- example code and tutorials for this module - * tests/ --- unit tests for this module - - In particular, the top-level API examples are at `src/r1cs_ppzksnark/examples/` and `src/gadgetlib2/examples/`. - -* depsrc/ --- created by `prepare_depends.sh` for retrieved sourcecode and local builds of external code - (currently: \[ate-pairing], and its dependency xbyak). - -* depinst/ --- created by `prepare_depends.sh` and `Makefile` - for local installation of locally-compiled dependencies. - -* doxygen/ --- created by `make doxy` and contains a Doxygen summary of all files, classes etc. in libsnark. - - --------------------------------------------------------------------------------- -Further considerations --------------------------------------------------------------------------------- - -### Multiexponentiation window size - -The ppzkSNARK's generator has to solve a fixed-base multi-exponentiation -problem. We use a window-based method in which the optimal window size depends -on the size of the multiexponentiation instance *and* the platform. - -On our benchmarking platform (a 3.40 GHz Intel Core i7-4770 CPU), we have -computed for each curve optimal windows, provided as -"fixed_base_exp_window_table" initialization sequences, for each curve; see -`X_init.cpp` for X=edwards,bn128,alt_bn128. - -Performance on other platforms may not be optimal (but probably not be far off). -Future releases of the libsnark library will include a tool that generates -optimal window sizes. - - --------------------------------------------------------------------------------- -References --------------------------------------------------------------------------------- - -\[BBFR15] [ - _ADSNARK: nearly practical and privacy-preserving proofs on authenticated data_ -](https://eprint.iacr.org/2014/617), - Michael Backes, Manuel Barbosa, Dario Fiore, Raphael M. Reischuk, - IEEE Symposium on Security and Privacy (Oakland) 2015 - -\[BCCT12] [ - _From extractable collision resistance to succinct non-Interactive arguments of knowledge, and back again_ -](http://eprint.iacr.org/2011/443), - Nir Bitansky, Ran Canetti, Alessandro Chiesa, Eran Tromer, - Innovations in Computer Science (ITCS) 2012 - -\[BCCT13] [ - _Recursive composition and bootstrapping for SNARKs and proof-carrying data_ -](http://eprint.iacr.org/2012/095) - Nir Bitansky, Ran Canetti, Alessandro Chiesa, Eran Tromer, - Symposium on Theory of Computing (STOC) 13 - -\[BCGTV13] [ - _SNARKs for C: Verifying Program Executions Succinctly and in Zero Knowledge_ -](http://eprint.iacr.org/2013/507), - Eli Ben-Sasson, Alessandro Chiesa, Daniel Genkin, Eran Tromer, Madars Virza, - CRYPTO 2013 - -\[BCIOP13] [ - _Succinct Non-Interactive Arguments via Linear Interactive Proofs_ -](http://eprint.iacr.org/2012/718), - Nir Bitansky, Alessandro Chiesa, Yuval Ishai, Rafail Ostrovsky, Omer Paneth, - Theory of Cryptography Conference 2013 - -\[BCTV14a] [ - _Succinct Non-Interactive Zero Knowledge for a von Neumann Architecture_ -](http://eprint.iacr.org/2013/879), - Eli Ben-Sasson, Alessandro Chiesa, Eran Tromer, Madars Virza, - USENIX Security 2014 - -\[BCTV14b] [ - _Scalable succinct non-interactive arguments via cycles of elliptic curves_ -](https://eprint.iacr.org/2014/595), - Eli Ben-Sasson, Alessandro Chiesa, Eran Tromer, Madars Virza, - CRYPTO 2014 - -\[CTV15] [ - _Cluster computing in zero knowledge_ -](https://eprint.iacr.org/2015/377), - Alessandro Chiesa, Eran Tromer, Madars Virza, - Eurocrypt 2015 - -\[DFGK14] [ - Square span programs with applications to succinct NIZK arguments -](https://eprint.iacr.org/2014/718), - George Danezis, Cedric Fournet, Jens Groth, Markulf Kohlweiss, - ASIACCS 2014 - -\[GGPR13] [ - _Quadratic span programs and succinct NIZKs without PCPs_ -](http://eprint.iacr.org/2012/215), - Rosario Gennaro, Craig Gentry, Bryan Parno, Mariana Raykova, - EUROCRYPT 2013 - -\[ate-pairing] [ - _High-Speed Software Implementation of the Optimal Ate Pairing over Barreto-Naehrig Curves_ -](https://github.com/herumi/ate-pairing), - MITSUNARI Shigeo, TERUYA Tadanori - -\[PGHR13] [ - _Pinocchio: Nearly Practical Verifiable Computation_ -](http://eprint.iacr.org/2013/279), - Bryan Parno, Craig Gentry, Jon Howell, Mariana Raykova, - IEEE Symposium on Security and Privacy (Oakland) 2013 - -[SCIPR Lab]: http://www.scipr-lab.org/ (Succinct Computational Integrity and Privacy Research Lab) - -[LICENSE]: LICENSE (LICENSE file in top directory of libsnark distribution) - -[AUTHORS]: AUTHORS (AUTHORS file in top directory of libsnark distribution) diff --git a/src/snark/doxygen.conf b/src/snark/doxygen.conf deleted file mode 100644 index 5fbe6168109..00000000000 --- a/src/snark/doxygen.conf +++ /dev/null @@ -1,1807 +0,0 @@ -# Doxyfile 1.8.2 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or sequence of words) that should -# identify the project. Note that if you do not use Doxywizard you need -# to put quotes around the project name if it contains spaces. - -PROJECT_NAME = libsnark - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = - -# Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer -# a quick idea about the purpose of the project. Keep the description short. - -PROJECT_BRIEF = - -# With the PROJECT_LOGO tag one can specify an logo or icon that is -# included in the documentation. The maximum height of the logo should not -# exceed 55 pixels and the maximum width should not exceed 200 pixels. -# Doxygen will copy the logo to the output directory. - -PROJECT_LOGO = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = YES - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. Note that you specify absolute paths here, but also -# relative paths, which will be relative from the directory where doxygen is -# started. - -STRIP_FROM_PATH = src - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful if your file system -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) - -JAVADOC_AUTOBRIEF = YES - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 8 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding -# "class=itcl::class" will allow you to use the command class in the -# itcl::class meaning. - -TCL_SUBST = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given -# extension. Doxygen has a built-in mapping, but you can override or extend it -# using this tag. The format is ext=language, where ext is a file extension, -# and language is one of the parsers supported by doxygen: IDL, Java, -# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, -# C++. For instance to make doxygen treat .inc files as Fortran files (default -# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note -# that for custom extensions you also need to set FILE_PATTERNS otherwise the -# files are not read by doxygen. - -EXTENSION_MAPPING = tcc=C++ - -# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all -# comments according to the Markdown format, which allows for more readable -# documentation. See http://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you -# can mix doxygen, HTML, and XML commands with Markdown formatting. -# Disable only in case of backward compatibilities issues. - -MARKDOWN_SUPPORT = YES - -# When enabled doxygen tries to link words that correspond to documented classes, -# or namespaces to their corresponding documentation. Such a link can be -# prevented in individual cases by by putting a % sign in front of the word or -# globally by setting AUTOLINK_SUPPORT to NO. - -AUTOLINK_SUPPORT = YES - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also makes the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate -# getter and setter methods for a property. Setting this option to YES (the -# default) will make doxygen replace the get and set methods by a property in -# the documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and -# unions are shown inside the group in which they are included (e.g. using -# @ingroup) instead of on a separate page (for HTML and Man pages) or -# section (for LaTeX and RTF). - -INLINE_GROUPED_CLASSES = NO - -# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and -# unions with only public data fields will be shown inline in the documentation -# of the scope in which they are defined (i.e. file, namespace, or group -# documentation), provided this scope is documented. If set to NO (the default), -# structs, classes, and unions are shown on a separate page (for HTML and Man -# pages) or section (for LaTeX and RTF). - -INLINE_SIMPLE_STRUCTS = NO - -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. - -TYPEDEF_HIDES_STRUCT = NO - -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penalty. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will roughly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols. - -SYMBOL_CACHE_SIZE = 0 - -# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be -# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given -# their name and scope. Since this can be an expensive process and often the -# same symbol appear multiple times in the code, doxygen keeps a cache of -# pre-resolved symbols. If the cache is too small doxygen will become slower. -# If the cache is too large, memory is wasted. The cache size is given by this -# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols. - -LOOKUP_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = YES - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = YES - -# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal -# scope will be included in the documentation. - -EXTRACT_PACKAGE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = YES - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespaces are hidden. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen -# will list include files with double quotes in the documentation -# rather than with sharp brackets. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen -# will sort the (brief and detailed) documentation of class members so that -# constructors and destructors are listed first. If set to NO (the default) -# the constructors will appear in the respective orders defined by -# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. -# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO -# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to -# do proper type resolution of all parameters of a function it will reject a -# match between the prototype and the implementation of a member function even -# if there is only one candidate or it is obvious which candidate to choose -# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen -# will still accept a match between prototype and implementation in such cases. - -STRICT_PROTO_MATCHING = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or macro consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and macros in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. To create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. -# You can optionally specify a file name after the option, if omitted -# DoxygenLayout.xml will be used as the name of the layout file. - -LAYOUT_FILE = - -# The CITE_BIB_FILES tag can be used to specify one or more bib files -# containing the references data. This must be a list of .bib files. The -# .bib extension is automatically appended if omitted. Using this command -# requires the bibtex tool to be installed. See also -# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style -# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this -# feature you need bibtex and perl available in the search path. - -CITE_BIB_FILES = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# The WARN_NO_PARAMDOC option can be enabled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = src README.md - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh -# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py -# *.f90 *.f *.for *.vhd *.vhdl - -FILE_PATTERNS = *.md *.c *.h *.cpp *.hpp *.tcc *.inc *.cc - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should be -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. -# Note that relative paths are relative to the directory from which doxygen is -# run. - -EXCLUDE = Debug \ - Release - -# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or -# directories that are symbolic links (a Unix file system feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = "perl -pe 's/^(libsnark: .*)$/$1 {#mainpage}/ if $.==1; s!//+ *(TODO|FIXME|XXX)!/// \\todo!'" - # The 1st replacement marks README.md as the main page. - # The 2nd replacement identifies additional TODO notations. - # These should be done with FILTER_PATTERNS instead, but it looks like shell escaping is different there. - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty or if -# non of the patterns match the file name, INPUT_FILTER is applied. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) -# and it is also possible to disable source filtering for a specific pattern -# using *.ext= (so without naming a filter). This option only has effect when -# FILTER_SOURCE_FILES is enabled. - -FILTER_SOURCE_PATTERNS = - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. - -SOURCE_BROWSER = YES - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = YES - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C, C++ and Fortran comments will always remain visible. - -STRIP_CODE_COMMENTS = NO - -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. Otherwise they will link to the documentation. - -REFERENCES_LINK_SOURCE = YES - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = YES - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = doxygen - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. Note that when using a custom header you are responsible -# for the proper inclusion of any scripts and style sheets that doxygen -# needs, which is dependent on the configuration options used. -# It is advised to generate a default header using "doxygen -w html -# header.html footer.html stylesheet.css YourConfigFile" and then modify -# that header. Note that the header is subject to change so you typically -# have to redo this when upgrading to a newer version of doxygen or when -# changing the value of configuration settings such as GENERATE_TREEVIEW! - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If left blank doxygen will -# generate a default style sheet. Note that it is recommended to use -# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this -# tag will in the future become obsolete. - -HTML_STYLESHEET = - -# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional -# user-defined cascading style sheet that is included after the standard -# style sheets created by doxygen. Using this option one can overrule -# certain style aspects. This is preferred over using HTML_STYLESHEET -# since it does not replace the standard style sheet and is therefor more -# robust against future updates. Doxygen will copy the style sheet file to -# the output directory. - -HTML_EXTRA_STYLESHEET = - -# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or -# other source files which should be copied to the HTML output directory. Note -# that these files will be copied to the base HTML output directory. Use the -# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that -# the files will be copied as-is; there are no commands or markers available. - -HTML_EXTRA_FILES = - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. -# Doxygen will adjust the colors in the style sheet and background images -# according to this color. Hue is specified as an angle on a colorwheel, -# see http://en.wikipedia.org/wiki/Hue for more information. -# For instance the value 0 represents red, 60 is yellow, 120 is green, -# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. -# The allowed range is 0 to 359. - -HTML_COLORSTYLE_HUE = 220 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of -# the colors in the HTML output. For a value of 0 the output will use -# grayscales only. A value of 255 will produce the most vivid colors. - -HTML_COLORSTYLE_SAT = 100 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to -# the luminance component of the colors in the HTML output. Values below -# 100 gradually make the output lighter, whereas values above 100 make -# the output darker. The value divided by 100 is the actual gamma applied, -# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, -# and 100 does not change the gamma. - -HTML_COLORSTYLE_GAMMA = 80 - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting -# this to NO can help when comparing the output of multiple runs. - -HTML_TIMESTAMP = NO - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. - -HTML_DYNAMIC_SECTIONS = NO - -# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of -# entries shown in the various tree structured indices initially; the user -# can expand and collapse entries dynamically later on. Doxygen will expand -# the tree to such a level that at most the specified number of entries are -# visible (unless a fully collapsed tree already exceeds this amount). -# So setting the number of entries 1 will produce a full collapsed tree by -# default. 0 is a special value representing an infinite number of entries -# and will result in a full expanded tree by default. - -HTML_INDEX_NUM_ENTRIES = 0 - -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. - -GENERATE_DOCSET = NO - -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely -# identify the documentation publisher. This should be a reverse domain-name -# style string, e.g. com.mycompany.MyDocSet.documentation. - -DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. - -DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. - -CHM_INDEX_ENCODING = - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated -# that can be used as input for Qt's qhelpgenerator to generate a -# Qt Compressed Help (.qch) of the generated HTML documentation. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders - -QHP_VIRTUAL_FOLDER = doc - -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to -# add. For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see -# -# Qt Help Project / Custom Filters. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's -# filter section matches. -# -# Qt Help Project / Filter Attributes. - -QHP_SECT_FILTER_ATTRS = - -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files -# will be generated, which together with the HTML files, form an Eclipse help -# plugin. To install this plugin and make it available under the help contents -# menu in Eclipse, the contents of the directory containing the HTML and XML -# files needs to be copied into the plugins directory of eclipse. The name of -# the directory within the plugins directory should be the same as -# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before -# the help appears. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have -# this name. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) -# at top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. Since the tabs have the same information as the -# navigation tree you can set this option to NO if you already set -# GENERATE_TREEVIEW to YES. - -DISABLE_INDEX = NO - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. -# Since the tree basically has the same information as the tab index you -# could consider to set DISABLE_INDEX to NO when enabling this option. - -GENERATE_TREEVIEW = YES - -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values -# (range [0,1..20]) that doxygen will group on one line in the generated HTML -# documentation. Note that a value of 0 will completely suppress the enum -# values from appearing in the overview section. - -ENUM_VALUES_PER_LINE = 4 - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open -# links to external symbols imported via tag files in a separate window. - -EXT_LINKS_IN_WINDOW = NO - -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are -# not supported properly for IE 6.0, but are supported on all modern browsers. -# Note that when changing this option you need to delete any form_*.png files -# in the HTML output before the changes have effect. - -FORMULA_TRANSPARENT = YES - -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax -# (see http://www.mathjax.org) which uses client side Javascript for the -# rendering instead of using prerendered bitmaps. Use this if you do not -# have LaTeX installed or if you want to formulas look prettier in the HTML -# output. When enabled you may also need to install MathJax separately and -# configure the path to it using the MATHJAX_RELPATH option. - -USE_MATHJAX = YES - -# When MathJax is enabled you need to specify the location relative to the -# HTML output directory using the MATHJAX_RELPATH option. The destination -# directory should contain the MathJax.js script. For instance, if the mathjax -# directory is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to -# the MathJax Content Delivery Network so you can quickly see the result without -# installing MathJax. However, it is strongly recommended to install a local -# copy of MathJax from http://www.mathjax.org before deployment. - -MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest - -# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension -# names that should be enabled during MathJax rendering. - -MATHJAX_EXTENSIONS = - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box -# for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using -# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets -# (GENERATE_DOCSET) there is already a search function so this one should -# typically be disabled. For large projects the javascript based search engine -# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. - -SEARCHENGINE = YES - -# When the SERVER_BASED_SEARCH tag is enabled the search engine will be -# implemented using a PHP enabled web server instead of at the web client -# using Javascript. Doxygen will generate the search PHP script and index -# file to put on the web server. The advantage of the server -# based approach is that it scales better to large projects and allows -# full text search. The disadvantages are that it is more difficult to setup -# and does not have live searching capabilities. - -SERVER_BASED_SEARCH = NO - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. -# Note that when enabling USE_PDFLATEX this option is only used for -# generating bitmaps for formulas in the HTML output, but not in the -# Makefile that is written to the output directory. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4 - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = amsfonts - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for -# the generated latex document. The footer should contain everything after -# the last chapter. If it is left blank doxygen will generate a -# standard footer. Notice: only use this tag if you know what you are doing! - -LATEX_FOOTER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = NO - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = NO - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -# If LATEX_SOURCE_CODE is set to YES then doxygen will include -# source code with syntax highlighting in the LaTeX output. -# Note that which sources are shown also depends on other settings -# such as SOURCE_BROWSER. - -LATEX_SOURCE_CODE = NO - -# The LATEX_BIB_STYLE tag can be used to specify the style to use for the -# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See -# http://en.wikipedia.org/wiki/BibTeX for more info. - -LATEX_BIB_STYLE = plain - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load style sheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. This is useful -# if you want to understand what is going on. On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# pointed to by INCLUDE_PATH will be searched when a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition that -# overrules the definition found in the source code. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all references to function-like macros -# that are alone on a line, have an all uppercase name, and do not end with a -# semicolon, because these will confuse the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. For each -# tag file the location of the external documentation should be added. The -# format of a tag file without this location is as follows: -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths -# or URLs. Note that each tag file must have a unique name (where the name does -# NOT include the path). If a tag file is not located in the directory in which -# doxygen is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option also works with HAVE_DOT disabled, but it is recommended to -# install and use dot, since it yields more powerful graphs. - -CLASS_DIAGRAMS = NO - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see -# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = YES - -# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is -# allowed to run in parallel. When set to 0 (the default) doxygen will -# base this on the number of processors available in the system. You can set it -# explicitly to a value larger than 0 to get control over the balance -# between CPU load and processing speed. - -DOT_NUM_THREADS = 0 - -# By default doxygen will use the Helvetica font for all dot files that -# doxygen generates. When you want a differently looking font you can specify -# the font name using DOT_FONTNAME. You need to make sure dot is able to find -# the font, which can be done by putting it in a standard location or by setting -# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the -# directory containing the font. - -DOT_FONTNAME = Helvetica - -# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. -# The default size is 10pt. - -DOT_FONTSIZE = 10 - -# By default doxygen will tell dot to use the Helvetica font. -# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to -# set the path where dot can find it. - -DOT_FONTPATH = - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = NO - -# If the UML_LOOK tag is enabled, the fields and methods are shown inside -# the class node. If there are many fields or methods and many nodes the -# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS -# threshold limits the number of items for each type to make the size more -# managable. Set this to 0 for no limit. Note that the threshold may be -# exceeded by 50% before the limit is enforced. - -UML_LIMIT_NUM_FIELDS = 10 - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = NO - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH and HAVE_DOT options are set to YES then -# doxygen will generate a call dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable call graphs -# for selected functions only using the \callgraph command. - -CALL_GRAPH = YES - -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -# doxygen will generate a caller dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable caller -# graphs for selected functions only using the \callergraph command. - -CALLER_GRAPH = YES - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will generate a graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are svg, png, jpg, or gif. -# If left blank png will be used. If you choose svg you need to set -# HTML_FILE_EXTENSION to xhtml in order to make the SVG files -# visible in IE 9+ (other browsers do not have this requirement). - -DOT_IMAGE_FORMAT = png - -# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to -# enable generation of interactive SVG images that allow zooming and panning. -# Note that this requires a modern browser other than Internet Explorer. -# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you -# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files -# visible. Older versions of IE do not have SVG support. - -INTERACTIVE_SVG = NO - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The MSCFILE_DIRS tag can be used to specify one or more directories that -# contain msc files that are included in the documentation (see the -# \mscfile command). - -MSCFILE_DIRS = - -# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the -# number of direct children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. - -MAX_DOT_GRAPH_DEPTH = 0 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not -# seem to support this out of the box. Warning: Depending on the platform used, -# enabling this option may lead to badly anti-aliased labels on the edges of -# a graph (i.e. they become hard to read). - -DOT_TRANSPARENT = NO - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = NO - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES diff --git a/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g1.cpp b/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g1.cpp deleted file mode 100644 index 2c62060566f..00000000000 --- a/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g1.cpp +++ /dev/null @@ -1,524 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#include "algebra/curves/alt_bn128/alt_bn128_g1.hpp" - -namespace libsnark { - -#ifdef PROFILE_OP_COUNTS -int64_t alt_bn128_G1::add_cnt = 0; -int64_t alt_bn128_G1::dbl_cnt = 0; -#endif - -std::vector alt_bn128_G1::wnaf_window_table; -std::vector alt_bn128_G1::fixed_base_exp_window_table; -alt_bn128_G1 alt_bn128_G1::G1_zero; -alt_bn128_G1 alt_bn128_G1::G1_one; - -alt_bn128_G1::alt_bn128_G1() -{ - this->X = G1_zero.X; - this->Y = G1_zero.Y; - this->Z = G1_zero.Z; -} - -void alt_bn128_G1::print() const -{ - if (this->is_zero()) - { - printf("O\n"); - } - else - { - alt_bn128_G1 copy(*this); - copy.to_affine_coordinates(); - gmp_printf("(%Nd , %Nd)\n", - copy.X.as_bigint().data, alt_bn128_Fq::num_limbs, - copy.Y.as_bigint().data, alt_bn128_Fq::num_limbs); - } -} - -void alt_bn128_G1::print_coordinates() const -{ - if (this->is_zero()) - { - printf("O\n"); - } - else - { - gmp_printf("(%Nd : %Nd : %Nd)\n", - this->X.as_bigint().data, alt_bn128_Fq::num_limbs, - this->Y.as_bigint().data, alt_bn128_Fq::num_limbs, - this->Z.as_bigint().data, alt_bn128_Fq::num_limbs); - } -} - -void alt_bn128_G1::to_affine_coordinates() -{ - if (this->is_zero()) - { - this->X = alt_bn128_Fq::zero(); - this->Y = alt_bn128_Fq::one(); - this->Z = alt_bn128_Fq::zero(); - } - else - { - alt_bn128_Fq Z_inv = Z.inverse(); - alt_bn128_Fq Z2_inv = Z_inv.squared(); - alt_bn128_Fq Z3_inv = Z2_inv * Z_inv; - this->X = this->X * Z2_inv; - this->Y = this->Y * Z3_inv; - this->Z = alt_bn128_Fq::one(); - } -} - -void alt_bn128_G1::to_special() -{ - this->to_affine_coordinates(); -} - -bool alt_bn128_G1::is_special() const -{ - return (this->is_zero() || this->Z == alt_bn128_Fq::one()); -} - -bool alt_bn128_G1::is_zero() const -{ - return (this->Z.is_zero()); -} - -bool alt_bn128_G1::operator==(const alt_bn128_G1 &other) const -{ - if (this->is_zero()) - { - return other.is_zero(); - } - - if (other.is_zero()) - { - return false; - } - - /* now neither is O */ - - // using Jacobian coordinates so: - // (X1:Y1:Z1) = (X2:Y2:Z2) - // iff - // X1/Z1^2 == X2/Z2^2 and Y1/Z1^3 == Y2/Z2^3 - // iff - // X1 * Z2^2 == X2 * Z1^2 and Y1 * Z2^3 == Y2 * Z1^3 - - alt_bn128_Fq Z1_squared = (this->Z).squared(); - alt_bn128_Fq Z2_squared = (other.Z).squared(); - - if ((this->X * Z2_squared) != (other.X * Z1_squared)) - { - return false; - } - - alt_bn128_Fq Z1_cubed = (this->Z) * Z1_squared; - alt_bn128_Fq Z2_cubed = (other.Z) * Z2_squared; - - if ((this->Y * Z2_cubed) != (other.Y * Z1_cubed)) - { - return false; - } - - return true; -} - -bool alt_bn128_G1::operator!=(const alt_bn128_G1& other) const -{ - return !(operator==(other)); -} - -alt_bn128_G1 alt_bn128_G1::operator+(const alt_bn128_G1 &other) const -{ - // handle special cases having to do with O - if (this->is_zero()) - { - return other; - } - - if (other.is_zero()) - { - return *this; - } - - // no need to handle points of order 2,4 - // (they cannot exist in a prime-order subgroup) - - // check for doubling case - - // using Jacobian coordinates so: - // (X1:Y1:Z1) = (X2:Y2:Z2) - // iff - // X1/Z1^2 == X2/Z2^2 and Y1/Z1^3 == Y2/Z2^3 - // iff - // X1 * Z2^2 == X2 * Z1^2 and Y1 * Z2^3 == Y2 * Z1^3 - - alt_bn128_Fq Z1Z1 = (this->Z).squared(); - alt_bn128_Fq Z2Z2 = (other.Z).squared(); - - alt_bn128_Fq U1 = this->X * Z2Z2; - alt_bn128_Fq U2 = other.X * Z1Z1; - - alt_bn128_Fq Z1_cubed = (this->Z) * Z1Z1; - alt_bn128_Fq Z2_cubed = (other.Z) * Z2Z2; - - alt_bn128_Fq S1 = (this->Y) * Z2_cubed; // S1 = Y1 * Z2 * Z2Z2 - alt_bn128_Fq S2 = (other.Y) * Z1_cubed; // S2 = Y2 * Z1 * Z1Z1 - - if (U1 == U2 && S1 == S2) - { - // dbl case; nothing of above can be reused - return this->dbl(); - } - - // rest of add case - alt_bn128_Fq H = U2 - U1; // H = U2-U1 - alt_bn128_Fq S2_minus_S1 = S2-S1; - alt_bn128_Fq I = (H+H).squared(); // I = (2 * H)^2 - alt_bn128_Fq J = H * I; // J = H * I - alt_bn128_Fq r = S2_minus_S1 + S2_minus_S1; // r = 2 * (S2-S1) - alt_bn128_Fq V = U1 * I; // V = U1 * I - alt_bn128_Fq X3 = r.squared() - J - (V+V); // X3 = r^2 - J - 2 * V - alt_bn128_Fq S1_J = S1 * J; - alt_bn128_Fq Y3 = r * (V-X3) - (S1_J+S1_J); // Y3 = r * (V-X3)-2 S1 J - alt_bn128_Fq Z3 = ((this->Z+other.Z).squared()-Z1Z1-Z2Z2) * H; // Z3 = ((Z1+Z2)^2-Z1Z1-Z2Z2) * H - - return alt_bn128_G1(X3, Y3, Z3); -} - -alt_bn128_G1 alt_bn128_G1::operator-() const -{ - return alt_bn128_G1(this->X, -(this->Y), this->Z); -} - - -alt_bn128_G1 alt_bn128_G1::operator-(const alt_bn128_G1 &other) const -{ - return (*this) + (-other); -} - -alt_bn128_G1 alt_bn128_G1::add(const alt_bn128_G1 &other) const -{ - // handle special cases having to do with O - if (this->is_zero()) - { - return other; - } - - if (other.is_zero()) - { - return *this; - } - - // no need to handle points of order 2,4 - // (they cannot exist in a prime-order subgroup) - - // handle double case - if (this->operator==(other)) - { - return this->dbl(); - } - -#ifdef PROFILE_OP_COUNTS - this->add_cnt++; -#endif - // NOTE: does not handle O and pts of order 2,4 - // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl - - alt_bn128_Fq Z1Z1 = (this->Z).squared(); // Z1Z1 = Z1^2 - alt_bn128_Fq Z2Z2 = (other.Z).squared(); // Z2Z2 = Z2^2 - alt_bn128_Fq U1 = (this->X) * Z2Z2; // U1 = X1 * Z2Z2 - alt_bn128_Fq U2 = (other.X) * Z1Z1; // U2 = X2 * Z1Z1 - alt_bn128_Fq S1 = (this->Y) * (other.Z) * Z2Z2; // S1 = Y1 * Z2 * Z2Z2 - alt_bn128_Fq S2 = (other.Y) * (this->Z) * Z1Z1; // S2 = Y2 * Z1 * Z1Z1 - alt_bn128_Fq H = U2 - U1; // H = U2-U1 - alt_bn128_Fq S2_minus_S1 = S2-S1; - alt_bn128_Fq I = (H+H).squared(); // I = (2 * H)^2 - alt_bn128_Fq J = H * I; // J = H * I - alt_bn128_Fq r = S2_minus_S1 + S2_minus_S1; // r = 2 * (S2-S1) - alt_bn128_Fq V = U1 * I; // V = U1 * I - alt_bn128_Fq X3 = r.squared() - J - (V+V); // X3 = r^2 - J - 2 * V - alt_bn128_Fq S1_J = S1 * J; - alt_bn128_Fq Y3 = r * (V-X3) - (S1_J+S1_J); // Y3 = r * (V-X3)-2 S1 J - alt_bn128_Fq Z3 = ((this->Z+other.Z).squared()-Z1Z1-Z2Z2) * H; // Z3 = ((Z1+Z2)^2-Z1Z1-Z2Z2) * H - - return alt_bn128_G1(X3, Y3, Z3); -} - -alt_bn128_G1 alt_bn128_G1::mixed_add(const alt_bn128_G1 &other) const -{ -#ifdef DEBUG - assert(other.is_special()); -#endif - - // handle special cases having to do with O - if (this->is_zero()) - { - return other; - } - - if (other.is_zero()) - { - return *this; - } - - // no need to handle points of order 2,4 - // (they cannot exist in a prime-order subgroup) - - // check for doubling case - - // using Jacobian coordinates so: - // (X1:Y1:Z1) = (X2:Y2:Z2) - // iff - // X1/Z1^2 == X2/Z2^2 and Y1/Z1^3 == Y2/Z2^3 - // iff - // X1 * Z2^2 == X2 * Z1^2 and Y1 * Z2^3 == Y2 * Z1^3 - - // we know that Z2 = 1 - - const alt_bn128_Fq Z1Z1 = (this->Z).squared(); - - const alt_bn128_Fq &U1 = this->X; - const alt_bn128_Fq U2 = other.X * Z1Z1; - - const alt_bn128_Fq Z1_cubed = (this->Z) * Z1Z1; - - const alt_bn128_Fq &S1 = (this->Y); // S1 = Y1 * Z2 * Z2Z2 - const alt_bn128_Fq S2 = (other.Y) * Z1_cubed; // S2 = Y2 * Z1 * Z1Z1 - - if (U1 == U2 && S1 == S2) - { - // dbl case; nothing of above can be reused - return this->dbl(); - } - -#ifdef PROFILE_OP_COUNTS - this->add_cnt++; -#endif - - // NOTE: does not handle O and pts of order 2,4 - // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl - alt_bn128_Fq H = U2-(this->X); // H = U2-X1 - alt_bn128_Fq HH = H.squared() ; // HH = H&2 - alt_bn128_Fq I = HH+HH; // I = 4*HH - I = I + I; - alt_bn128_Fq J = H*I; // J = H*I - alt_bn128_Fq r = S2-(this->Y); // r = 2*(S2-Y1) - r = r + r; - alt_bn128_Fq V = (this->X) * I ; // V = X1*I - alt_bn128_Fq X3 = r.squared()-J-V-V; // X3 = r^2-J-2*V - alt_bn128_Fq Y3 = (this->Y)*J; // Y3 = r*(V-X3)-2*Y1*J - Y3 = r*(V-X3) - Y3 - Y3; - alt_bn128_Fq Z3 = ((this->Z)+H).squared() - Z1Z1 - HH; // Z3 = (Z1+H)^2-Z1Z1-HH - - return alt_bn128_G1(X3, Y3, Z3); -} - -alt_bn128_G1 alt_bn128_G1::dbl() const -{ -#ifdef PROFILE_OP_COUNTS - this->dbl_cnt++; -#endif - // handle point at infinity - if (this->is_zero()) - { - return (*this); - } - - // no need to handle points of order 2,4 - // (they cannot exist in a prime-order subgroup) - - // NOTE: does not handle O and pts of order 2,4 - // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l - - alt_bn128_Fq A = (this->X).squared(); // A = X1^2 - alt_bn128_Fq B = (this->Y).squared(); // B = Y1^2 - alt_bn128_Fq C = B.squared(); // C = B^2 - alt_bn128_Fq D = (this->X + B).squared() - A - C; - D = D+D; // D = 2 * ((X1 + B)^2 - A - C) - alt_bn128_Fq E = A + A + A; // E = 3 * A - alt_bn128_Fq F = E.squared(); // F = E^2 - alt_bn128_Fq X3 = F - (D+D); // X3 = F - 2 D - alt_bn128_Fq eightC = C+C; - eightC = eightC + eightC; - eightC = eightC + eightC; - alt_bn128_Fq Y3 = E * (D - X3) - eightC; // Y3 = E * (D - X3) - 8 * C - alt_bn128_Fq Y1Z1 = (this->Y)*(this->Z); - alt_bn128_Fq Z3 = Y1Z1 + Y1Z1; // Z3 = 2 * Y1 * Z1 - - return alt_bn128_G1(X3, Y3, Z3); -} - -bool alt_bn128_G1::is_well_formed() const -{ - if (this->is_zero()) - { - return true; - } - else - { - /* - y^2 = x^3 + b - - We are using Jacobian coordinates, so equation we need to check is actually - - (y/z^3)^2 = (x/z^2)^3 + b - y^2 / z^6 = x^3 / z^6 + b - y^2 = x^3 + b z^6 - */ - alt_bn128_Fq X2 = this->X.squared(); - alt_bn128_Fq Y2 = this->Y.squared(); - alt_bn128_Fq Z2 = this->Z.squared(); - - alt_bn128_Fq X3 = this->X * X2; - alt_bn128_Fq Z3 = this->Z * Z2; - alt_bn128_Fq Z6 = Z3.squared(); - - return (Y2 == X3 + alt_bn128_coeff_b * Z6); - } -} - -alt_bn128_G1 alt_bn128_G1::zero() -{ - return G1_zero; -} - -alt_bn128_G1 alt_bn128_G1::one() -{ - return G1_one; -} - -alt_bn128_G1 alt_bn128_G1::random_element() -{ - return (scalar_field::random_element().as_bigint()) * G1_one; -} - -std::ostream& operator<<(std::ostream &out, const alt_bn128_G1 &g) -{ - alt_bn128_G1 copy(g); - copy.to_affine_coordinates(); - - out << (copy.is_zero() ? 1 : 0) << OUTPUT_SEPARATOR; -#ifdef NO_PT_COMPRESSION - out << copy.X << OUTPUT_SEPARATOR << copy.Y; -#else - /* storing LSB of Y */ - out << copy.X << OUTPUT_SEPARATOR << (copy.Y.as_bigint().data[0] & 1); -#endif - - return out; -} - -std::istream& operator>>(std::istream &in, alt_bn128_G1 &g) -{ - char is_zero; - alt_bn128_Fq tX, tY; - -#ifdef NO_PT_COMPRESSION - in >> is_zero >> tX >> tY; - is_zero -= '0'; -#else - in.read((char*)&is_zero, 1); // this reads is_zero; - is_zero -= '0'; - consume_OUTPUT_SEPARATOR(in); - - unsigned char Y_lsb; - in >> tX; - consume_OUTPUT_SEPARATOR(in); - in.read((char*)&Y_lsb, 1); - Y_lsb -= '0'; - - // y = +/- sqrt(x^3 + b) - if (!is_zero) - { - alt_bn128_Fq tX2 = tX.squared(); - alt_bn128_Fq tY2 = tX2*tX + alt_bn128_coeff_b; - tY = tY2.sqrt(); - - if ((tY.as_bigint().data[0] & 1) != Y_lsb) - { - tY = -tY; - } - } -#endif - // using Jacobian coordinates - if (!is_zero) - { - g.X = tX; - g.Y = tY; - g.Z = alt_bn128_Fq::one(); - } - else - { - g = alt_bn128_G1::zero(); - } - - return in; -} - -std::ostream& operator<<(std::ostream& out, const std::vector &v) -{ - out << v.size() << "\n"; - for (const alt_bn128_G1& t : v) - { - out << t << OUTPUT_NEWLINE; - } - - return out; -} - -std::istream& operator>>(std::istream& in, std::vector &v) -{ - v.clear(); - - size_t s; - in >> s; - consume_newline(in); - - v.reserve(s); - - for (size_t i = 0; i < s; ++i) - { - alt_bn128_G1 g; - in >> g; - consume_OUTPUT_NEWLINE(in); - v.emplace_back(g); - } - - return in; -} - -template<> -void batch_to_special_all_non_zeros(std::vector &vec) -{ - std::vector Z_vec; - Z_vec.reserve(vec.size()); - - for (auto &el: vec) - { - Z_vec.emplace_back(el.Z); - } - batch_invert(Z_vec); - - const alt_bn128_Fq one = alt_bn128_Fq::one(); - - for (size_t i = 0; i < vec.size(); ++i) - { - alt_bn128_Fq Z2 = Z_vec[i].squared(); - alt_bn128_Fq Z3 = Z_vec[i] * Z2; - - vec[i].X = vec[i].X * Z2; - vec[i].Y = vec[i].Y * Z3; - vec[i].Z = one; - } -} - -} // libsnark diff --git a/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g1.hpp b/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g1.hpp deleted file mode 100644 index 7053fe68899..00000000000 --- a/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g1.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef ALT_BN128_G1_HPP_ -#define ALT_BN128_G1_HPP_ -#include -#include "algebra/curves/alt_bn128/alt_bn128_init.hpp" -#include "algebra/curves/curve_utils.hpp" - -namespace libsnark { - -class alt_bn128_G1; -std::ostream& operator<<(std::ostream &, const alt_bn128_G1&); -std::istream& operator>>(std::istream &, alt_bn128_G1&); - -class alt_bn128_G1 { -public: -#ifdef PROFILE_OP_COUNTS - static int64_t add_cnt; - static int64_t dbl_cnt; -#endif - static std::vector wnaf_window_table; - static std::vector fixed_base_exp_window_table; - static alt_bn128_G1 G1_zero; - static alt_bn128_G1 G1_one; - - typedef alt_bn128_Fq base_field; - typedef alt_bn128_Fr scalar_field; - - alt_bn128_Fq X, Y, Z; - - // using Jacobian coordinates - alt_bn128_G1(); - alt_bn128_G1(const alt_bn128_Fq& X, const alt_bn128_Fq& Y, const alt_bn128_Fq& Z) : X(X), Y(Y), Z(Z) {}; - - void print() const; - void print_coordinates() const; - - void to_affine_coordinates(); - void to_special(); - bool is_special() const; - - bool is_zero() const; - - bool operator==(const alt_bn128_G1 &other) const; - bool operator!=(const alt_bn128_G1 &other) const; - - alt_bn128_G1 operator+(const alt_bn128_G1 &other) const; - alt_bn128_G1 operator-() const; - alt_bn128_G1 operator-(const alt_bn128_G1 &other) const; - - alt_bn128_G1 add(const alt_bn128_G1 &other) const; - alt_bn128_G1 mixed_add(const alt_bn128_G1 &other) const; - alt_bn128_G1 dbl() const; - - bool is_well_formed() const; - - static alt_bn128_G1 zero(); - static alt_bn128_G1 one(); - static alt_bn128_G1 random_element(); - - static size_t size_in_bits() { return base_field::size_in_bits() + 1; } - static bigint base_field_char() { return base_field::field_char(); } - static bigint order() { return scalar_field::field_char(); } - - friend std::ostream& operator<<(std::ostream &out, const alt_bn128_G1 &g); - friend std::istream& operator>>(std::istream &in, alt_bn128_G1 &g); -}; - -template -alt_bn128_G1 operator*(const bigint &lhs, const alt_bn128_G1 &rhs) -{ - return scalar_mul(rhs, lhs); -} - -template& modulus_p> -alt_bn128_G1 operator*(const Fp_model &lhs, const alt_bn128_G1 &rhs) -{ - return scalar_mul(rhs, lhs.as_bigint()); -} - -std::ostream& operator<<(std::ostream& out, const std::vector &v); -std::istream& operator>>(std::istream& in, std::vector &v); - -template -void batch_to_special_all_non_zeros(std::vector &vec); -template<> -void batch_to_special_all_non_zeros(std::vector &vec); - -} // libsnark -#endif // ALT_BN128_G1_HPP_ diff --git a/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g2.cpp b/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g2.cpp deleted file mode 100644 index 4b592e8044e..00000000000 --- a/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g2.cpp +++ /dev/null @@ -1,505 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#include "algebra/curves/alt_bn128/alt_bn128_g2.hpp" - -namespace libsnark { - -#ifdef PROFILE_OP_COUNTS -int64_t alt_bn128_G2::add_cnt = 0; -int64_t alt_bn128_G2::dbl_cnt = 0; -#endif - -std::vector alt_bn128_G2::wnaf_window_table; -std::vector alt_bn128_G2::fixed_base_exp_window_table; -alt_bn128_G2 alt_bn128_G2::G2_zero; -alt_bn128_G2 alt_bn128_G2::G2_one; - -alt_bn128_G2::alt_bn128_G2() -{ - this->X = G2_zero.X; - this->Y = G2_zero.Y; - this->Z = G2_zero.Z; -} - -alt_bn128_Fq2 alt_bn128_G2::mul_by_b(const alt_bn128_Fq2 &elt) -{ - return alt_bn128_Fq2(alt_bn128_twist_mul_by_b_c0 * elt.c0, alt_bn128_twist_mul_by_b_c1 * elt.c1); -} - -void alt_bn128_G2::print() const -{ - if (this->is_zero()) - { - printf("O\n"); - } - else - { - alt_bn128_G2 copy(*this); - copy.to_affine_coordinates(); - gmp_printf("(%Nd*z + %Nd , %Nd*z + %Nd)\n", - copy.X.c1.as_bigint().data, alt_bn128_Fq::num_limbs, - copy.X.c0.as_bigint().data, alt_bn128_Fq::num_limbs, - copy.Y.c1.as_bigint().data, alt_bn128_Fq::num_limbs, - copy.Y.c0.as_bigint().data, alt_bn128_Fq::num_limbs); - } -} - -void alt_bn128_G2::print_coordinates() const -{ - if (this->is_zero()) - { - printf("O\n"); - } - else - { - gmp_printf("(%Nd*z + %Nd : %Nd*z + %Nd : %Nd*z + %Nd)\n", - this->X.c1.as_bigint().data, alt_bn128_Fq::num_limbs, - this->X.c0.as_bigint().data, alt_bn128_Fq::num_limbs, - this->Y.c1.as_bigint().data, alt_bn128_Fq::num_limbs, - this->Y.c0.as_bigint().data, alt_bn128_Fq::num_limbs, - this->Z.c1.as_bigint().data, alt_bn128_Fq::num_limbs, - this->Z.c0.as_bigint().data, alt_bn128_Fq::num_limbs); - } -} - -void alt_bn128_G2::to_affine_coordinates() -{ - if (this->is_zero()) - { - this->X = alt_bn128_Fq2::zero(); - this->Y = alt_bn128_Fq2::one(); - this->Z = alt_bn128_Fq2::zero(); - } - else - { - alt_bn128_Fq2 Z_inv = Z.inverse(); - alt_bn128_Fq2 Z2_inv = Z_inv.squared(); - alt_bn128_Fq2 Z3_inv = Z2_inv * Z_inv; - this->X = this->X * Z2_inv; - this->Y = this->Y * Z3_inv; - this->Z = alt_bn128_Fq2::one(); - } -} - -void alt_bn128_G2::to_special() -{ - this->to_affine_coordinates(); -} - -bool alt_bn128_G2::is_special() const -{ - return (this->is_zero() || this->Z == alt_bn128_Fq2::one()); -} - -bool alt_bn128_G2::is_zero() const -{ - return (this->Z.is_zero()); -} - -bool alt_bn128_G2::operator==(const alt_bn128_G2 &other) const -{ - if (this->is_zero()) - { - return other.is_zero(); - } - - if (other.is_zero()) - { - return false; - } - - /* now neither is O */ - - // using Jacobian coordinates so: - // (X1:Y1:Z1) = (X2:Y2:Z2) - // iff - // X1/Z1^2 == X2/Z2^2 and Y1/Z1^3 == Y2/Z2^3 - // iff - // X1 * Z2^2 == X2 * Z1^2 and Y1 * Z2^3 == Y2 * Z1^3 - - alt_bn128_Fq2 Z1_squared = (this->Z).squared(); - alt_bn128_Fq2 Z2_squared = (other.Z).squared(); - - if ((this->X * Z2_squared) != (other.X * Z1_squared)) - { - return false; - } - - alt_bn128_Fq2 Z1_cubed = (this->Z) * Z1_squared; - alt_bn128_Fq2 Z2_cubed = (other.Z) * Z2_squared; - - if ((this->Y * Z2_cubed) != (other.Y * Z1_cubed)) - { - return false; - } - - return true; -} - -bool alt_bn128_G2::operator!=(const alt_bn128_G2& other) const -{ - return !(operator==(other)); -} - -alt_bn128_G2 alt_bn128_G2::operator+(const alt_bn128_G2 &other) const -{ - // handle special cases having to do with O - if (this->is_zero()) - { - return other; - } - - if (other.is_zero()) - { - return *this; - } - - // no need to handle points of order 2,4 - // (they cannot exist in a prime-order subgroup) - - // check for doubling case - - // using Jacobian coordinates so: - // (X1:Y1:Z1) = (X2:Y2:Z2) - // iff - // X1/Z1^2 == X2/Z2^2 and Y1/Z1^3 == Y2/Z2^3 - // iff - // X1 * Z2^2 == X2 * Z1^2 and Y1 * Z2^3 == Y2 * Z1^3 - - alt_bn128_Fq2 Z1Z1 = (this->Z).squared(); - alt_bn128_Fq2 Z2Z2 = (other.Z).squared(); - - alt_bn128_Fq2 U1 = this->X * Z2Z2; - alt_bn128_Fq2 U2 = other.X * Z1Z1; - - alt_bn128_Fq2 Z1_cubed = (this->Z) * Z1Z1; - alt_bn128_Fq2 Z2_cubed = (other.Z) * Z2Z2; - - alt_bn128_Fq2 S1 = (this->Y) * Z2_cubed; // S1 = Y1 * Z2 * Z2Z2 - alt_bn128_Fq2 S2 = (other.Y) * Z1_cubed; // S2 = Y2 * Z1 * Z1Z1 - - if (U1 == U2 && S1 == S2) - { - // dbl case; nothing of above can be reused - return this->dbl(); - } - - // rest of add case - alt_bn128_Fq2 H = U2 - U1; // H = U2-U1 - alt_bn128_Fq2 S2_minus_S1 = S2-S1; - alt_bn128_Fq2 I = (H+H).squared(); // I = (2 * H)^2 - alt_bn128_Fq2 J = H * I; // J = H * I - alt_bn128_Fq2 r = S2_minus_S1 + S2_minus_S1; // r = 2 * (S2-S1) - alt_bn128_Fq2 V = U1 * I; // V = U1 * I - alt_bn128_Fq2 X3 = r.squared() - J - (V+V); // X3 = r^2 - J - 2 * V - alt_bn128_Fq2 S1_J = S1 * J; - alt_bn128_Fq2 Y3 = r * (V-X3) - (S1_J+S1_J); // Y3 = r * (V-X3)-2 S1 J - alt_bn128_Fq2 Z3 = ((this->Z+other.Z).squared()-Z1Z1-Z2Z2) * H; // Z3 = ((Z1+Z2)^2-Z1Z1-Z2Z2) * H - - return alt_bn128_G2(X3, Y3, Z3); -} - -alt_bn128_G2 alt_bn128_G2::operator-() const -{ - return alt_bn128_G2(this->X, -(this->Y), this->Z); -} - - -alt_bn128_G2 alt_bn128_G2::operator-(const alt_bn128_G2 &other) const -{ - return (*this) + (-other); -} - -alt_bn128_G2 alt_bn128_G2::add(const alt_bn128_G2 &other) const -{ - // handle special cases having to do with O - if (this->is_zero()) - { - return other; - } - - if (other.is_zero()) - { - return *this; - } - - // no need to handle points of order 2,4 - // (they cannot exist in a prime-order subgroup) - - // handle double case - if (this->operator==(other)) - { - return this->dbl(); - } - -#ifdef PROFILE_OP_COUNTS - this->add_cnt++; -#endif - // NOTE: does not handle O and pts of order 2,4 - // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-projective.html#addition-add-1998-cmo-2 - - alt_bn128_Fq2 Z1Z1 = (this->Z).squared(); // Z1Z1 = Z1^2 - alt_bn128_Fq2 Z2Z2 = (other.Z).squared(); // Z2Z2 = Z2^2 - alt_bn128_Fq2 U1 = (this->X) * Z2Z2; // U1 = X1 * Z2Z2 - alt_bn128_Fq2 U2 = (other.X) * Z1Z1; // U2 = X2 * Z1Z1 - alt_bn128_Fq2 S1 = (this->Y) * (other.Z) * Z2Z2; // S1 = Y1 * Z2 * Z2Z2 - alt_bn128_Fq2 S2 = (other.Y) * (this->Z) * Z1Z1; // S2 = Y2 * Z1 * Z1Z1 - alt_bn128_Fq2 H = U2 - U1; // H = U2-U1 - alt_bn128_Fq2 S2_minus_S1 = S2-S1; - alt_bn128_Fq2 I = (H+H).squared(); // I = (2 * H)^2 - alt_bn128_Fq2 J = H * I; // J = H * I - alt_bn128_Fq2 r = S2_minus_S1 + S2_minus_S1; // r = 2 * (S2-S1) - alt_bn128_Fq2 V = U1 * I; // V = U1 * I - alt_bn128_Fq2 X3 = r.squared() - J - (V+V); // X3 = r^2 - J - 2 * V - alt_bn128_Fq2 S1_J = S1 * J; - alt_bn128_Fq2 Y3 = r * (V-X3) - (S1_J+S1_J); // Y3 = r * (V-X3)-2 S1 J - alt_bn128_Fq2 Z3 = ((this->Z+other.Z).squared()-Z1Z1-Z2Z2) * H; // Z3 = ((Z1+Z2)^2-Z1Z1-Z2Z2) * H - - return alt_bn128_G2(X3, Y3, Z3); -} - -alt_bn128_G2 alt_bn128_G2::mixed_add(const alt_bn128_G2 &other) const -{ -#ifdef DEBUG - assert(other.is_special()); -#endif - - // handle special cases having to do with O - if (this->is_zero()) - { - return other; - } - - if (other.is_zero()) - { - return *this; - } - - // no need to handle points of order 2,4 - // (they cannot exist in a prime-order subgroup) - - // check for doubling case - - // using Jacobian coordinates so: - // (X1:Y1:Z1) = (X2:Y2:Z2) - // iff - // X1/Z1^2 == X2/Z2^2 and Y1/Z1^3 == Y2/Z2^3 - // iff - // X1 * Z2^2 == X2 * Z1^2 and Y1 * Z2^3 == Y2 * Z1^3 - - // we know that Z2 = 1 - - const alt_bn128_Fq2 Z1Z1 = (this->Z).squared(); - - const alt_bn128_Fq2 &U1 = this->X; - const alt_bn128_Fq2 U2 = other.X * Z1Z1; - - const alt_bn128_Fq2 Z1_cubed = (this->Z) * Z1Z1; - - const alt_bn128_Fq2 &S1 = (this->Y); // S1 = Y1 * Z2 * Z2Z2 - const alt_bn128_Fq2 S2 = (other.Y) * Z1_cubed; // S2 = Y2 * Z1 * Z1Z1 - - if (U1 == U2 && S1 == S2) - { - // dbl case; nothing of above can be reused - return this->dbl(); - } - -#ifdef PROFILE_OP_COUNTS - this->add_cnt++; -#endif - - // NOTE: does not handle O and pts of order 2,4 - // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl - alt_bn128_Fq2 H = U2-(this->X); // H = U2-X1 - alt_bn128_Fq2 HH = H.squared() ; // HH = H&2 - alt_bn128_Fq2 I = HH+HH; // I = 4*HH - I = I + I; - alt_bn128_Fq2 J = H*I; // J = H*I - alt_bn128_Fq2 r = S2-(this->Y); // r = 2*(S2-Y1) - r = r + r; - alt_bn128_Fq2 V = (this->X) * I ; // V = X1*I - alt_bn128_Fq2 X3 = r.squared()-J-V-V; // X3 = r^2-J-2*V - alt_bn128_Fq2 Y3 = (this->Y)*J; // Y3 = r*(V-X3)-2*Y1*J - Y3 = r*(V-X3) - Y3 - Y3; - alt_bn128_Fq2 Z3 = ((this->Z)+H).squared() - Z1Z1 - HH; // Z3 = (Z1+H)^2-Z1Z1-HH - - return alt_bn128_G2(X3, Y3, Z3); -} - -alt_bn128_G2 alt_bn128_G2::dbl() const -{ -#ifdef PROFILE_OP_COUNTS - this->dbl_cnt++; -#endif - // handle point at infinity - if (this->is_zero()) - { - return (*this); - } - - // NOTE: does not handle O and pts of order 2,4 - // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-projective.html#doubling-dbl-2007-bl - - alt_bn128_Fq2 A = (this->X).squared(); // A = X1^2 - alt_bn128_Fq2 B = (this->Y).squared(); // B = Y1^2 - alt_bn128_Fq2 C = B.squared(); // C = B^2 - alt_bn128_Fq2 D = (this->X + B).squared() - A - C; - D = D+D; // D = 2 * ((X1 + B)^2 - A - C) - alt_bn128_Fq2 E = A + A + A; // E = 3 * A - alt_bn128_Fq2 F = E.squared(); // F = E^2 - alt_bn128_Fq2 X3 = F - (D+D); // X3 = F - 2 D - alt_bn128_Fq2 eightC = C+C; - eightC = eightC + eightC; - eightC = eightC + eightC; - alt_bn128_Fq2 Y3 = E * (D - X3) - eightC; // Y3 = E * (D - X3) - 8 * C - alt_bn128_Fq2 Y1Z1 = (this->Y)*(this->Z); - alt_bn128_Fq2 Z3 = Y1Z1 + Y1Z1; // Z3 = 2 * Y1 * Z1 - - return alt_bn128_G2(X3, Y3, Z3); -} - -alt_bn128_G2 alt_bn128_G2::mul_by_q() const -{ - return alt_bn128_G2(alt_bn128_twist_mul_by_q_X * (this->X).Frobenius_map(1), - alt_bn128_twist_mul_by_q_Y * (this->Y).Frobenius_map(1), - (this->Z).Frobenius_map(1)); -} - -bool alt_bn128_G2::is_well_formed() const -{ - if (this->is_zero()) - { - return true; - } - else - { - /* - y^2 = x^3 + b - - We are using Jacobian coordinates, so equation we need to check is actually - - (y/z^3)^2 = (x/z^2)^3 + b - y^2 / z^6 = x^3 / z^6 + b - y^2 = x^3 + b z^6 - */ - alt_bn128_Fq2 X2 = this->X.squared(); - alt_bn128_Fq2 Y2 = this->Y.squared(); - alt_bn128_Fq2 Z2 = this->Z.squared(); - - alt_bn128_Fq2 X3 = this->X * X2; - alt_bn128_Fq2 Z3 = this->Z * Z2; - alt_bn128_Fq2 Z6 = Z3.squared(); - - return (Y2 == X3 + alt_bn128_twist_coeff_b * Z6); - } -} - -alt_bn128_G2 alt_bn128_G2::zero() -{ - return G2_zero; -} - -alt_bn128_G2 alt_bn128_G2::one() -{ - return G2_one; -} - -alt_bn128_G2 alt_bn128_G2::random_element() -{ - return (alt_bn128_Fr::random_element().as_bigint()) * G2_one; -} - -std::ostream& operator<<(std::ostream &out, const alt_bn128_G2 &g) -{ - alt_bn128_G2 copy(g); - copy.to_affine_coordinates(); - out << (copy.is_zero() ? 1 : 0) << OUTPUT_SEPARATOR; -#ifdef NO_PT_COMPRESSION - out << copy.X << OUTPUT_SEPARATOR << copy.Y; -#else - /* storing LSB of Y */ - out << copy.X << OUTPUT_SEPARATOR << (copy.Y.c0.as_bigint().data[0] & 1); -#endif - - return out; -} - -std::istream& operator>>(std::istream &in, alt_bn128_G2 &g) -{ - char is_zero; - alt_bn128_Fq2 tX, tY; - -#ifdef NO_PT_COMPRESSION - in >> is_zero >> tX >> tY; - is_zero -= '0'; -#else - in.read((char*)&is_zero, 1); // this reads is_zero; - is_zero -= '0'; - consume_OUTPUT_SEPARATOR(in); - - unsigned char Y_lsb; - in >> tX; - consume_OUTPUT_SEPARATOR(in); - in.read((char*)&Y_lsb, 1); - Y_lsb -= '0'; - - // y = +/- sqrt(x^3 + b) - if (!is_zero) - { - alt_bn128_Fq2 tX2 = tX.squared(); - alt_bn128_Fq2 tY2 = tX2 * tX + alt_bn128_twist_coeff_b; - tY = tY2.sqrt(); - - if ((tY.c0.as_bigint().data[0] & 1) != Y_lsb) - { - tY = -tY; - } - } -#endif - // using projective coordinates - if (!is_zero) - { - g.X = tX; - g.Y = tY; - g.Z = alt_bn128_Fq2::one(); - } - else - { - g = alt_bn128_G2::zero(); - } - - return in; -} - -template<> -void batch_to_special_all_non_zeros(std::vector &vec) -{ - std::vector Z_vec; - Z_vec.reserve(vec.size()); - - for (auto &el: vec) - { - Z_vec.emplace_back(el.Z); - } - batch_invert(Z_vec); - - const alt_bn128_Fq2 one = alt_bn128_Fq2::one(); - - for (size_t i = 0; i < vec.size(); ++i) - { - alt_bn128_Fq2 Z2 = Z_vec[i].squared(); - alt_bn128_Fq2 Z3 = Z_vec[i] * Z2; - - vec[i].X = vec[i].X * Z2; - vec[i].Y = vec[i].Y * Z3; - vec[i].Z = one; - } -} - -} // libsnark diff --git a/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g2.hpp b/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g2.hpp deleted file mode 100644 index d6fa6a10d2a..00000000000 --- a/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g2.hpp +++ /dev/null @@ -1,96 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef ALT_BN128_G2_HPP_ -#define ALT_BN128_G2_HPP_ -#include -#include "algebra/curves/alt_bn128/alt_bn128_init.hpp" -#include "algebra/curves/curve_utils.hpp" - -namespace libsnark { - -class alt_bn128_G2; -std::ostream& operator<<(std::ostream &, const alt_bn128_G2&); -std::istream& operator>>(std::istream &, alt_bn128_G2&); - -class alt_bn128_G2 { -public: -#ifdef PROFILE_OP_COUNTS - static int64_t add_cnt; - static int64_t dbl_cnt; -#endif - static std::vector wnaf_window_table; - static std::vector fixed_base_exp_window_table; - static alt_bn128_G2 G2_zero; - static alt_bn128_G2 G2_one; - - typedef alt_bn128_Fq base_field; - typedef alt_bn128_Fq2 twist_field; - typedef alt_bn128_Fr scalar_field; - - alt_bn128_Fq2 X, Y, Z; - - // using Jacobian coordinates - alt_bn128_G2(); - alt_bn128_G2(const alt_bn128_Fq2& X, const alt_bn128_Fq2& Y, const alt_bn128_Fq2& Z) : X(X), Y(Y), Z(Z) {}; - - static alt_bn128_Fq2 mul_by_b(const alt_bn128_Fq2 &elt); - - void print() const; - void print_coordinates() const; - - void to_affine_coordinates(); - void to_special(); - bool is_special() const; - - bool is_zero() const; - - bool operator==(const alt_bn128_G2 &other) const; - bool operator!=(const alt_bn128_G2 &other) const; - - alt_bn128_G2 operator+(const alt_bn128_G2 &other) const; - alt_bn128_G2 operator-() const; - alt_bn128_G2 operator-(const alt_bn128_G2 &other) const; - - alt_bn128_G2 add(const alt_bn128_G2 &other) const; - alt_bn128_G2 mixed_add(const alt_bn128_G2 &other) const; - alt_bn128_G2 dbl() const; - alt_bn128_G2 mul_by_q() const; - - bool is_well_formed() const; - - static alt_bn128_G2 zero(); - static alt_bn128_G2 one(); - static alt_bn128_G2 random_element(); - - static size_t size_in_bits() { return twist_field::size_in_bits() + 1; } - static bigint base_field_char() { return base_field::field_char(); } - static bigint order() { return scalar_field::field_char(); } - - friend std::ostream& operator<<(std::ostream &out, const alt_bn128_G2 &g); - friend std::istream& operator>>(std::istream &in, alt_bn128_G2 &g); -}; - -template -alt_bn128_G2 operator*(const bigint &lhs, const alt_bn128_G2 &rhs) -{ - return scalar_mul(rhs, lhs); -} - -template& modulus_p> -alt_bn128_G2 operator*(const Fp_model &lhs, const alt_bn128_G2 &rhs) -{ - return scalar_mul(rhs, lhs.as_bigint()); -} - -template -void batch_to_special_all_non_zeros(std::vector &vec); -template<> -void batch_to_special_all_non_zeros(std::vector &vec); - -} // libsnark -#endif // ALT_BN128_G2_HPP_ diff --git a/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_init.cpp b/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_init.cpp deleted file mode 100644 index 7c23773d674..00000000000 --- a/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_init.cpp +++ /dev/null @@ -1,273 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#include "algebra/curves/alt_bn128/alt_bn128_init.hpp" -#include "algebra/curves/alt_bn128/alt_bn128_g1.hpp" -#include "algebra/curves/alt_bn128/alt_bn128_g2.hpp" - -namespace libsnark { - -bigint alt_bn128_modulus_r; -bigint alt_bn128_modulus_q; - -alt_bn128_Fq alt_bn128_coeff_b; -alt_bn128_Fq2 alt_bn128_twist; -alt_bn128_Fq2 alt_bn128_twist_coeff_b; -alt_bn128_Fq alt_bn128_twist_mul_by_b_c0; -alt_bn128_Fq alt_bn128_twist_mul_by_b_c1; -alt_bn128_Fq2 alt_bn128_twist_mul_by_q_X; -alt_bn128_Fq2 alt_bn128_twist_mul_by_q_Y; - -bigint alt_bn128_ate_loop_count; -bool alt_bn128_ate_is_loop_count_neg; -bigint<12*alt_bn128_q_limbs> alt_bn128_final_exponent; -bigint alt_bn128_final_exponent_z; -bool alt_bn128_final_exponent_is_z_neg; - -void init_alt_bn128_params() -{ - typedef bigint bigint_r; - typedef bigint bigint_q; - - assert(sizeof(mp_limb_t) == 8 || sizeof(mp_limb_t) == 4); // Montgomery assumes this - - /* parameters for scalar field Fr */ - - alt_bn128_modulus_r = bigint_r("21888242871839275222246405745257275088548364400416034343698204186575808495617"); - assert(alt_bn128_Fr::modulus_is_valid()); - if (sizeof(mp_limb_t) == 8) - { - alt_bn128_Fr::Rsquared = bigint_r("944936681149208446651664254269745548490766851729442924617792859073125903783"); - alt_bn128_Fr::Rcubed = bigint_r("5866548545943845227489894872040244720403868105578784105281690076696998248512"); - alt_bn128_Fr::inv = 0xc2e1f593efffffff; - } - if (sizeof(mp_limb_t) == 4) - { - alt_bn128_Fr::Rsquared = bigint_r("944936681149208446651664254269745548490766851729442924617792859073125903783"); - alt_bn128_Fr::Rcubed = bigint_r("5866548545943845227489894872040244720403868105578784105281690076696998248512"); - alt_bn128_Fr::inv = 0xefffffff; - } - alt_bn128_Fr::num_bits = 254; - alt_bn128_Fr::euler = bigint_r("10944121435919637611123202872628637544274182200208017171849102093287904247808"); - alt_bn128_Fr::s = 28; - alt_bn128_Fr::t = bigint_r("81540058820840996586704275553141814055101440848469862132140264610111"); - alt_bn128_Fr::t_minus_1_over_2 = bigint_r("40770029410420498293352137776570907027550720424234931066070132305055"); - alt_bn128_Fr::multiplicative_generator = alt_bn128_Fr("5"); - alt_bn128_Fr::root_of_unity = alt_bn128_Fr("19103219067921713944291392827692070036145651957329286315305642004821462161904"); - alt_bn128_Fr::nqr = alt_bn128_Fr("5"); - alt_bn128_Fr::nqr_to_t = alt_bn128_Fr("19103219067921713944291392827692070036145651957329286315305642004821462161904"); - - /* parameters for base field Fq */ - - alt_bn128_modulus_q = bigint_q("21888242871839275222246405745257275088696311157297823662689037894645226208583"); - assert(alt_bn128_Fq::modulus_is_valid()); - if (sizeof(mp_limb_t) == 8) - { - alt_bn128_Fq::Rsquared = bigint_q("3096616502983703923843567936837374451735540968419076528771170197431451843209"); - alt_bn128_Fq::Rcubed = bigint_q("14921786541159648185948152738563080959093619838510245177710943249661917737183"); - alt_bn128_Fq::inv = 0x87d20782e4866389; - } - if (sizeof(mp_limb_t) == 4) - { - alt_bn128_Fq::Rsquared = bigint_q("3096616502983703923843567936837374451735540968419076528771170197431451843209"); - alt_bn128_Fq::Rcubed = bigint_q("14921786541159648185948152738563080959093619838510245177710943249661917737183"); - alt_bn128_Fq::inv = 0xe4866389; - } - alt_bn128_Fq::num_bits = 254; - alt_bn128_Fq::euler = bigint_q("10944121435919637611123202872628637544348155578648911831344518947322613104291"); - alt_bn128_Fq::s = 1; - alt_bn128_Fq::t = bigint_q("10944121435919637611123202872628637544348155578648911831344518947322613104291"); - alt_bn128_Fq::t_minus_1_over_2 = bigint_q("5472060717959818805561601436314318772174077789324455915672259473661306552145"); - alt_bn128_Fq::multiplicative_generator = alt_bn128_Fq("3"); - alt_bn128_Fq::root_of_unity = alt_bn128_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582"); - alt_bn128_Fq::nqr = alt_bn128_Fq("3"); - alt_bn128_Fq::nqr_to_t = alt_bn128_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582"); - - /* parameters for twist field Fq2 */ - alt_bn128_Fq2::euler = bigint<2*alt_bn128_q_limbs>("239547588008311421220994022608339370399626158265550411218223901127035046843189118723920525909718935985594116157406550130918127817069793474323196511433944"); - alt_bn128_Fq2::s = 4; - alt_bn128_Fq2::t = bigint<2*alt_bn128_q_limbs>("29943448501038927652624252826042421299953269783193801402277987640879380855398639840490065738714866998199264519675818766364765977133724184290399563929243"); - alt_bn128_Fq2::t_minus_1_over_2 = bigint<2*alt_bn128_q_limbs>("14971724250519463826312126413021210649976634891596900701138993820439690427699319920245032869357433499099632259837909383182382988566862092145199781964621"); - alt_bn128_Fq2::non_residue = alt_bn128_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582"); - alt_bn128_Fq2::nqr = alt_bn128_Fq2(alt_bn128_Fq("2"),alt_bn128_Fq("1")); - alt_bn128_Fq2::nqr_to_t = alt_bn128_Fq2(alt_bn128_Fq("5033503716262624267312492558379982687175200734934877598599011485707452665730"),alt_bn128_Fq("314498342015008975724433667930697407966947188435857772134235984660852259084")); - alt_bn128_Fq2::Frobenius_coeffs_c1[0] = alt_bn128_Fq("1"); - alt_bn128_Fq2::Frobenius_coeffs_c1[1] = alt_bn128_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582"); - - /* parameters for Fq6 */ - alt_bn128_Fq6::non_residue = alt_bn128_Fq2(alt_bn128_Fq("9"),alt_bn128_Fq("1")); - alt_bn128_Fq6::Frobenius_coeffs_c1[0] = alt_bn128_Fq2(alt_bn128_Fq("1"),alt_bn128_Fq("0")); - alt_bn128_Fq6::Frobenius_coeffs_c1[1] = alt_bn128_Fq2(alt_bn128_Fq("21575463638280843010398324269430826099269044274347216827212613867836435027261"),alt_bn128_Fq("10307601595873709700152284273816112264069230130616436755625194854815875713954")); - alt_bn128_Fq6::Frobenius_coeffs_c1[2] = alt_bn128_Fq2(alt_bn128_Fq("21888242871839275220042445260109153167277707414472061641714758635765020556616"),alt_bn128_Fq("0")); - alt_bn128_Fq6::Frobenius_coeffs_c1[3] = alt_bn128_Fq2(alt_bn128_Fq("3772000881919853776433695186713858239009073593817195771773381919316419345261"),alt_bn128_Fq("2236595495967245188281701248203181795121068902605861227855261137820944008926")); - alt_bn128_Fq6::Frobenius_coeffs_c1[4] = alt_bn128_Fq2(alt_bn128_Fq("2203960485148121921418603742825762020974279258880205651966"),alt_bn128_Fq("0")); - alt_bn128_Fq6::Frobenius_coeffs_c1[5] = alt_bn128_Fq2(alt_bn128_Fq("18429021223477853657660792034369865839114504446431234726392080002137598044644"),alt_bn128_Fq("9344045779998320333812420223237981029506012124075525679208581902008406485703")); - alt_bn128_Fq6::Frobenius_coeffs_c2[0] = alt_bn128_Fq2(alt_bn128_Fq("1"),alt_bn128_Fq("0")); - alt_bn128_Fq6::Frobenius_coeffs_c2[1] = alt_bn128_Fq2(alt_bn128_Fq("2581911344467009335267311115468803099551665605076196740867805258568234346338"),alt_bn128_Fq("19937756971775647987995932169929341994314640652964949448313374472400716661030")); - alt_bn128_Fq6::Frobenius_coeffs_c2[2] = alt_bn128_Fq2(alt_bn128_Fq("2203960485148121921418603742825762020974279258880205651966"),alt_bn128_Fq("0")); - alt_bn128_Fq6::Frobenius_coeffs_c2[3] = alt_bn128_Fq2(alt_bn128_Fq("5324479202449903542726783395506214481928257762400643279780343368557297135718"),alt_bn128_Fq("16208900380737693084919495127334387981393726419856888799917914180988844123039")); - alt_bn128_Fq6::Frobenius_coeffs_c2[4] = alt_bn128_Fq2(alt_bn128_Fq("21888242871839275220042445260109153167277707414472061641714758635765020556616"),alt_bn128_Fq("0")); - alt_bn128_Fq6::Frobenius_coeffs_c2[5] = alt_bn128_Fq2(alt_bn128_Fq("13981852324922362344252311234282257507216387789820983642040889267519694726527"),alt_bn128_Fq("7629828391165209371577384193250820201684255241773809077146787135900891633097")); - - /* parameters for Fq12 */ - - alt_bn128_Fq12::non_residue = alt_bn128_Fq2(alt_bn128_Fq("9"),alt_bn128_Fq("1")); - alt_bn128_Fq12::Frobenius_coeffs_c1[0] = alt_bn128_Fq2(alt_bn128_Fq("1"),alt_bn128_Fq("0")); - alt_bn128_Fq12::Frobenius_coeffs_c1[1] = alt_bn128_Fq2(alt_bn128_Fq("8376118865763821496583973867626364092589906065868298776909617916018768340080"),alt_bn128_Fq("16469823323077808223889137241176536799009286646108169935659301613961712198316")); - alt_bn128_Fq12::Frobenius_coeffs_c1[2] = alt_bn128_Fq2(alt_bn128_Fq("21888242871839275220042445260109153167277707414472061641714758635765020556617"),alt_bn128_Fq("0")); - alt_bn128_Fq12::Frobenius_coeffs_c1[3] = alt_bn128_Fq2(alt_bn128_Fq("11697423496358154304825782922584725312912383441159505038794027105778954184319"),alt_bn128_Fq("303847389135065887422783454877609941456349188919719272345083954437860409601")); - alt_bn128_Fq12::Frobenius_coeffs_c1[4] = alt_bn128_Fq2(alt_bn128_Fq("21888242871839275220042445260109153167277707414472061641714758635765020556616"),alt_bn128_Fq("0")); - alt_bn128_Fq12::Frobenius_coeffs_c1[5] = alt_bn128_Fq2(alt_bn128_Fq("3321304630594332808241809054958361220322477375291206261884409189760185844239"),alt_bn128_Fq("5722266937896532885780051958958348231143373700109372999374820235121374419868")); - alt_bn128_Fq12::Frobenius_coeffs_c1[6] = alt_bn128_Fq2(alt_bn128_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582"),alt_bn128_Fq("0")); - alt_bn128_Fq12::Frobenius_coeffs_c1[7] = alt_bn128_Fq2(alt_bn128_Fq("13512124006075453725662431877630910996106405091429524885779419978626457868503"),alt_bn128_Fq("5418419548761466998357268504080738289687024511189653727029736280683514010267")); - alt_bn128_Fq12::Frobenius_coeffs_c1[8] = alt_bn128_Fq2(alt_bn128_Fq("2203960485148121921418603742825762020974279258880205651966"),alt_bn128_Fq("0")); - alt_bn128_Fq12::Frobenius_coeffs_c1[9] = alt_bn128_Fq2(alt_bn128_Fq("10190819375481120917420622822672549775783927716138318623895010788866272024264"),alt_bn128_Fq("21584395482704209334823622290379665147239961968378104390343953940207365798982")); - alt_bn128_Fq12::Frobenius_coeffs_c1[10] = alt_bn128_Fq2(alt_bn128_Fq("2203960485148121921418603742825762020974279258880205651967"),alt_bn128_Fq("0")); - alt_bn128_Fq12::Frobenius_coeffs_c1[11] = alt_bn128_Fq2(alt_bn128_Fq("18566938241244942414004596690298913868373833782006617400804628704885040364344"),alt_bn128_Fq("16165975933942742336466353786298926857552937457188450663314217659523851788715")); - - /* choice of short Weierstrass curve and its twist */ - - alt_bn128_coeff_b = alt_bn128_Fq("3"); - alt_bn128_twist = alt_bn128_Fq2(alt_bn128_Fq("9"), alt_bn128_Fq("1")); - alt_bn128_twist_coeff_b = alt_bn128_coeff_b * alt_bn128_twist.inverse(); - alt_bn128_twist_mul_by_b_c0 = alt_bn128_coeff_b * alt_bn128_Fq2::non_residue; - alt_bn128_twist_mul_by_b_c1 = alt_bn128_coeff_b * alt_bn128_Fq2::non_residue; - alt_bn128_twist_mul_by_q_X = alt_bn128_Fq2(alt_bn128_Fq("21575463638280843010398324269430826099269044274347216827212613867836435027261"), - alt_bn128_Fq("10307601595873709700152284273816112264069230130616436755625194854815875713954")); - alt_bn128_twist_mul_by_q_Y = alt_bn128_Fq2(alt_bn128_Fq("2821565182194536844548159561693502659359617185244120367078079554186484126554"), - alt_bn128_Fq("3505843767911556378687030309984248845540243509899259641013678093033130930403")); - - /* choice of group G1 */ - alt_bn128_G1::G1_zero = alt_bn128_G1(alt_bn128_Fq::zero(), - alt_bn128_Fq::one(), - alt_bn128_Fq::zero()); - alt_bn128_G1::G1_one = alt_bn128_G1(alt_bn128_Fq("1"), - alt_bn128_Fq("2"), - alt_bn128_Fq::one()); - alt_bn128_G1::wnaf_window_table.push_back(11); - alt_bn128_G1::wnaf_window_table.push_back(24); - alt_bn128_G1::wnaf_window_table.push_back(60); - alt_bn128_G1::wnaf_window_table.push_back(127); - - alt_bn128_G1::fixed_base_exp_window_table.resize(0); - // window 1 is unbeaten in [-inf, 4.99] - alt_bn128_G1::fixed_base_exp_window_table.push_back(1); - // window 2 is unbeaten in [4.99, 10.99] - alt_bn128_G1::fixed_base_exp_window_table.push_back(5); - // window 3 is unbeaten in [10.99, 32.29] - alt_bn128_G1::fixed_base_exp_window_table.push_back(11); - // window 4 is unbeaten in [32.29, 55.23] - alt_bn128_G1::fixed_base_exp_window_table.push_back(32); - // window 5 is unbeaten in [55.23, 162.03] - alt_bn128_G1::fixed_base_exp_window_table.push_back(55); - // window 6 is unbeaten in [162.03, 360.15] - alt_bn128_G1::fixed_base_exp_window_table.push_back(162); - // window 7 is unbeaten in [360.15, 815.44] - alt_bn128_G1::fixed_base_exp_window_table.push_back(360); - // window 8 is unbeaten in [815.44, 2373.07] - alt_bn128_G1::fixed_base_exp_window_table.push_back(815); - // window 9 is unbeaten in [2373.07, 6977.75] - alt_bn128_G1::fixed_base_exp_window_table.push_back(2373); - // window 10 is unbeaten in [6977.75, 7122.23] - alt_bn128_G1::fixed_base_exp_window_table.push_back(6978); - // window 11 is unbeaten in [7122.23, 57818.46] - alt_bn128_G1::fixed_base_exp_window_table.push_back(7122); - // window 12 is never the best - alt_bn128_G1::fixed_base_exp_window_table.push_back(0); - // window 13 is unbeaten in [57818.46, 169679.14] - alt_bn128_G1::fixed_base_exp_window_table.push_back(57818); - // window 14 is never the best - alt_bn128_G1::fixed_base_exp_window_table.push_back(0); - // window 15 is unbeaten in [169679.14, 439758.91] - alt_bn128_G1::fixed_base_exp_window_table.push_back(169679); - // window 16 is unbeaten in [439758.91, 936073.41] - alt_bn128_G1::fixed_base_exp_window_table.push_back(439759); - // window 17 is unbeaten in [936073.41, 4666554.74] - alt_bn128_G1::fixed_base_exp_window_table.push_back(936073); - // window 18 is never the best - alt_bn128_G1::fixed_base_exp_window_table.push_back(0); - // window 19 is unbeaten in [4666554.74, 7580404.42] - alt_bn128_G1::fixed_base_exp_window_table.push_back(4666555); - // window 20 is unbeaten in [7580404.42, 34552892.20] - alt_bn128_G1::fixed_base_exp_window_table.push_back(7580404); - // window 21 is never the best - alt_bn128_G1::fixed_base_exp_window_table.push_back(0); - // window 22 is unbeaten in [34552892.20, inf] - alt_bn128_G1::fixed_base_exp_window_table.push_back(34552892); - - /* choice of group G2 */ - - alt_bn128_G2::G2_zero = alt_bn128_G2(alt_bn128_Fq2::zero(), - alt_bn128_Fq2::one(), - alt_bn128_Fq2::zero()); - - alt_bn128_G2::G2_one = alt_bn128_G2(alt_bn128_Fq2(alt_bn128_Fq("10857046999023057135944570762232829481370756359578518086990519993285655852781"), - alt_bn128_Fq("11559732032986387107991004021392285783925812861821192530917403151452391805634")), - alt_bn128_Fq2(alt_bn128_Fq("8495653923123431417604973247489272438418190587263600148770280649306958101930"), - alt_bn128_Fq("4082367875863433681332203403145435568316851327593401208105741076214120093531")), - alt_bn128_Fq2::one()); - alt_bn128_G2::wnaf_window_table.push_back(5); - alt_bn128_G2::wnaf_window_table.push_back(15); - alt_bn128_G2::wnaf_window_table.push_back(39); - alt_bn128_G2::wnaf_window_table.push_back(109); - - alt_bn128_G2::fixed_base_exp_window_table.resize(0); - // window 1 is unbeaten in [-inf, 5.10] - alt_bn128_G2::fixed_base_exp_window_table.push_back(1); - // window 2 is unbeaten in [5.10, 10.43] - alt_bn128_G2::fixed_base_exp_window_table.push_back(5); - // window 3 is unbeaten in [10.43, 25.28] - alt_bn128_G2::fixed_base_exp_window_table.push_back(10); - // window 4 is unbeaten in [25.28, 59.00] - alt_bn128_G2::fixed_base_exp_window_table.push_back(25); - // window 5 is unbeaten in [59.00, 154.03] - alt_bn128_G2::fixed_base_exp_window_table.push_back(59); - // window 6 is unbeaten in [154.03, 334.25] - alt_bn128_G2::fixed_base_exp_window_table.push_back(154); - // window 7 is unbeaten in [334.25, 742.58] - alt_bn128_G2::fixed_base_exp_window_table.push_back(334); - // window 8 is unbeaten in [742.58, 2034.40] - alt_bn128_G2::fixed_base_exp_window_table.push_back(743); - // window 9 is unbeaten in [2034.40, 4987.56] - alt_bn128_G2::fixed_base_exp_window_table.push_back(2034); - // window 10 is unbeaten in [4987.56, 8888.27] - alt_bn128_G2::fixed_base_exp_window_table.push_back(4988); - // window 11 is unbeaten in [8888.27, 26271.13] - alt_bn128_G2::fixed_base_exp_window_table.push_back(8888); - // window 12 is unbeaten in [26271.13, 39768.20] - alt_bn128_G2::fixed_base_exp_window_table.push_back(26271); - // window 13 is unbeaten in [39768.20, 106275.75] - alt_bn128_G2::fixed_base_exp_window_table.push_back(39768); - // window 14 is unbeaten in [106275.75, 141703.40] - alt_bn128_G2::fixed_base_exp_window_table.push_back(106276); - // window 15 is unbeaten in [141703.40, 462422.97] - alt_bn128_G2::fixed_base_exp_window_table.push_back(141703); - // window 16 is unbeaten in [462422.97, 926871.84] - alt_bn128_G2::fixed_base_exp_window_table.push_back(462423); - // window 17 is unbeaten in [926871.84, 4873049.17] - alt_bn128_G2::fixed_base_exp_window_table.push_back(926872); - // window 18 is never the best - alt_bn128_G2::fixed_base_exp_window_table.push_back(0); - // window 19 is unbeaten in [4873049.17, 5706707.88] - alt_bn128_G2::fixed_base_exp_window_table.push_back(4873049); - // window 20 is unbeaten in [5706707.88, 31673814.95] - alt_bn128_G2::fixed_base_exp_window_table.push_back(5706708); - // window 21 is never the best - alt_bn128_G2::fixed_base_exp_window_table.push_back(0); - // window 22 is unbeaten in [31673814.95, inf] - alt_bn128_G2::fixed_base_exp_window_table.push_back(31673815); - - /* pairing parameters */ - - alt_bn128_ate_loop_count = bigint_q("29793968203157093288"); - alt_bn128_ate_is_loop_count_neg = false; - alt_bn128_final_exponent = bigint<12*alt_bn128_q_limbs>("552484233613224096312617126783173147097382103762957654188882734314196910839907541213974502761540629817009608548654680343627701153829446747810907373256841551006201639677726139946029199968412598804882391702273019083653272047566316584365559776493027495458238373902875937659943504873220554161550525926302303331747463515644711876653177129578303191095900909191624817826566688241804408081892785725967931714097716709526092261278071952560171111444072049229123565057483750161460024353346284167282452756217662335528813519139808291170539072125381230815729071544861602750936964829313608137325426383735122175229541155376346436093930287402089517426973178917569713384748081827255472576937471496195752727188261435633271238710131736096299798168852925540549342330775279877006784354801422249722573783561685179618816480037695005515426162362431072245638324744480"); - alt_bn128_final_exponent_z = bigint_q("4965661367192848881"); - alt_bn128_final_exponent_is_z_neg = false; - -} -} // libsnark diff --git a/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_init.hpp b/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_init.hpp deleted file mode 100644 index c3bea76738c..00000000000 --- a/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_init.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef ALT_BN128_INIT_HPP_ -#define ALT_BN128_INIT_HPP_ -#include "algebra/curves/public_params.hpp" -#include "algebra/fields/fp.hpp" -#include "algebra/fields/fp2.hpp" -#include "algebra/fields/fp6_3over2.hpp" -#include "algebra/fields/fp12_2over3over2.hpp" - -namespace libsnark { - -const mp_size_t alt_bn128_r_bitcount = 254; -const mp_size_t alt_bn128_q_bitcount = 254; - -const mp_size_t alt_bn128_r_limbs = (alt_bn128_r_bitcount+GMP_NUMB_BITS-1)/GMP_NUMB_BITS; -const mp_size_t alt_bn128_q_limbs = (alt_bn128_q_bitcount+GMP_NUMB_BITS-1)/GMP_NUMB_BITS; - -extern bigint alt_bn128_modulus_r; -extern bigint alt_bn128_modulus_q; - -typedef Fp_model alt_bn128_Fr; -typedef Fp_model alt_bn128_Fq; -typedef Fp2_model alt_bn128_Fq2; -typedef Fp6_3over2_model alt_bn128_Fq6; -typedef Fp12_2over3over2_model alt_bn128_Fq12; -typedef alt_bn128_Fq12 alt_bn128_GT; - -// parameters for Barreto--Naehrig curve E/Fq : y^2 = x^3 + b -extern alt_bn128_Fq alt_bn128_coeff_b; -// parameters for twisted Barreto--Naehrig curve E'/Fq2 : y^2 = x^3 + b/xi -extern alt_bn128_Fq2 alt_bn128_twist; -extern alt_bn128_Fq2 alt_bn128_twist_coeff_b; -extern alt_bn128_Fq alt_bn128_twist_mul_by_b_c0; -extern alt_bn128_Fq alt_bn128_twist_mul_by_b_c1; -extern alt_bn128_Fq2 alt_bn128_twist_mul_by_q_X; -extern alt_bn128_Fq2 alt_bn128_twist_mul_by_q_Y; - -// parameters for pairing -extern bigint alt_bn128_ate_loop_count; -extern bool alt_bn128_ate_is_loop_count_neg; -extern bigint<12*alt_bn128_q_limbs> alt_bn128_final_exponent; -extern bigint alt_bn128_final_exponent_z; -extern bool alt_bn128_final_exponent_is_z_neg; - -void init_alt_bn128_params(); - -class alt_bn128_G1; -class alt_bn128_G2; - -} // libsnark -#endif // ALT_BN128_INIT_HPP_ diff --git a/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pairing.cpp b/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pairing.cpp deleted file mode 100644 index 07b6a8c7188..00000000000 --- a/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pairing.cpp +++ /dev/null @@ -1,547 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#include "algebra/curves/alt_bn128/alt_bn128_pairing.hpp" -#include "algebra/curves/alt_bn128/alt_bn128_init.hpp" -#include "algebra/curves/alt_bn128/alt_bn128_g1.hpp" -#include "algebra/curves/alt_bn128/alt_bn128_g2.hpp" -#include -#include "common/profiling.hpp" -#include "common/assert_except.hpp" - -namespace libsnark { - -bool alt_bn128_ate_G1_precomp::operator==(const alt_bn128_ate_G1_precomp &other) const -{ - return (this->PX == other.PX && - this->PY == other.PY); -} - -std::ostream& operator<<(std::ostream &out, const alt_bn128_ate_G1_precomp &prec_P) -{ - out << prec_P.PX << OUTPUT_SEPARATOR << prec_P.PY; - - return out; -} - -std::istream& operator>>(std::istream &in, alt_bn128_ate_G1_precomp &prec_P) -{ - in >> prec_P.PX; - consume_OUTPUT_SEPARATOR(in); - in >> prec_P.PY; - - return in; -} - -bool alt_bn128_ate_ell_coeffs::operator==(const alt_bn128_ate_ell_coeffs &other) const -{ - return (this->ell_0 == other.ell_0 && - this->ell_VW == other.ell_VW && - this->ell_VV == other.ell_VV); -} - -std::ostream& operator<<(std::ostream &out, const alt_bn128_ate_ell_coeffs &c) -{ - out << c.ell_0 << OUTPUT_SEPARATOR << c.ell_VW << OUTPUT_SEPARATOR << c.ell_VV; - return out; -} - -std::istream& operator>>(std::istream &in, alt_bn128_ate_ell_coeffs &c) -{ - in >> c.ell_0; - consume_OUTPUT_SEPARATOR(in); - in >> c.ell_VW; - consume_OUTPUT_SEPARATOR(in); - in >> c.ell_VV; - - return in; -} - -bool alt_bn128_ate_G2_precomp::operator==(const alt_bn128_ate_G2_precomp &other) const -{ - return (this->QX == other.QX && - this->QY == other.QY && - this->coeffs == other.coeffs); -} - -std::ostream& operator<<(std::ostream& out, const alt_bn128_ate_G2_precomp &prec_Q) -{ - out << prec_Q.QX << OUTPUT_SEPARATOR << prec_Q.QY << "\n"; - out << prec_Q.coeffs.size() << "\n"; - for (const alt_bn128_ate_ell_coeffs &c : prec_Q.coeffs) - { - out << c << OUTPUT_NEWLINE; - } - return out; -} - -std::istream& operator>>(std::istream& in, alt_bn128_ate_G2_precomp &prec_Q) -{ - in >> prec_Q.QX; - consume_OUTPUT_SEPARATOR(in); - in >> prec_Q.QY; - consume_newline(in); - - prec_Q.coeffs.clear(); - size_t s; - in >> s; - - consume_newline(in); - - prec_Q.coeffs.reserve(s); - - for (size_t i = 0; i < s; ++i) - { - alt_bn128_ate_ell_coeffs c; - in >> c; - consume_OUTPUT_NEWLINE(in); - prec_Q.coeffs.emplace_back(c); - } - - return in; -} - -/* final exponentiations */ - -alt_bn128_Fq12 alt_bn128_final_exponentiation_first_chunk(const alt_bn128_Fq12 &elt) -{ - enter_block("Call to alt_bn128_final_exponentiation_first_chunk"); - - /* - Computes result = elt^((q^6-1)*(q^2+1)). - Follows, e.g., Beuchat et al page 9, by computing result as follows: - elt^((q^6-1)*(q^2+1)) = (conj(elt) * elt^(-1))^(q^2+1) - More precisely: - A = conj(elt) - B = elt.inverse() - C = A * B - D = C.Frobenius_map(2) - result = D * C - */ - - const alt_bn128_Fq12 A = alt_bn128_Fq12(elt.c0,-elt.c1); - const alt_bn128_Fq12 B = elt.inverse(); - const alt_bn128_Fq12 C = A * B; - const alt_bn128_Fq12 D = C.Frobenius_map(2); - const alt_bn128_Fq12 result = D * C; - - leave_block("Call to alt_bn128_final_exponentiation_first_chunk"); - - return result; -} - -alt_bn128_Fq12 alt_bn128_exp_by_neg_z(const alt_bn128_Fq12 &elt) -{ - enter_block("Call to alt_bn128_exp_by_neg_z"); - - alt_bn128_Fq12 result = elt.cyclotomic_exp(alt_bn128_final_exponent_z); - if (!alt_bn128_final_exponent_is_z_neg) - { - result = result.unitary_inverse(); - } - - leave_block("Call to alt_bn128_exp_by_neg_z"); - - return result; -} - -alt_bn128_Fq12 alt_bn128_final_exponentiation_last_chunk(const alt_bn128_Fq12 &elt) -{ - enter_block("Call to alt_bn128_final_exponentiation_last_chunk"); - - /* - Follows Laura Fuentes-Castaneda et al. "Faster hashing to G2" - by computing: - - result = elt^(q^3 * (12*z^3 + 6z^2 + 4z - 1) + - q^2 * (12*z^3 + 6z^2 + 6z) + - q * (12*z^3 + 6z^2 + 4z) + - 1 * (12*z^3 + 12z^2 + 6z + 1)) - which equals - - result = elt^( 2z * ( 6z^2 + 3z + 1 ) * (q^4 - q^2 + 1)/r ). - - Using the following addition chain: - - A = exp_by_neg_z(elt) // = elt^(-z) - B = A^2 // = elt^(-2*z) - C = B^2 // = elt^(-4*z) - D = C * B // = elt^(-6*z) - E = exp_by_neg_z(D) // = elt^(6*z^2) - F = E^2 // = elt^(12*z^2) - G = epx_by_neg_z(F) // = elt^(-12*z^3) - H = conj(D) // = elt^(6*z) - I = conj(G) // = elt^(12*z^3) - J = I * E // = elt^(12*z^3 + 6*z^2) - K = J * H // = elt^(12*z^3 + 6*z^2 + 6*z) - L = K * B // = elt^(12*z^3 + 6*z^2 + 4*z) - M = K * E // = elt^(12*z^3 + 12*z^2 + 6*z) - N = M * elt // = elt^(12*z^3 + 12*z^2 + 6*z + 1) - O = L.Frobenius_map(1) // = elt^(q*(12*z^3 + 6*z^2 + 4*z)) - P = O * N // = elt^(q*(12*z^3 + 6*z^2 + 4*z) * (12*z^3 + 12*z^2 + 6*z + 1)) - Q = K.Frobenius_map(2) // = elt^(q^2 * (12*z^3 + 6*z^2 + 6*z)) - R = Q * P // = elt^(q^2 * (12*z^3 + 6*z^2 + 6*z) + q*(12*z^3 + 6*z^2 + 4*z) * (12*z^3 + 12*z^2 + 6*z + 1)) - S = conj(elt) // = elt^(-1) - T = S * L // = elt^(12*z^3 + 6*z^2 + 4*z - 1) - U = T.Frobenius_map(3) // = elt^(q^3(12*z^3 + 6*z^2 + 4*z - 1)) - V = U * R // = elt^(q^3(12*z^3 + 6*z^2 + 4*z - 1) + q^2 * (12*z^3 + 6*z^2 + 6*z) + q*(12*z^3 + 6*z^2 + 4*z) * (12*z^3 + 12*z^2 + 6*z + 1)) - result = V - - */ - - const alt_bn128_Fq12 A = alt_bn128_exp_by_neg_z(elt); - const alt_bn128_Fq12 B = A.cyclotomic_squared(); - const alt_bn128_Fq12 C = B.cyclotomic_squared(); - const alt_bn128_Fq12 D = C * B; - const alt_bn128_Fq12 E = alt_bn128_exp_by_neg_z(D); - const alt_bn128_Fq12 F = E.cyclotomic_squared(); - const alt_bn128_Fq12 G = alt_bn128_exp_by_neg_z(F); - const alt_bn128_Fq12 H = D.unitary_inverse(); - const alt_bn128_Fq12 I = G.unitary_inverse(); - const alt_bn128_Fq12 J = I * E; - const alt_bn128_Fq12 K = J * H; - const alt_bn128_Fq12 L = K * B; - const alt_bn128_Fq12 M = K * E; - const alt_bn128_Fq12 N = M * elt; - const alt_bn128_Fq12 O = L.Frobenius_map(1); - const alt_bn128_Fq12 P = O * N; - const alt_bn128_Fq12 Q = K.Frobenius_map(2); - const alt_bn128_Fq12 R = Q * P; - const alt_bn128_Fq12 S = elt.unitary_inverse(); - const alt_bn128_Fq12 T = S * L; - const alt_bn128_Fq12 U = T.Frobenius_map(3); - const alt_bn128_Fq12 V = U * R; - - const alt_bn128_Fq12 result = V; - - leave_block("Call to alt_bn128_final_exponentiation_last_chunk"); - - return result; -} - -alt_bn128_GT alt_bn128_final_exponentiation(const alt_bn128_Fq12 &elt) -{ - enter_block("Call to alt_bn128_final_exponentiation"); - /* OLD naive version: - alt_bn128_GT result = elt^alt_bn128_final_exponent; - */ - alt_bn128_Fq12 A = alt_bn128_final_exponentiation_first_chunk(elt); - alt_bn128_GT result = alt_bn128_final_exponentiation_last_chunk(A); - - leave_block("Call to alt_bn128_final_exponentiation"); - return result; -} - -/* ate pairing */ - -void doubling_step_for_flipped_miller_loop(const alt_bn128_Fq two_inv, - alt_bn128_G2 ¤t, - alt_bn128_ate_ell_coeffs &c) -{ - const alt_bn128_Fq2 X = current.X, Y = current.Y, Z = current.Z; - - const alt_bn128_Fq2 A = two_inv * (X * Y); // A = X1 * Y1 / 2 - const alt_bn128_Fq2 B = Y.squared(); // B = Y1^2 - const alt_bn128_Fq2 C = Z.squared(); // C = Z1^2 - const alt_bn128_Fq2 D = C+C+C; // D = 3 * C - const alt_bn128_Fq2 E = alt_bn128_twist_coeff_b * D; // E = twist_b * D - const alt_bn128_Fq2 F = E+E+E; // F = 3 * E - const alt_bn128_Fq2 G = two_inv * (B+F); // G = (B+F)/2 - const alt_bn128_Fq2 H = (Y+Z).squared() - (B+C); // H = (Y1+Z1)^2-(B+C) - const alt_bn128_Fq2 I = E-B; // I = E-B - const alt_bn128_Fq2 J = X.squared(); // J = X1^2 - const alt_bn128_Fq2 E_squared = E.squared(); // E_squared = E^2 - - current.X = A * (B-F); // X3 = A * (B-F) - current.Y = G.squared() - (E_squared+E_squared+E_squared); // Y3 = G^2 - 3*E^2 - current.Z = B * H; // Z3 = B * H - c.ell_0 = alt_bn128_twist * I; // ell_0 = xi * I - c.ell_VW = -H; // ell_VW = - H (later: * yP) - c.ell_VV = J+J+J; // ell_VV = 3*J (later: * xP) -} - -void mixed_addition_step_for_flipped_miller_loop(const alt_bn128_G2 base, - alt_bn128_G2 ¤t, - alt_bn128_ate_ell_coeffs &c) -{ - const alt_bn128_Fq2 X1 = current.X, Y1 = current.Y, Z1 = current.Z; - const alt_bn128_Fq2 &x2 = base.X, &y2 = base.Y; - - const alt_bn128_Fq2 D = X1 - x2 * Z1; // D = X1 - X2*Z1 - const alt_bn128_Fq2 E = Y1 - y2 * Z1; // E = Y1 - Y2*Z1 - const alt_bn128_Fq2 F = D.squared(); // F = D^2 - const alt_bn128_Fq2 G = E.squared(); // G = E^2 - const alt_bn128_Fq2 H = D*F; // H = D*F - const alt_bn128_Fq2 I = X1 * F; // I = X1 * F - const alt_bn128_Fq2 J = H + Z1*G - (I+I); // J = H + Z1*G - (I+I) - - current.X = D * J; // X3 = D*J - current.Y = E * (I-J)-(H * Y1); // Y3 = E*(I-J)-(H*Y1) - current.Z = Z1 * H; // Z3 = Z1*H - c.ell_0 = alt_bn128_twist * (E * x2 - D * y2); // ell_0 = xi * (E * X2 - D * Y2) - c.ell_VV = - E; // ell_VV = - E (later: * xP) - c.ell_VW = D; // ell_VW = D (later: * yP ) -} - -alt_bn128_ate_G1_precomp alt_bn128_ate_precompute_G1(const alt_bn128_G1& P) -{ - enter_block("Call to alt_bn128_ate_precompute_G1"); - - alt_bn128_G1 Pcopy = P; - Pcopy.to_affine_coordinates(); - - alt_bn128_ate_G1_precomp result; - result.PX = Pcopy.X; - result.PY = Pcopy.Y; - - leave_block("Call to alt_bn128_ate_precompute_G1"); - return result; -} - -alt_bn128_ate_G2_precomp alt_bn128_ate_precompute_G2(const alt_bn128_G2& Q) -{ - enter_block("Call to alt_bn128_ate_precompute_G2"); - - alt_bn128_G2 Qcopy(Q); - Qcopy.to_affine_coordinates(); - - alt_bn128_Fq two_inv = (alt_bn128_Fq("2").inverse()); // could add to global params if needed - - alt_bn128_ate_G2_precomp result; - result.QX = Qcopy.X; - result.QY = Qcopy.Y; - - alt_bn128_G2 R; - R.X = Qcopy.X; - R.Y = Qcopy.Y; - R.Z = alt_bn128_Fq2::one(); - - const bigint &loop_count = alt_bn128_ate_loop_count; - bool found_one = false; - alt_bn128_ate_ell_coeffs c; - - for (int64_t i = loop_count.max_bits(); i >= 0; --i) - { - const bool bit = loop_count.test_bit(i); - if (!found_one) - { - /* this skips the MSB itself */ - found_one |= bit; - continue; - } - - doubling_step_for_flipped_miller_loop(two_inv, R, c); - result.coeffs.push_back(c); - - if (bit) - { - mixed_addition_step_for_flipped_miller_loop(Qcopy, R, c); - result.coeffs.push_back(c); - } - } - - alt_bn128_G2 Q1 = Qcopy.mul_by_q(); - assert_except(Q1.Z == alt_bn128_Fq2::one()); - alt_bn128_G2 Q2 = Q1.mul_by_q(); - assert_except(Q2.Z == alt_bn128_Fq2::one()); - - if (alt_bn128_ate_is_loop_count_neg) - { - R.Y = - R.Y; - } - Q2.Y = - Q2.Y; - - mixed_addition_step_for_flipped_miller_loop(Q1, R, c); - result.coeffs.push_back(c); - - mixed_addition_step_for_flipped_miller_loop(Q2, R, c); - result.coeffs.push_back(c); - - leave_block("Call to alt_bn128_ate_precompute_G2"); - return result; -} - -alt_bn128_Fq12 alt_bn128_ate_miller_loop(const alt_bn128_ate_G1_precomp &prec_P, - const alt_bn128_ate_G2_precomp &prec_Q) -{ - enter_block("Call to alt_bn128_ate_miller_loop"); - - alt_bn128_Fq12 f = alt_bn128_Fq12::one(); - - bool found_one = false; - size_t idx = 0; - - const bigint &loop_count = alt_bn128_ate_loop_count; - alt_bn128_ate_ell_coeffs c; - - for (int64_t i = loop_count.max_bits(); i >= 0; --i) - { - const bool bit = loop_count.test_bit(i); - if (!found_one) - { - /* this skips the MSB itself */ - found_one |= bit; - continue; - } - - /* code below gets executed for all bits (EXCEPT the MSB itself) of - alt_bn128_param_p (skipping leading zeros) in MSB to LSB - order */ - - c = prec_Q.coeffs[idx++]; - f = f.squared(); - f = f.mul_by_024(c.ell_0, prec_P.PY * c.ell_VW, prec_P.PX * c.ell_VV); - - if (bit) - { - c = prec_Q.coeffs[idx++]; - f = f.mul_by_024(c.ell_0, prec_P.PY * c.ell_VW, prec_P.PX * c.ell_VV); - } - - } - - if (alt_bn128_ate_is_loop_count_neg) - { - f = f.inverse(); - } - - c = prec_Q.coeffs[idx++]; - f = f.mul_by_024(c.ell_0,prec_P.PY * c.ell_VW,prec_P.PX * c.ell_VV); - - c = prec_Q.coeffs[idx++]; - f = f.mul_by_024(c.ell_0,prec_P.PY * c.ell_VW,prec_P.PX * c.ell_VV); - - leave_block("Call to alt_bn128_ate_miller_loop"); - return f; -} - -alt_bn128_Fq12 alt_bn128_ate_double_miller_loop(const alt_bn128_ate_G1_precomp &prec_P1, - const alt_bn128_ate_G2_precomp &prec_Q1, - const alt_bn128_ate_G1_precomp &prec_P2, - const alt_bn128_ate_G2_precomp &prec_Q2) -{ - enter_block("Call to alt_bn128_ate_double_miller_loop"); - - alt_bn128_Fq12 f = alt_bn128_Fq12::one(); - - bool found_one = false; - size_t idx = 0; - - const bigint &loop_count = alt_bn128_ate_loop_count; - for (int64_t i = loop_count.max_bits(); i >= 0; --i) - { - const bool bit = loop_count.test_bit(i); - if (!found_one) - { - /* this skips the MSB itself */ - found_one |= bit; - continue; - } - - /* code below gets executed for all bits (EXCEPT the MSB itself) of - alt_bn128_param_p (skipping leading zeros) in MSB to LSB - order */ - - alt_bn128_ate_ell_coeffs c1 = prec_Q1.coeffs[idx]; - alt_bn128_ate_ell_coeffs c2 = prec_Q2.coeffs[idx]; - ++idx; - - f = f.squared(); - - f = f.mul_by_024(c1.ell_0, prec_P1.PY * c1.ell_VW, prec_P1.PX * c1.ell_VV); - f = f.mul_by_024(c2.ell_0, prec_P2.PY * c2.ell_VW, prec_P2.PX * c2.ell_VV); - - if (bit) - { - alt_bn128_ate_ell_coeffs c1 = prec_Q1.coeffs[idx]; - alt_bn128_ate_ell_coeffs c2 = prec_Q2.coeffs[idx]; - ++idx; - - f = f.mul_by_024(c1.ell_0, prec_P1.PY * c1.ell_VW, prec_P1.PX * c1.ell_VV); - f = f.mul_by_024(c2.ell_0, prec_P2.PY * c2.ell_VW, prec_P2.PX * c2.ell_VV); - } - } - - if (alt_bn128_ate_is_loop_count_neg) - { - f = f.inverse(); - } - - alt_bn128_ate_ell_coeffs c1 = prec_Q1.coeffs[idx]; - alt_bn128_ate_ell_coeffs c2 = prec_Q2.coeffs[idx]; - ++idx; - f = f.mul_by_024(c1.ell_0, prec_P1.PY * c1.ell_VW, prec_P1.PX * c1.ell_VV); - f = f.mul_by_024(c2.ell_0, prec_P2.PY * c2.ell_VW, prec_P2.PX * c2.ell_VV); - - c1 = prec_Q1.coeffs[idx]; - c2 = prec_Q2.coeffs[idx]; - ++idx; - f = f.mul_by_024(c1.ell_0, prec_P1.PY * c1.ell_VW, prec_P1.PX * c1.ell_VV); - f = f.mul_by_024(c2.ell_0, prec_P2.PY * c2.ell_VW, prec_P2.PX * c2.ell_VV); - - leave_block("Call to alt_bn128_ate_double_miller_loop"); - - return f; -} - -alt_bn128_Fq12 alt_bn128_ate_pairing(const alt_bn128_G1& P, const alt_bn128_G2 &Q) -{ - enter_block("Call to alt_bn128_ate_pairing"); - alt_bn128_ate_G1_precomp prec_P = alt_bn128_ate_precompute_G1(P); - alt_bn128_ate_G2_precomp prec_Q = alt_bn128_ate_precompute_G2(Q); - alt_bn128_Fq12 result = alt_bn128_ate_miller_loop(prec_P, prec_Q); - leave_block("Call to alt_bn128_ate_pairing"); - return result; -} - -alt_bn128_GT alt_bn128_ate_reduced_pairing(const alt_bn128_G1 &P, const alt_bn128_G2 &Q) -{ - enter_block("Call to alt_bn128_ate_reduced_pairing"); - const alt_bn128_Fq12 f = alt_bn128_ate_pairing(P, Q); - const alt_bn128_GT result = alt_bn128_final_exponentiation(f); - leave_block("Call to alt_bn128_ate_reduced_pairing"); - return result; -} - -/* choice of pairing */ - -alt_bn128_G1_precomp alt_bn128_precompute_G1(const alt_bn128_G1& P) -{ - return alt_bn128_ate_precompute_G1(P); -} - -alt_bn128_G2_precomp alt_bn128_precompute_G2(const alt_bn128_G2& Q) -{ - return alt_bn128_ate_precompute_G2(Q); -} - -alt_bn128_Fq12 alt_bn128_miller_loop(const alt_bn128_G1_precomp &prec_P, - const alt_bn128_G2_precomp &prec_Q) -{ - return alt_bn128_ate_miller_loop(prec_P, prec_Q); -} - -alt_bn128_Fq12 alt_bn128_double_miller_loop(const alt_bn128_G1_precomp &prec_P1, - const alt_bn128_G2_precomp &prec_Q1, - const alt_bn128_G1_precomp &prec_P2, - const alt_bn128_G2_precomp &prec_Q2) -{ - return alt_bn128_ate_double_miller_loop(prec_P1, prec_Q1, prec_P2, prec_Q2); -} - -alt_bn128_Fq12 alt_bn128_pairing(const alt_bn128_G1& P, - const alt_bn128_G2 &Q) -{ - return alt_bn128_ate_pairing(P, Q); -} - -alt_bn128_GT alt_bn128_reduced_pairing(const alt_bn128_G1 &P, - const alt_bn128_G2 &Q) -{ - return alt_bn128_ate_reduced_pairing(P, Q); -} -} // libsnark diff --git a/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pairing.hpp b/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pairing.hpp deleted file mode 100644 index 15d325485f5..00000000000 --- a/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pairing.hpp +++ /dev/null @@ -1,92 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef ALT_BN128_PAIRING_HPP_ -#define ALT_BN128_PAIRING_HPP_ -#include -#include "algebra/curves/alt_bn128/alt_bn128_init.hpp" - -namespace libsnark { - -/* final exponentiation */ - -alt_bn128_GT alt_bn128_final_exponentiation(const alt_bn128_Fq12 &elt); - -/* ate pairing */ - -struct alt_bn128_ate_G1_precomp { - alt_bn128_Fq PX; - alt_bn128_Fq PY; - - bool operator==(const alt_bn128_ate_G1_precomp &other) const; - friend std::ostream& operator<<(std::ostream &out, const alt_bn128_ate_G1_precomp &prec_P); - friend std::istream& operator>>(std::istream &in, alt_bn128_ate_G1_precomp &prec_P); -}; - -struct alt_bn128_ate_ell_coeffs { - alt_bn128_Fq2 ell_0; - alt_bn128_Fq2 ell_VW; - alt_bn128_Fq2 ell_VV; - - bool operator==(const alt_bn128_ate_ell_coeffs &other) const; - friend std::ostream& operator<<(std::ostream &out, const alt_bn128_ate_ell_coeffs &dc); - friend std::istream& operator>>(std::istream &in, alt_bn128_ate_ell_coeffs &dc); -}; - -struct alt_bn128_ate_G2_precomp { - alt_bn128_Fq2 QX; - alt_bn128_Fq2 QY; - std::vector coeffs; - - bool operator==(const alt_bn128_ate_G2_precomp &other) const; - friend std::ostream& operator<<(std::ostream &out, const alt_bn128_ate_G2_precomp &prec_Q); - friend std::istream& operator>>(std::istream &in, alt_bn128_ate_G2_precomp &prec_Q); -}; - -alt_bn128_ate_G1_precomp alt_bn128_ate_precompute_G1(const alt_bn128_G1& P); -alt_bn128_ate_G2_precomp alt_bn128_ate_precompute_G2(const alt_bn128_G2& Q); - -alt_bn128_Fq12 alt_bn128_ate_miller_loop(const alt_bn128_ate_G1_precomp &prec_P, - const alt_bn128_ate_G2_precomp &prec_Q); -alt_bn128_Fq12 alt_bn128_ate_double_miller_loop(const alt_bn128_ate_G1_precomp &prec_P1, - const alt_bn128_ate_G2_precomp &prec_Q1, - const alt_bn128_ate_G1_precomp &prec_P2, - const alt_bn128_ate_G2_precomp &prec_Q2); - -alt_bn128_Fq12 alt_bn128_ate_pairing(const alt_bn128_G1& P, - const alt_bn128_G2 &Q); -alt_bn128_GT alt_bn128_ate_reduced_pairing(const alt_bn128_G1 &P, - const alt_bn128_G2 &Q); - -/* choice of pairing */ - -typedef alt_bn128_ate_G1_precomp alt_bn128_G1_precomp; -typedef alt_bn128_ate_G2_precomp alt_bn128_G2_precomp; - -alt_bn128_G1_precomp alt_bn128_precompute_G1(const alt_bn128_G1& P); - -alt_bn128_G2_precomp alt_bn128_precompute_G2(const alt_bn128_G2& Q); - -alt_bn128_Fq12 alt_bn128_miller_loop(const alt_bn128_G1_precomp &prec_P, - const alt_bn128_G2_precomp &prec_Q); - -alt_bn128_Fq12 alt_bn128_double_miller_loop(const alt_bn128_G1_precomp &prec_P1, - const alt_bn128_G2_precomp &prec_Q1, - const alt_bn128_G1_precomp &prec_P2, - const alt_bn128_G2_precomp &prec_Q2); - -alt_bn128_Fq12 alt_bn128_pairing(const alt_bn128_G1& P, - const alt_bn128_G2 &Q); - -alt_bn128_GT alt_bn128_reduced_pairing(const alt_bn128_G1 &P, - const alt_bn128_G2 &Q); - -alt_bn128_GT alt_bn128_affine_reduced_pairing(const alt_bn128_G1 &P, - const alt_bn128_G2 &Q); - -} // libsnark -#endif // ALT_BN128_PAIRING_HPP_ diff --git a/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pp.cpp b/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pp.cpp deleted file mode 100644 index 25ea924d8e1..00000000000 --- a/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pp.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp" - -namespace libsnark { - -void alt_bn128_pp::init_public_params() -{ - init_alt_bn128_params(); -} - -alt_bn128_GT alt_bn128_pp::final_exponentiation(const alt_bn128_Fq12 &elt) -{ - return alt_bn128_final_exponentiation(elt); -} - -alt_bn128_G1_precomp alt_bn128_pp::precompute_G1(const alt_bn128_G1 &P) -{ - return alt_bn128_precompute_G1(P); -} - -alt_bn128_G2_precomp alt_bn128_pp::precompute_G2(const alt_bn128_G2 &Q) -{ - return alt_bn128_precompute_G2(Q); -} - -alt_bn128_Fq12 alt_bn128_pp::miller_loop(const alt_bn128_G1_precomp &prec_P, - const alt_bn128_G2_precomp &prec_Q) -{ - return alt_bn128_miller_loop(prec_P, prec_Q); -} - -alt_bn128_Fq12 alt_bn128_pp::double_miller_loop(const alt_bn128_G1_precomp &prec_P1, - const alt_bn128_G2_precomp &prec_Q1, - const alt_bn128_G1_precomp &prec_P2, - const alt_bn128_G2_precomp &prec_Q2) -{ - return alt_bn128_double_miller_loop(prec_P1, prec_Q1, prec_P2, prec_Q2); -} - -alt_bn128_Fq12 alt_bn128_pp::pairing(const alt_bn128_G1 &P, - const alt_bn128_G2 &Q) -{ - return alt_bn128_pairing(P, Q); -} - -alt_bn128_Fq12 alt_bn128_pp::reduced_pairing(const alt_bn128_G1 &P, - const alt_bn128_G2 &Q) -{ - return alt_bn128_reduced_pairing(P, Q); -} - -} // libsnark diff --git a/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pp.hpp b/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pp.hpp deleted file mode 100644 index ec8059dcb1b..00000000000 --- a/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pp.hpp +++ /dev/null @@ -1,50 +0,0 @@ -/** @file -***************************************************************************** -* @author This file is part of libsnark, developed by SCIPR Lab -* and contributors (see AUTHORS). -* @copyright MIT license (see LICENSE file) -*****************************************************************************/ - -#ifndef ALT_BN128_PP_HPP_ -#define ALT_BN128_PP_HPP_ -#include "algebra/curves/public_params.hpp" -#include "algebra/curves/alt_bn128/alt_bn128_init.hpp" -#include "algebra/curves/alt_bn128/alt_bn128_g1.hpp" -#include "algebra/curves/alt_bn128/alt_bn128_g2.hpp" -#include "algebra/curves/alt_bn128/alt_bn128_pairing.hpp" - -namespace libsnark { - -class alt_bn128_pp { -public: - typedef alt_bn128_Fr Fp_type; - typedef alt_bn128_G1 G1_type; - typedef alt_bn128_G2 G2_type; - typedef alt_bn128_G1_precomp G1_precomp_type; - typedef alt_bn128_G2_precomp G2_precomp_type; - typedef alt_bn128_Fq Fq_type; - typedef alt_bn128_Fq2 Fqe_type; - typedef alt_bn128_Fq12 Fqk_type; - typedef alt_bn128_GT GT_type; - - static const bool has_affine_pairing = false; - - static void init_public_params(); - static alt_bn128_GT final_exponentiation(const alt_bn128_Fq12 &elt); - static alt_bn128_G1_precomp precompute_G1(const alt_bn128_G1 &P); - static alt_bn128_G2_precomp precompute_G2(const alt_bn128_G2 &Q); - static alt_bn128_Fq12 miller_loop(const alt_bn128_G1_precomp &prec_P, - const alt_bn128_G2_precomp &prec_Q); - static alt_bn128_Fq12 double_miller_loop(const alt_bn128_G1_precomp &prec_P1, - const alt_bn128_G2_precomp &prec_Q1, - const alt_bn128_G1_precomp &prec_P2, - const alt_bn128_G2_precomp &prec_Q2); - static alt_bn128_Fq12 pairing(const alt_bn128_G1 &P, - const alt_bn128_G2 &Q); - static alt_bn128_Fq12 reduced_pairing(const alt_bn128_G1 &P, - const alt_bn128_G2 &Q); -}; - -} // libsnark - -#endif // ALT_BN128_PP_HPP_ diff --git a/src/snark/libsnark/algebra/curves/curve_utils.hpp b/src/snark/libsnark/algebra/curves/curve_utils.hpp deleted file mode 100644 index 33a8e1e1784..00000000000 --- a/src/snark/libsnark/algebra/curves/curve_utils.hpp +++ /dev/null @@ -1,22 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef CURVE_UTILS_HPP_ -#define CURVE_UTILS_HPP_ -#include - -#include "algebra/fields/bigint.hpp" - -namespace libsnark { - -template -GroupT scalar_mul(const GroupT &base, const bigint &scalar); - -} // libsnark -#include "algebra/curves/curve_utils.tcc" - -#endif // CURVE_UTILS_HPP_ diff --git a/src/snark/libsnark/algebra/curves/curve_utils.tcc b/src/snark/libsnark/algebra/curves/curve_utils.tcc deleted file mode 100644 index 38140cd48af..00000000000 --- a/src/snark/libsnark/algebra/curves/curve_utils.tcc +++ /dev/null @@ -1,37 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef CURVE_UTILS_TCC_ -#define CURVE_UTILS_TCC_ - -namespace libsnark { - -template -GroupT scalar_mul(const GroupT &base, const bigint &scalar) -{ - GroupT result = GroupT::zero(); - - bool found_one = false; - for (int64_t i = scalar.max_bits() - 1; i >= 0; --i) - { - if (found_one) - { - result = result.dbl(); - } - - if (scalar.test_bit(i)) - { - found_one = true; - result = result + base; - } - } - - return result; -} - -} // libsnark -#endif // CURVE_UTILS_TCC_ diff --git a/src/snark/libsnark/algebra/curves/public_params.hpp b/src/snark/libsnark/algebra/curves/public_params.hpp deleted file mode 100644 index 07e047560df..00000000000 --- a/src/snark/libsnark/algebra/curves/public_params.hpp +++ /dev/null @@ -1,103 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef PUBLIC_PARAMS_HPP_ -#define PUBLIC_PARAMS_HPP_ -#include - -namespace libsnark { - -/* - for every curve the user should define corresponding - public_params with the following typedefs: - - Fp_type - G1_type - G2_type - G1_precomp_type - G2_precomp_type - affine_ate_G1_precomp_type - affine_ate_G2_precomp_type - Fq_type - Fqe_type - Fqk_type - GT_type - - one should also define the following static methods: - - void init_public_params(); - - GT final_exponentiation(const Fqk &elt); - - G1_precomp precompute_G1(const G1 &P); - G2_precomp precompute_G2(const G2 &Q); - - Fqk miller_loop(const G1_precomp &prec_P, - const G2_precomp &prec_Q); - - affine_ate_G1_precomp affine_ate_precompute_G1(const G1 &P); - affine_ate_G2_precomp affine_ate_precompute_G2(const G2 &Q); - - - Fqk affine_ate_miller_loop(const affine_ate_G1_precomp &prec_P, - const affine_ate_G2_precomp &prec_Q); - Fqk affine_ate_e_over_e_miller_loop(const affine_ate_G1_precomp &prec_P1, - const affine_ate_G2_precomp &prec_Q1, - const affine_ate_G1_precomp &prec_P2, - const affine_ate_G2_precomp &prec_Q2); - Fqk affine_ate_e_times_e_over_e_miller_loop(const affine_ate_G1_precomp &prec_P1, - const affine_ate_G2_precomp &prec_Q1, - const affine_ate_G1_precomp &prec_P2, - const affine_ate_G2_precomp &prec_Q2, - const affine_ate_G1_precomp &prec_P3, - const affine_ate_G2_precomp &prec_Q3); - Fqk double_miller_loop(const G1_precomp &prec_P1, - const G2_precomp &prec_Q1, - const G1_precomp &prec_P2, - const G2_precomp &prec_Q2); - - Fqk pairing(const G1 &P, - const G2 &Q); - GT reduced_pairing(const G1 &P, - const G2 &Q); - GT affine_reduced_pairing(const G1 &P, - const G2 &Q); -*/ - -template -using Fr = typename EC_ppT::Fp_type; -template -using G1 = typename EC_ppT::G1_type; -template -using G2 = typename EC_ppT::G2_type; -template -using G1_precomp = typename EC_ppT::G1_precomp_type; -template -using G2_precomp = typename EC_ppT::G2_precomp_type; -template -using affine_ate_G1_precomp = typename EC_ppT::affine_ate_G1_precomp_type; -template -using affine_ate_G2_precomp = typename EC_ppT::affine_ate_G2_precomp_type; -template -using Fq = typename EC_ppT::Fq_type; -template -using Fqe = typename EC_ppT::Fqe_type; -template -using Fqk = typename EC_ppT::Fqk_type; -template -using GT = typename EC_ppT::GT_type; - -template -using Fr_vector = std::vector >; -template -using G1_vector = std::vector >; -template -using G2_vector = std::vector >; - -} // libsnark - -#endif // PUBLIC_PARAMS_HPP_ diff --git a/src/snark/libsnark/algebra/curves/tests/test_bilinearity.cpp b/src/snark/libsnark/algebra/curves/tests/test_bilinearity.cpp deleted file mode 100644 index fe6593baeef..00000000000 --- a/src/snark/libsnark/algebra/curves/tests/test_bilinearity.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/** - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ -#include "common/profiling.hpp" -#ifdef CURVE_BN128 -#include "algebra/curves/bn128/bn128_pp.hpp" -#endif -#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp" - -#include - -using namespace libsnark; - -template -void pairing_test() -{ - GT GT_one = GT::one(); - - printf("Running bilinearity tests:\n"); - G1 P = (Fr::random_element()) * G1::one(); - //G1 P = Fr("2") * G1::one(); - G2 Q = (Fr::random_element()) * G2::one(); - //G2 Q = Fr("3") * G2::one(); - - printf("P:\n"); - P.print(); - P.print_coordinates(); - printf("Q:\n"); - Q.print(); - Q.print_coordinates(); - printf("\n\n"); - - Fr s = Fr::random_element(); - //Fr s = Fr("2"); - G1 sP = s * P; - G2 sQ = s * Q; - - printf("Pairing bilinearity tests (three must match):\n"); - GT ans1 = ppT::reduced_pairing(sP, Q); - GT ans2 = ppT::reduced_pairing(P, sQ); - GT ans3 = ppT::reduced_pairing(P, Q)^s; - ans1.print(); - ans2.print(); - ans3.print(); - EXPECT_EQ(ans1, ans2); - EXPECT_EQ(ans2, ans3); - - EXPECT_NE(ans1, GT_one); - EXPECT_EQ((ans1^Fr::field_char()), GT_one); - printf("\n\n"); -} - -template -void double_miller_loop_test() -{ - const G1 P1 = (Fr::random_element()) * G1::one(); - const G1 P2 = (Fr::random_element()) * G1::one(); - const G2 Q1 = (Fr::random_element()) * G2::one(); - const G2 Q2 = (Fr::random_element()) * G2::one(); - - const G1_precomp prec_P1 = ppT::precompute_G1(P1); - const G1_precomp prec_P2 = ppT::precompute_G1(P2); - const G2_precomp prec_Q1 = ppT::precompute_G2(Q1); - const G2_precomp prec_Q2 = ppT::precompute_G2(Q2); - - const Fqk ans_1 = ppT::miller_loop(prec_P1, prec_Q1); - const Fqk ans_2 = ppT::miller_loop(prec_P2, prec_Q2); - const Fqk ans_12 = ppT::double_miller_loop(prec_P1, prec_Q1, prec_P2, prec_Q2); - EXPECT_EQ(ans_1 * ans_2, ans_12); -} - -template -void affine_pairing_test() -{ - GT GT_one = GT::one(); - - printf("Running bilinearity tests:\n"); - G1 P = (Fr::random_element()) * G1::one(); - G2 Q = (Fr::random_element()) * G2::one(); - - printf("P:\n"); - P.print(); - printf("Q:\n"); - Q.print(); - printf("\n\n"); - - Fr s = Fr::random_element(); - G1 sP = s * P; - G2 sQ = s * Q; - - printf("Pairing bilinearity tests (three must match):\n"); - GT ans1 = ppT::affine_reduced_pairing(sP, Q); - GT ans2 = ppT::affine_reduced_pairing(P, sQ); - GT ans3 = ppT::affine_reduced_pairing(P, Q)^s; - ans1.print(); - ans2.print(); - ans3.print(); - EXPECT_EQ(ans1, ans2); - EXPECT_EQ(ans2, ans3); - - EXPECT_NE(ans1, GT_one); - EXPECT_EQ((ans1^Fr::field_char()), GT_one); - printf("\n\n"); -} - -TEST(algebra, bilinearity) -{ - start_profiling(); - alt_bn128_pp::init_public_params(); - pairing_test(); - double_miller_loop_test(); - -#ifdef CURVE_BN128 // BN128 has fancy dependencies so it may be disabled - bn128_pp::init_public_params(); - pairing_test(); - double_miller_loop_test(); -#endif -} diff --git a/src/snark/libsnark/algebra/curves/tests/test_groups.cpp b/src/snark/libsnark/algebra/curves/tests/test_groups.cpp deleted file mode 100644 index 7bb7c31ccfa..00000000000 --- a/src/snark/libsnark/algebra/curves/tests/test_groups.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/** - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ -#include "common/profiling.hpp" -#ifdef CURVE_BN128 -#include "algebra/curves/bn128/bn128_pp.hpp" -#endif -#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp" -#include - -#include - -using namespace libsnark; - -template -void test_mixed_add() -{ - GroupT base, el, result; - - base = GroupT::zero(); - el = GroupT::zero(); - el.to_special(); - result = base.mixed_add(el); - EXPECT_EQ(result, base + el); - - base = GroupT::zero(); - el = GroupT::random_element(); - el.to_special(); - result = base.mixed_add(el); - EXPECT_EQ(result, base + el); - - base = GroupT::random_element(); - el = GroupT::zero(); - el.to_special(); - result = base.mixed_add(el); - EXPECT_EQ(result, base + el); - - base = GroupT::random_element(); - el = GroupT::random_element(); - el.to_special(); - result = base.mixed_add(el); - EXPECT_EQ(result, base + el); - - base = GroupT::random_element(); - el = base; - el.to_special(); - result = base.mixed_add(el); - EXPECT_EQ(result, base.dbl()); -} - -template -void test_group() -{ - bigint<1> rand1 = bigint<1>("76749407"); - bigint<1> rand2 = bigint<1>("44410867"); - bigint<1> randsum = bigint<1>("121160274"); - - GroupT zero = GroupT::zero(); - EXPECT_EQ(zero, zero); - GroupT one = GroupT::one(); - EXPECT_EQ(one, one); - GroupT two = bigint<1>(2l) * GroupT::one(); - EXPECT_EQ(two, two); - GroupT five = bigint<1>(5l) * GroupT::one(); - - GroupT three = bigint<1>(3l) * GroupT::one(); - GroupT four = bigint<1>(4l) * GroupT::one(); - - EXPECT_EQ(two+five, three+four); - - GroupT a = GroupT::random_element(); - GroupT b = GroupT::random_element(); - - EXPECT_NE(one, zero); - EXPECT_NE(a, zero); - EXPECT_NE(a, one); - - EXPECT_NE(b, zero); - EXPECT_NE(b, one); - - EXPECT_EQ(a.dbl(), a + a); - EXPECT_EQ(b.dbl(), b + b); - EXPECT_EQ(one.add(two), three); - EXPECT_EQ(two.add(one), three); - EXPECT_EQ(a + b, b + a); - EXPECT_EQ(a - a, zero); - EXPECT_EQ(a - b, a + (-b)); - EXPECT_EQ(a - b, (-b) + a); - - // handle special cases - EXPECT_EQ(zero + (-a), -a); - EXPECT_EQ(zero - a, -a); - EXPECT_EQ(a - zero, a); - EXPECT_EQ(a + zero, a); - EXPECT_EQ(zero + a, a); - - EXPECT_EQ((a + b).dbl(), (a + b) + (b + a)); - EXPECT_EQ(bigint<1>("2") * (a + b), (a + b) + (b + a)); - - EXPECT_EQ((rand1 * a) + (rand2 * a), (randsum * a)); - - EXPECT_EQ(GroupT::order() * a, zero); - EXPECT_EQ(GroupT::order() * one, zero); - EXPECT_NE((GroupT::order() * a) - a, zero); - EXPECT_NE((GroupT::order() * one) - one, zero); - - test_mixed_add(); -} - -template -void test_mul_by_q() -{ - GroupT a = GroupT::random_element(); - EXPECT_EQ((GroupT::base_field_char()*a), a.mul_by_q()); -} - -template -void test_output() -{ - GroupT g = GroupT::zero(); - - for (size_t i = 0; i < 1000; ++i) - { - std::stringstream ss; - ss << g; - GroupT gg; - ss >> gg; - EXPECT_EQ(g, gg); - /* use a random point in next iteration */ - g = GroupT::random_element(); - } -} - -TEST(algebra, groups) -{ - alt_bn128_pp::init_public_params(); - test_group >(); - test_output >(); - test_group >(); - test_output >(); - test_mul_by_q >(); - -#ifdef CURVE_BN128 // BN128 has fancy dependencies so it may be disabled - bn128_pp::init_public_params(); - test_group >(); - test_output >(); - test_group >(); - test_output >(); -#endif -} diff --git a/src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain.hpp b/src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain.hpp deleted file mode 100644 index 3e127a063d1..00000000000 --- a/src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain.hpp +++ /dev/null @@ -1,45 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for the "basic radix-2" evaluation domain. - - Roughly, the domain has size m = 2^k and consists of the m-th roots of unity. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef BASIC_RADIX2_DOMAIN_HPP_ -#define BASIC_RADIX2_DOMAIN_HPP_ - -#include "algebra/evaluation_domain/evaluation_domain.hpp" - -namespace libsnark { - -template -class basic_radix2_domain : public evaluation_domain { -public: - - FieldT omega; - - basic_radix2_domain(const size_t m); - - void FFT(std::vector &a); - void iFFT(std::vector &a); - void cosetFFT(std::vector &a, const FieldT &g); - void icosetFFT(std::vector &a, const FieldT &g); - std::vector lagrange_coeffs(const FieldT &t); - FieldT get_element(const size_t idx); - FieldT compute_Z(const FieldT &t); - void add_poly_Z(const FieldT &coeff, std::vector &H); - void divide_by_Z_on_coset(std::vector &P); - -}; - -} // libsnark - -#include "algebra/evaluation_domain/domains/basic_radix2_domain.tcc" - -#endif // BASIC_RADIX2_DOMAIN_HPP_ diff --git a/src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain.tcc b/src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain.tcc deleted file mode 100644 index d315e8319e4..00000000000 --- a/src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain.tcc +++ /dev/null @@ -1,112 +0,0 @@ -/** @file - ***************************************************************************** - - Implementation of interfaces for the "basic radix-2" evaluation domain. - - See basic_radix2_domain.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef BASIC_RADIX2_DOMAIN_TCC_ -#define BASIC_RADIX2_DOMAIN_TCC_ - -#include "algebra/evaluation_domain/domains/basic_radix2_domain_aux.hpp" - -namespace libsnark { - -template -basic_radix2_domain::basic_radix2_domain(const size_t m) : evaluation_domain(m) -{ - assert(m > 1); - const size_t logm = log2(m); - assert(logm <= (FieldT::s)); - - omega = get_root_of_unity(m); -} - -template -void basic_radix2_domain::FFT(std::vector &a) -{ - enter_block("Execute FFT"); - assert(a.size() == this->m); - _basic_radix2_FFT(a, omega); - leave_block("Execute FFT"); -} - -template -void basic_radix2_domain::iFFT(std::vector &a) -{ - enter_block("Execute inverse FFT"); - assert(a.size() == this->m); - _basic_radix2_FFT(a, omega.inverse()); - - const FieldT sconst = FieldT(a.size()).inverse(); - for (size_t i = 0; i < a.size(); ++i) - { - a[i] *= sconst; - } - leave_block("Execute inverse FFT"); -} - -template -void basic_radix2_domain::cosetFFT(std::vector &a, const FieldT &g) -{ - enter_block("Execute coset FFT"); - _multiply_by_coset(a, g); - FFT(a); - leave_block("Execute coset FFT"); -} - -template -void basic_radix2_domain::icosetFFT(std::vector &a, const FieldT &g) -{ - enter_block("Execute inverse coset IFFT"); - iFFT(a); - _multiply_by_coset(a, g.inverse()); - leave_block("Execute inverse coset IFFT"); -} - -template -std::vector basic_radix2_domain::lagrange_coeffs(const FieldT &t) -{ - return _basic_radix2_lagrange_coeffs(this->m, t); -} - -template -FieldT basic_radix2_domain::get_element(const size_t idx) -{ - return omega^idx; -} - -template -FieldT basic_radix2_domain::compute_Z(const FieldT &t) -{ - return (t^this->m) - FieldT::one(); -} - -template -void basic_radix2_domain::add_poly_Z(const FieldT &coeff, std::vector &H) -{ - assert(H.size() == this->m+1); - H[this->m] += coeff; - H[0] -= coeff; -} - -template -void basic_radix2_domain::divide_by_Z_on_coset(std::vector &P) -{ - const FieldT coset = FieldT::multiplicative_generator; - const FieldT Z_inverse_at_coset = this->compute_Z(coset).inverse(); - for (size_t i = 0; i < this->m; ++i) - { - P[i] *= Z_inverse_at_coset; - } -} - -} // libsnark - -#endif // BASIC_RADIX2_DOMAIN_TCC_ diff --git a/src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain_aux.hpp b/src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain_aux.hpp deleted file mode 100644 index c42ab2f6fe7..00000000000 --- a/src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain_aux.hpp +++ /dev/null @@ -1,48 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for auxiliary functions for the "basic radix-2" evaluation domain. - - These functions compute the radix-2 FFT (in single- or multi-thread mode) and, - also compute Lagrange coefficients. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef BASIC_RADIX2_DOMAIN_AUX_HPP_ -#define BASIC_RADIX2_DOMAIN_AUX_HPP_ - -namespace libsnark { - -/** - * Compute the radix-2 FFT of the vector a over the set S={omega^{0},...,omega^{m-1}}. - */ -template -void _basic_radix2_FFT(std::vector &a, const FieldT &omega); - -/** - * A multi-thread version of _basic_radix2_FFT. - */ -template -void _parallel_basic_radix2_FFT(std::vector &a, const FieldT &omega); - -/** - * Translate the vector a to a coset defined by g. - */ -template -void _multiply_by_coset(std::vector &a, const FieldT &g); - -/** - * Compute the m Lagrange coefficients, relative to the set S={omega^{0},...,omega^{m-1}}, at the field element t. - */ -template -std::vector _basic_radix2_lagrange_coeffs(const size_t m, const FieldT &t); - -} // libsnark - -#include "algebra/evaluation_domain/domains/basic_radix2_domain_aux.tcc" - -#endif // BASIC_RADIX2_DOMAIN_AUX_HPP_ diff --git a/src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain_aux.tcc b/src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain_aux.tcc deleted file mode 100644 index 79f2ffec71a..00000000000 --- a/src/snark/libsnark/algebra/evaluation_domain/domains/basic_radix2_domain_aux.tcc +++ /dev/null @@ -1,242 +0,0 @@ -/** @file - ***************************************************************************** - - Implementation of interfaces for auxiliary functions for the "basic radix-2" evaluation domain. - - See basic_radix2_domain_aux.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef BASIC_RADIX2_DOMAIN_AUX_TCC_ -#define BASIC_RADIX2_DOMAIN_AUX_TCC_ - -#include -#ifdef MULTICORE -#include -#endif -#include "algebra/fields/field_utils.hpp" -#include "common/profiling.hpp" -#include "common/utils.hpp" - -namespace libsnark { - -#ifdef MULTICORE -#define _basic_radix2_FFT _basic_parallel_radix2_FFT -#else -#define _basic_radix2_FFT _basic_serial_radix2_FFT -#endif - -/* - Below we make use of pseudocode from [CLRS 2n Ed, pp. 864]. - Also, note that it's the caller's responsibility to multiply by 1/N. - */ -template -void _basic_serial_radix2_FFT(std::vector &a, const FieldT &omega) -{ - const size_t n = a.size(), logn = log2(n); - assert(n == (1u << logn)); - - /* swapping in place (from Storer's book) */ - for (size_t k = 0; k < n; ++k) - { - const size_t rk = bitreverse(k, logn); - if (k < rk) - std::swap(a[k], a[rk]); - } - - size_t m = 1; // invariant: m = 2^{s-1} - for (size_t s = 1; s <= logn; ++s) - { - // w_m is 2^s-th root of unity now - const FieldT w_m = omega^(n/(2*m)); - - asm volatile ("/* pre-inner */"); - for (size_t k = 0; k < n; k += 2*m) - { - FieldT w = FieldT::one(); - for (size_t j = 0; j < m; ++j) - { - const FieldT t = w * a[k+j+m]; - a[k+j+m] = a[k+j] - t; - a[k+j] += t; - w *= w_m; - } - } - asm volatile ("/* post-inner */"); - m *= 2; - } -} - -template -void _basic_parallel_radix2_FFT_inner(std::vector &a, const FieldT &omega, const size_t log_cpus) -{ - const size_t num_cpus = UINT64_C(1)< > tmp(num_cpus); - for (size_t j = 0; j < num_cpus; ++j) - { - tmp[j].resize(UINT64_C(1)<<(log_m-log_cpus), FieldT::zero()); - } - -#ifdef MULTICORE - #pragma omp parallel for -#endif - for (size_t j = 0; j < num_cpus; ++j) - { - const FieldT omega_j = omega^j; - const FieldT omega_step = omega^(j<<(log_m - log_cpus)); - - FieldT elt = FieldT::one(); - for (size_t i = 0; i < UINT64_C(1)<<(log_m - log_cpus); ++i) - { - for (size_t s = 0; s < num_cpus; ++s) - { - // invariant: elt is omega^(j*idx) - const size_t idx = (i + (s<<(log_m - log_cpus))) % (1u << log_m); - tmp[j][i] += a[idx] * elt; - elt *= omega_step; - } - elt *= omega_j; - } - } - leave_block("Shuffle inputs"); - - enter_block("Execute sub-FFTs"); - const FieldT omega_num_cpus = omega^num_cpus; - -#ifdef MULTICORE - #pragma omp parallel for -#endif - for (size_t j = 0; j < num_cpus; ++j) - { - _basic_serial_radix2_FFT(tmp[j], omega_num_cpus); - } - leave_block("Execute sub-FFTs"); - - enter_block("Re-shuffle outputs"); - -#ifdef MULTICORE - #pragma omp parallel for -#endif - for (size_t i = 0; i < num_cpus; ++i) - { - for (size_t j = 0; j < UINT64_C(1)<<(log_m - log_cpus); ++j) - { - // now: i = idx >> (log_m - log_cpus) and j = idx % (1u << (log_m - log_cpus)), for idx = ((i<<(log_m-log_cpus))+j) % (1u << log_m) - a[(j< -void _basic_parallel_radix2_FFT(std::vector &a, const FieldT &omega) -{ -#ifdef MULTICORE - const size_t num_cpus = omp_get_max_threads(); -#else - const size_t num_cpus = 1; -#endif - const size_t log_cpus = ((num_cpus & (num_cpus - 1)) == 0 ? log2(num_cpus) : log2(num_cpus) - 1); - -#ifdef DEBUG - print_indent(); printf("* Invoking parallel FFT on 2^%zu CPUs (omp_get_max_threads = %zu)\n", log_cpus, num_cpus); -#endif - - if (log_cpus == 0) - { - _basic_serial_radix2_FFT(a, omega); - } - else - { - _basic_parallel_radix2_FFT_inner(a, omega, log_cpus); - } -} - -template -void _multiply_by_coset(std::vector &a, const FieldT &g) -{ - //enter_block("Multiply by coset"); - FieldT u = g; - for (size_t i = 1; i < a.size(); ++i) - { - a[i] *= u; - u *= g; - } - //leave_block("Multiply by coset"); -} - -template -std::vector _basic_radix2_lagrange_coeffs(const size_t m, const FieldT &t) -{ - if (m == 1) - { - return std::vector(1, FieldT::one()); - } - - assert(m == (1u << log2(m))); - - const FieldT omega = get_root_of_unity(m); - - std::vector u(m, FieldT::zero()); - - /* - If t equals one of the roots of unity in S={omega^{0},...,omega^{m-1}} - then output 1 at the right place, and 0 elsewhere - */ - - if ((t^m) == (FieldT::one())) - { - FieldT omega_i = FieldT::one(); - for (size_t i = 0; i < m; ++i) - { - if (omega_i == t) // i.e., t equals omega^i - { - u[i] = FieldT::one(); - return u; - } - - omega_i *= omega; - } - } - - /* - Otherwise, if t does not equal any of the roots of unity in S, - then compute each L_{i,S}(t) as Z_{S}(t) * v_i / (t-\omega^i) - where: - - Z_{S}(t) = \prod_{j} (t-\omega^j) = (t^m-1), and - - v_{i} = 1 / \prod_{j \neq i} (\omega^i-\omega^j). - Below we use the fact that v_{0} = 1/m and v_{i+1} = \omega * v_{i}. - */ - - const FieldT Z = (t^m)-FieldT::one(); - FieldT l = Z * FieldT(m).inverse(); - FieldT r = FieldT::one(); - for (size_t i = 0; i < m; ++i) - { - u[i] = l * (t - r).inverse(); - l *= omega; - r *= omega; - } - - return u; -} - -} // libsnark - -#endif // BASIC_RADIX2_DOMAIN_AUX_TCC_ diff --git a/src/snark/libsnark/algebra/evaluation_domain/evaluation_domain.hpp b/src/snark/libsnark/algebra/evaluation_domain/evaluation_domain.hpp deleted file mode 100644 index d8d91ea686b..00000000000 --- a/src/snark/libsnark/algebra/evaluation_domain/evaluation_domain.hpp +++ /dev/null @@ -1,125 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for evaluation domains. - - Roughly, given a desired size m for the domain, the constructor selects - a choice of domain S with size ~m that has been selected so to optimize - - computations of Lagrange polynomials, and - - FFT/iFFT computations. - An evaluation domain also provides other functions, e.g., accessing - individual elements in S or evaluating its vanishing polynomial. - - The descriptions below make use of the definition of a *Lagrange polynomial*, - which we recall. Given a field F, a subset S=(a_i)_i of F, and an index idx - in {0,...,|S-1|}, the idx-th Lagrange polynomial (wrt to subset S) is defined to be - \f[ L_{idx,S}(z) := prod_{k \neq idx} (z - a_k) / prod_{k \neq idx} (a_{idx} - a_k) \f] - Note that, by construction: - \f[ \forall j \neq idx: L_{idx,S}(a_{idx}) = 1 \text{ and } L_{idx,S}(a_j) = 0 \f] - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef EVALUATION_DOMAIN_HPP_ -#define EVALUATION_DOMAIN_HPP_ - -#include - -namespace libsnark { - -/** - * An evaluation domain. - */ -template -class evaluation_domain { -public: - - const size_t m; - - /** - * Construct an evaluation domain S of size m, if possible. - * - * (See the function get_evaluation_domain below.) - */ - evaluation_domain(const size_t m) : m(m) {}; - - /** - * Get the idx-th element in S. - */ - virtual FieldT get_element(const size_t idx) = 0; - - /** - * Compute the FFT, over the domain S, of the vector a. - */ - virtual void FFT(std::vector &a) = 0; - - /** - * Compute the inverse FFT, over the domain S, of the vector a. - */ - virtual void iFFT(std::vector &a) = 0; - - /** - * Compute the FFT, over the domain g*S, of the vector a. - */ - virtual void cosetFFT(std::vector &a, const FieldT &g) = 0; - - /** - * Compute the inverse FFT, over the domain g*S, of the vector a. - */ - virtual void icosetFFT(std::vector &a, const FieldT &g) = 0; - - /** - * Evaluate all Lagrange polynomials. - * - * The inputs are: - * - an integer m - * - an element t - * The output is a vector (b_{0},...,b_{m-1}) - * where b_{i} is the evaluation of L_{i,S}(z) at z = t. - */ - virtual std::vector lagrange_coeffs(const FieldT &t) = 0; - - /** - * Evaluate the vanishing polynomial of S at the field element t. - */ - virtual FieldT compute_Z(const FieldT &t) = 0; - - /** - * Add the coefficients of the vanishing polynomial of S to the coefficients of the polynomial H. - */ - virtual void add_poly_Z(const FieldT &coeff, std::vector &H) = 0; - - /** - * Multiply by the evaluation, on a coset of S, of the inverse of the vanishing polynomial of S. - */ - virtual void divide_by_Z_on_coset(std::vector &P) = 0; -}; - -/** - * Return an evaluation domain object in which the domain S has size |S| >= min_size. - * The function chooses from different supported domains, depending on min_size. - */ -template -std::shared_ptr > get_evaluation_domain(const size_t min_size); - -/** - * Naive evaluation of a *single* Lagrange polynomial, used for testing purposes. - * - * The inputs are: - * - an integer m - * - a domain S = (a_{0},...,a_{m-1}) of size m - * - a field element t - * - an index idx in {0,...,m-1} - * The output is the polynomial L_{idx,S}(z) evaluated at z = t. - */ -template -FieldT lagrange_eval(const size_t m, const std::vector &domain, const FieldT &t, const size_t idx); - -} // libsnark - -#include "algebra/evaluation_domain/evaluation_domain.tcc" - -#endif // EVALUATION_DOMAIN_HPP_ diff --git a/src/snark/libsnark/algebra/evaluation_domain/evaluation_domain.tcc b/src/snark/libsnark/algebra/evaluation_domain/evaluation_domain.tcc deleted file mode 100644 index ec58ad87c11..00000000000 --- a/src/snark/libsnark/algebra/evaluation_domain/evaluation_domain.tcc +++ /dev/null @@ -1,117 +0,0 @@ -/** @file - ***************************************************************************** - - Imeplementation of interfaces for evaluation domains. - - See evaluation_domain.hpp . - - We currently implement, and select among, three types of domains: - - "basic radix-2": the domain has size m = 2^k and consists of the m-th roots of unity - - "extended radix-2": the domain has size m = 2^{k+1} and consists of "the m-th roots of unity" union "a coset" - - "step radix-2": the domain has size m = 2^k + 2^r and consists of "the 2^k-th roots of unity" union "a coset of 2^r-th roots of unity" - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef EVALUATION_DOMAIN_TCC_ -#define EVALUATION_DOMAIN_TCC_ - -#include -#include "algebra/fields/field_utils.hpp" -#include "algebra/evaluation_domain/domains/basic_radix2_domain.hpp" - -namespace libsnark { - -template -std::shared_ptr > get_evaluation_domain(const size_t min_size) -{ - assert(min_size > 1); - const size_t log_min_size = log2(min_size); - assert(log_min_size <= (FieldT::s+1)); - - std::shared_ptr > result; - if (min_size == (1u << log_min_size)) - { - if (log_min_size == FieldT::s+1) - { - if (!inhibit_profiling_info) - { - print_indent(); printf("* Selected domain: extended_radix2\n"); - } - assert(0); - } - else - { - if (!inhibit_profiling_info) - { - print_indent(); printf("* Selected domain: basic_radix2\n"); - } - result.reset(new basic_radix2_domain(min_size)); - } - } - else - { - const size_t big = UINT64_C(1)<<(log2(min_size)-1); - const size_t small = min_size - big; - const size_t rounded_small = (UINT64_C(1)<(big + rounded_small)); - } - else - { - if (!inhibit_profiling_info) - { - print_indent(); printf("* Selected domain: extended_radix2\n"); - } - assert(0); - } - } - else - { - if (!inhibit_profiling_info) - { - print_indent(); printf("* Selected domain: step_radix2\n"); - } - assert(0); - } - } - - return result; -} - -template -FieldT lagrange_eval(const size_t m, const std::vector &domain, const FieldT &t, const size_t idx) -{ - assert(m == domain.size()); - assert(idx < m); - - FieldT num = FieldT::one(); - FieldT denom = FieldT::one(); - - for (size_t k = 0; k < m; ++k) - { - if (k == idx) - { - continue; - } - - num *= t - domain[k]; - denom *= domain[idx] - domain[k]; - } - - return num * denom.inverse(); -} - -} // libsnark - -#endif // EVALUATION_DOMAIN_TCC_ diff --git a/src/snark/libsnark/algebra/exponentiation/exponentiation.hpp b/src/snark/libsnark/algebra/exponentiation/exponentiation.hpp deleted file mode 100644 index 836ebf0021e..00000000000 --- a/src/snark/libsnark/algebra/exponentiation/exponentiation.hpp +++ /dev/null @@ -1,31 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for (square-and-multiply) exponentiation. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef EXPONENTIATION_HPP_ -#define EXPONENTIATION_HPP_ - -#include - -#include "algebra/fields/bigint.hpp" - -namespace libsnark { - -template -FieldT power(const FieldT &base, const bigint &exponent); - -template -FieldT power(const FieldT &base, const uint64_t exponent); - -} // libsnark - -#include "algebra/exponentiation/exponentiation.tcc" - -#endif // EXPONENTIATION_HPP_ diff --git a/src/snark/libsnark/algebra/exponentiation/exponentiation.tcc b/src/snark/libsnark/algebra/exponentiation/exponentiation.tcc deleted file mode 100644 index 7ac3bf5d383..00000000000 --- a/src/snark/libsnark/algebra/exponentiation/exponentiation.tcc +++ /dev/null @@ -1,53 +0,0 @@ -/** @file - ***************************************************************************** - - Implementation of interfaces for (square-and-multiply) exponentiation. - - See exponentiation.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef EXPONENTIATION_TCC_ -#define EXPONENTIATION_TCC_ - -#include "common/utils.hpp" - -namespace libsnark { - -template -FieldT power(const FieldT &base, const bigint &exponent) -{ - FieldT result = FieldT::one(); - - bool found_one = false; - - for (int64_t i = exponent.max_bits() - 1; i >= 0; --i) - { - if (found_one) - { - result = result * result; - } - - if (exponent.test_bit(i)) - { - found_one = true; - result = result * base; - } - } - - return result; -} - -template -FieldT power(const FieldT &base, const uint64_t exponent) -{ - return power(base, bigint<1>(exponent)); -} - -} // libsnark - -#endif // EXPONENTIATION_TCC_ diff --git a/src/snark/libsnark/algebra/fields/bigint.hpp b/src/snark/libsnark/algebra/fields/bigint.hpp deleted file mode 100644 index d17e9a7bb5d..00000000000 --- a/src/snark/libsnark/algebra/fields/bigint.hpp +++ /dev/null @@ -1,70 +0,0 @@ -/** @file - ***************************************************************************** - Declaration of bigint wrapper class around GMP's MPZ long integers. - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef BIGINT_HPP_ -#define BIGINT_HPP_ -#include -#include -#include -#include "common/serialization.hpp" - -namespace libsnark { - -template class bigint; -template std::ostream& operator<<(std::ostream &, const bigint&); -template std::istream& operator>>(std::istream &, bigint&); - -/** - * Wrapper class around GMP's MPZ long integers. It supports arithmetic operations, - * serialization and randomization. Serialization is fragile, see common/serialization.hpp. - */ - -template -class bigint { -public: - static const mp_size_t N = n; - - mp_limb_t data[n] = {0}; - - bigint() = default; - bigint(const uint64_t x); /// Initalize from a small integer - bigint(const char* s); /// Initialize from a string containing an integer in decimal notation - bigint(const mpz_t r); /// Initialize from MPZ element - - void print() const; - void print_hex() const; - bool operator==(const bigint& other) const; - bool operator!=(const bigint& other) const; - void clear(); - bool is_zero() const; - size_t max_bits() const { return n * GMP_NUMB_BITS; } - size_t num_bits() const; - - uint64_t as_uint64() const; /* return the last limb of the integer */ - void to_mpz(mpz_t r) const; - bool test_bit(const std::size_t bitno) const; - - template inline void operator+=(const bigint& other); - template inline bigint operator*(const bigint& other) const; - template static inline void div_qr(bigint& quotient, bigint& remainder, - const bigint& dividend, const bigint& divisor); - template inline bigint shorten(const bigint& q, const char *msg) const; - - inline void limit(const bigint& q, const char *msg) const; - bool operator>(const bigint& other) const; - - bigint& randomize(); - - friend std::ostream& operator<< (std::ostream &out, const bigint &b); - friend std::istream& operator>> (std::istream &in, bigint &b); -}; - -} // libsnark -#include "algebra/fields/bigint.tcc" -#endif diff --git a/src/snark/libsnark/algebra/fields/bigint.tcc b/src/snark/libsnark/algebra/fields/bigint.tcc deleted file mode 100644 index 7a59233d48f..00000000000 --- a/src/snark/libsnark/algebra/fields/bigint.tcc +++ /dev/null @@ -1,279 +0,0 @@ -/** @file - ***************************************************************************** - Implementation of bigint wrapper class around GMP's MPZ long integers. - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef BIGINT_TCC_ -#define BIGINT_TCC_ -#include -#include -#include -#include "sodium.h" - -namespace libsnark { - -template -bigint::bigint(const uint64_t x) /// Initialize from a small integer -{ - static_assert(UINT64_MAX <= GMP_NUMB_MAX, "uint64_t does not fit in a GMP limb"); - this->data[0] = x; -} - -template -bigint::bigint(const char* s) /// Initialize from a string containing an integer in decimal notation -{ - size_t l = strlen(s); - unsigned char* s_copy = new unsigned char[l]; - - for (size_t i = 0; i < l; ++i) - { - assert(s[i] >= '0' && s[i] <= '9'); - s_copy[i] = s[i] - '0'; - } - - mp_size_t limbs_written = mpn_set_str(this->data, s_copy, l, 10); - assert(limbs_written <= n); - - delete[] s_copy; -} - -template -bigint::bigint(const mpz_t r) /// Initialize from MPZ element -{ - mpz_t k; - mpz_init_set(k, r); - - for (size_t i = 0; i < n; ++i) - { - data[i] = mpz_get_ui(k); - mpz_fdiv_q_2exp(k, k, GMP_NUMB_BITS); - } - - assert(mpz_sgn(k) == 0); - mpz_clear(k); -} - -template -void bigint::print() const -{ - gmp_printf("%Nd\n", this->data, n); -} - -template -void bigint::print_hex() const -{ - gmp_printf("%Nx\n", this->data, n); -} - -template -bool bigint::operator==(const bigint& other) const -{ - return (mpn_cmp(this->data, other.data, n) == 0); -} - -template -bool bigint::operator!=(const bigint& other) const -{ - return !(operator==(other)); -} - -template -void bigint::clear() -{ - mpn_zero(this->data, n); -} - -template -bool bigint::is_zero() const -{ - for (mp_size_t i = 0; i < n; ++i) - { - if (this->data[i]) - { - return false; - } - } - - return true; -} - -template -size_t bigint::num_bits() const -{ -/* - for (int64_t i = max_bits(); i >= 0; --i) - { - if (this->test_bit(i)) - { - return i+1; - } - } - - return 0; -*/ - for (int64_t i = n-1; i >= 0; --i) - { - mp_limb_t x = this->data[i]; - if (x == 0) - { - continue; - } - else - { - static_assert(GMP_NUMB_MAX <= ULLONG_MAX, "coercing limb to unsigned long long might truncate"); - return ((i+1) * GMP_NUMB_BITS) - __builtin_clzll(x); - } - } - return 0; -} - -template -uint64_t bigint::as_uint64() const -{ - return this->data[0]; -} - -template -void bigint::to_mpz(mpz_t r) const -{ - mpz_set_ui(r, 0); - - for (int i = n-1; i >= 0; --i) - { - mpz_mul_2exp(r, r, GMP_NUMB_BITS); - mpz_add_ui(r, r, this->data[i]); - } -} - -template -bool bigint::test_bit(const std::size_t bitno) const -{ - if (bitno >= n * GMP_NUMB_BITS) - { - return false; - } - else - { - const std::size_t part = bitno/GMP_NUMB_BITS; - const std::size_t bit = bitno - (GMP_NUMB_BITS*part); - const mp_limb_t one = 1; - return (this->data[part] & (one< template -inline void bigint::operator+=(const bigint& other) -{ - static_assert(n >= m, "first arg must not be smaller than second arg for bigint in-place add"); - mpn_add(data, data, n, other.data, m); -} - -template template -inline bigint bigint::operator*(const bigint& other) const -{ - static_assert(n >= m, "first arg must not be smaller than second arg for bigint mul"); - bigint res; - mpn_mul(res.data, data, n, other.data, m); - return res; -} - -template template -inline void bigint::div_qr(bigint& quotient, bigint& remainder, - const bigint& dividend, const bigint& divisor) -{ - static_assert(n >= d, "dividend must not be smaller than divisor for bigint::div_qr"); - assert(divisor.data[d-1] != 0); - mpn_tdiv_qr(quotient.data, remainder.data, 0, dividend.data, n, divisor.data, d); -} - -// Return a copy shortened to m limbs provided it is less than limit, throwing std::domain_error if not in range. -template template -inline bigint bigint::shorten(const bigint& q, const char *msg) const -{ - static_assert(m <= n, "number of limbs must not increase for bigint::shorten"); - for (mp_size_t i = m; i < n; i++) { // high-order limbs - if (data[i] != 0) { - throw std::domain_error(msg); - } - } - bigint res; - mpn_copyi(res.data, data, m); - res.limit(q, msg); - return res; -} - -template -inline void bigint::limit(const bigint& q, const char *msg) const -{ - if (!(q > *this)) { - throw std::domain_error(msg); - } -} - -template -inline bool bigint::operator>(const bigint& other) const -{ - return mpn_cmp(this->data, other.data, n) > 0; -} - -template -bigint& bigint::randomize() -{ - assert(GMP_NUMB_BITS == sizeof(mp_limb_t) * 8); - - randombytes_buf(this->data, sizeof(mp_limb_t) * n); - - return (*this); -} - - -template -std::ostream& operator<<(std::ostream &out, const bigint &b) -{ -#ifdef BINARY_OUTPUT - out.write((char*)b.data, sizeof(b.data[0]) * n); -#else - mpz_t t; - mpz_init(t); - b.to_mpz(t); - - out << t; - - mpz_clear(t); -#endif - return out; -} - -template -std::istream& operator>>(std::istream &in, bigint &b) -{ -#ifdef BINARY_OUTPUT - in.read((char*)b.data, sizeof(b.data[0]) * n); -#else - std::string s; - in >> s; - - size_t l = s.size(); - unsigned char* s_copy = new unsigned char[l]; - - for (size_t i = 0; i < l; ++i) - { - assert(s[i] >= '0' && s[i] <= '9'); - s_copy[i] = s[i] - '0'; - } - - mp_size_t limbs_written = mpn_set_str(b.data, s_copy, l, 10); - assert(limbs_written <= n); - - delete[] s_copy; -#endif - return in; -} - -} // libsnark -#endif // BIGINT_TCC_ diff --git a/src/snark/libsnark/algebra/fields/field_utils.hpp b/src/snark/libsnark/algebra/fields/field_utils.hpp deleted file mode 100644 index a07ecfe284e..00000000000 --- a/src/snark/libsnark/algebra/fields/field_utils.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef FIELD_UTILS_HPP_ -#define FIELD_UTILS_HPP_ -#include - -#include "common/utils.hpp" -#include "algebra/fields/bigint.hpp" - -namespace libsnark { - -// returns root of unity of order n (for n a power of 2), if one exists -template -FieldT get_root_of_unity(const size_t n); - -template -std::vector pack_int_vector_into_field_element_vector(const std::vector &v, const size_t w); - -template -std::vector pack_bit_vector_into_field_element_vector(const bit_vector &v, const size_t chunk_bits); - -template -std::vector pack_bit_vector_into_field_element_vector(const bit_vector &v); - -template -std::vector convert_bit_vector_to_field_element_vector(const bit_vector &v); - -template -bit_vector convert_field_element_vector_to_bit_vector(const std::vector &v); - -template -bit_vector convert_field_element_to_bit_vector(const FieldT &el); - -template -bit_vector convert_field_element_to_bit_vector(const FieldT &el, const size_t bitcount); - -template -FieldT convert_bit_vector_to_field_element(const bit_vector &v); - -template -void batch_invert(std::vector &vec); - -} // libsnark -#include "algebra/fields/field_utils.tcc" - -#endif // FIELD_UTILS_HPP_ diff --git a/src/snark/libsnark/algebra/fields/field_utils.tcc b/src/snark/libsnark/algebra/fields/field_utils.tcc deleted file mode 100644 index 66b53234560..00000000000 --- a/src/snark/libsnark/algebra/fields/field_utils.tcc +++ /dev/null @@ -1,183 +0,0 @@ -/** @file - ***************************************************************************** - Implementation of misc. math and serialization utility functions - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef FIELD_UTILS_TCC_ -#define FIELD_UTILS_TCC_ - -#include "common/utils.hpp" - -namespace libsnark { - -template -FieldT coset_shift() -{ - return FieldT::multiplicative_generator.squared(); -} - -template -FieldT get_root_of_unity(const size_t n) -{ - const size_t logn = log2(n); - assert(n == (1u << logn)); - assert(logn <= FieldT::s); - - FieldT omega = FieldT::root_of_unity; - for (size_t i = FieldT::s; i > logn; --i) - { - omega *= omega; - } - - return omega; -} - -template -std::vector pack_int_vector_into_field_element_vector(const std::vector &v, const size_t w) -{ - const size_t chunk_bits = FieldT::capacity(); - const size_t repacked_size = div_ceil(v.size() * w, chunk_bits); - std::vector result(repacked_size); - - for (size_t i = 0; i < repacked_size; ++i) - { - bigint b; - for (size_t j = 0; j < chunk_bits; ++j) - { - const size_t word_index = (i * chunk_bits + j) / w; - const size_t pos_in_word = (i * chunk_bits + j) % w; - const size_t word_or_0 = (word_index < v.size() ? v[word_index] : 0); - const size_t bit = (word_or_0 >> pos_in_word) & 1; - - b.data[j / GMP_NUMB_BITS] |= bit << (j % GMP_NUMB_BITS); - } - result[i] = FieldT(b); - } - - return result; -} - -template -std::vector pack_bit_vector_into_field_element_vector(const bit_vector &v, const size_t chunk_bits) -{ - assert(chunk_bits <= FieldT::capacity()); - - const size_t repacked_size = div_ceil(v.size(), chunk_bits); - std::vector result(repacked_size); - - for (size_t i = 0; i < repacked_size; ++i) - { - bigint b; - for (size_t j = 0; j < chunk_bits; ++j) - { - b.data[j / GMP_NUMB_BITS] |= ((i * chunk_bits + j) < v.size() && v[i * chunk_bits + j] ? 1ll : 0ll) << (j % GMP_NUMB_BITS); - } - result[i] = FieldT(b); - } - - return result; -} - -template -std::vector pack_bit_vector_into_field_element_vector(const bit_vector &v) -{ - return pack_bit_vector_into_field_element_vector(v, FieldT::capacity()); -} - -template -std::vector convert_bit_vector_to_field_element_vector(const bit_vector &v) -{ - std::vector result; - result.reserve(v.size()); - - for (const bool b : v) - { - result.emplace_back(b ? FieldT::one() : FieldT::zero()); - } - - return result; -} - -template -bit_vector convert_field_element_vector_to_bit_vector(const std::vector &v) -{ - bit_vector result; - - for (const FieldT &el : v) - { - const bit_vector el_bits = convert_field_element_to_bit_vector(el); - result.insert(result.end(), el_bits.begin(), el_bits.end()); - } - - return result; -} - -template -bit_vector convert_field_element_to_bit_vector(const FieldT &el) -{ - bit_vector result; - - bigint b = el.as_bigint(); - for (size_t i = 0; i < FieldT::size_in_bits(); ++i) - { - result.push_back(b.test_bit(i)); - } - - return result; -} - -template -bit_vector convert_field_element_to_bit_vector(const FieldT &el, const size_t bitcount) -{ - bit_vector result = convert_field_element_to_bit_vector(el); - result.resize(bitcount); - - return result; -} - -template -FieldT convert_bit_vector_to_field_element(const bit_vector &v) -{ - assert(v.size() <= FieldT::size_in_bits()); - - FieldT res = FieldT::zero(); - FieldT c = FieldT::one(); - for (bool b : v) - { - res += b ? c : FieldT::zero(); - c += c; - } - return res; -} - -template -void batch_invert(std::vector &vec) -{ - std::vector prod; - prod.reserve(vec.size()); - - FieldT acc = FieldT::one(); - - for (auto el : vec) - { - assert(!el.is_zero()); - prod.emplace_back(acc); - acc = acc * el; - } - - FieldT acc_inverse = acc.inverse(); - - for (int64_t i = vec.size()-1; i >= 0; --i) - { - const FieldT old_el = vec[i]; - vec[i] = acc_inverse * prod[i]; - acc_inverse = acc_inverse * old_el; - } -} - -} // libsnark -#endif // FIELD_UTILS_TCC_ diff --git a/src/snark/libsnark/algebra/fields/fp.hpp b/src/snark/libsnark/algebra/fields/fp.hpp deleted file mode 100644 index af9eb0b9a42..00000000000 --- a/src/snark/libsnark/algebra/fields/fp.hpp +++ /dev/null @@ -1,182 +0,0 @@ -/** @file - ***************************************************************************** - Declaration of arithmetic in the finite field F[p], for prime p of fixed length. - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef FP_HPP_ -#define FP_HPP_ - -#include "algebra/fields/bigint.hpp" -#include "algebra/exponentiation/exponentiation.hpp" - -namespace libsnark { - -template& modulus> -class Fp_model; - -template& modulus> -std::ostream& operator<<(std::ostream &, const Fp_model&); - -template& modulus> -std::istream& operator>>(std::istream &, Fp_model &); - -/** - * Arithmetic in the finite field F[p], for prime p of fixed length. - * - * This class implements Fp-arithmetic, for a large prime p, using a fixed number - * of words. It is optimized for tight memory consumption, so the modulus p is - * passed as a template parameter, to avoid per-element overheads. - * - * The implementation is mostly a wrapper around GMP's MPN (constant-size integers). - * But for the integer sizes of interest for libsnark (3 to 5 limbs of 64 bits each), - * we implement performance-critical routines, like addition and multiplication, - * using hand-optimized assembly code. -*/ -template& modulus> -class Fp_model { -public: - bigint mont_repr; -public: - static const mp_size_t num_limbs = n; - static const constexpr bigint& mod = modulus; -#ifdef PROFILE_OP_COUNTS - static int64_t add_cnt; - static int64_t sub_cnt; - static int64_t mul_cnt; - static int64_t sqr_cnt; - static int64_t inv_cnt; -#endif - static size_t num_bits; - static bigint euler; // (modulus-1)/2 - static size_t s; // modulus = 2^s * t + 1 - static bigint t; // with t odd - static bigint t_minus_1_over_2; // (t-1)/2 - static Fp_model nqr; // a quadratic nonresidue - static Fp_model nqr_to_t; // nqr^t - static Fp_model multiplicative_generator; // generator of Fp^* - static Fp_model root_of_unity; // generator^((modulus-1)/2^s) - static mp_limb_t inv; // modulus^(-1) mod W, where W = 2^(word size) - static bigint Rsquared; // R^2, where R = W^k, where k = ?? - static bigint Rcubed; // R^3 - - static bool modulus_is_valid() { return modulus.data[n-1] != 0; } // mpn inverse assumes that highest limb is non-zero - - Fp_model() {}; - Fp_model(const bigint &b); - Fp_model(const int64_t x, const bool is_unsigned=false); - - void set_uint64(const uint64_t x); - - void mul_reduce(const bigint &other); - - void clear(); - - /* Return the standard (not Montgomery) representation of the - Field element's requivalence class. I.e. Fp(2).as_bigint() - would return bigint(2) */ - bigint as_bigint() const; - /* Return the last limb of the standard representation of the - field element. E.g. on 64-bit architectures Fp(123).as_uint64() - and Fp(2^64+123).as_uint64() would both return 123. */ - uint64_t as_uint64() const; - - bool operator==(const Fp_model& other) const; - bool operator!=(const Fp_model& other) const; - bool is_zero() const; - - void print() const; - - Fp_model& operator+=(const Fp_model& other); - Fp_model& operator-=(const Fp_model& other); - Fp_model& operator*=(const Fp_model& other); - Fp_model& operator^=(const uint64_t pow); - - template - Fp_model& operator^=(const bigint &pow); - - Fp_model operator+(const Fp_model& other) const; - Fp_model operator-(const Fp_model& other) const; - Fp_model operator*(const Fp_model& other) const; - Fp_model operator-() const; - Fp_model squared() const; - Fp_model& invert(); - Fp_model inverse() const; - Fp_model sqrt() const; // HAS TO BE A SQUARE (else does not terminate) - - Fp_model operator^(const uint64_t pow) const; - template - Fp_model operator^(const bigint &pow) const; - - static size_t size_in_bits() { return num_bits; } - static size_t capacity() { return num_bits - 1; } - static bigint field_char() { return modulus; } - - static Fp_model zero(); - static Fp_model one(); - static Fp_model random_element(); - - friend std::ostream& operator<< (std::ostream &out, const Fp_model &p); - friend std::istream& operator>> (std::istream &in, Fp_model &p); -}; - -#ifdef PROFILE_OP_COUNTS -template& modulus> -int64_t Fp_model::add_cnt = 0; - -template& modulus> -int64_t Fp_model::sub_cnt = 0; - -template& modulus> -int64_t Fp_model::mul_cnt = 0; - -template& modulus> -int64_t Fp_model::sqr_cnt = 0; - -template& modulus> -int64_t Fp_model::inv_cnt = 0; -#endif - -template& modulus> -size_t Fp_model::num_bits; - -template& modulus> -bigint Fp_model::euler; - -template& modulus> -size_t Fp_model::s; - -template& modulus> -bigint Fp_model::t; - -template& modulus> -bigint Fp_model::t_minus_1_over_2; - -template& modulus> -Fp_model Fp_model::nqr; - -template& modulus> -Fp_model Fp_model::nqr_to_t; - -template& modulus> -Fp_model Fp_model::multiplicative_generator; - -template& modulus> -Fp_model Fp_model::root_of_unity; - -template& modulus> -mp_limb_t Fp_model::inv; - -template& modulus> -bigint Fp_model::Rsquared; - -template& modulus> -bigint Fp_model::Rcubed; - -} // libsnark -#include "algebra/fields/fp.tcc" - -#endif // FP_HPP_ diff --git a/src/snark/libsnark/algebra/fields/fp.tcc b/src/snark/libsnark/algebra/fields/fp.tcc deleted file mode 100644 index 02baf6274c3..00000000000 --- a/src/snark/libsnark/algebra/fields/fp.tcc +++ /dev/null @@ -1,790 +0,0 @@ -/** @file - ***************************************************************************** - Implementation of arithmetic in the finite field F[p], for prime p of fixed length. - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef FP_TCC_ -#define FP_TCC_ -#include -#include -#include - -#include "algebra/fields/fp_aux.tcc" -#include "algebra/fields/field_utils.hpp" -#include "common/assert_except.hpp" - -namespace libsnark { - -template& modulus> -void Fp_model::mul_reduce(const bigint &other) -{ - /* stupid pre-processor tricks; beware */ -#if defined(__x86_64__) && defined(USE_ASM) - if (n == 3) - { // Use asm-optimized Comba multiplication and reduction - mp_limb_t res[2*n]; - mp_limb_t c0, c1, c2; - COMBA_3_BY_3_MUL(c0, c1, c2, res, this->mont_repr.data, other.data); - - mp_limb_t k; - mp_limb_t tmp1, tmp2, tmp3; - REDUCE_6_LIMB_PRODUCT(k, tmp1, tmp2, tmp3, inv, res, modulus.data); - - /* subtract t > mod */ - __asm__ - ("/* check for overflow */ \n\t" - MONT_CMP(16) - MONT_CMP(8) - MONT_CMP(0) - - "/* subtract mod if overflow */ \n\t" - "subtract%=: \n\t" - MONT_FIRSTSUB - MONT_NEXTSUB(8) - MONT_NEXTSUB(16) - "done%=: \n\t" - : - : [tmp] "r" (res+n), [M] "r" (modulus.data) - : "cc", "memory", "%rax"); - mpn_copyi(this->mont_repr.data, res+n, n); - } - else if (n == 4) - { // use asm-optimized "CIOS method" - - mp_limb_t tmp[n+1]; - mp_limb_t T0=0, T1=1, cy=2, u=3; // TODO: fix this - - __asm__ (MONT_PRECOMPUTE - MONT_FIRSTITER(1) - MONT_FIRSTITER(2) - MONT_FIRSTITER(3) - MONT_FINALIZE(3) - MONT_ITERFIRST(1) - MONT_ITERITER(1, 1) - MONT_ITERITER(1, 2) - MONT_ITERITER(1, 3) - MONT_FINALIZE(3) - MONT_ITERFIRST(2) - MONT_ITERITER(2, 1) - MONT_ITERITER(2, 2) - MONT_ITERITER(2, 3) - MONT_FINALIZE(3) - MONT_ITERFIRST(3) - MONT_ITERITER(3, 1) - MONT_ITERITER(3, 2) - MONT_ITERITER(3, 3) - MONT_FINALIZE(3) - "/* check for overflow */ \n\t" - MONT_CMP(24) - MONT_CMP(16) - MONT_CMP(8) - MONT_CMP(0) - - "/* subtract mod if overflow */ \n\t" - "subtract%=: \n\t" - MONT_FIRSTSUB - MONT_NEXTSUB(8) - MONT_NEXTSUB(16) - MONT_NEXTSUB(24) - "done%=: \n\t" - : - : [tmp] "r" (tmp), [A] "r" (this->mont_repr.data), [B] "r" (other.data), [inv] "r" (inv), [M] "r" (modulus.data), - [T0] "r" (T0), [T1] "r" (T1), [cy] "r" (cy), [u] "r" (u) - : "cc", "memory", "%rax", "%rdx" - ); - mpn_copyi(this->mont_repr.data, tmp, n); - } - else if (n == 5) - { // use asm-optimized "CIOS method" - - mp_limb_t tmp[n+1]; - mp_limb_t T0=0, T1=1, cy=2, u=3; // TODO: fix this - - __asm__ (MONT_PRECOMPUTE - MONT_FIRSTITER(1) - MONT_FIRSTITER(2) - MONT_FIRSTITER(3) - MONT_FIRSTITER(4) - MONT_FINALIZE(4) - MONT_ITERFIRST(1) - MONT_ITERITER(1, 1) - MONT_ITERITER(1, 2) - MONT_ITERITER(1, 3) - MONT_ITERITER(1, 4) - MONT_FINALIZE(4) - MONT_ITERFIRST(2) - MONT_ITERITER(2, 1) - MONT_ITERITER(2, 2) - MONT_ITERITER(2, 3) - MONT_ITERITER(2, 4) - MONT_FINALIZE(4) - MONT_ITERFIRST(3) - MONT_ITERITER(3, 1) - MONT_ITERITER(3, 2) - MONT_ITERITER(3, 3) - MONT_ITERITER(3, 4) - MONT_FINALIZE(4) - MONT_ITERFIRST(4) - MONT_ITERITER(4, 1) - MONT_ITERITER(4, 2) - MONT_ITERITER(4, 3) - MONT_ITERITER(4, 4) - MONT_FINALIZE(4) - "/* check for overflow */ \n\t" - MONT_CMP(32) - MONT_CMP(24) - MONT_CMP(16) - MONT_CMP(8) - MONT_CMP(0) - - "/* subtract mod if overflow */ \n\t" - "subtract%=: \n\t" - MONT_FIRSTSUB - MONT_NEXTSUB(8) - MONT_NEXTSUB(16) - MONT_NEXTSUB(24) - MONT_NEXTSUB(32) - "done%=: \n\t" - : - : [tmp] "r" (tmp), [A] "r" (this->mont_repr.data), [B] "r" (other.data), [inv] "r" (inv), [M] "r" (modulus.data), - [T0] "r" (T0), [T1] "r" (T1), [cy] "r" (cy), [u] "r" (u) - : "cc", "memory", "%rax", "%rdx" - ); - mpn_copyi(this->mont_repr.data, tmp, n); - } - else -#endif - { - mp_limb_t res[2*n]; - mpn_mul_n(res, this->mont_repr.data, other.data, n); - - /* - The Montgomery reduction here is based on Algorithm 14.32 in - Handbook of Applied Cryptography - . - */ - for (size_t i = 0; i < n; ++i) - { - mp_limb_t k = inv * res[i]; - /* calculate res = res + k * mod * b^i */ - mp_limb_t carryout = mpn_addmul_1(res+i, modulus.data, n, k); - carryout = mpn_add_1(res+n+i, res+n+i, n-i, carryout); - assert(carryout == 0); - } - - if (mpn_cmp(res+n, modulus.data, n) >= 0) - { - const mp_limb_t borrow = mpn_sub(res+n, res+n, n, modulus.data, n); - assert(borrow == 0); - } - - mpn_copyi(this->mont_repr.data, res+n, n); - } -} - -template& modulus> -Fp_model::Fp_model(const bigint &b) -{ - mpn_copyi(this->mont_repr.data, Rsquared.data, n); - mul_reduce(b); -} - -template& modulus> -Fp_model::Fp_model(const int64_t x, const bool is_unsigned) -{ - if (is_unsigned || x >= 0) - { - this->mont_repr.data[0] = x; - } - else - { - const mp_limb_t borrow = mpn_sub_1(this->mont_repr.data, modulus.data, n, -x); - assert(borrow == 0); - } - - mul_reduce(Rsquared); -} - -template& modulus> -void Fp_model::set_uint64(const uint64_t x) -{ - this->mont_repr.clear(); - this->mont_repr.data[0] = x; - mul_reduce(Rsquared); -} - -template& modulus> -void Fp_model::clear() -{ - this->mont_repr.clear(); -} - -template& modulus> -bigint Fp_model::as_bigint() const -{ - bigint one; - one.clear(); - one.data[0] = 1; - - Fp_model res(*this); - res.mul_reduce(one); - - return (res.mont_repr); -} - -template& modulus> -uint64_t Fp_model::as_uint64() const -{ - return this->as_bigint().as_uint64(); -} - -template& modulus> -bool Fp_model::operator==(const Fp_model& other) const -{ - return (this->mont_repr == other.mont_repr); -} - -template& modulus> -bool Fp_model::operator!=(const Fp_model& other) const -{ - return (this->mont_repr != other.mont_repr); -} - -template& modulus> -bool Fp_model::is_zero() const -{ - return (this->mont_repr.is_zero()); // zero maps to zero -} - -template& modulus> -void Fp_model::print() const -{ - Fp_model tmp; - tmp.mont_repr.data[0] = 1; - tmp.mul_reduce(this->mont_repr); - - tmp.mont_repr.print(); -} - -template& modulus> -Fp_model Fp_model::zero() -{ - Fp_model res; - res.mont_repr.clear(); - return res; -} - -template& modulus> -Fp_model Fp_model::one() -{ - Fp_model res; - res.mont_repr.data[0] = 1; - res.mul_reduce(Rsquared); - return res; -} - -template& modulus> -Fp_model& Fp_model::operator+=(const Fp_model& other) -{ -#ifdef PROFILE_OP_COUNTS - this->add_cnt++; -#endif -#if defined(__x86_64__) && defined(USE_ASM) - if (n == 3) - { - __asm__ - ("/* perform bignum addition */ \n\t" - ADD_FIRSTADD - ADD_NEXTADD(8) - ADD_NEXTADD(16) - "/* if overflow: subtract */ \n\t" - "/* (tricky point: if A and B are in the range we do not need to do anything special for the possible carry flag) */ \n\t" - "jc subtract%= \n\t" - - "/* check for overflow */ \n\t" - ADD_CMP(16) - ADD_CMP(8) - ADD_CMP(0) - - "/* subtract mod if overflow */ \n\t" - "subtract%=: \n\t" - ADD_FIRSTSUB - ADD_NEXTSUB(8) - ADD_NEXTSUB(16) - "done%=: \n\t" - : - : [A] "r" (this->mont_repr.data), [B] "r" (other.mont_repr.data), [mod] "r" (modulus.data) - : "cc", "memory", "%rax"); - } - else if (n == 4) - { - __asm__ - ("/* perform bignum addition */ \n\t" - ADD_FIRSTADD - ADD_NEXTADD(8) - ADD_NEXTADD(16) - ADD_NEXTADD(24) - "/* if overflow: subtract */ \n\t" - "/* (tricky point: if A and B are in the range we do not need to do anything special for the possible carry flag) */ \n\t" - "jc subtract%= \n\t" - - "/* check for overflow */ \n\t" - ADD_CMP(24) - ADD_CMP(16) - ADD_CMP(8) - ADD_CMP(0) - - "/* subtract mod if overflow */ \n\t" - "subtract%=: \n\t" - ADD_FIRSTSUB - ADD_NEXTSUB(8) - ADD_NEXTSUB(16) - ADD_NEXTSUB(24) - "done%=: \n\t" - : - : [A] "r" (this->mont_repr.data), [B] "r" (other.mont_repr.data), [mod] "r" (modulus.data) - : "cc", "memory", "%rax"); - } - else if (n == 5) - { - __asm__ - ("/* perform bignum addition */ \n\t" - ADD_FIRSTADD - ADD_NEXTADD(8) - ADD_NEXTADD(16) - ADD_NEXTADD(24) - ADD_NEXTADD(32) - "/* if overflow: subtract */ \n\t" - "/* (tricky point: if A and B are in the range we do not need to do anything special for the possible carry flag) */ \n\t" - "jc subtract%= \n\t" - - "/* check for overflow */ \n\t" - ADD_CMP(32) - ADD_CMP(24) - ADD_CMP(16) - ADD_CMP(8) - ADD_CMP(0) - - "/* subtract mod if overflow */ \n\t" - "subtract%=: \n\t" - ADD_FIRSTSUB - ADD_NEXTSUB(8) - ADD_NEXTSUB(16) - ADD_NEXTSUB(24) - ADD_NEXTSUB(32) - "done%=: \n\t" - : - : [A] "r" (this->mont_repr.data), [B] "r" (other.mont_repr.data), [mod] "r" (modulus.data) - : "cc", "memory", "%rax"); - } - else -#endif - { - mp_limb_t scratch[n+1]; - const mp_limb_t carry = mpn_add_n(scratch, this->mont_repr.data, other.mont_repr.data, n); - scratch[n] = carry; - - if (carry || mpn_cmp(scratch, modulus.data, n) >= 0) - { - const mp_limb_t borrow = mpn_sub(scratch, scratch, n+1, modulus.data, n); - assert(borrow == 0); - } - - mpn_copyi(this->mont_repr.data, scratch, n); - } - - return *this; -} - -template& modulus> -Fp_model& Fp_model::operator-=(const Fp_model& other) -{ -#ifdef PROFILE_OP_COUNTS - this->sub_cnt++; -#endif -#if defined(__x86_64__) && defined(USE_ASM) - if (n == 3) - { - __asm__ - (SUB_FIRSTSUB - SUB_NEXTSUB(8) - SUB_NEXTSUB(16) - - "jnc done%=\n\t" - - SUB_FIRSTADD - SUB_NEXTADD(8) - SUB_NEXTADD(16) - - "done%=:\n\t" - : - : [A] "r" (this->mont_repr.data), [B] "r" (other.mont_repr.data), [mod] "r" (modulus.data) - : "cc", "memory", "%rax"); - } - else if (n == 4) - { - __asm__ - (SUB_FIRSTSUB - SUB_NEXTSUB(8) - SUB_NEXTSUB(16) - SUB_NEXTSUB(24) - - "jnc done%=\n\t" - - SUB_FIRSTADD - SUB_NEXTADD(8) - SUB_NEXTADD(16) - SUB_NEXTADD(24) - - "done%=:\n\t" - : - : [A] "r" (this->mont_repr.data), [B] "r" (other.mont_repr.data), [mod] "r" (modulus.data) - : "cc", "memory", "%rax"); - } - else if (n == 5) - { - __asm__ - (SUB_FIRSTSUB - SUB_NEXTSUB(8) - SUB_NEXTSUB(16) - SUB_NEXTSUB(24) - SUB_NEXTSUB(32) - - "jnc done%=\n\t" - - SUB_FIRSTADD - SUB_NEXTADD(8) - SUB_NEXTADD(16) - SUB_NEXTADD(24) - SUB_NEXTADD(32) - - "done%=:\n\t" - : - : [A] "r" (this->mont_repr.data), [B] "r" (other.mont_repr.data), [mod] "r" (modulus.data) - : "cc", "memory", "%rax"); - } - else -#endif - { - mp_limb_t scratch[n+1]; - if (mpn_cmp(this->mont_repr.data, other.mont_repr.data, n) < 0) - { - const mp_limb_t carry = mpn_add_n(scratch, this->mont_repr.data, modulus.data, n); - scratch[n] = carry; - } - else - { - mpn_copyi(scratch, this->mont_repr.data, n); - scratch[n] = 0; - } - - const mp_limb_t borrow = mpn_sub(scratch, scratch, n+1, other.mont_repr.data, n); - assert(borrow == 0); - - mpn_copyi(this->mont_repr.data, scratch, n); - } - return *this; -} - -template& modulus> -Fp_model& Fp_model::operator*=(const Fp_model& other) -{ -#ifdef PROFILE_OP_COUNTS - this->mul_cnt++; -#endif - - mul_reduce(other.mont_repr); - return *this; -} - -template& modulus> -Fp_model& Fp_model::operator^=(const uint64_t pow) -{ - (*this) = power >(*this, pow); - return (*this); -} - -template& modulus> -template -Fp_model& Fp_model::operator^=(const bigint &pow) -{ - (*this) = power, m>(*this, pow); - return (*this); -} - -template& modulus> -Fp_model Fp_model::operator+(const Fp_model& other) const -{ - Fp_model r(*this); - return (r += other); -} - -template& modulus> -Fp_model Fp_model::operator-(const Fp_model& other) const -{ - Fp_model r(*this); - return (r -= other); -} - -template& modulus> -Fp_model Fp_model::operator*(const Fp_model& other) const -{ - Fp_model r(*this); - return (r *= other); -} - -template& modulus> -Fp_model Fp_model::operator^(const uint64_t pow) const -{ - Fp_model r(*this); - return (r ^= pow); -} - -template& modulus> -template -Fp_model Fp_model::operator^(const bigint &pow) const -{ - Fp_model r(*this); - return (r ^= pow); -} - -template& modulus> -Fp_model Fp_model::operator-() const -{ -#ifdef PROFILE_OP_COUNTS - this->sub_cnt++; -#endif - - if (this->is_zero()) - { - return (*this); - } - else - { - Fp_model r; - mpn_sub_n(r.mont_repr.data, modulus.data, this->mont_repr.data, n); - return r; - } -} - -template& modulus> -Fp_model Fp_model::squared() const -{ -#ifdef PROFILE_OP_COUNTS - this->sqr_cnt++; - this->mul_cnt--; // zero out the upcoming mul -#endif - /* stupid pre-processor tricks; beware */ -#if defined(__x86_64__) && defined(USE_ASM) - if (n == 3) - { // use asm-optimized Comba squaring - mp_limb_t res[2*n]; - mp_limb_t c0, c1, c2; - COMBA_3_BY_3_SQR(c0, c1, c2, res, this->mont_repr.data); - - mp_limb_t k; - mp_limb_t tmp1, tmp2, tmp3; - REDUCE_6_LIMB_PRODUCT(k, tmp1, tmp2, tmp3, inv, res, modulus.data); - - /* subtract t > mod */ - __asm__ volatile - ("/* check for overflow */ \n\t" - MONT_CMP(16) - MONT_CMP(8) - MONT_CMP(0) - - "/* subtract mod if overflow */ \n\t" - "subtract%=: \n\t" - MONT_FIRSTSUB - MONT_NEXTSUB(8) - MONT_NEXTSUB(16) - "done%=: \n\t" - : - : [tmp] "r" (res+n), [M] "r" (modulus.data) - : "cc", "memory", "%rax"); - - Fp_model r; - mpn_copyi(r.mont_repr.data, res+n, n); - return r; - } - else -#endif - { - Fp_model r(*this); - return (r *= r); - } -} - -template& modulus> -Fp_model& Fp_model::invert() -{ -#ifdef PROFILE_OP_COUNTS - this->inv_cnt++; -#endif - - assert(!this->is_zero()); - - bigint g; /* gp should have room for vn = n limbs */ - - mp_limb_t s[n+1]; /* sp should have room for vn+1 limbs */ - mp_size_t sn; - - bigint v = modulus; // both source operands are destroyed by mpn_gcdext - - /* computes gcd(u, v) = g = u*s + v*t, so s*u will be 1 (mod v) */ - const mp_size_t gn = mpn_gcdext(g.data, s, &sn, this->mont_repr.data, n, v.data, n); - assert(gn == 1 && g.data[0] == 1); /* inverse exists */ - - mp_limb_t q; /* division result fits into q, as sn <= n+1 */ - /* sn < 0 indicates negative sn; will fix up later */ - - if (std::abs(sn) >= n) - { - /* if sn could require modulus reduction, do it here */ - mpn_tdiv_qr(&q, this->mont_repr.data, 0, s, std::abs(sn), modulus.data, n); - } - else - { - /* otherwise just copy it over */ - mpn_zero(this->mont_repr.data, n); - mpn_copyi(this->mont_repr.data, s, std::abs(sn)); - } - - /* fix up the negative sn */ - if (sn < 0) - { - const mp_limb_t borrow = mpn_sub_n(this->mont_repr.data, modulus.data, this->mont_repr.data, n); - assert(borrow == 0); - } - - mul_reduce(Rcubed); - return *this; -} - -template& modulus> -Fp_model Fp_model::inverse() const -{ - Fp_model r(*this); - return (r.invert()); -} - -template& modulus> -Fp_model Fp_model::random_element() /// returns random element of Fp_model -{ - /* note that as Montgomery representation is a bijection then - selecting a random element of {xR} is the same as selecting a - random element of {x} */ - Fp_model r; - do - { - r.mont_repr.randomize(); - - /* clear all bits higher than MSB of modulus */ - size_t bitno = GMP_NUMB_BITS * n - 1; - while (modulus.test_bit(bitno) == false) - { - const std::size_t part = bitno/GMP_NUMB_BITS; - const std::size_t bit = bitno - (GMP_NUMB_BITS*part); - - r.mont_repr.data[part] &= ~(UINT64_C(1)<= modulus -- repeat (rejection sampling) */ - while (mpn_cmp(r.mont_repr.data, modulus.data, n) >= 0); - - return r; -} - -template& modulus> -Fp_model Fp_model::sqrt() const -{ - if (is_zero()) { - return *this; - } - - Fp_model one = Fp_model::one(); - - size_t v = Fp_model::s; - Fp_model z = Fp_model::nqr_to_t; - Fp_model w = (*this)^Fp_model::t_minus_1_over_2; - Fp_model x = (*this) * w; - Fp_model b = x * w; // b = (*this)^t - - - // check if square with euler's criterion - Fp_model check = b; - for (size_t i = 0; i < v-1; ++i) - { - check = check.squared(); - } - if (check != one) - { - assert_except(0); - } - - - // compute square root with Tonelli--Shanks - // (does not terminate if not a square!) - - while (b != one) - { - size_t m = 0; - Fp_model b2m = b; - while (b2m != one) - { - /* invariant: b2m = b^(2^m) after entering this loop */ - b2m = b2m.squared(); - m += 1; - } - - int j = v-m-1; - w = z; - while (j > 0) - { - w = w.squared(); - --j; - } // w = z^2^(v-m-1) - - z = w.squared(); - b = b * z; - x = x * w; - v = m; - } - - return x; -} - -template& modulus> -std::ostream& operator<<(std::ostream &out, const Fp_model &p) -{ -#ifndef MONTGOMERY_OUTPUT - Fp_model tmp; - tmp.mont_repr.data[0] = 1; - tmp.mul_reduce(p.mont_repr); - out << tmp.mont_repr; -#else - out << p.mont_repr; -#endif - return out; -} - -template& modulus> -std::istream& operator>>(std::istream &in, Fp_model &p) -{ -#ifndef MONTGOMERY_OUTPUT - in >> p.mont_repr; - p.mul_reduce(Fp_model::Rsquared); -#else - in >> p.mont_repr; -#endif - return in; -} - -} // libsnark -#endif // FP_TCC_ diff --git a/src/snark/libsnark/algebra/fields/fp12_2over3over2.hpp b/src/snark/libsnark/algebra/fields/fp12_2over3over2.hpp deleted file mode 100644 index 62ac8aa292c..00000000000 --- a/src/snark/libsnark/algebra/fields/fp12_2over3over2.hpp +++ /dev/null @@ -1,116 +0,0 @@ -/** @file - ***************************************************************************** - Declaration of arithmetic in the finite field F[((p^2)^3)^2]. - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef FP12_2OVER3OVER2_HPP_ -#define FP12_2OVER3OVER2_HPP_ -#include "algebra/fields/fp.hpp" -#include "algebra/fields/fp2.hpp" -#include "algebra/fields/fp6_3over2.hpp" -#include - -namespace libsnark { - -template& modulus> -class Fp12_2over3over2_model; - -template& modulus> -std::ostream& operator<<(std::ostream &, const Fp12_2over3over2_model &); - -template& modulus> -std::istream& operator>>(std::istream &, Fp12_2over3over2_model &); - -/** - * Arithmetic in the finite field F[((p^2)^3)^2]. - * - * Let p := modulus. This interface provides arithmetic for the extension field - * Fp12 = Fp6[W]/(W^2-V) where Fp6 = Fp2[V]/(V^3-non_residue) and non_residue is in Fp2 - * - * ASSUMPTION: p = 1 (mod 6) - */ -template& modulus> -class Fp12_2over3over2_model { -public: - typedef Fp_model my_Fp; - typedef Fp2_model my_Fp2; - typedef Fp6_3over2_model my_Fp6; - - static Fp2_model non_residue; - static Fp2_model Frobenius_coeffs_c1[12]; // non_residue^((modulus^i-1)/6) for i=0,...,11 - - my_Fp6 c0, c1; - Fp12_2over3over2_model() {}; - Fp12_2over3over2_model(const my_Fp6& c0, const my_Fp6& c1) : c0(c0), c1(c1) {}; - - void clear() { c0.clear(); c1.clear(); } - void print() const { printf("c0/c1:\n"); c0.print(); c1.print(); } - - static Fp12_2over3over2_model zero(); - static Fp12_2over3over2_model one(); - static Fp12_2over3over2_model random_element(); - - bool is_zero() const { return c0.is_zero() && c1.is_zero(); } - bool operator==(const Fp12_2over3over2_model &other) const; - bool operator!=(const Fp12_2over3over2_model &other) const; - - Fp12_2over3over2_model operator+(const Fp12_2over3over2_model &other) const; - Fp12_2over3over2_model operator-(const Fp12_2over3over2_model &other) const; - Fp12_2over3over2_model operator*(const Fp12_2over3over2_model &other) const; - Fp12_2over3over2_model operator-() const; - Fp12_2over3over2_model squared() const; // default is squared_complex - Fp12_2over3over2_model squared_karatsuba() const; - Fp12_2over3over2_model squared_complex() const; - Fp12_2over3over2_model inverse() const; - Fp12_2over3over2_model Frobenius_map(uint64_t power) const; - Fp12_2over3over2_model unitary_inverse() const; - Fp12_2over3over2_model cyclotomic_squared() const; - - Fp12_2over3over2_model mul_by_024(const my_Fp2 &ell_0, const my_Fp2 &ell_VW, const my_Fp2 &ell_VV) const; - - static my_Fp6 mul_by_non_residue(const my_Fp6 &elt); - - template - Fp12_2over3over2_model cyclotomic_exp(const bigint &exponent) const; - - static bigint base_field_char() { return modulus; } - static size_t extension_degree() { return 12; } - - friend std::ostream& operator<< (std::ostream &out, const Fp12_2over3over2_model &el); - friend std::istream& operator>> (std::istream &in, Fp12_2over3over2_model &el); -}; - -template& modulus> -std::ostream& operator<<(std::ostream& out, const std::vector > &v); - -template& modulus> -std::istream& operator>>(std::istream& in, std::vector > &v); - -template& modulus> -Fp12_2over3over2_model operator*(const Fp_model &lhs, const Fp12_2over3over2_model &rhs); - -template& modulus> -Fp12_2over3over2_model operator*(const Fp2_model &lhs, const Fp12_2over3over2_model &rhs); - -template& modulus> -Fp12_2over3over2_model operator*(const Fp6_3over2_model &lhs, const Fp12_2over3over2_model &rhs); - -template& modulus, mp_size_t m> -Fp12_2over3over2_model operator^(const Fp12_2over3over2_model &self, const bigint &exponent); - -template& modulus, mp_size_t m, const bigint& exp_modulus> -Fp12_2over3over2_model operator^(const Fp12_2over3over2_model &self, const Fp_model &exponent); - -template& modulus> -Fp2_model Fp12_2over3over2_model::non_residue; - -template& modulus> -Fp2_model Fp12_2over3over2_model::Frobenius_coeffs_c1[12]; - -} // libsnark -#include "algebra/fields/fp12_2over3over2.tcc" -#endif // FP12_2OVER3OVER2_HPP_ diff --git a/src/snark/libsnark/algebra/fields/fp12_2over3over2.tcc b/src/snark/libsnark/algebra/fields/fp12_2over3over2.tcc deleted file mode 100644 index 5ce95fbad58..00000000000 --- a/src/snark/libsnark/algebra/fields/fp12_2over3over2.tcc +++ /dev/null @@ -1,412 +0,0 @@ -/** @file - ***************************************************************************** - Implementation of arithmetic in the finite field F[((p^2)^3)^2]. - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef FP12_2OVER3OVER2_TCC_ -#define FP12_2OVER3OVER2_TCC_ - -namespace libsnark { - -template& modulus> -Fp6_3over2_model Fp12_2over3over2_model::mul_by_non_residue(const Fp6_3over2_model &elt) -{ - return Fp6_3over2_model(non_residue * elt.c2, elt.c0, elt.c1); -} - -template& modulus> -Fp12_2over3over2_model Fp12_2over3over2_model::zero() -{ - return Fp12_2over3over2_model(my_Fp6::zero(), my_Fp6::zero()); -} - -template& modulus> -Fp12_2over3over2_model Fp12_2over3over2_model::one() -{ - return Fp12_2over3over2_model(my_Fp6::one(), my_Fp6::zero()); -} - -template& modulus> -Fp12_2over3over2_model Fp12_2over3over2_model::random_element() -{ - Fp12_2over3over2_model r; - r.c0 = my_Fp6::random_element(); - r.c1 = my_Fp6::random_element(); - - return r; -} - -template& modulus> -bool Fp12_2over3over2_model::operator==(const Fp12_2over3over2_model &other) const -{ - return (this->c0 == other.c0 && this->c1 == other.c1); -} - -template& modulus> -bool Fp12_2over3over2_model::operator!=(const Fp12_2over3over2_model &other) const -{ - return !(operator==(other)); -} - -template& modulus> -Fp12_2over3over2_model Fp12_2over3over2_model::operator+(const Fp12_2over3over2_model &other) const -{ - return Fp12_2over3over2_model(this->c0 + other.c0, - this->c1 + other.c1); -} - -template& modulus> -Fp12_2over3over2_model Fp12_2over3over2_model::operator-(const Fp12_2over3over2_model &other) const -{ - return Fp12_2over3over2_model(this->c0 - other.c0, - this->c1 - other.c1); -} - -template& modulus> -Fp12_2over3over2_model operator*(const Fp_model &lhs, const Fp12_2over3over2_model &rhs) -{ - return Fp12_2over3over2_model(lhs*rhs.c0, - lhs*rhs.c1); -} - -template& modulus> -Fp12_2over3over2_model operator*(const Fp2_model &lhs, const Fp12_2over3over2_model &rhs) -{ - return Fp12_2over3over2_model(lhs*rhs.c0, - lhs*rhs.c1); -} - -template& modulus> -Fp12_2over3over2_model operator*(const Fp6_3over2_model &lhs, const Fp12_2over3over2_model &rhs) -{ - return Fp12_2over3over2_model(lhs*rhs.c0, - lhs*rhs.c1); -} - -template& modulus> -Fp12_2over3over2_model Fp12_2over3over2_model::operator*(const Fp12_2over3over2_model &other) const -{ - /* Devegili OhEig Scott Dahab --- Multiplication and Squaring on Pairing-Friendly Fields.pdf; Section 3 (Karatsuba) */ - - const my_Fp6 &A = other.c0, &B = other.c1, - &a = this->c0, &b = this->c1; - const my_Fp6 aA = a * A; - const my_Fp6 bB = b * B; - - return Fp12_2over3over2_model(aA + Fp12_2over3over2_model::mul_by_non_residue(bB), - (a + b)*(A+B) - aA - bB); -} - -template& modulus> -Fp12_2over3over2_model Fp12_2over3over2_model::operator-() const -{ - return Fp12_2over3over2_model(-this->c0, - -this->c1); -} - -template& modulus> -Fp12_2over3over2_model Fp12_2over3over2_model::squared() const -{ - return squared_complex(); -} - -template& modulus> -Fp12_2over3over2_model Fp12_2over3over2_model::squared_karatsuba() const -{ - /* Devegili OhEig Scott Dahab --- Multiplication and Squaring on Pairing-Friendly Fields.pdf; Section 3 (Karatsuba squaring) */ - - const my_Fp6 &a = this->c0, &b = this->c1; - const my_Fp6 asq = a.squared(); - const my_Fp6 bsq = b.squared(); - - return Fp12_2over3over2_model(asq + Fp12_2over3over2_model::mul_by_non_residue(bsq), - (a + b).squared() - asq - bsq); -} - -template& modulus> -Fp12_2over3over2_model Fp12_2over3over2_model::squared_complex() const -{ - /* Devegili OhEig Scott Dahab --- Multiplication and Squaring on Pairing-Friendly Fields.pdf; Section 3 (Complex squaring) */ - - const my_Fp6 &a = this->c0, &b = this->c1; - const my_Fp6 ab = a * b; - - return Fp12_2over3over2_model((a + b) * (a + Fp12_2over3over2_model::mul_by_non_residue(b)) - ab - Fp12_2over3over2_model::mul_by_non_residue(ab), - ab + ab); -} - -template& modulus> -Fp12_2over3over2_model Fp12_2over3over2_model::inverse() const -{ - /* From "High-Speed Software Implementation of the Optimal Ate Pairing over Barreto-Naehrig Curves"; Algorithm 8 */ - - const my_Fp6 &a = this->c0, &b = this->c1; - const my_Fp6 t0 = a.squared(); - const my_Fp6 t1 = b.squared(); - const my_Fp6 t2 = t0 - Fp12_2over3over2_model::mul_by_non_residue(t1); - const my_Fp6 t3 = t2.inverse(); - const my_Fp6 c0 = a * t3; - const my_Fp6 c1 = - (b * t3); - - return Fp12_2over3over2_model(c0, c1); -} - -template& modulus> -Fp12_2over3over2_model Fp12_2over3over2_model::Frobenius_map(uint64_t power) const -{ - return Fp12_2over3over2_model(c0.Frobenius_map(power), - Frobenius_coeffs_c1[power % 12] * c1.Frobenius_map(power)); -} - -template& modulus> -Fp12_2over3over2_model Fp12_2over3over2_model::unitary_inverse() const -{ - return Fp12_2over3over2_model(this->c0, - -this->c1); -} - -template& modulus> -Fp12_2over3over2_model Fp12_2over3over2_model::cyclotomic_squared() const -{ - /* OLD: naive implementation - return (*this).squared(); - */ - my_Fp2 z0 = this->c0.c0; - my_Fp2 z4 = this->c0.c1; - my_Fp2 z3 = this->c0.c2; - my_Fp2 z2 = this->c1.c0; - my_Fp2 z1 = this->c1.c1; - my_Fp2 z5 = this->c1.c2; - - my_Fp2 t0, t1, t2, t3, t4, t5, tmp; - - // t0 + t1*y = (z0 + z1*y)^2 = a^2 - tmp = z0 * z1; - t0 = (z0 + z1) * (z0 + my_Fp6::non_residue * z1) - tmp - my_Fp6::non_residue * tmp; - t1 = tmp + tmp; - // t2 + t3*y = (z2 + z3*y)^2 = b^2 - tmp = z2 * z3; - t2 = (z2 + z3) * (z2 + my_Fp6::non_residue * z3) - tmp - my_Fp6::non_residue * tmp; - t3 = tmp + tmp; - // t4 + t5*y = (z4 + z5*y)^2 = c^2 - tmp = z4 * z5; - t4 = (z4 + z5) * (z4 + my_Fp6::non_residue * z5) - tmp - my_Fp6::non_residue * tmp; - t5 = tmp + tmp; - - // for A - - // z0 = 3 * t0 - 2 * z0 - z0 = t0 - z0; - z0 = z0 + z0; - z0 = z0 + t0; - // z1 = 3 * t1 + 2 * z1 - z1 = t1 + z1; - z1 = z1 + z1; - z1 = z1 + t1; - - // for B - - // z2 = 3 * (xi * t5) + 2 * z2 - tmp = my_Fp6::non_residue * t5; - z2 = tmp + z2; - z2 = z2 + z2; - z2 = z2 + tmp; - - // z3 = 3 * t4 - 2 * z3 - z3 = t4 - z3; - z3 = z3 + z3; - z3 = z3 + t4; - - // for C - - // z4 = 3 * t2 - 2 * z4 - z4 = t2 - z4; - z4 = z4 + z4; - z4 = z4 + t2; - - // z5 = 3 * t3 + 2 * z5 - z5 = t3 + z5; - z5 = z5 + z5; - z5 = z5 + t3; - - return Fp12_2over3over2_model(my_Fp6(z0,z4,z3),my_Fp6(z2,z1,z5)); -} - -template& modulus> -Fp12_2over3over2_model Fp12_2over3over2_model::mul_by_024(const Fp2_model &ell_0, - const Fp2_model &ell_VW, - const Fp2_model &ell_VV) const -{ - /* OLD: naive implementation - Fp12_2over3over2_model a(my_Fp6(ell_0, my_Fp2::zero(), ell_VV), - my_Fp6(my_Fp2::zero(), ell_VW, my_Fp2::zero())); - - return (*this) * a; - */ - my_Fp2 z0 = this->c0.c0; - my_Fp2 z1 = this->c0.c1; - my_Fp2 z2 = this->c0.c2; - my_Fp2 z3 = this->c1.c0; - my_Fp2 z4 = this->c1.c1; - my_Fp2 z5 = this->c1.c2; - - my_Fp2 x0 = ell_0; - my_Fp2 x2 = ell_VV; - my_Fp2 x4 = ell_VW; - - my_Fp2 t0, t1, t2, s0, T3, T4, D0, D2, D4, S1; - - D0 = z0 * x0; - D2 = z2 * x2; - D4 = z4 * x4; - t2 = z0 + z4; - t1 = z0 + z2; - s0 = z1 + z3 + z5; - - // For z.a_.a_ = z0. - S1 = z1 * x2; - T3 = S1 + D4; - T4 = my_Fp6::non_residue * T3 + D0; - z0 = T4; - - // For z.a_.b_ = z1 - T3 = z5 * x4; - S1 = S1 + T3; - T3 = T3 + D2; - T4 = my_Fp6::non_residue * T3; - T3 = z1 * x0; - S1 = S1 + T3; - T4 = T4 + T3; - z1 = T4; - - // For z.a_.c_ = z2 - t0 = x0 + x2; - T3 = t1 * t0 - D0 - D2; - T4 = z3 * x4; - S1 = S1 + T4; - T3 = T3 + T4; - - // For z.b_.a_ = z3 (z3 needs z2) - t0 = z2 + z4; - z2 = T3; - t1 = x2 + x4; - T3 = t0 * t1 - D2 - D4; - T4 = my_Fp6::non_residue * T3; - T3 = z3 * x0; - S1 = S1 + T3; - T4 = T4 + T3; - z3 = T4; - - // For z.b_.b_ = z4 - T3 = z5 * x2; - S1 = S1 + T3; - T4 = my_Fp6::non_residue * T3; - t0 = x0 + x4; - T3 = t2 * t0 - D0 - D4; - T4 = T4 + T3; - z4 = T4; - - // For z.b_.c_ = z5. - t0 = x0 + x2 + x4; - T3 = s0 * t0 - S1; - z5 = T3; - - return Fp12_2over3over2_model(my_Fp6(z0,z1,z2),my_Fp6(z3,z4,z5)); - -} - -template& modulus, mp_size_t m> -Fp12_2over3over2_model operator^(const Fp12_2over3over2_model &self, const bigint &exponent) -{ - return power >(self, exponent); -} - -template& modulus, mp_size_t m, const bigint& exp_modulus> -Fp12_2over3over2_model operator^(const Fp12_2over3over2_model &self, const Fp_model &exponent) -{ - return self^(exponent.as_bigint()); -} - - -template& modulus> -template -Fp12_2over3over2_model Fp12_2over3over2_model::cyclotomic_exp(const bigint &exponent) const -{ - Fp12_2over3over2_model res = Fp12_2over3over2_model::one(); - - bool found_one = false; - for (int64_t i = m-1; i >= 0; --i) - { - for (int64_t j = GMP_NUMB_BITS - 1; j >= 0; --j) - { - if (found_one) - { - res = res.cyclotomic_squared(); - } - - if (exponent.data[i] & (((mp_limb_t) 1)<& modulus> -std::ostream& operator<<(std::ostream &out, const Fp12_2over3over2_model &el) -{ - out << el.c0 << OUTPUT_SEPARATOR << el.c1; - return out; -} - -template& modulus> -std::istream& operator>>(std::istream &in, Fp12_2over3over2_model &el) -{ - in >> el.c0 >> el.c1; - return in; -} - -template& modulus> -std::ostream& operator<<(std::ostream& out, const std::vector > &v) -{ - out << v.size() << "\n"; - for (const Fp12_2over3over2_model& t : v) - { - out << t << OUTPUT_NEWLINE; - } - - return out; -} - -template& modulus> -std::istream& operator>>(std::istream& in, std::vector > &v) -{ - v.clear(); - - size_t s; - in >> s; - - char b; - in.read(&b, 1); - - v.reserve(s); - - for (size_t i = 0; i < s; ++i) - { - Fp12_2over3over2_model el; - in >> el; - v.emplace_back(el); - } - - return in; -} - -} // libsnark -#endif // FP12_2OVER3OVER2_TCC_ diff --git a/src/snark/libsnark/algebra/fields/fp2.hpp b/src/snark/libsnark/algebra/fields/fp2.hpp deleted file mode 100644 index 276c923e9b3..00000000000 --- a/src/snark/libsnark/algebra/fields/fp2.hpp +++ /dev/null @@ -1,120 +0,0 @@ -/** @file - ***************************************************************************** - Implementation of arithmetic in the finite field F[p^2]. - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef FP2_HPP_ -#define FP2_HPP_ -#include "algebra/fields/fp.hpp" -#include - -namespace libsnark { - -template& modulus> -class Fp2_model; - -template& modulus> -std::ostream& operator<<(std::ostream &, const Fp2_model &); - -template& modulus> -std::istream& operator>>(std::istream &, Fp2_model &); - -/** - * Arithmetic in the field F[p^3]. - * - * Let p := modulus. This interface provides arithmetic for the extension field - * Fp2 = Fp[U]/(U^2-non_residue), where non_residue is in Fp. - * - * ASSUMPTION: p = 1 (mod 6) - */ -template& modulus> -class Fp2_model { -public: - typedef Fp_model my_Fp; - - static bigint<2*n> euler; // (modulus^2-1)/2 - static size_t s; // modulus^2 = 2^s * t + 1 - static bigint<2*n> t; // with t odd - static bigint<2*n> t_minus_1_over_2; // (t-1)/2 - static my_Fp non_residue; // X^4-non_residue irreducible over Fp; used for constructing Fp2 = Fp[X] / (X^2 - non_residue) - static Fp2_model nqr; // a quadratic nonresidue in Fp2 - static Fp2_model nqr_to_t; // nqr^t - static my_Fp Frobenius_coeffs_c1[2]; // non_residue^((modulus^i-1)/2) for i=0,1 - - my_Fp c0, c1; - Fp2_model() {}; - Fp2_model(const my_Fp& c0, const my_Fp& c1) : c0(c0), c1(c1) {}; - - void clear() { c0.clear(); c1.clear(); } - void print() const { printf("c0/c1:\n"); c0.print(); c1.print(); } - - static Fp2_model zero(); - static Fp2_model one(); - static Fp2_model random_element(); - - bool is_zero() const { return c0.is_zero() && c1.is_zero(); } - bool operator==(const Fp2_model &other) const; - bool operator!=(const Fp2_model &other) const; - - Fp2_model operator+(const Fp2_model &other) const; - Fp2_model operator-(const Fp2_model &other) const; - Fp2_model operator*(const Fp2_model &other) const; - Fp2_model operator-() const; - Fp2_model squared() const; // default is squared_complex - Fp2_model inverse() const; - Fp2_model Frobenius_map(uint64_t power) const; - Fp2_model sqrt() const; // HAS TO BE A SQUARE (else does not terminate) - Fp2_model squared_karatsuba() const; - Fp2_model squared_complex() const; - - template - Fp2_model operator^(const bigint &other) const; - - static size_t size_in_bits() { return 2*my_Fp::size_in_bits(); } - static bigint base_field_char() { return modulus; } - - friend std::ostream& operator<< (std::ostream &out, const Fp2_model &el); - friend std::istream& operator>> (std::istream &in, Fp2_model &el); -}; - -template& modulus> -std::ostream& operator<<(std::ostream& out, const std::vector > &v); - -template& modulus> -std::istream& operator>>(std::istream& in, std::vector > &v); - -template& modulus> -Fp2_model operator*(const Fp_model &lhs, const Fp2_model &rhs); - -template& modulus> -bigint<2*n> Fp2_model::euler; - -template& modulus> -size_t Fp2_model::s; - -template& modulus> -bigint<2*n> Fp2_model::t; - -template& modulus> -bigint<2*n> Fp2_model::t_minus_1_over_2; - -template& modulus> -Fp_model Fp2_model::non_residue; - -template& modulus> -Fp2_model Fp2_model::nqr; - -template& modulus> -Fp2_model Fp2_model::nqr_to_t; - -template& modulus> -Fp_model Fp2_model::Frobenius_coeffs_c1[2]; - -} // libsnark -#include "algebra/fields/fp2.tcc" - -#endif // FP2_HPP_ diff --git a/src/snark/libsnark/algebra/fields/fp2.tcc b/src/snark/libsnark/algebra/fields/fp2.tcc deleted file mode 100644 index fb3eacda976..00000000000 --- a/src/snark/libsnark/algebra/fields/fp2.tcc +++ /dev/null @@ -1,261 +0,0 @@ -/** @file - ***************************************************************************** - Implementation of arithmetic in the finite field F[p^2]. - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef FP2_TCC_ -#define FP2_TCC_ - -#include "algebra/fields/field_utils.hpp" - -namespace libsnark { - -template& modulus> -Fp2_model Fp2_model::zero() -{ - return Fp2_model(my_Fp::zero(), my_Fp::zero()); -} - -template& modulus> -Fp2_model Fp2_model::one() -{ - return Fp2_model(my_Fp::one(), my_Fp::zero()); -} - -template& modulus> -Fp2_model Fp2_model::random_element() -{ - Fp2_model r; - r.c0 = my_Fp::random_element(); - r.c1 = my_Fp::random_element(); - - return r; -} - -template& modulus> -bool Fp2_model::operator==(const Fp2_model &other) const -{ - return (this->c0 == other.c0 && this->c1 == other.c1); -} - -template& modulus> -bool Fp2_model::operator!=(const Fp2_model &other) const -{ - return !(operator==(other)); -} - -template& modulus> -Fp2_model Fp2_model::operator+(const Fp2_model &other) const -{ - return Fp2_model(this->c0 + other.c0, - this->c1 + other.c1); -} - -template& modulus> -Fp2_model Fp2_model::operator-(const Fp2_model &other) const -{ - return Fp2_model(this->c0 - other.c0, - this->c1 - other.c1); -} - -template& modulus> -Fp2_model operator*(const Fp_model &lhs, const Fp2_model &rhs) -{ - return Fp2_model(lhs*rhs.c0, - lhs*rhs.c1); -} - -template& modulus> -Fp2_model Fp2_model::operator*(const Fp2_model &other) const -{ - /* Devegili OhEig Scott Dahab --- Multiplication and Squaring on Pairing-Friendly Fields.pdf; Section 3 (Karatsuba) */ - const my_Fp - &A = other.c0, &B = other.c1, - &a = this->c0, &b = this->c1; - const my_Fp aA = a * A; - const my_Fp bB = b * B; - - return Fp2_model(aA + non_residue * bB, - (a + b)*(A+B) - aA - bB); -} - -template& modulus> -Fp2_model Fp2_model::operator-() const -{ - return Fp2_model(-this->c0, - -this->c1); -} - -template& modulus> -Fp2_model Fp2_model::squared() const -{ - return squared_complex(); -} - -template& modulus> -Fp2_model Fp2_model::squared_karatsuba() const -{ - /* Devegili OhEig Scott Dahab --- Multiplication and Squaring on Pairing-Friendly Fields.pdf; Section 3 (Karatsuba squaring) */ - const my_Fp &a = this->c0, &b = this->c1; - const my_Fp asq = a.squared(); - const my_Fp bsq = b.squared(); - - return Fp2_model(asq + non_residue * bsq, - (a + b).squared() - asq - bsq); -} - -template& modulus> -Fp2_model Fp2_model::squared_complex() const -{ - /* Devegili OhEig Scott Dahab --- Multiplication and Squaring on Pairing-Friendly Fields.pdf; Section 3 (Complex squaring) */ - const my_Fp &a = this->c0, &b = this->c1; - const my_Fp ab = a * b; - - return Fp2_model((a + b) * (a + non_residue * b) - ab - non_residue * ab, - ab + ab); -} - -template& modulus> -Fp2_model Fp2_model::inverse() const -{ - const my_Fp &a = this->c0, &b = this->c1; - - /* From "High-Speed Software Implementation of the Optimal Ate Pairing over Barreto-Naehrig Curves"; Algorithm 8 */ - const my_Fp t0 = a.squared(); - const my_Fp t1 = b.squared(); - const my_Fp t2 = t0 - non_residue * t1; - const my_Fp t3 = t2.inverse(); - const my_Fp c0 = a * t3; - const my_Fp c1 = - (b * t3); - - return Fp2_model(c0, c1); -} - -template& modulus> -Fp2_model Fp2_model::Frobenius_map(uint64_t power) const -{ - return Fp2_model(c0, - Frobenius_coeffs_c1[power % 2] * c1); -} - -template& modulus> -Fp2_model Fp2_model::sqrt() const -{ - if (is_zero()) { - return *this; - } - - Fp2_model one = Fp2_model::one(); - - size_t v = Fp2_model::s; - Fp2_model z = Fp2_model::nqr_to_t; - Fp2_model w = (*this)^Fp2_model::t_minus_1_over_2; - Fp2_model x = (*this) * w; - Fp2_model b = x * w; // b = (*this)^t - - - // check if square with euler's criterion - Fp2_model check = b; - for (size_t i = 0; i < v-1; ++i) - { - check = check.squared(); - } - if (check != one) - { - assert_except(0); - } - - - // compute square root with Tonelli--Shanks - // (does not terminate if not a square!) - - while (b != one) - { - size_t m = 0; - Fp2_model b2m = b; - while (b2m != one) - { - /* invariant: b2m = b^(2^m) after entering this loop */ - b2m = b2m.squared(); - m += 1; - } - - int j = v-m-1; - w = z; - while (j > 0) - { - w = w.squared(); - --j; - } // w = z^2^(v-m-1) - - z = w.squared(); - b = b * z; - x = x * w; - v = m; - } - - return x; -} - -template& modulus> -template -Fp2_model Fp2_model::operator^(const bigint &pow) const -{ - return power, m>(*this, pow); -} - -template& modulus> -std::ostream& operator<<(std::ostream &out, const Fp2_model &el) -{ - out << el.c0 << OUTPUT_SEPARATOR << el.c1; - return out; -} - -template& modulus> -std::istream& operator>>(std::istream &in, Fp2_model &el) -{ - in >> el.c0 >> el.c1; - return in; -} - -template& modulus> -std::ostream& operator<<(std::ostream& out, const std::vector > &v) -{ - out << v.size() << "\n"; - for (const Fp2_model& t : v) - { - out << t << OUTPUT_NEWLINE; - } - - return out; -} - -template& modulus> -std::istream& operator>>(std::istream& in, std::vector > &v) -{ - v.clear(); - - size_t s; - in >> s; - - char b; - in.read(&b, 1); - - v.reserve(s); - - for (size_t i = 0; i < s; ++i) - { - Fp2_model el; - in >> el; - v.emplace_back(el); - } - - return in; -} - -} // libsnark -#endif // FP2_TCC_ diff --git a/src/snark/libsnark/algebra/fields/fp6_3over2.hpp b/src/snark/libsnark/algebra/fields/fp6_3over2.hpp deleted file mode 100644 index 912c58a7429..00000000000 --- a/src/snark/libsnark/algebra/fields/fp6_3over2.hpp +++ /dev/null @@ -1,104 +0,0 @@ -/** @file - ***************************************************************************** - Declaration of arithmetic in the finite field F[(p^2)^3] - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef FP6_3OVER2_HPP_ -#define FP6_3OVER2_HPP_ -#include "algebra/fields/fp.hpp" -#include "algebra/fields/fp2.hpp" -#include - -namespace libsnark { - -template& modulus> -class Fp6_3over2_model; - -template& modulus> -std::ostream& operator<<(std::ostream &, const Fp6_3over2_model &); - -template& modulus> -std::istream& operator>>(std::istream &, Fp6_3over2_model &); - -/** - * Arithmetic in the finite field F[(p^2)^3]. - * - * Let p := modulus. This interface provides arithmetic for the extension field - * Fp6 = Fp2[V]/(V^3-non_residue) where non_residue is in Fp. - * - * ASSUMPTION: p = 1 (mod 6) - */ -template& modulus> -class Fp6_3over2_model { -public: - typedef Fp_model my_Fp; - typedef Fp2_model my_Fp2; - - static my_Fp2 non_residue; - static my_Fp2 Frobenius_coeffs_c1[6]; // non_residue^((modulus^i-1)/3) for i=0,1,2,3,4,5 - static my_Fp2 Frobenius_coeffs_c2[6]; // non_residue^((2*modulus^i-2)/3) for i=0,1,2,3,4,5 - - my_Fp2 c0, c1, c2; - Fp6_3over2_model() {}; - Fp6_3over2_model(const my_Fp2& c0, const my_Fp2& c1, const my_Fp2& c2) : c0(c0), c1(c1), c2(c2) {}; - - void clear() { c0.clear(); c1.clear(); c2.clear(); } - void print() const { printf("c0/c1/c2:\n"); c0.print(); c1.print(); c2.print(); } - - static Fp6_3over2_model zero(); - static Fp6_3over2_model one(); - static Fp6_3over2_model random_element(); - - bool is_zero() const { return c0.is_zero() && c1.is_zero() && c2.is_zero(); } - bool operator==(const Fp6_3over2_model &other) const; - bool operator!=(const Fp6_3over2_model &other) const; - - Fp6_3over2_model operator+(const Fp6_3over2_model &other) const; - Fp6_3over2_model operator-(const Fp6_3over2_model &other) const; - Fp6_3over2_model operator*(const Fp6_3over2_model &other) const; - Fp6_3over2_model operator-() const; - Fp6_3over2_model squared() const; - Fp6_3over2_model inverse() const; - Fp6_3over2_model Frobenius_map(uint64_t power) const; - - static my_Fp2 mul_by_non_residue(const my_Fp2 &elt); - - template - Fp6_3over2_model operator^(const bigint &other) const; - - static bigint base_field_char() { return modulus; } - static size_t extension_degree() { return 6; } - - friend std::ostream& operator<< (std::ostream &out, const Fp6_3over2_model &el); - friend std::istream& operator>> (std::istream &in, Fp6_3over2_model &el); -}; - -template& modulus> -std::ostream& operator<<(std::ostream& out, const std::vector > &v); - -template& modulus> -std::istream& operator>>(std::istream& in, std::vector > &v); - -template& modulus> -Fp6_3over2_model operator*(const Fp_model &lhs, const Fp6_3over2_model &rhs); - -template& modulus> -Fp6_3over2_model operator*(const Fp2_model &lhs, const Fp6_3over2_model &rhs); - -template& modulus> -Fp2_model Fp6_3over2_model::non_residue; - -template& modulus> -Fp2_model Fp6_3over2_model::Frobenius_coeffs_c1[6]; - -template& modulus> -Fp2_model Fp6_3over2_model::Frobenius_coeffs_c2[6]; - -} // libsnark -#include "algebra/fields/fp6_3over2.tcc" - -#endif // FP6_3OVER2_HPP_ diff --git a/src/snark/libsnark/algebra/fields/fp6_3over2.tcc b/src/snark/libsnark/algebra/fields/fp6_3over2.tcc deleted file mode 100644 index 86b864ef02d..00000000000 --- a/src/snark/libsnark/algebra/fields/fp6_3over2.tcc +++ /dev/null @@ -1,216 +0,0 @@ -/** @file - ***************************************************************************** - Implementation of arithmetic in the finite field F[(p^2)^3]. - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef FP6_3OVER2_TCC_ -#define FP6_3OVER2_TCC_ -#include "algebra/fields/field_utils.hpp" - -namespace libsnark { - -template& modulus> -Fp2_model Fp6_3over2_model::mul_by_non_residue(const Fp2_model &elt) -{ - return Fp2_model(non_residue * elt); -} - -template& modulus> -Fp6_3over2_model Fp6_3over2_model::zero() -{ - return Fp6_3over2_model(my_Fp2::zero(), my_Fp2::zero(), my_Fp2::zero()); -} - -template& modulus> -Fp6_3over2_model Fp6_3over2_model::one() -{ - return Fp6_3over2_model(my_Fp2::one(), my_Fp2::zero(), my_Fp2::zero()); -} - -template& modulus> -Fp6_3over2_model Fp6_3over2_model::random_element() -{ - Fp6_3over2_model r; - r.c0 = my_Fp2::random_element(); - r.c1 = my_Fp2::random_element(); - r.c2 = my_Fp2::random_element(); - - return r; -} - -template& modulus> -bool Fp6_3over2_model::operator==(const Fp6_3over2_model &other) const -{ - return (this->c0 == other.c0 && this->c1 == other.c1 && this->c2 == other.c2); -} - -template& modulus> -bool Fp6_3over2_model::operator!=(const Fp6_3over2_model &other) const -{ - return !(operator==(other)); -} - -template& modulus> -Fp6_3over2_model Fp6_3over2_model::operator+(const Fp6_3over2_model &other) const -{ - return Fp6_3over2_model(this->c0 + other.c0, - this->c1 + other.c1, - this->c2 + other.c2); -} - -template& modulus> -Fp6_3over2_model Fp6_3over2_model::operator-(const Fp6_3over2_model &other) const -{ - return Fp6_3over2_model(this->c0 - other.c0, - this->c1 - other.c1, - this->c2 - other.c2); -} - -template& modulus> -Fp6_3over2_model operator*(const Fp_model &lhs, const Fp6_3over2_model &rhs) -{ - return Fp6_3over2_model(lhs*rhs.c0, - lhs*rhs.c1, - lhs*rhs.c2); -} - -template& modulus> -Fp6_3over2_model operator*(const Fp2_model &lhs, const Fp6_3over2_model &rhs) -{ - return Fp6_3over2_model(lhs*rhs.c0, - lhs*rhs.c1, - lhs*rhs.c2); -} - -template& modulus> -Fp6_3over2_model Fp6_3over2_model::operator*(const Fp6_3over2_model &other) const -{ - /* Devegili OhEig Scott Dahab --- Multiplication and Squaring on Pairing-Friendly Fields.pdf; Section 4 (Karatsuba) */ - - const my_Fp2 &A = other.c0, &B = other.c1, &C = other.c2, - &a = this->c0, &b = this->c1, &c = this->c2; - const my_Fp2 aA = a*A; - const my_Fp2 bB = b*B; - const my_Fp2 cC = c*C; - - return Fp6_3over2_model(aA + Fp6_3over2_model::mul_by_non_residue((b+c)*(B+C)-bB-cC), - (a+b)*(A+B)-aA-bB+Fp6_3over2_model::mul_by_non_residue(cC), - (a+c)*(A+C)-aA+bB-cC); -} - -template& modulus> -Fp6_3over2_model Fp6_3over2_model::operator-() const -{ - return Fp6_3over2_model(-this->c0, - -this->c1, - -this->c2); -} - -template& modulus> -Fp6_3over2_model Fp6_3over2_model::squared() const -{ - /* Devegili OhEig Scott Dahab --- Multiplication and Squaring on Pairing-Friendly Fields.pdf; Section 4 (CH-SQR2) */ - - const my_Fp2 &a = this->c0, &b = this->c1, &c = this->c2; - const my_Fp2 s0 = a.squared(); - const my_Fp2 ab = a*b; - const my_Fp2 s1 = ab + ab; - const my_Fp2 s2 = (a - b + c).squared(); - const my_Fp2 bc = b*c; - const my_Fp2 s3 = bc + bc; - const my_Fp2 s4 = c.squared(); - - return Fp6_3over2_model(s0 + Fp6_3over2_model::mul_by_non_residue(s3), - s1 + Fp6_3over2_model::mul_by_non_residue(s4), - s1 + s2 + s3 - s0 - s4); -} - -template& modulus> -Fp6_3over2_model Fp6_3over2_model::inverse() const -{ - /* From "High-Speed Software Implementation of the Optimal Ate Pairing over Barreto-Naehrig Curves"; Algorithm 17 */ - - const my_Fp2 &a = this->c0, &b = this->c1, &c = this->c2; - const my_Fp2 t0 = a.squared(); - const my_Fp2 t1 = b.squared(); - const my_Fp2 t2 = c.squared(); - const my_Fp2 t3 = a*b; - const my_Fp2 t4 = a*c; - const my_Fp2 t5 = b*c; - const my_Fp2 c0 = t0 - Fp6_3over2_model::mul_by_non_residue(t5); - const my_Fp2 c1 = Fp6_3over2_model::mul_by_non_residue(t2) - t3; - const my_Fp2 c2 = t1 - t4; // typo in paper referenced above. should be "-" as per Scott, but is "*" - const my_Fp2 t6 = (a * c0 + Fp6_3over2_model::mul_by_non_residue((c * c1 + b * c2))).inverse(); - return Fp6_3over2_model(t6 * c0, t6 * c1, t6 * c2); -} - -template& modulus> -Fp6_3over2_model Fp6_3over2_model::Frobenius_map(uint64_t power) const -{ - return Fp6_3over2_model(c0.Frobenius_map(power), - Frobenius_coeffs_c1[power % 6] * c1.Frobenius_map(power), - Frobenius_coeffs_c2[power % 6] * c2.Frobenius_map(power)); -} - -template& modulus> -template -Fp6_3over2_model Fp6_3over2_model::operator^(const bigint &pow) const -{ - return power, m>(*this, pow); -} - -template& modulus> -std::ostream& operator<<(std::ostream &out, const Fp6_3over2_model &el) -{ - out << el.c0 << OUTPUT_SEPARATOR << el.c1 << OUTPUT_SEPARATOR << el.c2; - return out; -} - -template& modulus> -std::istream& operator>>(std::istream &in, Fp6_3over2_model &el) -{ - in >> el.c0 >> el.c1 >> el.c2; - return in; -} - -template& modulus> -std::ostream& operator<<(std::ostream& out, const std::vector > &v) -{ - out << v.size() << "\n"; - for (const Fp6_3over2_model& t : v) - { - out << t << OUTPUT_NEWLINE; - } - - return out; -} - -template& modulus> -std::istream& operator>>(std::istream& in, std::vector > &v) -{ - v.clear(); - - size_t s; - in >> s; - - char b; - in.read(&b, 1); - - v.reserve(s); - - for (size_t i = 0; i < s; ++i) - { - Fp6_3over2_model el; - in >> el; - v.emplace_back(el); - } - - return in; -} - -} // libsnark -#endif // FP6_3_OVER_2_TCC_ diff --git a/src/snark/libsnark/algebra/fields/fp_aux.tcc b/src/snark/libsnark/algebra/fields/fp_aux.tcc deleted file mode 100644 index 7f8a3eadff6..00000000000 --- a/src/snark/libsnark/algebra/fields/fp_aux.tcc +++ /dev/null @@ -1,389 +0,0 @@ -/** @file - ***************************************************************************** - Assembly code snippets for F[p] finite field arithmetic, used by fp.tcc . - Specific to x86-64, and used only if USE_ASM is defined. - On other architectures or without USE_ASM, fp.tcc uses a portable - C++ implementation instead. - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef FP_AUX_TCC_ -#define FP_AUX_TCC_ - -namespace libsnark { - -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) - -/* addq is faster than adcq, even if preceded by clc */ -#define ADD_FIRSTADD \ - "movq (%[B]), %%rax \n\t" \ - "addq %%rax, (%[A]) \n\t" - -#define ADD_NEXTADD(ofs) \ - "movq " STR(ofs) "(%[B]), %%rax \n\t" \ - "adcq %%rax, " STR(ofs) "(%[A]) \n\t" - -#define ADD_CMP(ofs) \ - "movq " STR(ofs) "(%[mod]), %%rax \n\t" \ - "cmpq %%rax, " STR(ofs) "(%[A]) \n\t" \ - "jb done%= \n\t" \ - "ja subtract%= \n\t" - -#define ADD_FIRSTSUB \ - "movq (%[mod]), %%rax \n\t" \ - "subq %%rax, (%[A]) \n\t" - -#define ADD_FIRSTSUB \ - "movq (%[mod]), %%rax \n\t" \ - "subq %%rax, (%[A]) \n\t" - -#define ADD_NEXTSUB(ofs) \ - "movq " STR(ofs) "(%[mod]), %%rax \n\t" \ - "sbbq %%rax, " STR(ofs) "(%[A]) \n\t" - -#define SUB_FIRSTSUB \ - "movq (%[B]), %%rax\n\t" \ - "subq %%rax, (%[A])\n\t" - -#define SUB_NEXTSUB(ofs) \ - "movq " STR(ofs) "(%[B]), %%rax\n\t" \ - "sbbq %%rax, " STR(ofs) "(%[A])\n\t" - -#define SUB_FIRSTADD \ - "movq (%[mod]), %%rax\n\t" \ - "addq %%rax, (%[A])\n\t" - -#define SUB_NEXTADD(ofs) \ - "movq " STR(ofs) "(%[mod]), %%rax\n\t" \ - "adcq %%rax, " STR(ofs) "(%[A])\n\t" - -#define MONT_CMP(ofs) \ - "movq " STR(ofs) "(%[M]), %%rax \n\t" \ - "cmpq %%rax, " STR(ofs) "(%[tmp]) \n\t" \ - "jb done%= \n\t" \ - "ja subtract%= \n\t" - -#define MONT_FIRSTSUB \ - "movq (%[M]), %%rax \n\t" \ - "subq %%rax, (%[tmp]) \n\t" - -#define MONT_NEXTSUB(ofs) \ - "movq " STR(ofs) "(%[M]), %%rax \n\t" \ - "sbbq %%rax, " STR(ofs) "(%[tmp]) \n\t" - -/* - The x86-64 Montgomery multiplication here is similar - to Algorithm 2 (CIOS method) in http://eprint.iacr.org/2012/140.pdf - and the PowerPC pseudocode of gmp-ecm library (c) Paul Zimmermann and Alexander Kruppa - (see comments on top of powerpc64/mulredc.m4). -*/ - -#define MONT_PRECOMPUTE \ - "xorq %[cy], %[cy] \n\t" \ - "movq 0(%[A]), %%rax \n\t" \ - "mulq 0(%[B]) \n\t" \ - "movq %%rax, %[T0] \n\t" \ - "movq %%rdx, %[T1] # T1:T0 <- A[0] * B[0] \n\t" \ - "mulq %[inv] \n\t" \ - "movq %%rax, %[u] # u <- T0 * inv \n\t" \ - "mulq 0(%[M]) \n\t" \ - "addq %[T0], %%rax \n\t" \ - "adcq %%rdx, %[T1] \n\t" \ - "adcq $0, %[cy] # cy:T1 <- (M[0]*u + T1 * b + T0) / b\n\t" - -#define MONT_FIRSTITER(j) \ - "xorq %[T0], %[T0] \n\t" \ - "movq 0(%[A]), %%rax \n\t" \ - "mulq " STR((j*8)) "(%[B]) \n\t" \ - "addq %[T1], %%rax \n\t" \ - "movq %%rax, " STR(((j-1)*8)) "(%[tmp]) \n\t" \ - "adcq $0, %%rdx \n\t" \ - "movq %%rdx, %[T1] # now T1:tmp[j-1] <-- X[0] * Y[j] + T1\n\t" \ - "movq " STR((j*8)) "(%[M]), %%rax \n\t" \ - "mulq %[u] \n\t" \ - "addq %%rax, " STR(((j-1)*8)) "(%[tmp]) \n\t" \ - "adcq %[cy], %%rdx \n\t" \ - "adcq $0, %[T0] \n\t" \ - "xorq %[cy], %[cy] \n\t" \ - "addq %%rdx, %[T1] \n\t" \ - "adcq %[T0], %[cy] # cy:T1:tmp[j-1] <---- (X[0] * Y[j] + T1) + (M[j] * u + cy * b) \n\t" - -#define MONT_ITERFIRST(i) \ - "xorq %[cy], %[cy] \n\t" \ - "movq " STR((i*8)) "(%[A]), %%rax \n\t" \ - "mulq 0(%[B]) \n\t" \ - "addq 0(%[tmp]), %%rax \n\t" \ - "adcq 8(%[tmp]), %%rdx \n\t" \ - "adcq $0, %[cy] \n\t" \ - "movq %%rax, %[T0] \n\t" \ - "movq %%rdx, %[T1] # cy:T1:T0 <- A[i] * B[0] + tmp[1] * b + tmp[0]\n\t" \ - "mulq %[inv] \n\t" \ - "movq %%rax, %[u] # u <- T0 * inv\n\t" \ - "mulq 0(%[M]) \n\t" \ - "addq %[T0], %%rax \n\t" \ - "adcq %%rdx, %[T1] \n\t" \ - "adcq $0, %[cy] # cy:T1 <- (M[0]*u + cy * b * b + T1 * b + T0) / b\n\t" - -#define MONT_ITERITER(i, j) \ - "xorq %[T0], %[T0] \n\t" \ - "movq " STR((i*8)) "(%[A]), %%rax \n\t" \ - "mulq " STR((j*8)) "(%[B]) \n\t" \ - "addq %[T1], %%rax \n\t" \ - "movq %%rax, " STR(((j-1)*8)) "(%[tmp]) \n\t" \ - "adcq $0, %%rdx \n\t" \ - "movq %%rdx, %[T1] # now T1:tmp[j-1] <-- X[i] * Y[j] + T1 \n\t" \ - "movq " STR((j*8)) "(%[M]), %%rax \n\t" \ - "mulq %[u] \n\t" \ - "addq %%rax, " STR(((j-1)*8)) "(%[tmp]) \n\t" \ - "adcq %[cy], %%rdx \n\t" \ - "adcq $0, %[T0] \n\t" \ - "xorq %[cy], %[cy] \n\t" \ - "addq %%rdx, %[T1] \n\t" \ - "adcq %[T0], %[cy] # cy:T1:tmp[j-1] <-- (X[i] * Y[j] + T1) + M[j] * u + cy * b \n\t" \ - "addq " STR(((j+1)*8)) "(%[tmp]), %[T1] \n\t" \ - "adcq $0, %[cy] # cy:T1:tmp[j-1] <-- (X[i] * Y[j] + T1) + M[j] * u + (tmp[j+1] + cy) * b \n\t" - -#define MONT_FINALIZE(j) \ - "movq %[T1], " STR((j*8)) "(%[tmp]) \n\t" \ - "movq %[cy], " STR(((j+1)*8)) "(%[tmp]) \n\t" - -/* - Comba multiplication and squaring routines are based on the - public-domain tomsfastmath library by Tom St Denis - - - - Compared to the above, we save 5-20% of cycles by using careful register - renaming to implement Comba forward operation. - */ - -#define COMBA_3_BY_3_MUL(c0_, c1_, c2_, res_, A_, B_) \ - asm volatile ( \ - "movq 0(%[A]), %%rax \n\t" \ - "mulq 0(%[B]) \n\t" \ - "movq %%rax, 0(%[res]) \n\t" \ - "movq %%rdx, %[c0] \n\t" \ - \ - "xorq %[c1], %[c1] \n\t" \ - "movq 0(%[A]), %%rax \n\t" \ - "mulq 8(%[B]) \n\t" \ - "addq %%rax, %[c0] \n\t" \ - "adcq %%rdx, %[c1] \n\t" \ - \ - "xorq %[c2], %[c2] \n\t" \ - "movq 8(%[A]), %%rax \n\t" \ - "mulq 0(%[B]) \n\t" \ - "addq %%rax, %[c0] \n\t" \ - "movq %[c0], 8(%[res]) \n\t" \ - "adcq %%rdx, %[c1] \n\t" \ - "adcq $0, %[c2] \n\t" \ - \ - "// register renaming (c1, c2, c0)\n\t" \ - "xorq %[c0], %[c0] \n\t" \ - "movq 0(%[A]), %%rax \n\t" \ - "mulq 16(%[B]) \n\t" \ - "addq %%rax, %[c1] \n\t" \ - "adcq %%rdx, %[c2] \n\t" \ - "adcq $0, %[c0] \n\t" \ - \ - "movq 8(%[A]), %%rax \n\t" \ - "mulq 8(%[B]) \n\t" \ - "addq %%rax, %[c1] \n\t" \ - "adcq %%rdx, %[c2] \n\t" \ - "adcq $0, %[c0] \n\t" \ - \ - "movq 16(%[A]), %%rax \n\t" \ - "mulq 0(%[B]) \n\t" \ - "addq %%rax, %[c1] \n\t" \ - "movq %[c1], 16(%[res]) \n\t" \ - "adcq %%rdx, %[c2] \n\t" \ - "adcq $0, %[c0] \n\t" \ - \ - "// register renaming (c2, c0, c1)\n\t" \ - "xorq %[c1], %[c1] \n\t" \ - "movq 8(%[A]), %%rax \n\t" \ - "mulq 16(%[B]) \n\t" \ - "addq %%rax, %[c2] \n\t" \ - "adcq %%rdx, %[c0] \n\t" \ - "adcq $0, %[c1] \n\t" \ - \ - "movq 16(%[A]), %%rax \n\t" \ - "mulq 8(%[B]) \n\t" \ - "addq %%rax, %[c2] \n\t" \ - "movq %[c2], 24(%[res]) \n\t" \ - "adcq %%rdx, %[c0] \n\t" \ - "adcq $0, %[c1] \n\t" \ - \ - "// register renaming (c0, c1, c2)\n\t" \ - "xorq %[c2], %[c2] \n\t" \ - "movq 16(%[A]), %%rax \n\t" \ - "mulq 16(%[B]) \n\t" \ - "addq %%rax, %[c0] \n\t" \ - "movq %[c0], 32(%[res]) \n\t" \ - "adcq %%rdx, %[c1] \n\t" \ - "movq %[c1], 40(%[res]) \n\t" \ - : [c0] "=&r" (c0_), [c1] "=&r" (c1_), [c2] "=&r" (c2_) \ - : [res] "r" (res_), [A] "r" (A_), [B] "r" (B_) \ - : "%rax", "%rdx", "cc", "memory") - -#define COMBA_3_BY_3_SQR(c0_, c1_, c2_, res_, A_) \ - asm volatile ( \ - "xorq %[c1], %[c1] \n\t" \ - "xorq %[c2], %[c2] \n\t" \ - "movq 0(%[A]), %%rax \n\t" \ - "mulq %%rax \n\t" \ - "movq %%rax, 0(%[res]) \n\t" \ - "movq %%rdx, %[c0] \n\t" \ - \ - "movq 0(%[A]), %%rax \n\t" \ - "mulq 8(%[A]) \n\t" \ - "addq %%rax, %[c0] \n\t" \ - "adcq %%rdx, %[c1] \n\t" \ - "addq %%rax, %[c0] \n\t" \ - "movq %[c0], 8(%[res]) \n\t" \ - "adcq %%rdx, %[c1] \n\t" \ - "adcq $0, %[c2] \n\t" \ - \ - "// register renaming (c1, c2, c0)\n\t" \ - "movq 0(%[A]), %%rax \n\t" \ - "xorq %[c0], %[c0] \n\t" \ - "mulq 16(%[A]) \n\t" \ - "addq %%rax, %[c1] \n\t" \ - "adcq %%rdx, %[c2] \n\t" \ - "adcq $0, %[c0] \n\t" \ - "addq %%rax, %[c1] \n\t" \ - "adcq %%rdx, %[c2] \n\t" \ - "adcq $0, %[c0] \n\t" \ - \ - "movq 8(%[A]), %%rax \n\t" \ - "mulq %%rax \n\t" \ - "addq %%rax, %[c1] \n\t" \ - "movq %[c1], 16(%[res]) \n\t" \ - "adcq %%rdx, %[c2] \n\t" \ - "adcq $0, %[c0] \n\t" \ - \ - "// register renaming (c2, c0, c1)\n\t" \ - "movq 8(%[A]), %%rax \n\t" \ - "xorq %[c1], %[c1] \n\t" \ - "mulq 16(%[A]) \n\t" \ - "addq %%rax, %[c2] \n\t" \ - "adcq %%rdx, %[c0] \n\t" \ - "adcq $0, %[c1] \n\t" \ - "addq %%rax, %[c2] \n\t" \ - "movq %[c2], 24(%[res]) \n\t" \ - "adcq %%rdx, %[c0] \n\t" \ - "adcq $0, %[c1] \n\t" \ - \ - "// register renaming (c0, c1, c2)\n\t" \ - "movq 16(%[A]), %%rax \n\t" \ - "mulq %%rax \n\t" \ - "addq %%rax, %[c0] \n\t" \ - "movq %[c0], 32(%[res]) \n\t" \ - "adcq %%rdx, %[c1] \n\t" \ - "movq %[c1], 40(%[res]) \n\t" \ - \ - : [c0] "=&r" (c0_), [c1] "=&r" (c1_), [c2] "=&r" (c2_) \ - : [res] "r" (res_), [A] "r" (A_) \ - : "%rax", "%rdx", "cc", "memory") - -/* - The Montgomery reduction here is based on Algorithm 14.32 in - Handbook of Applied Cryptography - . - */ -#define REDUCE_6_LIMB_PRODUCT(k_, tmp1_, tmp2_, tmp3_, inv_, res_, mod_) \ - __asm__ volatile \ - ("///////////////////////////////////\n\t" \ - "movq 0(%[res]), %%rax \n\t" \ - "mulq %[modprime] \n\t" \ - "movq %%rax, %[k] \n\t" \ - \ - "movq (%[mod]), %%rax \n\t" \ - "mulq %[k] \n\t" \ - "movq %%rax, %[tmp1] \n\t" \ - "movq %%rdx, %[tmp2] \n\t" \ - \ - "xorq %[tmp3], %[tmp3] \n\t" \ - "movq 8(%[mod]), %%rax \n\t" \ - "mulq %[k] \n\t" \ - "addq %[tmp1], 0(%[res]) \n\t" \ - "adcq %%rax, %[tmp2] \n\t" \ - "adcq %%rdx, %[tmp3] \n\t" \ - \ - "xorq %[tmp1], %[tmp1] \n\t" \ - "movq 16(%[mod]), %%rax \n\t" \ - "mulq %[k] \n\t" \ - "addq %[tmp2], 8(%[res]) \n\t" \ - "adcq %%rax, %[tmp3] \n\t" \ - "adcq %%rdx, %[tmp1] \n\t" \ - \ - "addq %[tmp3], 16(%[res]) \n\t" \ - "adcq %[tmp1], 24(%[res]) \n\t" \ - "adcq $0, 32(%[res]) \n\t" \ - "adcq $0, 40(%[res]) \n\t" \ - \ - "///////////////////////////////////\n\t" \ - "movq 8(%[res]), %%rax \n\t" \ - "mulq %[modprime] \n\t" \ - "movq %%rax, %[k] \n\t" \ - \ - "movq (%[mod]), %%rax \n\t" \ - "mulq %[k] \n\t" \ - "movq %%rax, %[tmp1] \n\t" \ - "movq %%rdx, %[tmp2] \n\t" \ - \ - "xorq %[tmp3], %[tmp3] \n\t" \ - "movq 8(%[mod]), %%rax \n\t" \ - "mulq %[k] \n\t" \ - "addq %[tmp1], 8(%[res]) \n\t" \ - "adcq %%rax, %[tmp2] \n\t" \ - "adcq %%rdx, %[tmp3] \n\t" \ - \ - "xorq %[tmp1], %[tmp1] \n\t" \ - "movq 16(%[mod]), %%rax \n\t" \ - "mulq %[k] \n\t" \ - "addq %[tmp2], 16(%[res]) \n\t" \ - "adcq %%rax, %[tmp3] \n\t" \ - "adcq %%rdx, %[tmp1] \n\t" \ - \ - "addq %[tmp3], 24(%[res]) \n\t" \ - "adcq %[tmp1], 32(%[res]) \n\t" \ - "adcq $0, 40(%[res]) \n\t" \ - \ - "///////////////////////////////////\n\t" \ - "movq 16(%[res]), %%rax \n\t" \ - "mulq %[modprime] \n\t" \ - "movq %%rax, %[k] \n\t" \ - \ - "movq (%[mod]), %%rax \n\t" \ - "mulq %[k] \n\t" \ - "movq %%rax, %[tmp1] \n\t" \ - "movq %%rdx, %[tmp2] \n\t" \ - \ - "xorq %[tmp3], %[tmp3] \n\t" \ - "movq 8(%[mod]), %%rax \n\t" \ - "mulq %[k] \n\t" \ - "addq %[tmp1], 16(%[res]) \n\t" \ - "adcq %%rax, %[tmp2] \n\t" \ - "adcq %%rdx, %[tmp3] \n\t" \ - \ - "xorq %[tmp1], %[tmp1] \n\t" \ - "movq 16(%[mod]), %%rax \n\t" \ - "mulq %[k] \n\t" \ - "addq %[tmp2], 24(%[res]) \n\t" \ - "adcq %%rax, %[tmp3] \n\t" \ - "adcq %%rdx, %[tmp1] \n\t" \ - \ - "addq %[tmp3], 32(%[res]) \n\t" \ - "adcq %[tmp1], 40(%[res]) \n\t" \ - : [k] "=&r" (k_), [tmp1] "=&r" (tmp1_), [tmp2] "=&r" (tmp2_), [tmp3] "=&r" (tmp3_) \ - : [modprime] "r" (inv_), [res] "r" (res_), [mod] "r" (mod_) \ - : "%rax", "%rdx", "cc", "memory") - -} // libsnark -#endif // FP_AUX_TCC_ diff --git a/src/snark/libsnark/algebra/fields/tests/test_bigint.cpp b/src/snark/libsnark/algebra/fields/tests/test_bigint.cpp deleted file mode 100644 index 24832ed5103..00000000000 --- a/src/snark/libsnark/algebra/fields/tests/test_bigint.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/** - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#include "algebra/fields/bigint.hpp" - -#include - -using namespace libsnark; - -TEST(algebra, bigint) -{ - static_assert(GMP_NUMB_BITS == 64, "GMP limb not 64-bit"); - - const char *b1_decimal = "76749407"; - const char *b2_decimal = "435020359732196472065729437602"; - const char *b3_decimal = "33387554642372758038536799358397002014"; - const char *b2_binary = "0000000000000000000000000000010101111101101000000110100001011010" - "1101101010001001000001101000101000100110011001110001111110100010"; - - bigint<1> b0 = bigint<1>(UINT64_C(0)); - bigint<1> b1 = bigint<1>(b1_decimal); - bigint<2> b2 = bigint<2>(b2_decimal); - - EXPECT_EQ(b0.as_uint64(), UINT64_C(0)); - EXPECT_TRUE(b0.is_zero()); - EXPECT_EQ(b1.as_uint64(), UINT64_C(76749407)); - EXPECT_FALSE(b1.is_zero()); - EXPECT_EQ(b2.as_uint64(), UINT64_C(15747124762497195938)); - EXPECT_FALSE(b2.is_zero()); - EXPECT_NE(b0, b1); - EXPECT_FALSE(b0 == b1); - - EXPECT_EQ(b2.max_bits(), 128u); - EXPECT_EQ(b2.num_bits(), 99u); - for (size_t i = 0; i < 128; i++) { - EXPECT_EQ(b2.test_bit(i), (b2_binary[127-i] == '1')); - } - - bigint<3> b3 = b2 * b1; - - EXPECT_EQ(b3, bigint<3>(b3_decimal)); - EXPECT_FALSE(b3.is_zero()); - - bigint<3> b3a { b3 }; - EXPECT_EQ(b3a, bigint<3>(b3_decimal)); - EXPECT_EQ(b3a, b3); - EXPECT_FALSE(b3a.is_zero()); - - mpz_t m3; - mpz_init(m3); - b3.to_mpz(m3); - bigint<3> b3b { m3 }; - EXPECT_EQ(b3b, b3); - - bigint<2> quotient; - bigint<2> remainder; - bigint<3>::div_qr(quotient, remainder, b3, b2); - EXPECT_LT(quotient.num_bits(), static_cast(GMP_NUMB_BITS)); - EXPECT_EQ(quotient.as_uint64(), b1.as_uint64()); - bigint<1> b1inc = bigint<1>("76749408"); - bigint<1> b1a = quotient.shorten(b1inc, "test"); - EXPECT_EQ(b1a, b1); - EXPECT_TRUE(remainder.is_zero()); - remainder.limit(b2, "test"); - - EXPECT_THROW((void)(quotient.shorten(b1, "test")), std::domain_error); - EXPECT_THROW(remainder.limit(remainder, "test"), std::domain_error); - - bigint<1> br = bigint<1>("42"); - b3 += br; - EXPECT_NE(b3, b3a); - EXPECT_GT(b3, b3a); - EXPECT_FALSE(b3a > b3); - - bigint<3>::div_qr(quotient, remainder, b3, b2); - EXPECT_LT(quotient.num_bits(), static_cast(GMP_NUMB_BITS)); - EXPECT_EQ(quotient.as_uint64(), b1.as_uint64()); - EXPECT_LT(remainder.num_bits(), static_cast(GMP_NUMB_BITS)); - EXPECT_EQ(remainder.as_uint64(), 42u); - - b3a.clear(); - EXPECT_TRUE(b3a.is_zero()); - EXPECT_EQ(b3a.num_bits(), 0u); - EXPECT_FALSE(b3.is_zero()); - - bigint<4> bx = bigint<4>().randomize(); - bigint<4> by = bigint<4>().randomize(); - EXPECT_FALSE(bx == by); - - // TODO: test serialization -} - diff --git a/src/snark/libsnark/algebra/fields/tests/test_fields.cpp b/src/snark/libsnark/algebra/fields/tests/test_fields.cpp deleted file mode 100644 index 2101fad9db1..00000000000 --- a/src/snark/libsnark/algebra/fields/tests/test_fields.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/** - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ -#include "common/profiling.hpp" -#ifdef CURVE_BN128 -#include "algebra/curves/bn128/bn128_pp.hpp" -#endif -#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp" -#include "algebra/fields/fp6_3over2.hpp" -#include "algebra/fields/fp12_2over3over2.hpp" - -#include - -using namespace libsnark; - -template -void test_field() -{ - bigint<1> rand1 = bigint<1>("76749407"); - bigint<1> rand2 = bigint<1>("44410867"); - bigint<1> randsum = bigint<1>("121160274"); - - FieldT zero = FieldT::zero(); - FieldT one = FieldT::one(); - FieldT a = FieldT::random_element(); - FieldT a_ser; - a_ser = reserialize(a); - EXPECT_EQ(a_ser, a); - - FieldT b = FieldT::random_element(); - FieldT c = FieldT::random_element(); - FieldT d = FieldT::random_element(); - - EXPECT_NE(a, zero); - EXPECT_NE(a, one); - - EXPECT_EQ(a * a, a.squared()); - EXPECT_EQ((a + b).squared(), a.squared() + a*b + b*a + b.squared()); - EXPECT_EQ((a + b)*(c + d), a*c + a*d + b*c + b*d); - EXPECT_EQ(a - b, a + (-b)); - EXPECT_EQ(a - b, (-b) + a); - - EXPECT_EQ((a ^ rand1) * (a ^ rand2), (a^randsum)); - - EXPECT_EQ(a * a.inverse(), one); - EXPECT_EQ((a + b) * c.inverse(), a * c.inverse() + (b.inverse() * c).inverse()); - -} - -template -void test_sqrt() -{ - for (size_t i = 0; i < 100; ++i) - { - FieldT a = FieldT::random_element(); - FieldT asq = a.squared(); - EXPECT_TRUE(asq.sqrt() == a || asq.sqrt() == -a); - } -} - -template -void test_two_squarings() -{ - FieldT a = FieldT::random_element(); - EXPECT_EQ(a.squared(), a * a); - EXPECT_EQ(a.squared(), a.squared_complex()); - EXPECT_EQ(a.squared(), a.squared_karatsuba()); -} - -template -void test_Frobenius() -{ - FieldT a = FieldT::random_element(); - EXPECT_EQ(a.Frobenius_map(0), a); - FieldT a_q = a ^ FieldT::base_field_char(); - for (size_t power = 1; power < 10; ++power) - { - const FieldT a_qi = a.Frobenius_map(power); - EXPECT_EQ(a_qi, a_q); - - a_q = a_q ^ FieldT::base_field_char(); - } -} - -template -void test_unitary_inverse() -{ - EXPECT_EQ(FieldT::extension_degree() % 2, 0u); - FieldT a = FieldT::random_element(); - FieldT aqcubed_minus1 = a.Frobenius_map(FieldT::extension_degree()/2) * a.inverse(); - EXPECT_EQ(aqcubed_minus1.inverse(), aqcubed_minus1.unitary_inverse()); -} - -template -void test_all_fields() -{ - test_field >(); - test_field >(); - test_field >(); - test_field >(); - - test_sqrt >(); - test_sqrt >(); - test_sqrt >(); - - test_Frobenius >(); - test_Frobenius >(); - - test_unitary_inverse >(); -} - -template -void test_Fp4_tom_cook() -{ - typedef typename Fp4T::my_Fp FieldT; - for (size_t i = 0; i < 100; ++i) - { - const Fp4T a = Fp4T::random_element(); - const Fp4T b = Fp4T::random_element(); - const Fp4T correct_res = a * b; - - Fp4T res; - - const FieldT - &a0 = a.c0.c0, - &a1 = a.c1.c0, - &a2 = a.c0.c1, - &a3 = a.c1.c1; - - const FieldT - &b0 = b.c0.c0, - &b1 = b.c1.c0, - &b2 = b.c0.c1, - &b3 = b.c1.c1; - - FieldT - &c0 = res.c0.c0, - &c1 = res.c1.c0, - &c2 = res.c0.c1, - &c3 = res.c1.c1; - - const FieldT v0 = a0 * b0; - const FieldT v1 = (a0 + a1 + a2 + a3) * (b0 + b1 + b2 + b3); - const FieldT v2 = (a0 - a1 + a2 - a3) * (b0 - b1 + b2 - b3); - const FieldT v3 = (a0 + FieldT(2)*a1 + FieldT(4)*a2 + FieldT(8)*a3) * (b0 + FieldT(2)*b1 + FieldT(4)*b2 + FieldT(8)*b3); - const FieldT v4 = (a0 - FieldT(2)*a1 + FieldT(4)*a2 - FieldT(8)*a3) * (b0 - FieldT(2)*b1 + FieldT(4)*b2 - FieldT(8)*b3); - const FieldT v5 = (a0 + FieldT(3)*a1 + FieldT(9)*a2 + FieldT(27)*a3) * (b0 + FieldT(3)*b1 + FieldT(9)*b2 + FieldT(27)*b3); - const FieldT v6 = a3 * b3; - - const FieldT beta = Fp4T::non_residue; - - c0 = v0 + beta*(FieldT(4).inverse()*v0 - FieldT(6).inverse()*(v1 + v2) + FieldT(24).inverse() * (v3 + v4) - FieldT(5) * v6); - c1 = - FieldT(3).inverse()*v0 + v1 - FieldT(2).inverse()*v2 - FieldT(4).inverse()*v3 + FieldT(20).inverse() * v4 + FieldT(30).inverse() * v5 - FieldT(12) * v6 + beta * ( - FieldT(12).inverse() * (v0 - v1) + FieldT(24).inverse()*(v2 - v3) - FieldT(120).inverse() * (v4 - v5) - FieldT(3) * v6); - c2 = - (FieldT(5)*(FieldT(4).inverse()))* v0 + (FieldT(2)*(FieldT(3).inverse()))*(v1 + v2) - FieldT(24).inverse()*(v3 + v4) + FieldT(4)*v6 + beta*v6; - c3 = FieldT(12).inverse() * (FieldT(5)*v0 - FieldT(7)*v1) - FieldT(24).inverse()*(v2 - FieldT(7)*v3 + v4 + v5) + FieldT(15)*v6; - - EXPECT_EQ(res, correct_res); - - // {v0, v3, v4, v5} - const FieldT u = (FieldT::one() - beta).inverse(); - EXPECT_EQ(v0, u * c0 + beta * u * c2 - beta * u * FieldT(2).inverse() * v1 - beta * u * FieldT(2).inverse() * v2 + beta * v6); - EXPECT_EQ(v3, - FieldT(15) * u * c0 - FieldT(30) * u * c1 - FieldT(3) * (FieldT(4) + beta) * u * c2 - FieldT(6) * (FieldT(4) + beta) * u * c3 + (FieldT(24) - FieldT(3) * beta * FieldT(2).inverse()) * u * v1 + (-FieldT(8) + beta * FieldT(2).inverse()) * u * v2 - - FieldT(3) * (-FieldT(16) + beta) * v6); - EXPECT_EQ(v4, - FieldT(15) * u * c0 + FieldT(30) * u * c1 - FieldT(3) * (FieldT(4) + beta) * u * c2 + FieldT(6) * (FieldT(4) + beta) * u * c3 + (FieldT(24) - FieldT(3) * beta * FieldT(2).inverse()) * u * v2 + (-FieldT(8) + beta * FieldT(2).inverse()) * u * v1 - - FieldT(3) * (-FieldT(16) + beta) * v6); - EXPECT_EQ(v5, - FieldT(80) * u * c0 - FieldT(240) * u * c1 - FieldT(8) * (FieldT(9) + beta) * u * c2 - FieldT(24) * (FieldT(9) + beta) * u * c3 - FieldT(2) * (-FieldT(81) + beta) * u * v1 + (-FieldT(81) + beta) * u * v2 - - FieldT(8) * (-FieldT(81) + beta) * v6); - - // c0 + beta c2 - (beta v1)/2 - (beta v2)/ 2 - (-1 + beta) beta v6, - // -15 c0 - 30 c1 - 3 (4 + beta) c2 - 6 (4 + beta) c3 + (24 - (3 beta)/2) v1 + (-8 + beta/2) v2 + 3 (-16 + beta) (-1 + beta) v6, - // -15 c0 + 30 c1 - 3 (4 + beta) c2 + 6 (4 + beta) c3 + (-8 + beta/2) v1 + (24 - (3 beta)/2) v2 + 3 (-16 + beta) (-1 + beta) v6, - // -80 c0 - 240 c1 - 8 (9 + beta) c2 - 24 (9 + beta) c3 - 2 (-81 + beta) v1 + (-81 + beta) v2 + 8 (-81 + beta) (-1 + beta) v6 - } -} - -TEST(algebra, fields) -{ - alt_bn128_pp::init_public_params(); - test_field(); - test_Frobenius(); - test_all_fields(); - -#ifdef CURVE_BN128 // BN128 has fancy dependencies so it may be disabled - bn128_pp::init_public_params(); - test_field >(); - test_field >(); -#endif -} diff --git a/src/snark/libsnark/algebra/knowledge_commitment/knowledge_commitment.hpp b/src/snark/libsnark/algebra/knowledge_commitment/knowledge_commitment.hpp deleted file mode 100644 index 90242313455..00000000000 --- a/src/snark/libsnark/algebra/knowledge_commitment/knowledge_commitment.hpp +++ /dev/null @@ -1,84 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for: - - a knowledge commitment, and - - a knowledge commitment vector. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef KNOWLEDGE_COMMITMENT_HPP_ -#define KNOWLEDGE_COMMITMENT_HPP_ - -#include "algebra/fields/fp.hpp" -#include "common/data_structures/sparse_vector.hpp" - -namespace libsnark { - -/********************** Knowledge commitment *********************************/ - -/** - * A knowledge commitment is a pair (g,h) where g is in T1 and h in T2, - * and T1 and T2 are groups (written additively). - * - * Such pairs form a group by defining: - * - "zero" = (0,0) - * - "one" = (1,1) - * - a * (g,h) + b * (g',h') := ( a * g + b * g', a * h + b * h'). - */ -template -struct knowledge_commitment { - - T1 g; - T2 h; - - knowledge_commitment() = default; - knowledge_commitment(const knowledge_commitment &other) = default; - knowledge_commitment(knowledge_commitment &&other) = default; - knowledge_commitment(const T1 &g, const T2 &h); - - knowledge_commitment& operator=(const knowledge_commitment &other) = default; - knowledge_commitment& operator=(knowledge_commitment &&other) = default; - knowledge_commitment operator+(const knowledge_commitment &other) const; - - bool is_zero() const; - bool operator==(const knowledge_commitment &other) const; - bool operator!=(const knowledge_commitment &other) const; - - static knowledge_commitment zero(); - static knowledge_commitment one(); - - void print() const; - - static size_t size_in_bits(); -}; - -template -knowledge_commitment operator*(const bigint &lhs, const knowledge_commitment &rhs); - -template &modulus_p> -knowledge_commitment operator*(const Fp_model &lhs, const knowledge_commitment &rhs); - -template -std::ostream& operator<<(std::ostream& out, const knowledge_commitment &kc); - -template -std::istream& operator>>(std::istream& in, knowledge_commitment &kc); - -/******************** Knowledge commitment vector ****************************/ - -/** - * A knowledge commitment vector is a sparse vector of knowledge commitments. - */ -template -using knowledge_commitment_vector = sparse_vector >; - -} // libsnark - -#include "algebra/knowledge_commitment/knowledge_commitment.tcc" - -#endif // KNOWLEDGE_COMMITMENT_HPP_ diff --git a/src/snark/libsnark/algebra/knowledge_commitment/knowledge_commitment.tcc b/src/snark/libsnark/algebra/knowledge_commitment/knowledge_commitment.tcc deleted file mode 100644 index 15b2926c8ad..00000000000 --- a/src/snark/libsnark/algebra/knowledge_commitment/knowledge_commitment.tcc +++ /dev/null @@ -1,111 +0,0 @@ -/** @file - ***************************************************************************** - - Implementation of interfaces for: - - a knowledge commitment, and - - a knowledge commitment vector. - - See knowledge_commitment.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef KNOWLEDGE_COMMITMENT_TCC_ -#define KNOWLEDGE_COMMITMENT_TCC_ - -namespace libsnark { - -template -knowledge_commitment::knowledge_commitment(const T1 &g, const T2 &h) : - g(g), h(h) -{ -} - -template -knowledge_commitment knowledge_commitment::zero() -{ - return knowledge_commitment(T1::zero(), T2::zero()); -} - -template -knowledge_commitment knowledge_commitment::one() -{ - return knowledge_commitment(T1::one(), T2::one()); -} - -template -knowledge_commitment knowledge_commitment::operator+(const knowledge_commitment &other) const -{ - return knowledge_commitment(this->g + other.g, - this->h + other.h); -} - -template -bool knowledge_commitment::is_zero() const -{ - return (g.is_zero() && h.is_zero()); -} - -template -bool knowledge_commitment::operator==(const knowledge_commitment &other) const -{ - return (this->g == other.g && - this->h == other.h); -} - -template -bool knowledge_commitment::operator!=(const knowledge_commitment &other) const -{ - return !((*this) == other); -} - -template -knowledge_commitment operator*(const bigint &lhs, const knowledge_commitment &rhs) -{ - return knowledge_commitment(lhs * rhs.g, - lhs * rhs.h); -} - -template &modulus_p> -knowledge_commitment operator*(const Fp_model &lhs, const knowledge_commitment &rhs) -{ - return (lhs.as_bigint()) * rhs; -} - -template -void knowledge_commitment::print() const -{ - printf("knowledge_commitment.g:\n"); - g.print(); - printf("knowledge_commitment.h:\n"); - h.print(); -} - -template -size_t knowledge_commitment::size_in_bits() -{ - return T1::size_in_bits() + T2::size_in_bits(); -} - -template -std::ostream& operator<<(std::ostream& out, const knowledge_commitment &kc) -{ - out << kc.g << OUTPUT_SEPARATOR << kc.h; - return out; -} - -template -std::istream& operator>>(std::istream& in, knowledge_commitment &kc) -{ - in >> kc.g; - consume_OUTPUT_SEPARATOR(in); - in >> kc.h; - return in; -} - -} // libsnark - -#endif // KNOWLEDGE_COMMITMENT_TCC_ diff --git a/src/snark/libsnark/algebra/scalar_multiplication/kc_multiexp.hpp b/src/snark/libsnark/algebra/scalar_multiplication/kc_multiexp.hpp deleted file mode 100644 index 27e48f82179..00000000000 --- a/src/snark/libsnark/algebra/scalar_multiplication/kc_multiexp.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef KC_MULTIEXP_HPP_ -#define KC_MULTIEXP_HPP_ - -/* - Split out from multiexp to prevent cyclical - dependencies. I.e. previously multiexp depended on - knowledge_commitment, which depended on sparse_vector, which - depended on multiexp (to do accumulate). - - Will probably go away in more general exp refactoring. -*/ - -#include "algebra/knowledge_commitment/knowledge_commitment.hpp" - -namespace libsnark { - -template -knowledge_commitment opt_window_wnaf_exp(const knowledge_commitment &base, - const bigint &scalar, const size_t scalar_bits); - -template -knowledge_commitment kc_multi_exp_with_mixed_addition(const knowledge_commitment_vector &vec, - const size_t min_idx, - const size_t max_idx, - typename std::vector::const_iterator scalar_start, - typename std::vector::const_iterator scalar_end, - const size_t chunks, - const bool use_multiexp=false); - -template -void kc_batch_to_special(std::vector > &vec); - -template -knowledge_commitment_vector kc_batch_exp(const size_t scalar_size, - const size_t T1_window, - const size_t T2_window, - const window_table &T1_table, - const window_table &T2_table, - const FieldT &T1_coeff, - const FieldT &T2_coeff, - const std::vector &v, - const size_t suggested_num_chunks); - -} // libsnark - -#include "algebra/scalar_multiplication/kc_multiexp.tcc" - -#endif // KC_MULTIEXP_HPP_ diff --git a/src/snark/libsnark/algebra/scalar_multiplication/kc_multiexp.tcc b/src/snark/libsnark/algebra/scalar_multiplication/kc_multiexp.tcc deleted file mode 100644 index e9c08d4bcea..00000000000 --- a/src/snark/libsnark/algebra/scalar_multiplication/kc_multiexp.tcc +++ /dev/null @@ -1,274 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef KC_MULTIEXP_TCC_ -#define KC_MULTIEXP_TCC_ - -namespace libsnark { - -template -knowledge_commitment opt_window_wnaf_exp(const knowledge_commitment &base, - const bigint &scalar, const size_t scalar_bits) -{ - return knowledge_commitment(opt_window_wnaf_exp(base.g, scalar, scalar_bits), - opt_window_wnaf_exp(base.h, scalar, scalar_bits)); -} - -template -knowledge_commitment kc_multi_exp_with_mixed_addition(const knowledge_commitment_vector &vec, - const size_t min_idx, - const size_t max_idx, - typename std::vector::const_iterator scalar_start, - typename std::vector::const_iterator scalar_end, - const size_t chunks, - const bool use_multiexp) -{ - enter_block("Process scalar vector"); - auto index_it = std::lower_bound(vec.indices.begin(), vec.indices.end(), min_idx); - const size_t offset = index_it - vec.indices.begin(); - - auto value_it = vec.values.begin() + offset; - - const FieldT zero = FieldT::zero(); - const FieldT one = FieldT::one(); - - std::vector p; - std::vector > g; - - knowledge_commitment acc = knowledge_commitment::zero(); - - size_t num_skip = 0; - size_t num_add = 0; - size_t num_other = 0; - - const size_t scalar_length = std::distance(scalar_start, scalar_end); - - while (index_it != vec.indices.end() && *index_it < max_idx) - { - const size_t scalar_position = (*index_it) - min_idx; - assert(scalar_position < scalar_length); - - const FieldT scalar = *(scalar_start + scalar_position); - - if (scalar == zero) - { - // do nothing - ++num_skip; - } - else if (scalar == one) - { -#ifdef USE_MIXED_ADDITION - acc.g = acc.g.mixed_add(value_it->g); - acc.h = acc.h.mixed_add(value_it->h); -#else - acc.g = acc.g + value_it->g; - acc.h = acc.h + value_it->h; -#endif - ++num_add; - } - else - { - p.emplace_back(scalar); - g.emplace_back(*value_it); - ++num_other; - } - - ++index_it; - ++value_it; - } - - //print_indent(); printf("* Elements of w skipped: %zu (%0.2f%%)\n", num_skip, 100.*num_skip/(num_skip+num_add+num_other)); - //print_indent(); printf("* Elements of w processed with special addition: %zu (%0.2f%%)\n", num_add, 100.*num_add/(num_skip+num_add+num_other)); - //print_indent(); printf("* Elements of w remaining: %zu (%0.2f%%)\n", num_other, 100.*num_other/(num_skip+num_add+num_other)); - leave_block("Process scalar vector"); - - return acc + multi_exp, FieldT>(g.begin(), g.end(), p.begin(), p.end(), chunks, use_multiexp); -} - -template -void kc_batch_to_special(std::vector > &vec) -{ - enter_block("Batch-convert knowledge-commitments to special form"); - - std::vector g_vec; - g_vec.reserve(vec.size()); - - for (size_t i = 0; i < vec.size(); ++i) - { - if (!vec[i].g.is_zero()) - { - g_vec.emplace_back(vec[i].g); - } - } - - batch_to_special_all_non_zeros(g_vec); - auto g_it = g_vec.begin(); - T1 T1_zero_special = T1::zero(); - T1_zero_special.to_special(); - - for (size_t i = 0; i < vec.size(); ++i) - { - if (!vec[i].g.is_zero()) - { - vec[i].g = *g_it; - ++g_it; - } - else - { - vec[i].g = T1_zero_special; - } - } - - g_vec.clear(); - - std::vector h_vec; - h_vec.reserve(vec.size()); - - for (size_t i = 0; i < vec.size(); ++i) - { - if (!vec[i].h.is_zero()) - { - h_vec.emplace_back(vec[i].h); - } - } - - batch_to_special_all_non_zeros(h_vec); - auto h_it = h_vec.begin(); - T2 T2_zero_special = T2::zero(); - T2_zero_special.to_special(); - - for (size_t i = 0; i < vec.size(); ++i) - { - if (!vec[i].h.is_zero()) - { - vec[i].h = *h_it; - ++h_it; - } - else - { - vec[i].h = T2_zero_special; - } - } - - g_vec.clear(); - - leave_block("Batch-convert knowledge-commitments to special form"); -} - -template -knowledge_commitment_vector kc_batch_exp_internal(const size_t scalar_size, - const size_t T1_window, - const size_t T2_window, - const window_table &T1_table, - const window_table &T2_table, - const FieldT &T1_coeff, - const FieldT &T2_coeff, - const std::vector &v, - const size_t start_pos, - const size_t end_pos, - const size_t expected_size) -{ - knowledge_commitment_vector res; - - res.values.reserve(expected_size); - res.indices.reserve(expected_size); - - for (size_t pos = start_pos; pos != end_pos; ++pos) - { - if (!v[pos].is_zero()) - { - res.values.emplace_back(knowledge_commitment(windowed_exp(scalar_size, T1_window, T1_table, T1_coeff * v[pos]), - windowed_exp(scalar_size, T2_window, T2_table, T2_coeff * v[pos]))); - res.indices.emplace_back(pos); - } - } - - return res; -} - -template -knowledge_commitment_vector kc_batch_exp(const size_t scalar_size, - const size_t T1_window, - const size_t T2_window, - const window_table &T1_table, - const window_table &T2_table, - const FieldT &T1_coeff, - const FieldT &T2_coeff, - const std::vector &v, - const size_t suggested_num_chunks) -{ - knowledge_commitment_vector res; - res.domain_size_ = v.size(); - - size_t nonzero = 0; - for (size_t i = 0; i < v.size(); ++i) - { - nonzero += (v[i].is_zero() ? 0 : 1); - } - - const size_t num_chunks = std::max((size_t)1, std::min(nonzero, suggested_num_chunks)); - - if (!inhibit_profiling_info) - { - print_indent(); printf("Non-zero coordinate count: %zu/%zu (%0.2f%%)\n", nonzero, v.size(), 100.*nonzero/v.size()); - } - - std::vector > tmp(num_chunks); - std::vector chunk_pos(num_chunks+1); - - const size_t chunk_size = nonzero / num_chunks; - const size_t last_chunk = nonzero - chunk_size * (num_chunks - 1); - - chunk_pos[0] = 0; - - size_t cnt = 0; - size_t chunkno = 1; - - for (size_t i = 0; i < v.size(); ++i) - { - cnt += (v[i].is_zero() ? 0 : 1); - if (cnt == chunk_size && chunkno < num_chunks) - { - chunk_pos[chunkno] = i; - cnt = 0; - ++chunkno; - } - } - - chunk_pos[num_chunks] = v.size(); - -#ifdef MULTICORE -#pragma omp parallel for -#endif - for (size_t i = 0; i < num_chunks; ++i) - { - tmp[i] = kc_batch_exp_internal(scalar_size, T1_window, T2_window, T1_table, T2_table, T1_coeff, T2_coeff, v, - chunk_pos[i], chunk_pos[i+1], i == num_chunks - 1 ? last_chunk : chunk_size); -#ifdef USE_MIXED_ADDITION - kc_batch_to_special(tmp[i].values); -#endif - } - - if (num_chunks == 1) - { - tmp[0].domain_size_ = v.size(); - return tmp[0]; - } - else - { - for (size_t i = 0; i < num_chunks; ++i) - { - res.values.insert(res.values.end(), tmp[i].values.begin(), tmp[i].values.end()); - res.indices.insert(res.indices.end(), tmp[i].indices.begin(), tmp[i].indices.end()); - } - return res; - } -} - -} // libsnark - -#endif // KC_MULTIEXP_TCC_ diff --git a/src/snark/libsnark/algebra/scalar_multiplication/multiexp.hpp b/src/snark/libsnark/algebra/scalar_multiplication/multiexp.hpp deleted file mode 100644 index eaf72d61f88..00000000000 --- a/src/snark/libsnark/algebra/scalar_multiplication/multiexp.hpp +++ /dev/null @@ -1,110 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for multi-exponentiation routines. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef MULTIEXP_HPP_ -#define MULTIEXP_HPP_ - -namespace libsnark { - -/** - * Naive multi-exponentiation individually multiplies each base by the - * corresponding scalar and adds up the results. - */ -template -T naive_exp(typename std::vector::const_iterator vec_start, - typename std::vector::const_iterator vec_end, - typename std::vector::const_iterator scalar_start, - typename std::vector::const_iterator scalar_end); - -template -T naive_plain_exp(typename std::vector::const_iterator vec_start, - typename std::vector::const_iterator vec_end, - typename std::vector::const_iterator scalar_start, - typename std::vector::const_iterator scalar_end); - -/** - * Naive multi-exponentiation uses a variant of the Bos-Coster algorithm [1], - * and implementation suggestions from [2]. - * - * [1] = Bos and Coster, "Addition chain heuristics", CRYPTO '89 - * [2] = Bernstein, Duif, Lange, Schwabe, and Yang, "High-speed high-security signatures", CHES '11 - */ -template -T multi_exp(typename std::vector::const_iterator vec_start, - typename std::vector::const_iterator vec_end, - typename std::vector::const_iterator scalar_start, - typename std::vector::const_iterator scalar_end, - const size_t chunks, - const bool use_multiexp=false); - - -/** - * A variant of multi_exp that takes advantage of the method mixed_add (instead of the operator '+'). - */ -template -T multi_exp_with_mixed_addition(typename std::vector::const_iterator vec_start, - typename std::vector::const_iterator vec_end, - typename std::vector::const_iterator scalar_start, - typename std::vector::const_iterator scalar_end, - const size_t chunks, - const bool use_multiexp); - -/** - * A window table stores window sizes for different instance sizes for fixed-base multi-scalar multiplications. - */ -template -using window_table = std::vector >; - -/** - * Compute window size for the given number of scalars. - */ -template -size_t get_exp_window_size(const size_t num_scalars); - -/** - * Compute table of window sizes. - */ -template -window_table get_window_table(const size_t scalar_size, - const size_t window, - const T &g); - -template -T windowed_exp(const size_t scalar_size, - const size_t window, - const window_table &powers_of_g, - const FieldT &pow); - -template -std::vector batch_exp(const size_t scalar_size, - const size_t window, - const window_table &table, - const std::vector &v); - -template -std::vector batch_exp_with_coeff(const size_t scalar_size, - const size_t window, - const window_table &table, - const FieldT &coeff, - const std::vector &v); - -// defined in every curve -template -void batch_to_special_all_non_zeros(std::vector &vec); - -template -void batch_to_special(std::vector &vec); - -} // libsnark - -#include "algebra/scalar_multiplication/multiexp.tcc" - -#endif // MULTIEXP_HPP_ diff --git a/src/snark/libsnark/algebra/scalar_multiplication/multiexp.tcc b/src/snark/libsnark/algebra/scalar_multiplication/multiexp.tcc deleted file mode 100644 index e1783a8811c..00000000000 --- a/src/snark/libsnark/algebra/scalar_multiplication/multiexp.tcc +++ /dev/null @@ -1,590 +0,0 @@ -/** @file - ***************************************************************************** - - Implementation of interfaces for multi-exponentiation routines. - - See multiexp.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef MULTIEXP_TCC_ -#define MULTIEXP_TCC_ - -#include "algebra/fields/fp_aux.tcc" - -#include -#include -#include - -#include "common/profiling.hpp" -#include "common/utils.hpp" -#include "algebra/scalar_multiplication/wnaf.hpp" - -namespace libsnark { - -template -class ordered_exponent { -// to use std::push_heap and friends later -public: - size_t idx; - bigint r; - - ordered_exponent(const size_t idx, const bigint &r) : idx(idx), r(r) {}; - - bool operator<(const ordered_exponent &other) const - { -#if defined(__x86_64__) && defined(USE_ASM) - if (n == 3) - { - int64_t res; - __asm__ - ("// check for overflow \n\t" - "mov $0, %[res] \n\t" - ADD_CMP(16) - ADD_CMP(8) - ADD_CMP(0) - "jmp done%= \n\t" - "subtract%=: \n\t" - "mov $1, %[res] \n\t" - "done%=: \n\t" - : [res] "=&r" (res) - : [A] "r" (other.r.data), [mod] "r" (this->r.data) - : "cc", "%rax"); - return res; - } - else if (n == 4) - { - int64_t res; - __asm__ - ("// check for overflow \n\t" - "mov $0, %[res] \n\t" - ADD_CMP(24) - ADD_CMP(16) - ADD_CMP(8) - ADD_CMP(0) - "jmp done%= \n\t" - "subtract%=: \n\t" - "mov $1, %[res] \n\t" - "done%=: \n\t" - : [res] "=&r" (res) - : [A] "r" (other.r.data), [mod] "r" (this->r.data) - : "cc", "%rax"); - return res; - } - else if (n == 5) - { - int64_t res; - __asm__ - ("// check for overflow \n\t" - "mov $0, %[res] \n\t" - ADD_CMP(32) - ADD_CMP(24) - ADD_CMP(16) - ADD_CMP(8) - ADD_CMP(0) - "jmp done%= \n\t" - "subtract%=: \n\t" - "mov $1, %[res] \n\t" - "done%=: \n\t" - : [res] "=&r" (res) - : [A] "r" (other.r.data), [mod] "r" (this->r.data) - : "cc", "%rax"); - return res; - } - else -#endif - { - return (mpn_cmp(this->r.data, other.r.data, n) < 0); - } - } -}; - -template -T naive_exp(typename std::vector::const_iterator vec_start, - typename std::vector::const_iterator vec_end, - typename std::vector::const_iterator scalar_start, - typename std::vector::const_iterator scalar_end) -{ - T result(T::zero()); - - typename std::vector::const_iterator vec_it; - typename std::vector::const_iterator scalar_it; - - for (vec_it = vec_start, scalar_it = scalar_start; vec_it != vec_end; ++vec_it, ++scalar_it) - { - bigint scalar_bigint = scalar_it->as_bigint(); - result = result + opt_window_wnaf_exp(*vec_it, scalar_bigint, scalar_bigint.num_bits()); - } - assert(scalar_it == scalar_end); - - return result; -} - -template -T naive_plain_exp(typename std::vector::const_iterator vec_start, - typename std::vector::const_iterator vec_end, - typename std::vector::const_iterator scalar_start, - typename std::vector::const_iterator scalar_end) -{ - T result(T::zero()); - - typename std::vector::const_iterator vec_it; - typename std::vector::const_iterator scalar_it; - - for (vec_it = vec_start, scalar_it = scalar_start; vec_it != vec_end; ++vec_it, ++scalar_it) - { - result = result + (*scalar_it) * (*vec_it); - } - assert(scalar_it == scalar_end); - - return result; -} - -/* - The multi-exponentiation algorithm below is a variant of the Bos-Coster algorithm - [Bos and Coster, "Addition chain heuristics", CRYPTO '89]. - The implementation uses suggestions from - [Bernstein, Duif, Lange, Schwabe, and Yang, "High-speed high-security signatures", CHES '11]. -*/ -template -T multi_exp_inner(typename std::vector::const_iterator vec_start, - typename std::vector::const_iterator vec_end, - typename std::vector::const_iterator scalar_start, - typename std::vector::const_iterator scalar_end) -{ - const mp_size_t n = std::remove_reference::type::num_limbs; - - if (vec_start == vec_end) - { - return T::zero(); - } - - if (vec_start + 1 == vec_end) - { - return (*scalar_start)*(*vec_start); - } - - std::vector > opt_q; - const size_t vec_len = scalar_end - scalar_start; - const size_t odd_vec_len = (vec_len % 2 == 1 ? vec_len : vec_len + 1); - opt_q.reserve(odd_vec_len); - std::vector g; - g.reserve(odd_vec_len); - - typename std::vector::const_iterator vec_it; - typename std::vector::const_iterator scalar_it; - size_t i; - for (i=0, vec_it = vec_start, scalar_it = scalar_start; vec_it != vec_end; ++vec_it, ++scalar_it, ++i) - { - g.emplace_back(*vec_it); - - opt_q.emplace_back(ordered_exponent(i, scalar_it->as_bigint())); - } - std::make_heap(opt_q.begin(),opt_q.end()); - assert(scalar_it == scalar_end); - - if (vec_len != odd_vec_len) - { - g.emplace_back(T::zero()); - opt_q.emplace_back(ordered_exponent(odd_vec_len - 1, bigint(UINT64_C(0)))); - } - assert(g.size() % 2 == 1); - assert(opt_q.size() == g.size()); - - T opt_result = T::zero(); - - while (true) - { - ordered_exponent &a = opt_q[0]; - ordered_exponent &b = (opt_q[1] < opt_q[2] ? opt_q[2] : opt_q[1]); - - const size_t abits = a.r.num_bits(); - - if (b.r.is_zero()) - { - // opt_result = opt_result + (a.r * g[a.idx]); - opt_result = opt_result + opt_window_wnaf_exp(g[a.idx], a.r, abits); - break; - } - - const size_t bbits = b.r.num_bits(); - const size_t limit = (abits-bbits >= 20 ? 20 : abits-bbits); - - if (bbits < UINT64_C(1)< (x-y) A + y (B+A) - mpn_sub_n(a.r.data, a.r.data, b.r.data, n); - g[b.idx] = g[b.idx] + g[a.idx]; - } - - // regardless of whether a was cleared or subtracted from we push it down, then take back up - - /* heapify A down */ - size_t a_pos = 0; - while (2*a_pos + 2< odd_vec_len) - { - // this is a max-heap so to maintain a heap property we swap with the largest of the two - if (opt_q[2*a_pos+1] < opt_q[2*a_pos+2]) - { - std::swap(opt_q[a_pos], opt_q[2*a_pos+2]); - a_pos = 2*a_pos+2; - } - else - { - std::swap(opt_q[a_pos], opt_q[2*a_pos+1]); - a_pos = 2*a_pos+1; - } - } - - /* now heapify A up appropriate amount of times */ - while (a_pos > 0 && opt_q[(a_pos-1)/2] < opt_q[a_pos]) - { - std::swap(opt_q[a_pos], opt_q[(a_pos-1)/2]); - a_pos = (a_pos-1) / 2; - } - } - - return opt_result; -} - -template -T multi_exp(typename std::vector::const_iterator vec_start, - typename std::vector::const_iterator vec_end, - typename std::vector::const_iterator scalar_start, - typename std::vector::const_iterator scalar_end, - const size_t chunks, - const bool use_multiexp) -{ - const size_t total = vec_end - vec_start; - if (total < chunks) - { - return naive_exp(vec_start, vec_end, scalar_start, scalar_end); - } - - const size_t one = total/chunks; - - std::vector partial(chunks, T::zero()); - - if (use_multiexp) - { -#ifdef MULTICORE -#pragma omp parallel for -#endif - for (size_t i = 0; i < chunks; ++i) - { - partial[i] = multi_exp_inner(vec_start + i*one, - (i == chunks-1 ? vec_end : vec_start + (i+1)*one), - scalar_start + i*one, - (i == chunks-1 ? scalar_end : scalar_start + (i+1)*one)); - } - } - else - { -#ifdef MULTICORE -#pragma omp parallel for -#endif - for (size_t i = 0; i < chunks; ++i) - { - partial[i] = naive_exp(vec_start + i*one, - (i == chunks-1 ? vec_end : vec_start + (i+1)*one), - scalar_start + i*one, - (i == chunks-1 ? scalar_end : scalar_start + (i+1)*one)); - } - } - - T final = T::zero(); - - for (size_t i = 0; i < chunks; ++i) - { - final = final + partial[i]; - } - - return final; -} - -template -T multi_exp_with_mixed_addition(typename std::vector::const_iterator vec_start, - typename std::vector::const_iterator vec_end, - typename std::vector::const_iterator scalar_start, - typename std::vector::const_iterator scalar_end, - const size_t chunks, - const bool use_multiexp) -{ - assert(std::distance(vec_start, vec_end) == std::distance(scalar_start, scalar_end)); - enter_block("Process scalar vector"); - auto value_it = vec_start; - auto scalar_it = scalar_start; - - const FieldT zero = FieldT::zero(); - const FieldT one = FieldT::one(); - std::vector p; - std::vector g; - - T acc = T::zero(); - - size_t num_skip = 0; - size_t num_add = 0; - size_t num_other = 0; - - for (; scalar_it != scalar_end; ++scalar_it, ++value_it) - { - if (*scalar_it == zero) - { - // do nothing - ++num_skip; - } - else if (*scalar_it == one) - { -#ifdef USE_MIXED_ADDITION - acc = acc.mixed_add(*value_it); -#else - acc = acc + (*value_it); -#endif - ++num_add; - } - else - { - p.emplace_back(*scalar_it); - g.emplace_back(*value_it); - ++num_other; - } - } - //print_indent(); printf("* Elements of w skipped: %zu (%0.2f%%)\n", num_skip, 100.*num_skip/(num_skip+num_add+num_other)); - //print_indent(); printf("* Elements of w processed with special addition: %zu (%0.2f%%)\n", num_add, 100.*num_add/(num_skip+num_add+num_other)); - //print_indent(); printf("* Elements of w remaining: %zu (%0.2f%%)\n", num_other, 100.*num_other/(num_skip+num_add+num_other)); - - leave_block("Process scalar vector"); - - return acc + multi_exp(g.begin(), g.end(), p.begin(), p.end(), chunks, use_multiexp); -} - -template -size_t get_exp_window_size(const size_t num_scalars) -{ - if (T::fixed_base_exp_window_table.empty()) - { -#ifdef LOWMEM - return 14; -#else - return 17; -#endif - } - size_t window = 1; - for (int64_t i = T::fixed_base_exp_window_table.size()-1; i >= 0; --i) - { -#ifdef DEBUG - if (!inhibit_profiling_info) - { - printf("%ld %zu %zu\n", i, num_scalars, T::fixed_base_exp_window_table[i]); - } -#endif - if (T::fixed_base_exp_window_table[i] != 0 && num_scalars >= T::fixed_base_exp_window_table[i]) - { - window = i+1; - break; - } - } - - if (!inhibit_profiling_info) - { - print_indent(); printf("Choosing window size %zu for %zu elements\n", window, num_scalars); - } - -#ifdef LOWMEM - window = std::min((size_t)14, window); -#endif - return window; -} - -template -window_table get_window_table(const size_t scalar_size, - const size_t window, - const T &g) -{ - const size_t in_window = UINT64_C(1)< powers_of_g(outerc, std::vector(in_window, T::zero())); - - T gouter = g; - - for (size_t outer = 0; outer < outerc; ++outer) - { - T ginner = T::zero(); - size_t cur_in_window = outer == outerc-1 ? last_in_window : in_window; - for (size_t inner = 0; inner < cur_in_window; ++inner) - { - powers_of_g[outer][inner] = ginner; - ginner = ginner + gouter; - } - - for (size_t i = 0; i < window; ++i) - { - gouter = gouter + gouter; - } - } - - return powers_of_g; -} - -template -T windowed_exp(const size_t scalar_size, - const size_t window, - const window_table &powers_of_g, - const FieldT &pow) -{ - const size_t outerc = (scalar_size+window-1)/window; - const bigint pow_val = pow.as_bigint(); - - /* exp */ - T res = powers_of_g[0][0]; - - for (size_t outer = 0; outer < outerc; ++outer) - { - size_t inner = 0; - for (size_t i = 0; i < window; ++i) - { - if (pow_val.test_bit(outer*window + i)) - { - inner |= 1u << i; - } - } - - res = res + powers_of_g[outer][inner]; - } - - return res; -} - -template -std::vector batch_exp(const size_t scalar_size, - const size_t window, - const window_table &table, - const std::vector &v) -{ - if (!inhibit_profiling_info) - { - print_indent(); - } - std::vector res(v.size(), table[0][0]); - -#ifdef MULTICORE -#pragma omp parallel for -#endif - for (size_t i = 0; i < v.size(); ++i) - { - res[i] = windowed_exp(scalar_size, window, table, v[i]); - - if (!inhibit_profiling_info && (i % 10000 == 0)) - { - printf("."); - fflush(stdout); - } - } - - if (!inhibit_profiling_info) - { - printf(" DONE!\n"); - } - - return res; -} - -template -std::vector batch_exp_with_coeff(const size_t scalar_size, - const size_t window, - const window_table &table, - const FieldT &coeff, - const std::vector &v) -{ - if (!inhibit_profiling_info) - { - print_indent(); - } - std::vector res(v.size(), table[0][0]); - -#ifdef MULTICORE -#pragma omp parallel for -#endif - for (size_t i = 0; i < v.size(); ++i) - { - res[i] = windowed_exp(scalar_size, window, table, coeff * v[i]); - - if (!inhibit_profiling_info && (i % 10000 == 0)) - { - printf("."); - fflush(stdout); - } - } - - if (!inhibit_profiling_info) - { - printf(" DONE!\n"); - } - - return res; -} - -template -void batch_to_special(std::vector &vec) -{ - enter_block("Batch-convert elements to special form"); - - std::vector non_zero_vec; - for (size_t i = 0; i < vec.size(); ++i) - { - if (!vec[i].is_zero()) - { - non_zero_vec.emplace_back(vec[i]); - } - } - - batch_to_special_all_non_zeros(non_zero_vec); - auto it = non_zero_vec.begin(); - T zero_special = T::zero(); - zero_special.to_special(); - - for (size_t i = 0; i < vec.size(); ++i) - { - if (!vec[i].is_zero()) - { - vec[i] = *it; - ++it; - } - else - { - vec[i] = zero_special; - } - } - leave_block("Batch-convert elements to special form"); -} - -} // libsnark - -#endif // MULTIEXP_TCC_ diff --git a/src/snark/libsnark/algebra/scalar_multiplication/wnaf.hpp b/src/snark/libsnark/algebra/scalar_multiplication/wnaf.hpp deleted file mode 100644 index d6c43267eb8..00000000000 --- a/src/snark/libsnark/algebra/scalar_multiplication/wnaf.hpp +++ /dev/null @@ -1,39 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for wNAF ("width-w Non-Adjacent Form") exponentiation routines. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef WNAF_HPP_ -#define WNAF_HPP_ - -namespace libsnark { - -/** - * Find the wNAF representation of the given scalar relative to the given window size. - */ -template -std::vector find_wnaf(const size_t window_size, const bigint &scalar); - -/** - * In additive notation, use wNAF exponentiation (with the given window size) to compute scalar * base. - */ -template -T fixed_window_wnaf_exp(const size_t window_size, const T &base, const bigint &scalar); - -/** - * In additive notation, use wNAF exponentiation (with the window size determined by T) to compute scalar * base. - */ -template -T opt_window_wnaf_exp(const T &base, const bigint &scalar, const size_t scalar_bits); - -} // libsnark - -#include "algebra/scalar_multiplication/wnaf.tcc" - -#endif // WNAF_HPP_ diff --git a/src/snark/libsnark/algebra/scalar_multiplication/wnaf.tcc b/src/snark/libsnark/algebra/scalar_multiplication/wnaf.tcc deleted file mode 100644 index 4f2e4072c7d..00000000000 --- a/src/snark/libsnark/algebra/scalar_multiplication/wnaf.tcc +++ /dev/null @@ -1,123 +0,0 @@ -/** @file - ***************************************************************************** - - Implementation of interfaces for wNAF ("weighted Non-Adjacent Form") exponentiation routines. - - See wnaf.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef WNAF_TCC_ -#define WNAF_TCC_ - -namespace libsnark { - -template -std::vector find_wnaf(const size_t window_size, const bigint &scalar) -{ - const size_t length = scalar.max_bits(); // upper bound - std::vector res(length+1); - bigint c = scalar; - int64_t j = 0; - while (!c.is_zero()) - { - int64_t u; - if ((c.data[0] & 1) == 1) - { - u = c.data[0] % (1u << (window_size+1)); - if (u > (1 << window_size)) - { - u = u - (1 << (window_size+1)); - } - - if (u > 0) - { - mpn_sub_1(c.data, c.data, n, u); - } - else - { - mpn_add_1(c.data, c.data, n, -u); - } - } - else - { - u = 0; - } - res[j] = u; - ++j; - - mpn_rshift(c.data, c.data, n, 1); // c = c/2 - } - - return res; -} - -template -T fixed_window_wnaf_exp(const size_t window_size, const T &base, const bigint &scalar) -{ - std::vector naf = find_wnaf(window_size, scalar); - std::vector table(UINT64_C(1)<<(window_size-1)); - T tmp = base; - T dbl = base.dbl(); - for (size_t i = 0; i < UINT64_C(1)<<(window_size-1); ++i) - { - table[i] = tmp; - tmp = tmp + dbl; - } - - T res = T::zero(); - bool found_nonzero = false; - for (int64_t i = naf.size()-1; i >= 0; --i) - { - if (found_nonzero) - { - res = res.dbl(); - } - - if (naf[i] != 0) - { - found_nonzero = true; - if (naf[i] > 0) - { - res = res + table[naf[i]/2]; - } - else - { - res = res - table[(-naf[i])/2]; - } - } - } - - return res; -} - -template -T opt_window_wnaf_exp(const T &base, const bigint &scalar, const size_t scalar_bits) -{ - size_t best = 0; - for (int64_t i = T::wnaf_window_table.size() - 1; i >= 0; --i) - { - if (scalar_bits >= T::wnaf_window_table[i]) - { - best = i+1; - break; - } - } - - if (best > 0) - { - return fixed_window_wnaf_exp(best, base, scalar); - } - else - { - return scalar * base; - } -} - -} // libsnark - -#endif // WNAF_TCC_ diff --git a/src/snark/libsnark/common/assert_except.hpp b/src/snark/libsnark/common/assert_except.hpp deleted file mode 100644 index 7819230445d..00000000000 --- a/src/snark/libsnark/common/assert_except.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef ASSERT_except_H -#define ASSERT_except_H - -#include - -inline void assert_except(bool condition) { - if (!condition) { - throw std::runtime_error("Assertion failed."); - } -} - -#endif diff --git a/src/snark/libsnark/common/data_structures/accumulation_vector.hpp b/src/snark/libsnark/common/data_structures/accumulation_vector.hpp deleted file mode 100644 index 37e0c9841c9..00000000000 --- a/src/snark/libsnark/common/data_structures/accumulation_vector.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for an accumulation vector. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef ACCUMULATION_VECTOR_HPP_ -#define ACCUMULATION_VECTOR_HPP_ - -#include "common/data_structures/sparse_vector.hpp" - -namespace libsnark { - -template -class accumulation_vector; - -template -std::ostream& operator<<(std::ostream &out, const accumulation_vector &v); - -template -std::istream& operator>>(std::istream &in, accumulation_vector &v); - -/** - * An accumulation vector comprises an accumulation value and a sparse vector. - * The method "accumulate_chunk" allows one to accumlate portions of the sparse - * vector into the accumualation value. - */ -template -class accumulation_vector { -public: - T first; - sparse_vector rest; - - accumulation_vector() = default; - accumulation_vector(const accumulation_vector &other) = default; - accumulation_vector(accumulation_vector &&other) = default; - accumulation_vector(T &&first, sparse_vector &&rest) : first(std::move(first)), rest(std::move(rest)) {}; - accumulation_vector(T &&first, std::vector &&v) : first(std::move(first)), rest(std::move(v)) {} - accumulation_vector(std::vector &&v) : first(T::zero()), rest(std::move(v)) {}; - - accumulation_vector& operator=(const accumulation_vector &other) = default; - accumulation_vector& operator=(accumulation_vector &&other) = default; - - bool operator==(const accumulation_vector &other) const; - - bool is_fully_accumulated() const; - - size_t domain_size() const; - size_t size() const; - size_t size_in_bits() const; - - template - accumulation_vector accumulate_chunk(const typename std::vector::const_iterator &it_begin, - const typename std::vector::const_iterator &it_end, - const size_t offset) const; - -}; - -template -std::ostream& operator<<(std::ostream &out, const accumulation_vector &v); - -template -std::istream& operator>>(std::istream &in, accumulation_vector &v); - -} // libsnark - -#include "common/data_structures/accumulation_vector.tcc" - -#endif // ACCUMULATION_VECTOR_HPP_ diff --git a/src/snark/libsnark/common/data_structures/accumulation_vector.tcc b/src/snark/libsnark/common/data_structures/accumulation_vector.tcc deleted file mode 100644 index 9e524aba723..00000000000 --- a/src/snark/libsnark/common/data_structures/accumulation_vector.tcc +++ /dev/null @@ -1,84 +0,0 @@ -/** @file - ***************************************************************************** - - Implementation of interfaces for an accumulation vector. - - See accumulation_vector.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef ACCUMULATION_VECTOR_TCC_ -#define ACCUMULATION_VECTOR_TCC_ - -namespace libsnark { - -template -bool accumulation_vector::operator==(const accumulation_vector &other) const -{ - return (this->first == other.first && this->rest == other.rest); -} - -template -bool accumulation_vector::is_fully_accumulated() const -{ - return rest.empty(); -} - -template -size_t accumulation_vector::domain_size() const -{ - return rest.domain_size(); -} - -template -size_t accumulation_vector::size() const -{ - return rest.domain_size(); -} - -template -size_t accumulation_vector::size_in_bits() const -{ - const size_t first_size_in_bits = T::size_in_bits(); - const size_t rest_size_in_bits = rest.size_in_bits(); - return first_size_in_bits + rest_size_in_bits; -} - -template -template -accumulation_vector accumulation_vector::accumulate_chunk(const typename std::vector::const_iterator &it_begin, - const typename std::vector::const_iterator &it_end, - const size_t offset) const -{ - std::pair > acc_result = rest.template accumulate(it_begin, it_end, offset); - T new_first = first + acc_result.first; - return accumulation_vector(std::move(new_first), std::move(acc_result.second)); -} - -template -std::ostream& operator<<(std::ostream& out, const accumulation_vector &v) -{ - out << v.first << OUTPUT_NEWLINE; - out << v.rest << OUTPUT_NEWLINE; - - return out; -} - -template -std::istream& operator>>(std::istream& in, accumulation_vector &v) -{ - in >> v.first; - consume_OUTPUT_NEWLINE(in); - in >> v.rest; - consume_OUTPUT_NEWLINE(in); - - return in; -} - -} // libsnark - -#endif // ACCUMULATION_VECTOR_TCC_ diff --git a/src/snark/libsnark/common/data_structures/merkle_tree.hpp b/src/snark/libsnark/common/data_structures/merkle_tree.hpp deleted file mode 100644 index 6f0c851ba96..00000000000 --- a/src/snark/libsnark/common/data_structures/merkle_tree.hpp +++ /dev/null @@ -1,71 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for a Merkle tree. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef MERKLE_TREE_HPP_ -#define MERKLE_TREE_HPP_ - -#include -#include -#include "common/utils.hpp" - -namespace libsnark { - -/** - * A Merkle tree is maintained as two maps: - * - a map from addresses to values, and - * - a map from addresses to hashes. - * - * The second map maintains the intermediate hashes of a Merkle tree - * built atop the values currently stored in the tree (the - * implementation admits a very efficient support for sparse - * trees). Besides offering methods to load and store values, the - * class offers methods to retrieve the root of the Merkle tree and to - * obtain the authentication paths for (the value at) a given address. - */ - -typedef bit_vector merkle_authentication_node; -typedef std::vector merkle_authentication_path; - -template -class merkle_tree { -private: - - typedef typename HashT::hash_value_type hash_value_type; - typedef typename HashT::merkle_authentication_path_type merkle_authentication_path_type; - -public: - - std::vector hash_defaults; - std::map values; - std::map hashes; - - size_t depth; - size_t value_size; - size_t digest_size; - - merkle_tree(const size_t depth, const size_t value_size); - merkle_tree(const size_t depth, const size_t value_size, const std::vector &contents_as_vector); - merkle_tree(const size_t depth, const size_t value_size, const std::map &contents); - - bit_vector get_value(const size_t address) const; - void set_value(const size_t address, const bit_vector &value); - - hash_value_type get_root() const; - merkle_authentication_path_type get_path(const size_t address) const; - - void dump() const; -}; - -} // libsnark - -#include "common/data_structures/merkle_tree.tcc" - -#endif // MERKLE_TREE_HPP_ diff --git a/src/snark/libsnark/common/data_structures/merkle_tree.tcc b/src/snark/libsnark/common/data_structures/merkle_tree.tcc deleted file mode 100644 index ce28b124fb1..00000000000 --- a/src/snark/libsnark/common/data_structures/merkle_tree.tcc +++ /dev/null @@ -1,246 +0,0 @@ -/** @file - ***************************************************************************** - - Implementation of interfaces for Merkle tree. - - See merkle_tree.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef MERKLE_TREE_TCC -#define MERKLE_TREE_TCC - -#include - -#include "common/profiling.hpp" -#include "common/utils.hpp" - -namespace libsnark { - -template -typename HashT::hash_value_type two_to_one_CRH(const typename HashT::hash_value_type &l, - const typename HashT::hash_value_type &r) -{ - typename HashT::hash_value_type new_input; - new_input.insert(new_input.end(), l.begin(), l.end()); - new_input.insert(new_input.end(), r.begin(), r.end()); - - const size_t digest_size = HashT::get_digest_len(); - assert(l.size() == digest_size); - assert(r.size() == digest_size); - - return HashT::get_hash(new_input); -} - -template -merkle_tree::merkle_tree(const size_t depth, const size_t value_size) : - depth(depth), value_size(value_size) -{ - assert(depth < sizeof(size_t) * 8); - - digest_size = HashT::get_digest_len(); - assert(value_size <= digest_size); - - hash_value_type last(digest_size); - hash_defaults.reserve(depth+1); - hash_defaults.emplace_back(last); - for (size_t i = 0; i < depth; ++i) - { - last = two_to_one_CRH(last, last); - hash_defaults.emplace_back(last); - } - - std::reverse(hash_defaults.begin(), hash_defaults.end()); -} - -template -merkle_tree::merkle_tree(const size_t depth, - const size_t value_size, - const std::vector &contents_as_vector) : - merkle_tree(depth, value_size) -{ - assert(log2(contents_as_vector.size()) <= depth); - for (size_t address = 0; address < contents_as_vector.size(); ++address) - { - const size_t idx = address + (UINT64_C(1)< 0; --layer) - { - for (size_t idx = idx_begin; idx < idx_end; idx += 2) - { - hash_value_type l = hashes[idx]; // this is sound, because idx_begin is always a left child - hash_value_type r = (idx + 1 < idx_end ? hashes[idx+1] : hash_defaults[layer]); - - hash_value_type h = two_to_one_CRH(l, r); - hashes[(idx-1)/2] = h; - } - - idx_begin = (idx_begin-1)/2; - idx_end = (idx_end-1)/2; - } -} - -template -merkle_tree::merkle_tree(const size_t depth, - const size_t value_size, - const std::map &contents) : - merkle_tree(depth, value_size) -{ - - if (!contents.empty()) - { - assert(contents.rbegin()->first < UINT64_C(1)<first; - const bit_vector value = it->second; - const size_t idx = address + (UINT64_C(1)< 0; --layer) - { - auto next_last_it = hashes.begin(); - - for (auto it = hashes.begin(); it != last_it; ++it) - { - const size_t idx = it->first; - const hash_value_type hash = it->second; - - if (idx % 2 == 0) - { - // this is the right child of its parent and by invariant we are missing the left child - hashes[(idx-1)/2] = two_to_one_CRH(hash_defaults[layer], hash); - } - else - { - if (std::next(it) == last_it || std::next(it)->first != idx + 1) - { - // this is the left child of its parent and is missing its right child - hashes[(idx-1)/2] = two_to_one_CRH(hash, hash_defaults[layer]); - } - else - { - // typical case: this is the left child of the parent and adjecent to it there is a right child - hashes[(idx-1)/2] = two_to_one_CRH(hash, std::next(it)->second); - ++it; - } - } - } - - last_it = next_last_it; - } - } -} - -template -bit_vector merkle_tree::get_value(const size_t address) const -{ - assert(log2(address) <= depth); - - auto it = values.find(address); - bit_vector padded_result = (it == values.end() ? bit_vector(digest_size) : it->second); - padded_result.resize(value_size); - - return padded_result; -} - -template -void merkle_tree::set_value(const size_t address, - const bit_vector &value) -{ - assert(log2(address) <= depth); - size_t idx = address + (UINT64_C(1)<=0; --layer) - { - idx = (idx-1)/2; - - auto it = hashes.find(2*idx+1); - hash_value_type l = (it == hashes.end() ? hash_defaults[layer+1] : it->second); - - it = hashes.find(2*idx+2); - hash_value_type r = (it == hashes.end() ? hash_defaults[layer+1] : it->second); - - hash_value_type h = two_to_one_CRH(l, r); - hashes[idx] = h; - } -} - -template -typename HashT::hash_value_type merkle_tree::get_root() const -{ - auto it = hashes.find(0); - return (it == hashes.end() ? hash_defaults[0] : it->second); -} - -template -typename HashT::merkle_authentication_path_type merkle_tree::get_path(const size_t address) const -{ - typename HashT::merkle_authentication_path_type result(depth); - assert(log2(address) <= depth); - size_t idx = address + (UINT64_C(1)< 0; --layer) - { - size_t sibling_idx = ((idx + 1) ^ 1) - 1; - auto it = hashes.find(sibling_idx); - if (layer == depth) - { - auto it2 = values.find(sibling_idx - ((UINT64_C(1)<second); - result[layer-1].resize(digest_size); - } - else - { - result[layer-1] = (it == hashes.end() ? hash_defaults[layer] : it->second); - } - - idx = (idx-1)/2; - } - - return result; -} - -template -void merkle_tree::dump() const -{ - for (size_t i = 0; i < UINT64_C(1)< ", i); - const bit_vector value = (it == values.end() ? bit_vector(value_size) : it->second); - for (bool b : value) - { - printf("%d", b ? 1 : 0); - } - printf("\n"); - } - printf("\n"); -} - -} // libsnark - -#endif // MERKLE_TREE_TCC diff --git a/src/snark/libsnark/common/data_structures/sparse_vector.hpp b/src/snark/libsnark/common/data_structures/sparse_vector.hpp deleted file mode 100644 index 6c5a104471d..00000000000 --- a/src/snark/libsnark/common/data_structures/sparse_vector.hpp +++ /dev/null @@ -1,79 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for a sparse vector. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef SPARSE_VECTOR_HPP_ -#define SPARSE_VECTOR_HPP_ - -#include - -namespace libsnark { - -template -struct sparse_vector; - -template -std::ostream& operator<<(std::ostream &out, const sparse_vector &v); - -template -std::istream& operator>>(std::istream &in, sparse_vector &v); - -/** - * A sparse vector is a list of indices along with corresponding values. - * The indices are selected from the set {0,1,...,domain_size-1}. - */ -template -struct sparse_vector { - - std::vector indices; - std::vector values; - size_t domain_size_ = 0; - - sparse_vector() = default; - sparse_vector(const sparse_vector &other) = default; - sparse_vector(sparse_vector &&other) = default; - sparse_vector(std::vector &&v); /* constructor from std::vector */ - - sparse_vector& operator=(const sparse_vector &other) = default; - sparse_vector& operator=(sparse_vector &&other) = default; - - T operator[](const size_t idx) const; - - bool operator==(const sparse_vector &other) const; - bool operator==(const std::vector &other) const; - - bool is_valid() const; - bool empty() const; - - size_t domain_size() const; // return domain_size_ - size_t size() const; // return the number of indices (representing the number of non-zero entries) - size_t size_in_bits() const; // return the number bits needed to store the sparse vector - - /* return a pair consisting of the accumulated value and the sparse vector of non-accumulated values */ - template - std::pair > accumulate(const typename std::vector::const_iterator &it_begin, - const typename std::vector::const_iterator &it_end, - const size_t offset) const; - - friend std::ostream& operator<< (std::ostream &out, const sparse_vector &v); - friend std::istream& operator>> (std::istream &in, sparse_vector &v); -}; - -template -std::ostream& operator<<(std::ostream& out, const sparse_vector &v); - -template -std::istream& operator>>(std::istream& in, sparse_vector &v); - -} // libsnark - -#include "common/data_structures/sparse_vector.tcc" - -#endif // SPARSE_VECTOR_HPP_ diff --git a/src/snark/libsnark/common/data_structures/sparse_vector.tcc b/src/snark/libsnark/common/data_structures/sparse_vector.tcc deleted file mode 100644 index cfc5d755990..00000000000 --- a/src/snark/libsnark/common/data_structures/sparse_vector.tcc +++ /dev/null @@ -1,316 +0,0 @@ -/** @file - ***************************************************************************** - - Implementation of interfaces for a sparse vector. - - See sparse_vector.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef SPARSE_VECTOR_TCC_ -#define SPARSE_VECTOR_TCC_ - -#include "algebra/scalar_multiplication/multiexp.hpp" - -#include - -namespace libsnark { - -template -sparse_vector::sparse_vector(std::vector &&v) : - values(std::move(v)), domain_size_(values.size()) -{ - indices.resize(domain_size_); - std::iota(indices.begin(), indices.end(), 0); -} - -template -T sparse_vector::operator[](const size_t idx) const -{ - auto it = std::lower_bound(indices.begin(), indices.end(), idx); - return (it != indices.end() && *it == idx) ? values[it - indices.begin()] : T(); -} - -template -bool sparse_vector::operator==(const sparse_vector &other) const -{ - if (this->domain_size_ != other.domain_size_) - { - return false; - } - - size_t this_pos = 0, other_pos = 0; - while (this_pos < this->indices.size() && other_pos < other.indices.size()) - { - if (this->indices[this_pos] == other.indices[other_pos]) - { - if (this->values[this_pos] != other.values[other_pos]) - { - return false; - } - ++this_pos; - ++other_pos; - } - else if (this->indices[this_pos] < other.indices[other_pos]) - { - if (!this->values[this_pos].is_zero()) - { - return false; - } - ++this_pos; - } - else - { - if (!other.values[other_pos].is_zero()) - { - return false; - } - ++other_pos; - } - } - - /* at least one of the vectors has been exhausted, so other must be empty */ - while (this_pos < this->indices.size()) - { - if (!this->values[this_pos].is_zero()) - { - return false; - } - ++this_pos; - } - - while (other_pos < other.indices.size()) - { - if (!other.values[other_pos].is_zero()) - { - return false; - } - ++other_pos; - } - - return true; -} - -template -bool sparse_vector::operator==(const std::vector &other) const -{ - if (this->domain_size_ < other.size()) - { - return false; - } - - size_t j = 0; - for (size_t i = 0; i < other.size(); ++i) - { - if (this->indices[j] == i) - { - if (this->values[j] != other[j]) - { - return false; - } - ++j; - } - else - { - if (!other[j].is_zero()) - { - return false; - } - } - } - - return true; -} - -template -bool sparse_vector::is_valid() const -{ - if (values.size() == indices.size() && values.size() <= domain_size_) - { - return false; - } - - for (size_t i = 0; i + 1 < indices.size(); ++i) - { - if (indices[i] >= indices[i+1]) - { - return false; - } - } - - if (!indices.empty() && indices[indices.size()-1] >= domain_size_) - { - return false; - } - - return true; -} - -template -bool sparse_vector::empty() const -{ - return indices.empty(); -} - -template -size_t sparse_vector::domain_size() const -{ - return domain_size_; -} - -template -size_t sparse_vector::size() const -{ - return indices.size(); -} - -template -size_t sparse_vector::size_in_bits() const -{ - return indices.size() * (sizeof(size_t) * 8 + T::size_in_bits()); -} - -template -template -std::pair > sparse_vector::accumulate(const typename std::vector::const_iterator &it_begin, - const typename std::vector::const_iterator &it_end, - const size_t offset) const -{ - // TODO: does not really belong here. - const size_t chunks = 1; - const bool use_multiexp = true; - - T accumulated_value = T::zero(); - sparse_vector resulting_vector; - resulting_vector.domain_size_ = domain_size_; - - const size_t range_len = it_end - it_begin; - bool in_block = false; - size_t first_pos = -1, last_pos = -1; // g++ -flto emits unitialized warning, even though in_block guards for such cases. - - for (size_t i = 0; i < indices.size(); ++i) - { - const bool matching_pos = (offset <= indices[i] && indices[i] < offset + range_len); - // printf("i = %zu, pos[i] = %zu, offset = %zu, w_size = %zu\n", i, indices[i], offset, w_size); - bool copy_over; - - if (in_block) - { - if (matching_pos && last_pos == i-1) - { - // block can be extended, do it - last_pos = i; - copy_over = false; - } - else - { - // block has ended here - in_block = false; - copy_over = true; - -#ifdef DEBUG - print_indent(); printf("doing multiexp for w_%zu ... w_%zu\n", indices[first_pos], indices[last_pos]); -#endif - accumulated_value = accumulated_value + multi_exp(values.begin() + first_pos, - values.begin() + last_pos + 1, - it_begin + (indices[first_pos] - offset), - it_begin + (indices[last_pos] - offset) + 1, - chunks, use_multiexp); - } - } - else - { - if (matching_pos) - { - // block can be started - first_pos = i; - last_pos = i; - in_block = true; - copy_over = false; - } - else - { - copy_over = true; - } - } - - if (copy_over) - { - resulting_vector.indices.emplace_back(indices[i]); - resulting_vector.values.emplace_back(values[i]); - } - } - - if (in_block) - { -#ifdef DEBUG - print_indent(); printf("doing multiexp for w_%zu ... w_%zu\n", indices[first_pos], indices[last_pos]); -#endif - accumulated_value = accumulated_value + multi_exp(values.begin() + first_pos, - values.begin() + last_pos + 1, - it_begin + (indices[first_pos] - offset), - it_begin + (indices[last_pos] - offset) + 1, - chunks, use_multiexp); - } - - return std::make_pair(accumulated_value, resulting_vector); -} - -template -std::ostream& operator<<(std::ostream& out, const sparse_vector &v) -{ - out << v.domain_size_ << "\n"; - out << v.indices.size() << "\n"; - for (const size_t& i : v.indices) - { - out << i << "\n"; - } - - out << v.values.size() << "\n"; - for (const T& t : v.values) - { - out << t << OUTPUT_NEWLINE; - } - - return out; -} - -template -std::istream& operator>>(std::istream& in, sparse_vector &v) -{ - in >> v.domain_size_; - consume_newline(in); - - size_t s; - in >> s; - consume_newline(in); - v.indices.resize(s); - for (size_t i = 0; i < s; ++i) - { - in >> v.indices[i]; - consume_newline(in); - } - - v.values.clear(); - in >> s; - consume_newline(in); - v.values.reserve(s); - - for (size_t i = 0; i < s; ++i) - { - T t; - in >> t; - consume_OUTPUT_NEWLINE(in); - v.values.emplace_back(t); - } - - return in; -} - -} // libsnark - -#endif // SPARSE_VECTOR_TCC_ diff --git a/src/snark/libsnark/common/default_types/ec_pp.hpp b/src/snark/libsnark/common/default_types/ec_pp.hpp deleted file mode 100644 index b08c2da8816..00000000000 --- a/src/snark/libsnark/common/default_types/ec_pp.hpp +++ /dev/null @@ -1,53 +0,0 @@ -/** @file - ***************************************************************************** - - This file defines default_ec_pp based on the CURVE=... make flag, which selects - which elliptic curve is used to implement group arithmetic and pairings. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef EC_PP_HPP_ -#define EC_PP_HPP_ - -/************************ Pick the elliptic curve ****************************/ - -#ifdef CURVE_ALT_BN128 -#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp" -namespace libsnark { -typedef alt_bn128_pp default_ec_pp; -} // libsnark -#endif - -#ifdef CURVE_BN128 -#include "algebra/curves/bn128/bn128_pp.hpp" -namespace libsnark { -typedef bn128_pp default_ec_pp; -} // libsnark -#endif - -#ifdef CURVE_EDWARDS -#include "algebra/curves/edwards/edwards_pp.hpp" -namespace libsnark { -typedef edwards_pp default_ec_pp; -} // libsnark -#endif - -#ifdef CURVE_MNT4 -#include "algebra/curves/mnt/mnt4/mnt4_pp.hpp" -namespace libsnark { -typedef mnt4_pp default_ec_pp; -} // libsnark -#endif - -#ifdef CURVE_MNT6 -#include "algebra/curves/mnt/mnt6/mnt6_pp.hpp" -namespace libsnark { -typedef mnt6_pp default_ec_pp; -} // libsnark -#endif - -#endif // EC_PP_HPP_ diff --git a/src/snark/libsnark/common/default_types/r1cs_ppzksnark_pp.hpp b/src/snark/libsnark/common/default_types/r1cs_ppzksnark_pp.hpp deleted file mode 100644 index c819b4a85e9..00000000000 --- a/src/snark/libsnark/common/default_types/r1cs_ppzksnark_pp.hpp +++ /dev/null @@ -1,22 +0,0 @@ -/** @file - ***************************************************************************** - - This file defines default_r1cs_ppzksnark_pp based on the elliptic curve - choice selected in ec_pp.hpp. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef R1CS_PPZKSNARK_PP_HPP_ -#define R1CS_PPZKSNARK_PP_HPP_ - -#include "common/default_types/ec_pp.hpp" - -namespace libsnark { -typedef default_ec_pp default_r1cs_ppzksnark_pp; -} // libsnark - -#endif // R1CS_PPZKSNARK_PP_HPP_ diff --git a/src/snark/libsnark/common/profiling.cpp b/src/snark/libsnark/common/profiling.cpp deleted file mode 100644 index e6f1f4525c0..00000000000 --- a/src/snark/libsnark/common/profiling.cpp +++ /dev/null @@ -1,382 +0,0 @@ -/** @file - ***************************************************************************** - - Implementation of functions for profiling code blocks. - - See profiling.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#include "common/profiling.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include "common/default_types/ec_pp.hpp" -#include "common/utils.hpp" - -#ifndef NO_PROCPS -#include -#endif - -namespace libsnark { - -int64_t get_nsec_time() -{ - auto timepoint = std::chrono::high_resolution_clock::now(); - return std::chrono::duration_cast(timepoint.time_since_epoch()).count(); -} - -/* Return total CPU time consumed by all threads of the process, in nanoseconds. */ -int64_t get_nsec_cpu_time() -{ - ::timespec ts; - if ( ::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) ) - throw ::std::runtime_error("clock_gettime(CLOCK_PROCESS_CPUTIME_ID) failed"); - // If we expected this to work, don't silently ignore failures, because that would hide the problem and incur an unnecessarily system-call overhead. So if we ever observe this exception, we should probably add a suitable #ifdef . - //TODO: clock_gettime(CLOCK_PROCESS_CPUTIME_ID) is not supported by native Windows. What about Cygwin? Should we #ifdef on CLOCK_PROCESS_CPUTIME_ID or on __linux__? - return ts.tv_sec * 1000000000ll + ts.tv_nsec; -} - -static int64_t start_time; -static int64_t last_time; -static int64_t start_cpu_time; -static int64_t last_cpu_time; - -void start_profiling() -{ - printf("Reset time counters for profiling\n"); - - last_time = start_time = get_nsec_time(); - last_cpu_time = start_cpu_time = get_nsec_cpu_time(); -} - -std::map invocation_counts; -static std::map enter_times; -std::map last_times; -std::map cumulative_times; -//TODO: Instead of analogous maps for time and cpu_time, use a single struct-valued map -static std::map enter_cpu_times; -static std::map last_cpu_times; -static std::map, int64_t> op_counts; -static std::map, int64_t> cumulative_op_counts; // ((msg, data_point), value) - // TODO: Convert op_counts and cumulative_op_counts from pair to structs -static size_t indentation = 0; - -static std::vector block_names; - -static std::list > op_data_points = { -#ifdef PROFILE_OP_COUNTS - std::make_pair("Fradd", &Fr::add_cnt), - std::make_pair("Frsub", &Fr::sub_cnt), - std::make_pair("Frmul", &Fr::mul_cnt), - std::make_pair("Frinv", &Fr::inv_cnt), - std::make_pair("Fqadd", &Fq::add_cnt), - std::make_pair("Fqsub", &Fq::sub_cnt), - std::make_pair("Fqmul", &Fq::mul_cnt), - std::make_pair("Fqinv", &Fq::inv_cnt), - std::make_pair("G1add", &G1::add_cnt), - std::make_pair("G1dbl", &G1::dbl_cnt), - std::make_pair("G2add", &G2::add_cnt), - std::make_pair("G2dbl", &G2::dbl_cnt) -#endif -}; - -bool inhibit_profiling_info = true; -bool inhibit_profiling_counters = false; - -void clear_profiling_counters() -{ - invocation_counts.clear(); - last_times.clear(); - last_cpu_times.clear(); - cumulative_times.clear(); -} - -void print_cumulative_time_entry(const std::string &key, const int64_t factor) -{ - const double total_ms = (cumulative_times.at(key) * 1e-6); - const size_t cnt = invocation_counts.at(key); - const double avg_ms = total_ms / cnt; - printf(" %-45s: %12.5fms = %" PRId64 " * %0.5fms (%zu invocations, %0.5fms = %" PRId64 " * %0.5fms per invocation)\n", key.c_str(), total_ms, factor, total_ms/factor, cnt, avg_ms, factor, avg_ms/factor); -} - -void print_cumulative_times(const int64_t factor) -{ - printf("Dumping times:\n"); - for (auto& kv : cumulative_times) - { - print_cumulative_time_entry(kv.first, factor); - } -} - -void print_cumulative_op_counts(const bool only_fq) -{ -#ifdef PROFILE_OP_COUNTS - printf("Dumping operation counts:\n"); - for (auto& msg : invocation_counts) - { - printf(" %-45s: ", msg.first.c_str()); - bool first = true; - for (auto& data_point : op_data_points) - { - if (only_fq && data_point.first.compare(0, 2, "Fq") != 0) - { - continue; - } - - if (!first) - { - printf(", "); - } - printf("%-5s = %7.0f (%3zu)", - data_point.first.c_str(), - 1. * cumulative_op_counts[std::make_pair(msg.first, data_point.first)] / msg.second, - msg.second); - first = false; - } - printf("\n"); - } -#else - UNUSED(only_fq); -#endif -} - -void print_op_profiling(const std::string &msg) -{ -#ifdef PROFILE_OP_COUNTS - printf("\n"); - print_indent(); - - printf("(opcounts) = ("); - bool first = true; - for (std::pair p : op_data_points) - { - if (!first) - { - printf(", "); - } - - printf("%s=%lld", p.first.c_str(), *(p.second)-op_counts[std::make_pair(msg, p.first)]); - first = false; - } - printf(")"); -#else - UNUSED(msg); -#endif -} - -static void print_times_from_last_and_start(int64_t now, int64_t last, - int64_t cpu_now, int64_t cpu_last) -{ - int64_t time_from_start = now - start_time; - int64_t time_from_last = now - last; - - int64_t cpu_time_from_start = cpu_now - start_cpu_time; - int64_t cpu_time_from_last = cpu_now - cpu_last; - - if (time_from_last != 0) { - double parallelism_from_last = 1.0 * cpu_time_from_last / time_from_last; - printf("[%0.4fs x%0.2f]", time_from_last * 1e-9, parallelism_from_last); - } else { - printf("[ ]"); - } - if (time_from_start != 0) { - double parallelism_from_start = 1.0 * cpu_time_from_start / time_from_start; - printf("\t(%0.4fs x%0.2f from start)", time_from_start * 1e-9, parallelism_from_start); - } -} - -void print_time(const char* msg) -{ - if (inhibit_profiling_info) - { - return; - } - - int64_t now = get_nsec_time(); - int64_t cpu_now = get_nsec_cpu_time(); - - printf("%-35s\t", msg); - print_times_from_last_and_start(now, last_time, cpu_now, last_cpu_time); -#ifdef PROFILE_OP_COUNTS - print_op_profiling(msg); -#endif - printf("\n"); - - fflush(stdout); - last_time = now; - last_cpu_time = cpu_now; -} - -void print_header(const char *msg) -{ - printf("\n================================================================================\n"); - printf("%s\n", msg); - printf("================================================================================\n\n"); -} - -void print_indent() -{ - for (size_t i = 0; i < indentation; ++i) - { - printf(" "); - } -} - -void op_profiling_enter(const std::string &msg) -{ - for (std::pair p : op_data_points) - { - op_counts[std::make_pair(msg, p.first)] = *(p.second); - } -} - -void enter_block(const std::string &msg, const bool indent) -{ - if (inhibit_profiling_counters) - { - return; - } - - block_names.emplace_back(msg); - int64_t t = get_nsec_time(); - enter_times[msg] = t; - int64_t cpu_t = get_nsec_cpu_time(); - enter_cpu_times[msg] = cpu_t; - - if (inhibit_profiling_info) - { - return; - } - -#ifdef MULTICORE -#pragma omp critical -#endif - { - op_profiling_enter(msg); - - print_indent(); - printf("(enter) %-35s\t", msg.c_str()); - print_times_from_last_and_start(t, t, cpu_t, cpu_t); - printf("\n"); - fflush(stdout); - - if (indent) - { - ++indentation; - } - } -} - -void leave_block(const std::string &msg, const bool indent) -{ - if (inhibit_profiling_counters) - { - return; - } - -#ifndef MULTICORE - assert(*(--block_names.end()) == msg); -#endif - block_names.pop_back(); - - ++invocation_counts[msg]; - - int64_t t = get_nsec_time(); - last_times[msg] = (t - enter_times[msg]); - cumulative_times[msg] += (t - enter_times[msg]); - - int64_t cpu_t = get_nsec_cpu_time(); - last_cpu_times[msg] = (cpu_t - enter_cpu_times[msg]); - -#ifdef PROFILE_OP_COUNTS - for (std::pair p : op_data_points) - { - cumulative_op_counts[std::make_pair(msg, p.first)] += *(p.second)-op_counts[std::make_pair(msg, p.first)]; - } -#endif - - if (inhibit_profiling_info) - { - return; - } - -#ifdef MULTICORE -#pragma omp critical -#endif - { - if (indent) - { - --indentation; - } - - print_indent(); - printf("(leave) %-35s\t", msg.c_str()); - print_times_from_last_and_start(t, enter_times[msg], cpu_t, enter_cpu_times[msg]); - print_op_profiling(msg); - printf("\n"); - fflush(stdout); - } -} - -void print_mem(const std::string &s) -{ -#ifndef NO_PROCPS - struct proc_t usage; - look_up_our_self(&usage); - if (s.empty()) - { - printf("* Peak vsize (physical memory+swap) in mebibytes: %lu\n", usage.vsize >> 20); - } - else - { - printf("* Peak vsize (physical memory+swap) in mebibytes (%s): %lu\n", s.c_str(), usage.vsize >> 20); - } -#else - printf("* Memory profiling not supported in NO_PROCPS mode\n"); -#endif -} - -void print_compilation_info() -{ -#ifdef __GNUC__ - printf("g++ version: %s\n", __VERSION__); - //printf("Compiled on %s %s\n", __DATE__, __TIME__); -#endif -#ifdef STATIC - printf("STATIC: yes\n"); -#else - printf("STATIC: no\n"); -#endif -#ifdef MULTICORE - printf("MULTICORE: yes\n"); -#else - printf("MULTICORE: no\n"); -#endif -#ifdef DEBUG - printf("DEBUG: yes\n"); -#else - printf("DEBUG: no\n"); -#endif -#ifdef PROFILE_OP_COUNTS - printf("PROFILE_OP_COUNTS: yes\n"); -#else - printf("PROFILE_OP_COUNTS: no\n"); -#endif -#ifdef _GLIBCXX_DEBUG - printf("_GLIBCXX_DEBUG: yes\n"); -#else - printf("_GLIBCXX_DEBUG: no\n"); -#endif -} - -} // libsnark diff --git a/src/snark/libsnark/common/profiling.hpp b/src/snark/libsnark/common/profiling.hpp deleted file mode 100644 index 4a496107b37..00000000000 --- a/src/snark/libsnark/common/profiling.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of functions for profiling code blocks. - - Reports time, operation counts, memory usage, and others. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef PROFILING_HPP_ -#define PROFILING_HPP_ - -#include -#include -#include -#include - -namespace libsnark { - -void start_profiling(); -int64_t get_nsec_time(); -void print_time(const char* msg); -void print_header(const char* msg); - -void print_indent(); - -extern bool inhibit_profiling_info; -extern bool inhibit_profiling_counters; -extern std::map invocation_counts; -extern std::map last_times; -extern std::map cumulative_times; - -void clear_profiling_counters(); - -void print_cumulative_time_entry(const std::string &key, const int64_t factor=1); -void print_cumulative_times(const int64_t factor=1); -void print_cumulative_op_counts(const bool only_fq=false); - -void enter_block(const std::string &msg, const bool indent=true); -void leave_block(const std::string &msg, const bool indent=true); - -void print_mem(const std::string &s = ""); -void print_compilation_info(); - -} // libsnark - -#endif // PROFILING_HPP_ diff --git a/src/snark/libsnark/common/serialization.hpp b/src/snark/libsnark/common/serialization.hpp deleted file mode 100644 index 6757e196627..00000000000 --- a/src/snark/libsnark/common/serialization.hpp +++ /dev/null @@ -1,104 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of serialization routines and constants. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef SERIALIZATION_HPP_ -#define SERIALIZATION_HPP_ - -#include -#include -#include -#include -#include - -namespace libsnark { - -/* - * @todo - * The serialization is fragile. Should be rewritten using a standard, portable-format - * library like boost::serialize. - * - * However, for now the following conventions are used within the code. - * - * All algebraic objects support either binary or decimal output using - * the standard C++ stream operators (operator<<, operator>>). - * - * The binary mode is activated by defining a BINARY_OUTPUT - * preprocessor macro (e.g. g++ -DBINARY_OUTPUT ...). - * - * Binary output assumes that the stream is to be binary read at its - * current position so any white space should be consumed beforehand. - * - * Consecutive algebraic objects are separated by OUTPUT_NEWLINE and - * within themselves (e.g. X and Y coordinates for field elements) with - * OUTPUT_SEPARATOR (as defined below). - * - * Therefore to dump two integers, two Fp elements and another integer - * one would: - * - * out << 3 << "\n"; - * out << 4 << "\n"; - * out << FieldT(56) << OUTPUT_NEWLINE; - * out << FieldT(78) << OUTPUT_NEWLINE; - * out << 9 << "\n"; - * - * Then reading back it its reader's responsibility (!) to consume "\n" - * after 4, but Fp::operator<< will correctly consume OUTPUT_NEWLINE. - * - * The reader should also consume "\n" after 9, so that another field - * element can be properly chained. This is especially important for - * binary output. - * - * The binary serialization of algebraic objects is currently *not* - * portable between machines of different word sizes. - */ - -#ifdef BINARY_OUTPUT -#define OUTPUT_NEWLINE "" -#define OUTPUT_SEPARATOR "" -#else -#define OUTPUT_NEWLINE "\n" -#define OUTPUT_SEPARATOR " " -#endif - -inline void consume_newline(std::istream &in); -inline void consume_OUTPUT_NEWLINE(std::istream &in); -inline void consume_OUTPUT_SEPARATOR(std::istream &in); - -inline void output_bool(std::ostream &out, const bool b); - -inline void output_bool_vector(std::ostream &out, const std::vector &v); - -template -T reserialize(const T &obj); - -template -std::ostream& operator<<(std::ostream& out, const std::vector &v); - -template -std::istream& operator>>(std::ostream& out, std::vector &v); - -template -std::ostream& operator<<(std::ostream& out, const std::map &m); - -template -std::istream& operator>>(std::istream& in, std::map &m); - -template -std::ostream& operator<<(std::ostream& out, const std::set &s); - -template -std::istream& operator>>(std::istream& in, std::set &s); - -} // libsnark - -#include "common/serialization.tcc" - -#endif // SERIALIZATION_HPP_ diff --git a/src/snark/libsnark/common/serialization.tcc b/src/snark/libsnark/common/serialization.tcc deleted file mode 100644 index 398f978500d..00000000000 --- a/src/snark/libsnark/common/serialization.tcc +++ /dev/null @@ -1,180 +0,0 @@ -/** @file - ***************************************************************************** - - Implementation of serialization routines. - - See serialization.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef SERIALIZATION_TCC_ -#define SERIALIZATION_TCC_ - -#include -#include -#include "common/utils.hpp" - -namespace libsnark { - -inline void consume_newline(std::istream &in) -{ - char c; - in.read(&c, 1); -} - -inline void consume_OUTPUT_NEWLINE(std::istream &in) -{ -#ifdef BINARY_OUTPUT - // nothing to consume - UNUSED(in); -#else - char c; - in.read(&c, 1); -#endif -} - -inline void consume_OUTPUT_SEPARATOR(std::istream &in) -{ -#ifdef BINARY_OUTPUT - // nothing to consume - UNUSED(in); -#else - char c; - in.read(&c, 1); -#endif -} - -inline void output_bool(std::ostream &out, const bool b) -{ - out << (b ? 1 : 0) << "\n"; -} - -inline void output_bool_vector(std::ostream &out, const std::vector &v) -{ - out << v.size() << "\n"; - for (const bool b : v) - { - output_bool(out, b); - } -} - -template -T reserialize(const T &obj) -{ - std::stringstream ss; - ss << obj; - T tmp; - ss >> tmp; - assert(obj == tmp); - return tmp; -} - -template -std::ostream& operator<<(std::ostream& out, const std::vector &v) -{ - static_assert(!std::is_same::value, "this does not work for std::vector"); - out << v.size() << "\n"; - for (const T& t : v) - { - out << t << OUTPUT_NEWLINE; - } - - return out; -} - -template -std::istream& operator>>(std::istream& in, std::vector &v) -{ - static_assert(!std::is_same::value, "this does not work for std::vector"); - size_t size; - in >> size; - consume_newline(in); - - v.resize(0); - for (size_t i = 0; i < size; ++i) - { - T elt; - in >> elt; - consume_OUTPUT_NEWLINE(in); - v.push_back(elt); - } - - return in; -} - -template -std::ostream& operator<<(std::ostream& out, const std::map &m) -{ - out << m.size() << "\n"; - - for (auto &it : m) - { - out << it.first << "\n"; - out << it.second << "\n"; - } - - return out; -} - -template -std::istream& operator>>(std::istream& in, std::map &m) -{ - m.clear(); - size_t size; - in >> size; - consume_newline(in); - - for (size_t i = 0; i < size; ++i) - { - T1 k; - T2 v; - in >> k; - consume_newline(in); - in >> v; - consume_newline(in); - m[k] = v; - } - - return in; -} - -template -std::ostream& operator<<(std::ostream& out, const std::set &s) -{ - out << s.size() << "\n"; - - for (auto &el : s) - { - out << el << "\n"; - } - - return out; -} - - -template -std::istream& operator>>(std::istream& in, std::set &s) -{ - s.clear(); - size_t size; - in >> size; - consume_newline(in); - - for (size_t i = 0; i < size; ++i) - { - T el; - in >> el; - consume_newline(in); - s.insert(el); - } - - return in; -} - -} - -#endif // SERIALIZATION_TCC_ diff --git a/src/snark/libsnark/common/template_utils.hpp b/src/snark/libsnark/common/template_utils.hpp deleted file mode 100644 index 8dbfd261dd6..00000000000 --- a/src/snark/libsnark/common/template_utils.hpp +++ /dev/null @@ -1,26 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of functions for supporting the use of templates. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef TEMPLATE_UTILS_HPP_ -#define TEMPLATE_UTILS_HPP_ - -namespace libsnark { - -/* A commonly used SFINAE helper type */ -template -struct void_type -{ - typedef void type; -}; - -} // libsnark - -#endif // TEMPLATE_UTILS_HPP_ diff --git a/src/snark/libsnark/common/utils.cpp b/src/snark/libsnark/common/utils.cpp deleted file mode 100644 index 06af6eff84e..00000000000 --- a/src/snark/libsnark/common/utils.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/** @file - ***************************************************************************** - Implementation of misc math and serialization utility functions - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#include -#include -#include -#include -#include "common/utils.hpp" - -namespace libsnark { - -size_t log2(size_t n) -/* returns ceil(log2(n)), so UINT64_C(1)< 1) - { - n >>= 1; - r++; - } - - return r; -} - -size_t bitreverse(size_t n, const size_t l) -{ - size_t r = 0; - for (size_t k = 0; k < l; ++k) - { - r = (r << 1) | (n & 1); - n >>= 1; - } - return r; -} - -bit_vector int_list_to_bits(const std::initializer_list &l, const size_t wordsize) -{ - bit_vector res(wordsize*l.size()); - for (size_t i = 0; i < l.size(); ++i) - { - for (size_t j = 0; j < wordsize; ++j) - { - res[i*wordsize + j] = (*(l.begin()+i) & (UINT64_C(1)<<(wordsize-1-j))); - } - } - return res; -} - -int64_t div_ceil(int64_t x, int64_t y) -{ - return (x + (y-1)) / y; -} - -bool is_little_endian() -{ - uint64_t a = 0x12345678; - unsigned char *c = (unsigned char*)(&a); - return (*c = 0x78); -} - -std::string FORMAT(const std::string &prefix, const char* format, ...) -{ - const static size_t MAX_FMT = 256; - char buf[MAX_FMT]; - va_list args; - va_start(args, format); - vsnprintf(buf, MAX_FMT, format, args); - va_end(args); - - return prefix + std::string(buf); -} - -void serialize_bit_vector(std::ostream &out, const bit_vector &v) -{ - out << v.size() << "\n"; - for (size_t i = 0; i < v.size(); ++i) - { - out << v[i] << "\n"; - } -} - -void deserialize_bit_vector(std::istream &in, bit_vector &v) -{ - size_t size; - in >> size; - v.resize(size); - for (size_t i = 0; i < size; ++i) - { - bool b; - in >> b; - v[i] = b; - } -} -} // libsnark diff --git a/src/snark/libsnark/common/utils.hpp b/src/snark/libsnark/common/utils.hpp deleted file mode 100644 index 505f67410b1..00000000000 --- a/src/snark/libsnark/common/utils.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/** @file - ***************************************************************************** - Declaration of misc math and serialization utility functions - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef UTILS_HPP_ -#define UTILS_HPP_ - -#include -#include -#include -#include -#include - -namespace libsnark { - -typedef std::vector bit_vector; - -/// returns ceil(log2(n)), so UINT64_C(1)< &l, const size_t wordsize); -int64_t div_ceil(int64_t x, int64_t y); - -bool is_little_endian(); - -std::string FORMAT(const std::string &prefix, const char* format, ...); - -/* A variadic template to suppress unused argument warnings */ -template -void UNUSED(Types&&...) {} - -#ifdef DEBUG -#define FMT FORMAT -#else -#define FMT(...) (UNUSED(__VA_ARGS__), "") -#endif - -void serialize_bit_vector(std::ostream &out, const bit_vector &v); -void deserialize_bit_vector(std::istream &in, bit_vector &v); - -template -size_t size_in_bits(const std::vector &v); - -#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) - -} // libsnark - -#include "common/utils.tcc" /* note that utils has a templatized part (utils.tcc) and non-templatized part (utils.cpp) */ -#endif // UTILS_HPP_ diff --git a/src/snark/libsnark/common/utils.tcc b/src/snark/libsnark/common/utils.tcc deleted file mode 100644 index f97178f8cc5..00000000000 --- a/src/snark/libsnark/common/utils.tcc +++ /dev/null @@ -1,23 +0,0 @@ -/** @file - ***************************************************************************** - Implementation of templatized utility functions - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef UTILS_TCC_ -#define UTILS_TCC_ - -namespace libsnark { - -template -size_t size_in_bits(const std::vector &v) -{ - return v.size() * T::size_in_bits(); -} - -} // libsnark - -#endif // UTILS_TCC_ diff --git a/src/snark/libsnark/gadgetlib1/constraint_profiling.cpp b/src/snark/libsnark/gadgetlib1/constraint_profiling.cpp deleted file mode 100644 index bc17e63bc35..00000000000 --- a/src/snark/libsnark/gadgetlib1/constraint_profiling.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/** @file - ***************************************************************************** - - Implementation of interfaces for profiling constraints. - - See constraint_profiling.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#include "gadgetlib1/constraint_profiling.hpp" -#include "common/profiling.hpp" - -namespace libsnark { - -size_t constraint_profiling_indent = 0; -std::vector constraint_profiling_table; - -size_t PRINT_CONSTRAINT_PROFILING() -{ - size_t accounted = 0; - print_indent(); - printf("Constraint profiling:\n"); - for (constraint_profiling_entry &ent : constraint_profiling_table) - { - if (ent.indent == 0) - { - accounted += ent.count; - } - - print_indent(); - for (size_t i = 0; i < ent.indent; ++i) - { - printf(" "); - } - printf("* Number of constraints in [%s]: %zu\n", ent.annotation.c_str(), ent.count); - } - - constraint_profiling_table.clear(); - constraint_profiling_indent = 0; - - return accounted; -} - -} diff --git a/src/snark/libsnark/gadgetlib1/constraint_profiling.hpp b/src/snark/libsnark/gadgetlib1/constraint_profiling.hpp deleted file mode 100644 index df8a55de197..00000000000 --- a/src/snark/libsnark/gadgetlib1/constraint_profiling.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for profiling constraints. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef CONSTRAINT_PROFILING_HPP_ -#define CONSTRAINT_PROFILING_HPP_ - -#include -#include -#include -#include - -namespace libsnark { - -extern size_t constraint_profiling_indent; - -struct constraint_profiling_entry { - size_t indent; - std::string annotation; - size_t count; -}; - -extern std::vector constraint_profiling_table; - -#define PROFILE_CONSTRAINTS(pb, annotation) \ - for (size_t _num_constraints_before = pb.num_constraints(), _iter = (++constraint_profiling_indent, 0), _cp_pos = constraint_profiling_table.size(); \ - _iter == 0; \ - constraint_profiling_table.insert(constraint_profiling_table.begin() + _cp_pos, constraint_profiling_entry{--constraint_profiling_indent, annotation, pb.num_constraints() - _num_constraints_before}), \ - _iter = 1) - -size_t PRINT_CONSTRAINT_PROFILING(); // returns # of top level constraints - -} // libsnark - -#endif // CONSTRAINT_PROFILING_HPP_ diff --git a/src/snark/libsnark/gadgetlib1/examples/simple_example.hpp b/src/snark/libsnark/gadgetlib1/examples/simple_example.hpp deleted file mode 100644 index faa3a960525..00000000000 --- a/src/snark/libsnark/gadgetlib1/examples/simple_example.hpp +++ /dev/null @@ -1,23 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef SIMPLE_EXAMPLE_HPP_ -#define SIMPLE_EXAMPLE_HPP_ - -#include "examples/r1cs_examples.hpp" - -namespace libsnark { - -template -r1cs_example gen_r1cs_example_from_protoboard(const size_t num_constraints, - const size_t num_inputs); - -} // libsnark - -#include "gadgetlib1/examples/simple_example.tcc" - -#endif // SIMPLE_EXAMPLE_HPP_ diff --git a/src/snark/libsnark/gadgetlib1/examples/simple_example.tcc b/src/snark/libsnark/gadgetlib1/examples/simple_example.tcc deleted file mode 100644 index 9d500b5c752..00000000000 --- a/src/snark/libsnark/gadgetlib1/examples/simple_example.tcc +++ /dev/null @@ -1,54 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef SIMPLE_EXAMPLE_TCC_ -#define SIMPLE_EXAMPLE_TCC_ - -#include -#include "gadgetlib1/gadgets/basic_gadgets.hpp" - -namespace libsnark { - -/* NOTE: all examples here actually generate one constraint less to account for soundness constraint in QAP */ - -template -r1cs_example gen_r1cs_example_from_protoboard(const size_t num_constraints, - const size_t num_inputs) -{ - const size_t new_num_constraints = num_constraints - 1; - - /* construct dummy example: inner products of two vectors */ - protoboard pb; - pb_variable_array A; - pb_variable_array B; - pb_variable res; - - // the variables on the protoboard are (ONE (constant 1 term), res, A[0], ..., A[num_constraints-1], B[0], ..., B[num_constraints-1]) - res.allocate(pb, "res"); - A.allocate(pb, new_num_constraints, "A"); - B.allocate(pb, new_num_constraints, "B"); - - inner_product_gadget compute_inner_product(pb, A, B, res, "compute_inner_product"); - compute_inner_product.generate_r1cs_constraints(); - - /* fill in random example */ - for (size_t i = 0; i < new_num_constraints; ++i) - { - pb.val(A[i]) = FieldT::random_element(); - pb.val(B[i]) = FieldT::random_element(); - } - - compute_inner_product.generate_r1cs_witness(); - - pb.constraint_system.num_inputs = num_inputs; - const r1cs_variable_assignment va = pb.values; - const r1cs_variable_assignment input(va.begin(), va.begin() + num_inputs); - return r1cs_example(pb.constraint_system, input, va, num_inputs); -} - -} // libsnark -#endif // R1CS_EXAMPLES_TCC_ diff --git a/src/snark/libsnark/gadgetlib1/gadget.hpp b/src/snark/libsnark/gadgetlib1/gadget.hpp deleted file mode 100644 index dbeaa9d4b49..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadget.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef GADGET_HPP_ -#define GADGET_HPP_ - -#include "gadgetlib1/protoboard.hpp" - -namespace libsnark { - -template -class gadget { -protected: - protoboard &pb; - const std::string annotation_prefix; -public: - gadget(protoboard &pb, const std::string &annotation_prefix=""); -}; - -} // libsnark -#include "gadgetlib1/gadget.tcc" - -#endif // GADGET_HPP_ diff --git a/src/snark/libsnark/gadgetlib1/gadget.tcc b/src/snark/libsnark/gadgetlib1/gadget.tcc deleted file mode 100644 index 120229bbea8..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadget.tcc +++ /dev/null @@ -1,23 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef GADGET_TCC_ -#define GADGET_TCC_ - -namespace libsnark { - -template -gadget::gadget(protoboard &pb, const std::string &annotation_prefix) : - pb(pb), annotation_prefix(annotation_prefix) -{ -#ifdef DEBUG - assert(annotation_prefix != ""); -#endif -} - -} // libsnark -#endif // GADGET_TCC_ diff --git a/src/snark/libsnark/gadgetlib1/gadgets/basic_gadgets.hpp b/src/snark/libsnark/gadgetlib1/gadgets/basic_gadgets.hpp deleted file mode 100644 index 08e596bee73..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/basic_gadgets.hpp +++ /dev/null @@ -1,351 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef BASIC_GADGETS_HPP_ -#define BASIC_GADGETS_HPP_ - -#include -#include - -#include "gadgetlib1/gadget.hpp" - -namespace libsnark { - -/* forces lc to take value 0 or 1 by adding constraint lc * (1-lc) = 0 */ -template -void generate_boolean_r1cs_constraint(protoboard &pb, const pb_linear_combination &lc, const std::string &annotation_prefix=""); - -template -void generate_r1cs_equals_const_constraint(protoboard &pb, const pb_linear_combination &lc, const FieldT& c, const std::string &annotation_prefix=""); - -template -class packing_gadget : public gadget { -private: - /* no internal variables */ -public: - const pb_linear_combination_array bits; - const pb_linear_combination packed; - - packing_gadget(protoboard &pb, - const pb_linear_combination_array &bits, - const pb_linear_combination &packed, - const std::string &annotation_prefix="") : - gadget(pb, annotation_prefix), bits(bits), packed(packed) {} - - void generate_r1cs_constraints(const bool enforce_bitness); - /* adds constraint result = \sum bits[i] * 2^i */ - - void generate_r1cs_witness_from_packed(); - void generate_r1cs_witness_from_bits(); -}; - -template -class multipacking_gadget : public gadget { -private: - std::vector > packers; -public: - const pb_linear_combination_array bits; - const pb_linear_combination_array packed_vars; - - const size_t chunk_size; - const size_t num_chunks; - // const size_t last_chunk_size; - - multipacking_gadget(protoboard &pb, - const pb_linear_combination_array &bits, - const pb_linear_combination_array &packed_vars, - const size_t chunk_size, - const std::string &annotation_prefix=""); - void generate_r1cs_constraints(const bool enforce_bitness); - void generate_r1cs_witness_from_packed(); - void generate_r1cs_witness_from_bits(); -}; - -template -class field_vector_copy_gadget : public gadget { -public: - const pb_variable_array source; - const pb_variable_array target; - const pb_linear_combination do_copy; - - field_vector_copy_gadget(protoboard &pb, - const pb_variable_array &source, - const pb_variable_array &target, - const pb_linear_combination &do_copy, - const std::string &annotation_prefix=""); - void generate_r1cs_constraints(); - void generate_r1cs_witness(); -}; - -template -class bit_vector_copy_gadget : public gadget { -public: - const pb_variable_array source_bits; - const pb_variable_array target_bits; - const pb_linear_combination do_copy; - - pb_variable_array packed_source; - pb_variable_array packed_target; - - std::shared_ptr > pack_source; - std::shared_ptr > pack_target; - std::shared_ptr > copier; - - const size_t chunk_size; - const size_t num_chunks; - - bit_vector_copy_gadget(protoboard &pb, - const pb_variable_array &source_bits, - const pb_variable_array &target_bits, - const pb_linear_combination &do_copy, - const size_t chunk_size, - const std::string &annotation_prefix=""); - void generate_r1cs_constraints(const bool enforce_source_bitness, const bool enforce_target_bitness); - void generate_r1cs_witness(); -}; - -template -class dual_variable_gadget : public gadget { -private: - std::shared_ptr > consistency_check; -public: - pb_variable packed; - pb_variable_array bits; - - dual_variable_gadget(protoboard &pb, - const size_t width, - const std::string &annotation_prefix="") : - gadget(pb, annotation_prefix) - { - packed.allocate(pb, FMT(this->annotation_prefix, " packed")); - bits.allocate(pb, width, FMT(this->annotation_prefix, " bits")); - consistency_check.reset(new packing_gadget(pb, - bits, - packed, - FMT(this->annotation_prefix, " consistency_check"))); - } - - dual_variable_gadget(protoboard &pb, - const pb_variable_array &bits, - const std::string &annotation_prefix="") : - gadget(pb, annotation_prefix), bits(bits) - { - packed.allocate(pb, FMT(this->annotation_prefix, " packed")); - consistency_check.reset(new packing_gadget(pb, - bits, - packed, - FMT(this->annotation_prefix, " consistency_check"))); - } - - dual_variable_gadget(protoboard &pb, - const pb_variable &packed, - const size_t width, - const std::string &annotation_prefix="") : - gadget(pb, annotation_prefix), packed(packed) - { - bits.allocate(pb, width, FMT(this->annotation_prefix, " bits")); - consistency_check.reset(new packing_gadget(pb, - bits, - packed, - FMT(this->annotation_prefix, " consistency_check"))); - } - - void generate_r1cs_constraints(const bool enforce_bitness); - void generate_r1cs_witness_from_packed(); - void generate_r1cs_witness_from_bits(); -}; - -/* - the gadgets below are Fp specific: - I * X = R - (1-R) * X = 0 - - if X = 0 then R = 0 - if X != 0 then R = 1 and I = X^{-1} -*/ - -template -class disjunction_gadget : public gadget { -private: - pb_variable inv; -public: - const pb_variable_array inputs; - const pb_variable output; - - disjunction_gadget(protoboard& pb, - const pb_variable_array &inputs, - const pb_variable &output, - const std::string &annotation_prefix="") : - gadget(pb, annotation_prefix), inputs(inputs), output(output) - { - assert(inputs.size() >= 1); - inv.allocate(pb, FMT(this->annotation_prefix, " inv")); - } - - void generate_r1cs_constraints(); - void generate_r1cs_witness(); -}; - -template -void test_disjunction_gadget(const size_t n); - -template -class conjunction_gadget : public gadget { -private: - pb_variable inv; -public: - const pb_variable_array inputs; - const pb_variable output; - - conjunction_gadget(protoboard& pb, - const pb_variable_array &inputs, - const pb_variable &output, - const std::string &annotation_prefix="") : - gadget(pb, annotation_prefix), inputs(inputs), output(output) - { - assert(inputs.size() >= 1); - inv.allocate(pb, FMT(this->annotation_prefix, " inv")); - } - - void generate_r1cs_constraints(); - void generate_r1cs_witness(); -}; - -template -void test_conjunction_gadget(const size_t n); - -template -class comparison_gadget : public gadget { -private: - pb_variable_array alpha; - pb_variable alpha_packed; - std::shared_ptr > pack_alpha; - - std::shared_ptr > all_zeros_test; - pb_variable not_all_zeros; -public: - const size_t n; - const pb_linear_combination A; - const pb_linear_combination B; - const pb_variable less; - const pb_variable less_or_eq; - - comparison_gadget(protoboard& pb, - const size_t n, - const pb_linear_combination &A, - const pb_linear_combination &B, - const pb_variable &less, - const pb_variable &less_or_eq, - const std::string &annotation_prefix="") : - gadget(pb, annotation_prefix), n(n), A(A), B(B), less(less), less_or_eq(less_or_eq) - { - alpha.allocate(pb, n, FMT(this->annotation_prefix, " alpha")); - alpha.emplace_back(less_or_eq); // alpha[n] is less_or_eq - - alpha_packed.allocate(pb, FMT(this->annotation_prefix, " alpha_packed")); - not_all_zeros.allocate(pb, FMT(this->annotation_prefix, " not_all_zeros")); - - pack_alpha.reset(new packing_gadget(pb, alpha, alpha_packed, - FMT(this->annotation_prefix, " pack_alpha"))); - - all_zeros_test.reset(new disjunction_gadget(pb, - pb_variable_array(alpha.begin(), alpha.begin() + n), - not_all_zeros, - FMT(this->annotation_prefix, " all_zeros_test"))); - }; - - void generate_r1cs_constraints(); - void generate_r1cs_witness(); -}; - -template -void test_comparison_gadget(const size_t n); - -template -class inner_product_gadget : public gadget { -private: - /* S_i = \sum_{k=0}^{i+1} A[i] * B[i] */ - pb_variable_array S; -public: - const pb_linear_combination_array A; - const pb_linear_combination_array B; - const pb_variable result; - - inner_product_gadget(protoboard& pb, - const pb_linear_combination_array &A, - const pb_linear_combination_array &B, - const pb_variable &result, - const std::string &annotation_prefix="") : - gadget(pb, annotation_prefix), A(A), B(B), result(result) - { - assert(A.size() >= 1); - assert(A.size() == B.size()); - - S.allocate(pb, A.size()-1, FMT(this->annotation_prefix, " S")); - } - - void generate_r1cs_constraints(); - void generate_r1cs_witness(); -}; - -template -void test_inner_product_gadget(const size_t n); - -template -class loose_multiplexing_gadget : public gadget { -/* - this implements loose multiplexer: - index not in bounds -> success_flag = 0 - index in bounds && success_flag = 1 -> result is correct - however if index is in bounds we can also set success_flag to 0 (and then result will be forced to be 0) -*/ -public: - pb_variable_array alpha; -private: - std::shared_ptr > compute_result; -public: - const pb_linear_combination_array arr; - const pb_variable index; - const pb_variable result; - const pb_variable success_flag; - - loose_multiplexing_gadget(protoboard& pb, - const pb_linear_combination_array &arr, - const pb_variable &index, - const pb_variable &result, - const pb_variable &success_flag, - const std::string &annotation_prefix="") : - gadget(pb, annotation_prefix), arr(arr), index(index), result(result), success_flag(success_flag) - { - alpha.allocate(pb, arr.size(), FMT(this->annotation_prefix, " alpha")); - compute_result.reset(new inner_product_gadget(pb, alpha, arr, result, FMT(this->annotation_prefix, " compute_result"))); - }; - - void generate_r1cs_constraints(); - void generate_r1cs_witness(); -}; - -template -void test_loose_multiplexing_gadget(const size_t n); - -template -void create_linear_combination_constraints(protoboard &pb, - const std::vector &base, - const std::vector > &v, - const VarT &target, - const std::string &annotation_prefix); - -template -void create_linear_combination_witness(protoboard &pb, - const std::vector &base, - const std::vector > &v, - const VarT &target); - -} // libsnark -#include "gadgetlib1/gadgets/basic_gadgets.tcc" - -#endif // BASIC_GADGETS_HPP_ diff --git a/src/snark/libsnark/gadgetlib1/gadgets/basic_gadgets.tcc b/src/snark/libsnark/gadgetlib1/gadgets/basic_gadgets.tcc deleted file mode 100644 index 4e2d9fce3ee..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/basic_gadgets.tcc +++ /dev/null @@ -1,705 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef BASIC_GADGETS_TCC_ -#define BASIC_GADGETS_TCC_ - -#include "common/profiling.hpp" -#include "common/utils.hpp" - -namespace libsnark { - -template -void generate_boolean_r1cs_constraint(protoboard &pb, const pb_linear_combination &lc, const std::string &annotation_prefix) -/* forces lc to take value 0 or 1 by adding constraint lc * (1-lc) = 0 */ -{ - pb.add_r1cs_constraint(r1cs_constraint(lc, 1-lc, 0), - FMT(annotation_prefix, " boolean_r1cs_constraint")); -} - -template -void generate_r1cs_equals_const_constraint(protoboard &pb, const pb_linear_combination &lc, const FieldT& c, const std::string &annotation_prefix) -{ - pb.add_r1cs_constraint(r1cs_constraint(1, lc, c), - FMT(annotation_prefix, " constness_constraint")); -} - -template -void packing_gadget::generate_r1cs_constraints(const bool enforce_bitness) -/* adds constraint result = \sum bits[i] * 2^i */ -{ - this->pb.add_r1cs_constraint(r1cs_constraint(1, pb_packing_sum(bits), packed), FMT(this->annotation_prefix, " packing_constraint")); - - if (enforce_bitness) - { - for (size_t i = 0; i < bits.size(); ++i) - { - generate_boolean_r1cs_constraint(this->pb, bits[i], FMT(this->annotation_prefix, " bitness_%zu", i)); - } - } -} - -template -void packing_gadget::generate_r1cs_witness_from_packed() -{ - packed.evaluate(this->pb); - assert(this->pb.lc_val(packed).as_bigint().num_bits() <= bits.size()); - bits.fill_with_bits_of_field_element(this->pb, this->pb.lc_val(packed)); -} - -template -void packing_gadget::generate_r1cs_witness_from_bits() -{ - bits.evaluate(this->pb); - this->pb.lc_val(packed) = bits.get_field_element_from_bits(this->pb); -} - -template -multipacking_gadget::multipacking_gadget(protoboard &pb, - const pb_linear_combination_array &bits, - const pb_linear_combination_array &packed_vars, - const size_t chunk_size, - const std::string &annotation_prefix) : - gadget(pb, annotation_prefix), bits(bits), packed_vars(packed_vars), - chunk_size(chunk_size), - num_chunks(div_ceil(bits.size(), chunk_size)) - // last_chunk_size(bits.size() - (num_chunks-1) * chunk_size) -{ - assert(packed_vars.size() == num_chunks); - for (size_t i = 0; i < num_chunks; ++i) - { - packers.emplace_back(packing_gadget(this->pb, pb_linear_combination_array(bits.begin() + i * chunk_size, - bits.begin() + std::min((i+1) * chunk_size, bits.size())), - packed_vars[i], FMT(this->annotation_prefix, " packers_%zu", i))); - } -} - -template -void multipacking_gadget::generate_r1cs_constraints(const bool enforce_bitness) -{ - for (size_t i = 0; i < num_chunks; ++i) - { - packers[i].generate_r1cs_constraints(enforce_bitness); - } -} - -template -void multipacking_gadget::generate_r1cs_witness_from_packed() -{ - for (size_t i = 0; i < num_chunks; ++i) - { - packers[i].generate_r1cs_witness_from_packed(); - } -} - -template -void multipacking_gadget::generate_r1cs_witness_from_bits() -{ - for (size_t i = 0; i < num_chunks; ++i) - { - packers[i].generate_r1cs_witness_from_bits(); - } -} - -template -size_t multipacking_num_chunks(const size_t num_bits) -{ - return div_ceil(num_bits, FieldT::capacity()); -} - -template -field_vector_copy_gadget::field_vector_copy_gadget(protoboard &pb, - const pb_variable_array &source, - const pb_variable_array &target, - const pb_linear_combination &do_copy, - const std::string &annotation_prefix) : -gadget(pb, annotation_prefix), source(source), target(target), do_copy(do_copy) -{ - assert(source.size() == target.size()); -} - -template -void field_vector_copy_gadget::generate_r1cs_constraints() -{ - for (size_t i = 0; i < source.size(); ++i) - { - this->pb.add_r1cs_constraint(r1cs_constraint(do_copy, source[i] - target[i], 0), - FMT(this->annotation_prefix, " copying_check_%zu", i)); - } -} - -template -void field_vector_copy_gadget::generate_r1cs_witness() -{ - do_copy.evaluate(this->pb); - assert(this->pb.lc_val(do_copy) == FieldT::one() || this->pb.lc_val(do_copy) == FieldT::zero()); - if (this->pb.lc_val(do_copy) != FieldT::zero()) - { - for (size_t i = 0; i < source.size(); ++i) - { - this->pb.val(target[i]) = this->pb.val(source[i]); - } - } -} - -template -bit_vector_copy_gadget::bit_vector_copy_gadget(protoboard &pb, - const pb_variable_array &source_bits, - const pb_variable_array &target_bits, - const pb_linear_combination &do_copy, - const size_t chunk_size, - const std::string &annotation_prefix) : - gadget(pb, annotation_prefix), source_bits(source_bits), target_bits(target_bits), do_copy(do_copy), - chunk_size(chunk_size), num_chunks(div_ceil(source_bits.size(), chunk_size)) -{ - assert(source_bits.size() == target_bits.size()); - - packed_source.allocate(pb, num_chunks, FMT(annotation_prefix, " packed_source")); - pack_source.reset(new multipacking_gadget(pb, source_bits, packed_source, chunk_size, FMT(annotation_prefix, " pack_source"))); - - packed_target.allocate(pb, num_chunks, FMT(annotation_prefix, " packed_target")); - pack_target.reset(new multipacking_gadget(pb, target_bits, packed_target, chunk_size, FMT(annotation_prefix, " pack_target"))); - - copier.reset(new field_vector_copy_gadget(pb, packed_source, packed_target, do_copy, FMT(annotation_prefix, " copier"))); -} - -template -void bit_vector_copy_gadget::generate_r1cs_constraints(const bool enforce_source_bitness, const bool enforce_target_bitness) -{ - pack_source->generate_r1cs_constraints(enforce_source_bitness); - pack_target->generate_r1cs_constraints(enforce_target_bitness); - - copier->generate_r1cs_constraints(); -} - -template -void bit_vector_copy_gadget::generate_r1cs_witness() -{ - do_copy.evaluate(this->pb); - assert(this->pb.lc_val(do_copy) == FieldT::zero() || this->pb.lc_val(do_copy) == FieldT::one()); - if (this->pb.lc_val(do_copy) == FieldT::one()) - { - for (size_t i = 0; i < source_bits.size(); ++i) - { - this->pb.val(target_bits[i]) = this->pb.val(source_bits[i]); - } - } - - pack_source->generate_r1cs_witness_from_bits(); - pack_target->generate_r1cs_witness_from_bits(); -} - -template -void dual_variable_gadget::generate_r1cs_constraints(const bool enforce_bitness) -{ - consistency_check->generate_r1cs_constraints(enforce_bitness); -} - -template -void dual_variable_gadget::generate_r1cs_witness_from_packed() -{ - consistency_check->generate_r1cs_witness_from_packed(); -} - -template -void dual_variable_gadget::generate_r1cs_witness_from_bits() -{ - consistency_check->generate_r1cs_witness_from_bits(); -} - -template -void disjunction_gadget::generate_r1cs_constraints() -{ - /* inv * sum = output */ - linear_combination a1, b1, c1; - a1.add_term(inv); - for (size_t i = 0; i < inputs.size(); ++i) - { - b1.add_term(inputs[i]); - } - c1.add_term(output); - - this->pb.add_r1cs_constraint(r1cs_constraint(a1, b1, c1), FMT(this->annotation_prefix, " inv*sum=output")); - - /* (1-output) * sum = 0 */ - linear_combination a2, b2, c2; - a2.add_term(ONE); - a2.add_term(output, -1); - for (size_t i = 0; i < inputs.size(); ++i) - { - b2.add_term(inputs[i]); - } - c2.add_term(ONE, 0); - - this->pb.add_r1cs_constraint(r1cs_constraint(a2, b2, c2), FMT(this->annotation_prefix, " (1-output)*sum=0")); -} - -template -void disjunction_gadget::generate_r1cs_witness() -{ - FieldT sum = FieldT::zero(); - - for (size_t i = 0; i < inputs.size(); ++i) - { - sum += this->pb.val(inputs[i]); - } - - if (sum.is_zero()) - { - this->pb.val(inv) = FieldT::zero(); - this->pb.val(output) = FieldT::zero(); - } - else - { - this->pb.val(inv) = sum.inverse(); - this->pb.val(output) = FieldT::one(); - } -} - -template -void test_disjunction_gadget(const size_t n) -{ - printf("testing disjunction_gadget on all %zu bit strings\n", n); - - protoboard pb; - pb_variable_array inputs; - inputs.allocate(pb, n, "inputs"); - - pb_variable output; - output.allocate(pb, "output"); - - disjunction_gadget d(pb, inputs, output, "d"); - d.generate_r1cs_constraints(); - - for (size_t w = 0; w < UINT64_C(1)< -void conjunction_gadget::generate_r1cs_constraints() -{ - /* inv * (n-sum) = 1-output */ - linear_combination a1, b1, c1; - a1.add_term(inv); - b1.add_term(ONE, inputs.size()); - for (size_t i = 0; i < inputs.size(); ++i) - { - b1.add_term(inputs[i], -1); - } - c1.add_term(ONE); - c1.add_term(output, -1); - - this->pb.add_r1cs_constraint(r1cs_constraint(a1, b1, c1), FMT(this->annotation_prefix, " inv*(n-sum)=(1-output)")); - - /* output * (n-sum) = 0 */ - linear_combination a2, b2, c2; - a2.add_term(output); - b2.add_term(ONE, inputs.size()); - for (size_t i = 0; i < inputs.size(); ++i) - { - b2.add_term(inputs[i], -1); - } - c2.add_term(ONE, 0); - - this->pb.add_r1cs_constraint(r1cs_constraint(a2, b2, c2), FMT(this->annotation_prefix, " output*(n-sum)=0")); -} - -template -void conjunction_gadget::generate_r1cs_witness() -{ - FieldT sum = FieldT(inputs.size()); - - for (size_t i = 0; i < inputs.size(); ++i) - { - sum -= this->pb.val(inputs[i]); - } - - if (sum.is_zero()) - { - this->pb.val(inv) = FieldT::zero(); - this->pb.val(output) = FieldT::one(); - } - else - { - this->pb.val(inv) = sum.inverse(); - this->pb.val(output) = FieldT::zero(); - } -} - -template -void test_conjunction_gadget(const size_t n) -{ - printf("testing conjunction_gadget on all %zu bit strings\n", n); - - protoboard pb; - pb_variable_array inputs; - inputs.allocate(pb, n, "inputs"); - - pb_variable output; - output.allocate(pb, "output"); - - conjunction_gadget c(pb, inputs, output, "c"); - c.generate_r1cs_constraints(); - - for (size_t w = 0; w < UINT64_C(1)< -void comparison_gadget::generate_r1cs_constraints() -{ - /* - packed(alpha) = 2^n + B - A - - not_all_zeros = \bigvee_{i=0}^{n-1} alpha_i - - if B - A > 0, then 2^n + B - A > 2^n, - so alpha_n = 1 and not_all_zeros = 1 - if B - A = 0, then 2^n + B - A = 2^n, - so alpha_n = 1 and not_all_zeros = 0 - if B - A < 0, then 2^n + B - A \in {0, 1, \ldots, 2^n-1}, - so alpha_n = 0 - - therefore alpha_n = less_or_eq and alpha_n * not_all_zeros = less - */ - - /* not_all_zeros to be Boolean, alpha_i are Boolean by packing gadget */ - generate_boolean_r1cs_constraint(this->pb, not_all_zeros, - FMT(this->annotation_prefix, " not_all_zeros")); - - /* constraints for packed(alpha) = 2^n + B - A */ - pack_alpha->generate_r1cs_constraints(true); - this->pb.add_r1cs_constraint(r1cs_constraint(1, (FieldT(2)^n) + B - A, alpha_packed), FMT(this->annotation_prefix, " main_constraint")); - - /* compute result */ - all_zeros_test->generate_r1cs_constraints(); - this->pb.add_r1cs_constraint(r1cs_constraint(less_or_eq, not_all_zeros, less), - FMT(this->annotation_prefix, " less")); -} - -template -void comparison_gadget::generate_r1cs_witness() -{ - A.evaluate(this->pb); - B.evaluate(this->pb); - - /* unpack 2^n + B - A into alpha_packed */ - this->pb.val(alpha_packed) = (FieldT(2)^n) + this->pb.lc_val(B) - this->pb.lc_val(A); - pack_alpha->generate_r1cs_witness_from_packed(); - - /* compute result */ - all_zeros_test->generate_r1cs_witness(); - this->pb.val(less) = this->pb.val(less_or_eq) * this->pb.val(not_all_zeros); -} - -template -void test_comparison_gadget(const size_t n) -{ - printf("testing comparison_gadget on all %zu bit inputs\n", n); - - protoboard pb; - - pb_variable A, B, less, less_or_eq; - A.allocate(pb, "A"); - B.allocate(pb, "B"); - less.allocate(pb, "less"); - less_or_eq.allocate(pb, "less_or_eq"); - - comparison_gadget cmp(pb, n, A, B, less, less_or_eq, "cmp"); - cmp.generate_r1cs_constraints(); - - for (size_t a = 0; a < UINT64_C(1)< -void inner_product_gadget::generate_r1cs_constraints() -{ - /* - S_i = \sum_{k=0}^{i+1} A[i] * B[i] - S[0] = A[0] * B[0] - S[i+1] - S[i] = A[i] * B[i] - */ - for (size_t i = 0; i < A.size(); ++i) - { - this->pb.add_r1cs_constraint( - r1cs_constraint(A[i], B[i], - (i == A.size()-1 ? result : S[i]) + (i == 0 ? 0 * ONE : -S[i-1])), - FMT(this->annotation_prefix, " S_%zu", i)); - } -} - -template -void inner_product_gadget::generate_r1cs_witness() -{ - FieldT total = FieldT::zero(); - for (size_t i = 0; i < A.size(); ++i) - { - A[i].evaluate(this->pb); - B[i].evaluate(this->pb); - - total += this->pb.lc_val(A[i]) * this->pb.lc_val(B[i]); - this->pb.val(i == A.size()-1 ? result : S[i]) = total; - } -} - -template -void test_inner_product_gadget(const size_t n) -{ - printf("testing inner_product_gadget on all %zu bit strings\n", n); - - protoboard pb; - pb_variable_array A; - A.allocate(pb, n, "A"); - pb_variable_array B; - B.allocate(pb, n, "B"); - - pb_variable result; - result.allocate(pb, "result"); - - inner_product_gadget g(pb, A, B, result, "g"); - g.generate_r1cs_constraints(); - - for (size_t i = 0; i < UINT64_C(1)< -void loose_multiplexing_gadget::generate_r1cs_constraints() -{ - /* \alpha_i (index - i) = 0 */ - for (size_t i = 0; i < arr.size(); ++i) - { - this->pb.add_r1cs_constraint( - r1cs_constraint(alpha[i], index - i, 0), - FMT(this->annotation_prefix, " alpha_%zu", i)); - } - - /* 1 * (\sum \alpha_i) = success_flag */ - linear_combination a, b, c; - a.add_term(ONE); - for (size_t i = 0; i < arr.size(); ++i) - { - b.add_term(alpha[i]); - } - c.add_term(success_flag); - this->pb.add_r1cs_constraint(r1cs_constraint(a, b, c), FMT(this->annotation_prefix, " main_constraint")); - - /* now success_flag is constrained to either 0 (if index is out of - range) or \alpha_i. constrain it and \alpha_i to zero */ - generate_boolean_r1cs_constraint(this->pb, success_flag, FMT(this->annotation_prefix, " success_flag")); - - /* compute result */ - compute_result->generate_r1cs_constraints(); -} - -template -void loose_multiplexing_gadget::generate_r1cs_witness() -{ - /* assumes that idx can be fit in uint64_t; true for our purposes for now */ - const bigint valint = this->pb.val(index).as_bigint(); - uint64_t idx = valint.as_uint64(); - const bigint arrsize(arr.size()); - - if (idx >= arr.size() || mpn_cmp(valint.data, arrsize.data, FieldT::num_limbs) >= 0) - { - for (size_t i = 0; i < arr.size(); ++i) - { - this->pb.val(alpha[i]) = FieldT::zero(); - } - - this->pb.val(success_flag) = FieldT::zero(); - } - else - { - for (size_t i = 0; i < arr.size(); ++i) - { - this->pb.val(alpha[i]) = (i == idx ? FieldT::one() : FieldT::zero()); - } - - this->pb.val(success_flag) = FieldT::one(); - } - - compute_result->generate_r1cs_witness(); -} - -template -void test_loose_multiplexing_gadget(const size_t n) -{ - printf("testing loose_multiplexing_gadget on 2**%zu pb_variable array inputs\n", n); - protoboard pb; - - pb_variable_array arr; - arr.allocate(pb, UINT64_C(1)< index, result, success_flag; - index.allocate(pb, "index"); - result.allocate(pb, "result"); - success_flag.allocate(pb, "success_flag"); - - loose_multiplexing_gadget g(pb, arr, index, result, success_flag, "g"); - g.generate_r1cs_constraints(); - - for (size_t i = 0; i < UINT64_C(1)< -void create_linear_combination_constraints(protoboard &pb, - const std::vector &base, - const std::vector > &v, - const VarT &target, - const std::string &annotation_prefix) -{ - for (size_t i = 0; i < base.size(); ++i) - { - linear_combination a, b, c; - - a.add_term(ONE); - b.add_term(ONE, base[i]); - - for (auto &p : v) - { - b.add_term(p.first.all_vars[i], p.second); - } - - c.add_term(target.all_vars[i]); - - pb.add_r1cs_constraint(r1cs_constraint(a, b, c), FMT(annotation_prefix, " linear_combination_%zu", i)); - } -} - -template -void create_linear_combination_witness(protoboard &pb, - const std::vector &base, - const std::vector > &v, - const VarT &target) -{ - for (size_t i = 0; i < base.size(); ++i) - { - pb.val(target.all_vars[i]) = base[i]; - - for (auto &p : v) - { - pb.val(target.all_vars[i]) += p.second * pb.val(p.first.all_vars[i]); - } - } -} - -} // libsnark -#endif // BASIC_GADGETS_TCC_ diff --git a/src/snark/libsnark/gadgetlib1/gadgets/gadget_from_r1cs.hpp b/src/snark/libsnark/gadgetlib1/gadgets/gadget_from_r1cs.hpp deleted file mode 100644 index e4b8a2acf54..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/gadget_from_r1cs.hpp +++ /dev/null @@ -1,45 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for a gadget that can be created from an R1CS constraint system. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef GADGET_FROM_R1CS_HPP_ -#define GADGET_FROM_R1CS_HPP_ - -#include - -#include "gadgetlib1/gadget.hpp" - -namespace libsnark { - -template -class gadget_from_r1cs : public gadget { - -private: - const std::vector > vars; - const r1cs_constraint_system cs; - std::map cs_to_vars; - -public: - - gadget_from_r1cs(protoboard &pb, - const std::vector > &vars, - const r1cs_constraint_system &cs, - const std::string &annotation_prefix); - - void generate_r1cs_constraints(); - void generate_r1cs_witness(const r1cs_primary_input &primary_input, - const r1cs_auxiliary_input &auxiliary_input); -}; - -} // libsnark - -#include "gadgetlib1/gadgets/gadget_from_r1cs.tcc" - -#endif // GADGET_FROM_R1CS_HPP_ diff --git a/src/snark/libsnark/gadgetlib1/gadgets/gadget_from_r1cs.tcc b/src/snark/libsnark/gadgetlib1/gadgets/gadget_from_r1cs.tcc deleted file mode 100644 index bc59b4587e5..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/gadget_from_r1cs.tcc +++ /dev/null @@ -1,123 +0,0 @@ -/** @file - ***************************************************************************** - - Implementation of interfaces for a gadget that can be created from an R1CS constraint system. - - See gadget_from_r1cs.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef GADGET_FROM_R1CS_TCC_ -#define GADGET_FROM_R1CS_TCC_ - -namespace libsnark { - -template -gadget_from_r1cs::gadget_from_r1cs(protoboard &pb, - const std::vector > &vars, - const r1cs_constraint_system &cs, - const std::string &annotation_prefix) : - gadget(pb, annotation_prefix), - vars(vars), - cs(cs) -{ - cs_to_vars[0] = 0; /* constant term maps to constant term */ - - size_t cs_var_idx = 1; - for (auto va : vars) - { -#ifdef DEBUG - printf("gadget_from_r1cs: translating a block of variables with length %zu\n", va.size()); -#endif - for (auto v : va) - { - cs_to_vars[cs_var_idx] = v.index; - -#ifdef DEBUG - if (v.index != 0) - { - // handle annotations, except for re-annotating constant term - const std::map::const_iterator it = cs.variable_annotations.find(cs_var_idx); - - std::string annotation = FMT(annotation_prefix, " variable_%zu", cs_var_idx); - if (it != cs.variable_annotations.end()) - { - annotation = annotation_prefix + " " + it->second; - } - - pb.augment_variable_annotation(v, annotation); - } -#endif - ++cs_var_idx; - } - } - -#ifdef DEBUG - printf("gadget_from_r1cs: sum of all block lengths: %zu\n", cs_var_idx-1); - printf("gadget_from_r1cs: cs.num_variables(): %zu\n", cs.num_variables()); -#endif - - assert(cs_var_idx - 1 == cs.num_variables()); -} - -template -void gadget_from_r1cs::generate_r1cs_constraints() -{ - for (size_t i = 0; i < cs.num_constraints(); ++i) - { - const r1cs_constraint &constr = cs.constraints[i]; - r1cs_constraint translated_constr; - - for (const linear_term &t: constr.a.terms) - { - translated_constr.a.terms.emplace_back(linear_term(pb_variable(cs_to_vars[t.index]), t.coeff)); - } - - for (const linear_term &t: constr.b.terms) - { - translated_constr.b.terms.emplace_back(linear_term(pb_variable(cs_to_vars[t.index]), t.coeff)); - } - - for (const linear_term &t: constr.c.terms) - { - translated_constr.c.terms.emplace_back(linear_term(pb_variable(cs_to_vars[t.index]), t.coeff)); - } - - std::string annotation = FMT(this->annotation_prefix, " constraint_%zu", i); - -#ifdef DEBUG - auto it = cs.constraint_annotations.find(i); - if (it != cs.constraint_annotations.end()) - { - annotation = this->annotation_prefix + " " + it->second; - } -#endif - this->pb.add_r1cs_constraint(translated_constr, annotation); - } -} - -template -void gadget_from_r1cs::generate_r1cs_witness(const r1cs_primary_input &primary_input, - const r1cs_auxiliary_input &auxiliary_input) -{ - assert(cs.num_inputs() == primary_input.size()); - assert(cs.num_variables() == primary_input.size() + auxiliary_input.size()); - - for (size_t i = 0; i < primary_input.size(); ++i) - { - this->pb.val(pb_variable(cs_to_vars[i+1])) = primary_input[i]; - } - - for (size_t i = 0; i < auxiliary_input.size(); ++i) - { - this->pb.val(pb_variable(cs_to_vars[primary_input.size()+i+1])) = auxiliary_input[i]; - } -} - -} // libsnark - -#endif // GADGET_FROM_R1CS_TCC_ diff --git a/src/snark/libsnark/gadgetlib1/gadgets/hashes/digest_selector_gadget.hpp b/src/snark/libsnark/gadgetlib1/gadgets/hashes/digest_selector_gadget.hpp deleted file mode 100644 index a7598b9be71..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/hashes/digest_selector_gadget.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/** - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ -#ifndef DIGEST_SELECTOR_GADGET_HPP_ -#define DIGEST_SELECTOR_GADGET_HPP_ - -#include - -#include "gadgetlib1/gadgets/basic_gadgets.hpp" -#include "gadgetlib1/gadgets/hashes/hash_io.hpp" - -namespace libsnark { - -template -class digest_selector_gadget : public gadget { -public: - size_t digest_size; - digest_variable input; - pb_linear_combination is_right; - digest_variable left; - digest_variable right; - - digest_selector_gadget(protoboard &pb, - const size_t digest_size, - const digest_variable &input, - const pb_linear_combination &is_right, - const digest_variable &left, - const digest_variable &right, - const std::string &annotation_prefix); - - void generate_r1cs_constraints(); - void generate_r1cs_witness(); -}; - -} // libsnark - -#include "gadgetlib1/gadgets/hashes/digest_selector_gadget.tcc" - -#endif // DIGEST_SELECTOR_GADGET_HPP_ diff --git a/src/snark/libsnark/gadgetlib1/gadgets/hashes/digest_selector_gadget.tcc b/src/snark/libsnark/gadgetlib1/gadgets/hashes/digest_selector_gadget.tcc deleted file mode 100644 index 422ee170a6c..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/hashes/digest_selector_gadget.tcc +++ /dev/null @@ -1,62 +0,0 @@ -/** - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ -#ifndef DIGEST_SELECTOR_GADGET_TCC_ -#define DIGEST_SELECTOR_GADGET_TCC_ - -namespace libsnark { - -template -digest_selector_gadget::digest_selector_gadget(protoboard &pb, - const size_t digest_size, - const digest_variable &input, - const pb_linear_combination &is_right, - const digest_variable &left, - const digest_variable &right, - const std::string &annotation_prefix) : -gadget(pb, annotation_prefix), digest_size(digest_size), input(input), is_right(is_right), left(left), right(right) -{ -} - -template -void digest_selector_gadget::generate_r1cs_constraints() -{ - for (size_t i = 0; i < digest_size; ++i) - { - /* - input = is_right * right + (1-is_right) * left - input - left = is_right(right - left) - */ - this->pb.add_r1cs_constraint(r1cs_constraint(is_right, right.bits[i] - left.bits[i], input.bits[i] - left.bits[i]), - FMT(this->annotation_prefix, " propagate_%zu", i)); - } -} - -template -void digest_selector_gadget::generate_r1cs_witness() -{ - is_right.evaluate(this->pb); - - assert(this->pb.lc_val(is_right) == FieldT::one() || this->pb.lc_val(is_right) == FieldT::zero()); - if (this->pb.lc_val(is_right) == FieldT::one()) - { - for (size_t i = 0; i < digest_size; ++i) - { - this->pb.val(right.bits[i]) = this->pb.val(input.bits[i]); - } - } - else - { - for (size_t i = 0; i < digest_size; ++i) - { - this->pb.val(left.bits[i]) = this->pb.val(input.bits[i]); - } - } -} - -} // libsnark - -#endif // DIGEST_SELECTOR_GADGET_TCC_ diff --git a/src/snark/libsnark/gadgetlib1/gadgets/hashes/hash_io.hpp b/src/snark/libsnark/gadgetlib1/gadgets/hashes/hash_io.hpp deleted file mode 100644 index 80ca19c61ed..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/hashes/hash_io.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/** - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ -#ifndef HASH_IO_HPP_ -#define HASH_IO_HPP_ -#include -#include -#include "gadgetlib1/gadgets/basic_gadgets.hpp" - -namespace libsnark { - -template -class digest_variable : public gadget { -public: - size_t digest_size; - pb_variable_array bits; - - digest_variable(protoboard &pb, - const size_t digest_size, - const std::string &annotation_prefix); - - digest_variable(protoboard &pb, - const size_t digest_size, - const pb_variable_array &partial_bits, - const pb_variable &padding, - const std::string &annotation_prefix); - - void generate_r1cs_constraints(); - void generate_r1cs_witness(const bit_vector& contents); - bit_vector get_digest() const; -}; - -template -class block_variable : public gadget { -public: - size_t block_size; - pb_variable_array bits; - - block_variable(protoboard &pb, - const size_t block_size, - const std::string &annotation_prefix); - - block_variable(protoboard &pb, - const std::vector > &parts, - const std::string &annotation_prefix); - - block_variable(protoboard &pb, - const digest_variable &left, - const digest_variable &right, - const std::string &annotation_prefix); - - void generate_r1cs_constraints(); - void generate_r1cs_witness(const bit_vector& contents); - bit_vector get_block() const; -}; - -} // libsnark -#include "gadgetlib1/gadgets/hashes/hash_io.tcc" - -#endif // HASH_IO_HPP_ diff --git a/src/snark/libsnark/gadgetlib1/gadgets/hashes/hash_io.tcc b/src/snark/libsnark/gadgetlib1/gadgets/hashes/hash_io.tcc deleted file mode 100644 index b122d8f98e0..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/hashes/hash_io.tcc +++ /dev/null @@ -1,105 +0,0 @@ -/** - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ -#ifndef HASH_IO_TCC_ -#define HASH_IO_TCC_ - -namespace libsnark { - -template -digest_variable::digest_variable(protoboard &pb, - const size_t digest_size, - const std::string &annotation_prefix) : - gadget(pb, annotation_prefix), digest_size(digest_size) -{ - bits.allocate(pb, digest_size, FMT(this->annotation_prefix, " bits")); -} - -template -digest_variable::digest_variable(protoboard &pb, - const size_t digest_size, - const pb_variable_array &partial_bits, - const pb_variable &padding, - const std::string &annotation_prefix) : - gadget(pb, annotation_prefix), digest_size(digest_size) -{ - assert(bits.size() <= digest_size); - bits = partial_bits; - while (bits.size() != digest_size) - { - bits.emplace_back(padding); - } -} - -template -void digest_variable::generate_r1cs_constraints() -{ - for (size_t i = 0; i < digest_size; ++i) - { - generate_boolean_r1cs_constraint(this->pb, bits[i], FMT(this->annotation_prefix, " bits_%zu", i)); - } -} - -template -void digest_variable::generate_r1cs_witness(const bit_vector& contents) -{ - bits.fill_with_bits(this->pb, contents); -} - -template -bit_vector digest_variable::get_digest() const -{ - return bits.get_bits(this->pb); -} - -template -block_variable::block_variable(protoboard &pb, - const size_t block_size, - const std::string &annotation_prefix) : - gadget(pb, annotation_prefix), block_size(block_size) -{ - bits.allocate(pb, block_size, FMT(this->annotation_prefix, " bits")); -} - -template -block_variable::block_variable(protoboard &pb, - const std::vector > &parts, - const std::string &annotation_prefix) : - gadget(pb, annotation_prefix) -{ - for (auto &part : parts) - { - bits.insert(bits.end(), part.begin(), part.end()); - } -} - -template -block_variable::block_variable(protoboard &pb, - const digest_variable &left, - const digest_variable &right, - const std::string &annotation_prefix) : - gadget(pb, annotation_prefix) -{ - assert(left.bits.size() == right.bits.size()); - block_size = 2 * left.bits.size(); - bits.insert(bits.end(), left.bits.begin(), left.bits.end()); - bits.insert(bits.end(), right.bits.begin(), right.bits.end()); -} - -template -void block_variable::generate_r1cs_witness(const bit_vector& contents) -{ - bits.fill_with_bits(this->pb, contents); -} - -template -bit_vector block_variable::get_block() const -{ - return bits.get_bits(this->pb); -} - -} // libsnark -#endif // HASH_IO_TCC_ diff --git a/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_aux.hpp b/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_aux.hpp deleted file mode 100644 index e0c7a7e0b57..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_aux.hpp +++ /dev/null @@ -1,160 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for auxiliary gadgets for the SHA256 gadget. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef SHA256_AUX_HPP_ -#define SHA256_AUX_HPP_ - -#include "gadgetlib1/gadgets/basic_gadgets.hpp" - -namespace libsnark { - -template -class lastbits_gadget : public gadget { -public: - pb_variable X; - size_t X_bits; - pb_variable result; - pb_linear_combination_array result_bits; - - pb_linear_combination_array full_bits; - std::shared_ptr > unpack_bits; - std::shared_ptr > pack_result; - - lastbits_gadget(protoboard &pb, - const pb_variable &X, - const size_t X_bits, - const pb_variable &result, - const pb_linear_combination_array &result_bits, - const std::string &annotation_prefix); - - void generate_r1cs_constraints(); - void generate_r1cs_witness(); -}; - -template -class XOR3_gadget : public gadget { -private: - pb_variable tmp; -public: - pb_linear_combination A; - pb_linear_combination B; - pb_linear_combination C; - bool assume_C_is_zero; - pb_linear_combination out; - - XOR3_gadget(protoboard &pb, - const pb_linear_combination &A, - const pb_linear_combination &B, - const pb_linear_combination &C, - const bool assume_C_is_zero, - const pb_linear_combination &out, - const std::string &annotation_prefix); - - void generate_r1cs_constraints(); - void generate_r1cs_witness(); -}; - -/* Page 10 of http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf */ -template -class small_sigma_gadget : public gadget { -private: - pb_variable_array W; - pb_variable result; -public: - pb_variable_array result_bits; - std::vector > > compute_bits; - std::shared_ptr > pack_result; - - small_sigma_gadget(protoboard &pb, - const pb_variable_array &W, - const pb_variable &result, - const size_t rot1, - const size_t rot2, - const size_t shift, - const std::string &annotation_prefix); - - void generate_r1cs_constraints(); - void generate_r1cs_witness(); -}; - -/* Page 10 of http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf */ -template -class big_sigma_gadget : public gadget { -private: - pb_linear_combination_array W; - pb_variable result; -public: - pb_variable_array result_bits; - std::vector > > compute_bits; - std::shared_ptr > pack_result; - - big_sigma_gadget(protoboard &pb, - const pb_linear_combination_array &W, - const pb_variable &result, - const size_t rot1, - const size_t rot2, - const size_t rot3, - const std::string &annotation_prefix); - - void generate_r1cs_constraints(); - void generate_r1cs_witness(); -}; - -/* Page 10 of http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf */ -template -class choice_gadget : public gadget { -private: - pb_variable_array result_bits; -public: - pb_linear_combination_array X; - pb_linear_combination_array Y; - pb_linear_combination_array Z; - pb_variable result; - std::shared_ptr > pack_result; - - choice_gadget(protoboard &pb, - const pb_linear_combination_array &X, - const pb_linear_combination_array &Y, - const pb_linear_combination_array &Z, - const pb_variable &result, const std::string &annotation_prefix); - - void generate_r1cs_constraints(); - void generate_r1cs_witness(); -}; - -/* Page 10 of http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf */ -template -class majority_gadget : public gadget { -private: - pb_variable_array result_bits; - std::shared_ptr > pack_result; -public: - pb_linear_combination_array X; - pb_linear_combination_array Y; - pb_linear_combination_array Z; - pb_variable result; - - majority_gadget(protoboard &pb, - const pb_linear_combination_array &X, - const pb_linear_combination_array &Y, - const pb_linear_combination_array &Z, - const pb_variable &result, - const std::string &annotation_prefix); - - void generate_r1cs_constraints(); - void generate_r1cs_witness(); -}; - -} // libsnark - -#include "gadgetlib1/gadgets/hashes/sha256/sha256_aux.tcc" - -#endif // SHA256_AUX_HPP_ diff --git a/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_aux.tcc b/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_aux.tcc deleted file mode 100644 index 0885f0b6dcf..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_aux.tcc +++ /dev/null @@ -1,297 +0,0 @@ -/** @file - ***************************************************************************** - - Implementation of interfaces for auxiliary gadgets for the SHA256 gadget. - - See sha256_aux.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef SHA256_AUX_TCC_ -#define SHA256_AUX_TCC_ - -namespace libsnark { - -template -lastbits_gadget::lastbits_gadget(protoboard &pb, - const pb_variable &X, - const size_t X_bits, - const pb_variable &result, - const pb_linear_combination_array &result_bits, - const std::string &annotation_prefix) : - gadget(pb, annotation_prefix), - X(X), - X_bits(X_bits), - result(result), - result_bits(result_bits) -{ - full_bits = result_bits; - for (size_t i = result_bits.size(); i < X_bits; ++i) - { - pb_variable full_bits_overflow; - full_bits_overflow.allocate(pb, FMT(this->annotation_prefix, " full_bits_%zu", i)); - full_bits.emplace_back(full_bits_overflow); - } - - unpack_bits.reset(new packing_gadget(pb, full_bits, X, FMT(this->annotation_prefix, " unpack_bits"))); - pack_result.reset(new packing_gadget(pb, result_bits, result, FMT(this->annotation_prefix, " pack_result"))); -} - -template -void lastbits_gadget::generate_r1cs_constraints() -{ - unpack_bits->generate_r1cs_constraints(true); - pack_result->generate_r1cs_constraints(false); -} - -template -void lastbits_gadget::generate_r1cs_witness() -{ - unpack_bits->generate_r1cs_witness_from_packed(); - pack_result->generate_r1cs_witness_from_bits(); -} - -template -XOR3_gadget::XOR3_gadget(protoboard &pb, - const pb_linear_combination &A, - const pb_linear_combination &B, - const pb_linear_combination &C, - const bool assume_C_is_zero, - const pb_linear_combination &out, - const std::string &annotation_prefix) : - gadget(pb, annotation_prefix), - A(A), - B(B), - C(C), - assume_C_is_zero(assume_C_is_zero), - out(out) -{ - if (!assume_C_is_zero) - { - tmp.allocate(pb, FMT(this->annotation_prefix, " tmp")); - } -} - -template -void XOR3_gadget::generate_r1cs_constraints() -{ - /* - tmp = A + B - 2AB i.e. tmp = A xor B - out = tmp + C - 2tmp C i.e. out = tmp xor C - */ - if (assume_C_is_zero) - { - this->pb.add_r1cs_constraint(r1cs_constraint(2*A, B, A + B - out), FMT(this->annotation_prefix, " implicit_tmp_equals_out")); - } - else - { - this->pb.add_r1cs_constraint(r1cs_constraint(2*A, B, A + B - tmp), FMT(this->annotation_prefix, " tmp")); - this->pb.add_r1cs_constraint(r1cs_constraint(2 * tmp, C, tmp + C - out), FMT(this->annotation_prefix, " out")); - } -} - -template -void XOR3_gadget::generate_r1cs_witness() -{ - if (assume_C_is_zero) - { - this->pb.lc_val(out) = this->pb.lc_val(A) + this->pb.lc_val(B) - FieldT(2) * this->pb.lc_val(A) * this->pb.lc_val(B); - } - else - { - this->pb.val(tmp) = this->pb.lc_val(A) + this->pb.lc_val(B) - FieldT(2) * this->pb.lc_val(A) * this->pb.lc_val(B); - this->pb.lc_val(out) = this->pb.val(tmp) + this->pb.lc_val(C) - FieldT(2) * this->pb.val(tmp) * this->pb.lc_val(C); - } -} - -#define SHA256_GADGET_ROTR(A, i, k) A[((i)+(k)) % 32] - -/* Page 10 of http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf */ -template -small_sigma_gadget::small_sigma_gadget(protoboard &pb, - const pb_variable_array &W, - const pb_variable &result, - const size_t rot1, - const size_t rot2, - const size_t shift, - const std::string &annotation_prefix) : - gadget(pb, annotation_prefix), - W(W), - result(result) -{ - result_bits.allocate(pb, 32, FMT(this->annotation_prefix, " result_bits")); - compute_bits.resize(32); - for (size_t i = 0; i < 32; ++i) - { - compute_bits[i].reset(new XOR3_gadget(pb, SHA256_GADGET_ROTR(W, i, rot1), SHA256_GADGET_ROTR(W, i, rot2), - (i + shift < 32 ? W[i+shift] : ONE), - (i + shift >= 32), result_bits[i], - FMT(this->annotation_prefix, " compute_bits_%zu", i))); - } - pack_result.reset(new packing_gadget(pb, result_bits, result, FMT(this->annotation_prefix, " pack_result"))); -} - -template -void small_sigma_gadget::generate_r1cs_constraints() -{ - for (size_t i = 0; i < 32; ++i) - { - compute_bits[i]->generate_r1cs_constraints(); - } - - pack_result->generate_r1cs_constraints(false); -} - -template -void small_sigma_gadget::generate_r1cs_witness() -{ - for (size_t i = 0; i < 32; ++i) - { - compute_bits[i]->generate_r1cs_witness(); - } - - pack_result->generate_r1cs_witness_from_bits(); -} - -template -big_sigma_gadget::big_sigma_gadget(protoboard &pb, - const pb_linear_combination_array &W, - const pb_variable &result, - const size_t rot1, - const size_t rot2, - const size_t rot3, - const std::string &annotation_prefix) : - gadget(pb, annotation_prefix), - W(W), - result(result) -{ - result_bits.allocate(pb, 32, FMT(this->annotation_prefix, " result_bits")); - compute_bits.resize(32); - for (size_t i = 0; i < 32; ++i) - { - compute_bits[i].reset(new XOR3_gadget(pb, SHA256_GADGET_ROTR(W, i, rot1), SHA256_GADGET_ROTR(W, i, rot2), SHA256_GADGET_ROTR(W, i, rot3), false, result_bits[i], - FMT(this->annotation_prefix, " compute_bits_%zu", i))); - } - - pack_result.reset(new packing_gadget(pb, result_bits, result, FMT(this->annotation_prefix, " pack_result"))); -} - -template -void big_sigma_gadget::generate_r1cs_constraints() -{ - for (size_t i = 0; i < 32; ++i) - { - compute_bits[i]->generate_r1cs_constraints(); - } - - pack_result->generate_r1cs_constraints(false); -} - -template -void big_sigma_gadget::generate_r1cs_witness() -{ - for (size_t i = 0; i < 32; ++i) - { - compute_bits[i]->generate_r1cs_witness(); - } - - pack_result->generate_r1cs_witness_from_bits(); -} - -/* Page 10 of http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf */ -template -choice_gadget::choice_gadget(protoboard &pb, - const pb_linear_combination_array &X, - const pb_linear_combination_array &Y, - const pb_linear_combination_array &Z, - const pb_variable &result, const std::string &annotation_prefix) : - gadget(pb, annotation_prefix), - X(X), - Y(Y), - Z(Z), - result(result) -{ - result_bits.allocate(pb, 32, FMT(this->annotation_prefix, " result_bits")); - pack_result.reset(new packing_gadget(pb, result_bits, result, FMT(this->annotation_prefix, " result"))); -} - -template -void choice_gadget::generate_r1cs_constraints() -{ - for (size_t i = 0; i < 32; ++i) - { - /* - result = x * y + (1-x) * z - result - z = x * (y - z) - */ - this->pb.add_r1cs_constraint(r1cs_constraint(X[i], Y[i] - Z[i], result_bits[i] - Z[i]), FMT(this->annotation_prefix, " result_bits_%zu", i)); - } - pack_result->generate_r1cs_constraints(false); -} - -template -void choice_gadget::generate_r1cs_witness() -{ - for (size_t i = 0; i < 32; ++i) - { - this->pb.val(result_bits[i]) = this->pb.lc_val(X[i]) * this->pb.lc_val(Y[i]) + (FieldT::one() - this->pb.lc_val(X[i])) * this->pb.lc_val(Z[i]); - } - pack_result->generate_r1cs_witness_from_bits(); -} - -/* Page 10 of http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf */ -template -majority_gadget::majority_gadget(protoboard &pb, - const pb_linear_combination_array &X, - const pb_linear_combination_array &Y, - const pb_linear_combination_array &Z, - const pb_variable &result, - const std::string &annotation_prefix) : - gadget(pb, annotation_prefix), - X(X), - Y(Y), - Z(Z), - result(result) -{ - result_bits.allocate(pb, 32, FMT(this->annotation_prefix, " result_bits")); - pack_result.reset(new packing_gadget(pb, result_bits, result, FMT(this->annotation_prefix, " result"))); -} - -template -void majority_gadget::generate_r1cs_constraints() -{ - for (size_t i = 0; i < 32; ++i) - { - /* - 2*result + aux = x + y + z - x, y, z, aux -- bits - aux = x + y + z - 2*result - */ - generate_boolean_r1cs_constraint(this->pb, result_bits[i], FMT(this->annotation_prefix, " result_%zu", i)); - this->pb.add_r1cs_constraint(r1cs_constraint(X[i] + Y[i] + Z[i] - 2 * result_bits[i], - 1 - (X[i] + Y[i] + Z[i] - 2 * result_bits[i]), - 0), - FMT(this->annotation_prefix, " result_bits_%zu", i)); - } - pack_result->generate_r1cs_constraints(false); -} - -template -void majority_gadget::generate_r1cs_witness() -{ - for (size_t i = 0; i < 32; ++i) - { - const uint64_t v = (this->pb.lc_val(X[i]) + this->pb.lc_val(Y[i]) + this->pb.lc_val(Z[i])).as_uint64(); - this->pb.val(result_bits[i]) = FieldT(v / 2); - } - - pack_result->generate_r1cs_witness_from_bits(); -} - -} // libsnark - -#endif // SHA256_AUX_TCC_ diff --git a/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_components.hpp b/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_components.hpp deleted file mode 100644 index 2f7e71e357a..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_components.hpp +++ /dev/null @@ -1,108 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for gadgets for the SHA256 message schedule and round function. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef SHA256_COMPONENTS_HPP_ -#define SHA256_COMPONENTS_HPP_ - -#include "gadgetlib1/gadgets/basic_gadgets.hpp" -#include "gadgetlib1/gadgets/hashes/hash_io.hpp" -#include "gadgetlib1/gadgets/hashes/sha256/sha256_aux.hpp" - -namespace libsnark { - -const size_t SHA256_digest_size = 256; -const size_t SHA256_block_size = 512; - -template -pb_linear_combination_array SHA256_default_IV(protoboard &pb); - -template -class sha256_message_schedule_gadget : public gadget { -public: - std::vector > W_bits; - std::vector > > pack_W; - - std::vector > sigma0; - std::vector > sigma1; - std::vector > > compute_sigma0; - std::vector > > compute_sigma1; - std::vector > unreduced_W; - std::vector > > mod_reduce_W; -public: - pb_variable_array M; - pb_variable_array packed_W; - sha256_message_schedule_gadget(protoboard &pb, - const pb_variable_array &M, - const pb_variable_array &packed_W, - const std::string &annotation_prefix); - void generate_r1cs_constraints(); - void generate_r1cs_witness(); -}; - -template -class sha256_round_function_gadget : public gadget { -public: - pb_variable sigma0; - pb_variable sigma1; - std::shared_ptr > compute_sigma0; - std::shared_ptr > compute_sigma1; - pb_variable choice; - pb_variable majority; - std::shared_ptr > compute_choice; - std::shared_ptr > compute_majority; - pb_variable packed_d; - std::shared_ptr > pack_d; - pb_variable packed_h; - std::shared_ptr > pack_h; - pb_variable unreduced_new_a; - pb_variable unreduced_new_e; - std::shared_ptr > mod_reduce_new_a; - std::shared_ptr > mod_reduce_new_e; - pb_variable packed_new_a; - pb_variable packed_new_e; -public: - pb_linear_combination_array a; - pb_linear_combination_array b; - pb_linear_combination_array c; - pb_linear_combination_array d; - pb_linear_combination_array e; - pb_linear_combination_array f; - pb_linear_combination_array g; - pb_linear_combination_array h; - pb_variable W; - uint32_t K; - pb_linear_combination_array new_a; - pb_linear_combination_array new_e; - - sha256_round_function_gadget(protoboard &pb, - const pb_linear_combination_array &a, - const pb_linear_combination_array &b, - const pb_linear_combination_array &c, - const pb_linear_combination_array &d, - const pb_linear_combination_array &e, - const pb_linear_combination_array &f, - const pb_linear_combination_array &g, - const pb_linear_combination_array &h, - const pb_variable &W, - const uint32_t &K, - const pb_linear_combination_array &new_a, - const pb_linear_combination_array &new_e, - const std::string &annotation_prefix); - - void generate_r1cs_constraints(); - void generate_r1cs_witness(); -}; - -} // libsnark - -#include "gadgetlib1/gadgets/hashes/sha256/sha256_components.tcc" - -#endif // SHA256_COMPONENTS_HPP_ diff --git a/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_components.tcc b/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_components.tcc deleted file mode 100644 index 41ad20883cf..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_components.tcc +++ /dev/null @@ -1,250 +0,0 @@ -/** @file - ***************************************************************************** - - Implementation of interfaces for gadgets for the SHA256 message schedule and round function. - - See sha256_components.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef SHA256_COMPONENTS_TCC_ -#define SHA256_COMPONENTS_TCC_ - -namespace libsnark { - -const uint32_t SHA256_K[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -const uint32_t SHA256_H[8] = { - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 -}; - -template -pb_linear_combination_array SHA256_default_IV(protoboard &pb) -{ - pb_linear_combination_array result; - result.reserve(SHA256_digest_size); - - for (size_t i = 0; i < SHA256_digest_size; ++i) - { - int iv_val = (SHA256_H[i / 32] >> (31-(i % 32))) & 1; - - pb_linear_combination iv_element; - iv_element.assign(pb, iv_val * ONE); - iv_element.evaluate(pb); - - result.emplace_back(iv_element); - } - - return result; -} - -template -sha256_message_schedule_gadget::sha256_message_schedule_gadget(protoboard &pb, - const pb_variable_array &M, - const pb_variable_array &packed_W, - const std::string &annotation_prefix) : - gadget(pb, annotation_prefix), - M(M), - packed_W(packed_W) -{ - W_bits.resize(64); - - pack_W.resize(16); - for (size_t i = 0; i < 16; ++i) - { - W_bits[i] = pb_variable_array(M.rbegin() + (15-i) * 32, M.rbegin() + (16-i) * 32); - pack_W[i].reset(new packing_gadget(pb, W_bits[i], packed_W[i], FMT(this->annotation_prefix, " pack_W_%zu", i))); - } - - /* NB: some of those will be un-allocated */ - sigma0.resize(64); - sigma1.resize(64); - compute_sigma0.resize(64); - compute_sigma1.resize(64); - unreduced_W.resize(64); - mod_reduce_W.resize(64); - - for (size_t i = 16; i < 64; ++i) - { - /* allocate result variables for sigma0/sigma1 invocations */ - sigma0[i].allocate(pb, FMT(this->annotation_prefix, " sigma0_%zu", i)); - sigma1[i].allocate(pb, FMT(this->annotation_prefix, " sigma1_%zu", i)); - - /* compute sigma0/sigma1 */ - compute_sigma0[i].reset(new small_sigma_gadget(pb, W_bits[i-15], sigma0[i], 7, 18, 3, FMT(this->annotation_prefix, " compute_sigma0_%zu", i))); - compute_sigma1[i].reset(new small_sigma_gadget(pb, W_bits[i-2], sigma1[i], 17, 19, 10, FMT(this->annotation_prefix, " compute_sigma1_%zu", i))); - - /* unreduced_W = sigma0(W_{i-15}) + sigma1(W_{i-2}) + W_{i-7} + W_{i-16} before modulo 2^32 */ - unreduced_W[i].allocate(pb, FMT(this->annotation_prefix, "unreduced_W_%zu", i)); - - /* allocate the bit representation of packed_W[i] */ - W_bits[i].allocate(pb, 32, FMT(this->annotation_prefix, " W_bits_%zu", i)); - - /* and finally reduce this into packed and bit representations */ - mod_reduce_W[i].reset(new lastbits_gadget(pb, unreduced_W[i], 32+2, packed_W[i], W_bits[i], FMT(this->annotation_prefix, " mod_reduce_W_%zu", i))); - } -} - -template -void sha256_message_schedule_gadget::generate_r1cs_constraints() -{ - for (size_t i = 0; i < 16; ++i) - { - pack_W[i]->generate_r1cs_constraints(false); // do not enforce bitness here; caller be aware. - } - - for (size_t i = 16; i < 64; ++i) - { - compute_sigma0[i]->generate_r1cs_constraints(); - compute_sigma1[i]->generate_r1cs_constraints(); - - this->pb.add_r1cs_constraint(r1cs_constraint(1, - sigma0[i] + sigma1[i] + packed_W[i-16] + packed_W[i-7], - unreduced_W[i]), - FMT(this->annotation_prefix, " unreduced_W_%zu", i)); - - mod_reduce_W[i]->generate_r1cs_constraints(); - } -} - -template -void sha256_message_schedule_gadget::generate_r1cs_witness() -{ - for (size_t i = 0; i < 16; ++i) - { - pack_W[i]->generate_r1cs_witness_from_bits(); - } - - for (size_t i = 16; i < 64; ++i) - { - compute_sigma0[i]->generate_r1cs_witness(); - compute_sigma1[i]->generate_r1cs_witness(); - - this->pb.val(unreduced_W[i]) = this->pb.val(sigma0[i]) + this->pb.val(sigma1[i]) + this->pb.val(packed_W[i-16]) + this->pb.val(packed_W[i-7]); - mod_reduce_W[i]->generate_r1cs_witness(); - } -} - -template -sha256_round_function_gadget::sha256_round_function_gadget(protoboard &pb, - const pb_linear_combination_array &a, - const pb_linear_combination_array &b, - const pb_linear_combination_array &c, - const pb_linear_combination_array &d, - const pb_linear_combination_array &e, - const pb_linear_combination_array &f, - const pb_linear_combination_array &g, - const pb_linear_combination_array &h, - const pb_variable &W, - const uint32_t &K, - const pb_linear_combination_array &new_a, - const pb_linear_combination_array &new_e, - const std::string &annotation_prefix) : - gadget(pb, annotation_prefix), - a(a), - b(b), - c(c), - d(d), - e(e), - f(f), - g(g), - h(h), - W(W), - K(K), - new_a(new_a), - new_e(new_e) -{ - /* compute sigma0 and sigma1 */ - sigma0.allocate(pb, FMT(this->annotation_prefix, " sigma0")); - sigma1.allocate(pb, FMT(this->annotation_prefix, " sigma1")); - compute_sigma0.reset(new big_sigma_gadget(pb, a, sigma0, 2, 13, 22, FMT(this->annotation_prefix, " compute_sigma0"))); - compute_sigma1.reset(new big_sigma_gadget(pb, e, sigma1, 6, 11, 25, FMT(this->annotation_prefix, " compute_sigma1"))); - - /* compute choice */ - choice.allocate(pb, FMT(this->annotation_prefix, " choice")); - compute_choice.reset(new choice_gadget(pb, e, f, g, choice, FMT(this->annotation_prefix, " compute_choice"))); - - /* compute majority */ - majority.allocate(pb, FMT(this->annotation_prefix, " majority")); - compute_majority.reset(new majority_gadget(pb, a, b, c, majority, FMT(this->annotation_prefix, " compute_majority"))); - - /* pack d */ - packed_d.allocate(pb, FMT(this->annotation_prefix, " packed_d")); - pack_d.reset(new packing_gadget(pb, d, packed_d, FMT(this->annotation_prefix, " pack_d"))); - - /* pack h */ - packed_h.allocate(pb, FMT(this->annotation_prefix, " packed_h")); - pack_h.reset(new packing_gadget(pb, h, packed_h, FMT(this->annotation_prefix, " pack_h"))); - - /* compute the actual results for the round */ - unreduced_new_a.allocate(pb, FMT(this->annotation_prefix, " unreduced_new_a")); - unreduced_new_e.allocate(pb, FMT(this->annotation_prefix, " unreduced_new_e")); - - packed_new_a.allocate(pb, FMT(this->annotation_prefix, " packed_new_a")); - packed_new_e.allocate(pb, FMT(this->annotation_prefix, " packed_new_e")); - - mod_reduce_new_a.reset(new lastbits_gadget(pb, unreduced_new_a, 32+3, packed_new_a, new_a, FMT(this->annotation_prefix, " mod_reduce_new_a"))); - mod_reduce_new_e.reset(new lastbits_gadget(pb, unreduced_new_e, 32+3, packed_new_e, new_e, FMT(this->annotation_prefix, " mod_reduce_new_e"))); -} - -template -void sha256_round_function_gadget::generate_r1cs_constraints() -{ - compute_sigma0->generate_r1cs_constraints(); - compute_sigma1->generate_r1cs_constraints(); - - compute_choice->generate_r1cs_constraints(); - compute_majority->generate_r1cs_constraints(); - - pack_d->generate_r1cs_constraints(false); - pack_h->generate_r1cs_constraints(false); - - this->pb.add_r1cs_constraint(r1cs_constraint(1, - packed_h + sigma1 + choice + K + W + sigma0 + majority, - unreduced_new_a), - FMT(this->annotation_prefix, " unreduced_new_a")); - - this->pb.add_r1cs_constraint(r1cs_constraint(1, - packed_d + packed_h + sigma1 + choice + K + W, - unreduced_new_e), - FMT(this->annotation_prefix, " unreduced_new_e")); - - mod_reduce_new_a->generate_r1cs_constraints(); - mod_reduce_new_e->generate_r1cs_constraints(); -} - -template -void sha256_round_function_gadget::generate_r1cs_witness() -{ - compute_sigma0->generate_r1cs_witness(); - compute_sigma1->generate_r1cs_witness(); - - compute_choice->generate_r1cs_witness(); - compute_majority->generate_r1cs_witness(); - - pack_d->generate_r1cs_witness_from_bits(); - pack_h->generate_r1cs_witness_from_bits(); - - this->pb.val(unreduced_new_a) = this->pb.val(packed_h) + this->pb.val(sigma1) + this->pb.val(choice) + FieldT(K) + this->pb.val(W) + this->pb.val(sigma0) + this->pb.val(majority); - this->pb.val(unreduced_new_e) = this->pb.val(packed_d) + this->pb.val(packed_h) + this->pb.val(sigma1) + this->pb.val(choice) + FieldT(K) + this->pb.val(W); - - mod_reduce_new_a->generate_r1cs_witness(); - mod_reduce_new_e->generate_r1cs_witness(); -} - -} // libsnark - -#endif // SHA256_COMPONENTS_TCC_ diff --git a/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp b/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp deleted file mode 100644 index 8cb6365c8a0..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp +++ /dev/null @@ -1,98 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for top-level SHA256 gadgets. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef SHA256_GADGET_HPP_ -#define SHA256_GADGET_HPP_ - -#include "common/data_structures/merkle_tree.hpp" -#include "gadgetlib1/gadgets/basic_gadgets.hpp" -#include "gadgetlib1/gadgets/hashes/hash_io.hpp" -#include "gadgetlib1/gadgets/hashes/sha256/sha256_components.hpp" - -namespace libsnark { - -/** - * Gadget for the SHA256 compression function. - */ -template -class sha256_compression_function_gadget : public gadget { -public: - std::vector > round_a; - std::vector > round_b; - std::vector > round_c; - std::vector > round_d; - std::vector > round_e; - std::vector > round_f; - std::vector > round_g; - std::vector > round_h; - - pb_variable_array packed_W; - std::shared_ptr > message_schedule; - std::vector > round_functions; - - pb_variable_array unreduced_output; - pb_variable_array reduced_output; - std::vector > reduce_output; -public: - pb_linear_combination_array prev_output; - pb_variable_array new_block; - digest_variable output; - - sha256_compression_function_gadget(protoboard &pb, - const pb_linear_combination_array &prev_output, - const pb_variable_array &new_block, - const digest_variable &output, - const std::string &annotation_prefix); - void generate_r1cs_constraints(); - void generate_r1cs_witness(); -}; - -/** - * Gadget for the SHA256 compression function, viewed as a 2-to-1 hash - * function, and using the same initialization vector as in SHA256 - * specification. Thus, any collision for - * sha256_two_to_one_hash_gadget trivially extends to a collision for - * full SHA256 (by appending the same padding). - */ -template -class sha256_two_to_one_hash_gadget : public gadget { -public: - typedef bit_vector hash_value_type; - typedef merkle_authentication_path merkle_authentication_path_type; - - std::shared_ptr > f; - - sha256_two_to_one_hash_gadget(protoboard &pb, - const digest_variable &left, - const digest_variable &right, - const digest_variable &output, - const std::string &annotation_prefix); - sha256_two_to_one_hash_gadget(protoboard &pb, - const size_t block_length, - const block_variable &input_block, - const digest_variable &output, - const std::string &annotation_prefix); - - void generate_r1cs_constraints(const bool ensure_output_bitness=true); // TODO: ignored for now - void generate_r1cs_witness(); - - static size_t get_block_len(); - static size_t get_digest_len(); - static bit_vector get_hash(const bit_vector &input); - - static size_t expected_constraints(const bool ensure_output_bitness=true); // TODO: ignored for now -}; - -} // libsnark - -#include "gadgetlib1/gadgets/hashes/sha256/sha256_gadget.tcc" - -#endif // SHA256_GADGET_HPP_ diff --git a/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.tcc b/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.tcc deleted file mode 100644 index 3004f9e83b0..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.tcc +++ /dev/null @@ -1,230 +0,0 @@ -/** @file - ***************************************************************************** - - Implementation of interfaces for top-level SHA256 gadgets. - - See sha256_gadget.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef SHA256_GADGET_TCC_ -#define SHA256_GADGET_TCC_ - -namespace libsnark { - -template -sha256_compression_function_gadget::sha256_compression_function_gadget(protoboard &pb, - const pb_linear_combination_array &prev_output, - const pb_variable_array &new_block, - const digest_variable &output, - const std::string &annotation_prefix) : - gadget(pb, annotation_prefix), - prev_output(prev_output), - new_block(new_block), - output(output) -{ - /* message schedule and inputs for it */ - packed_W.allocate(pb, 64, FMT(this->annotation_prefix, " packed_W")); - message_schedule.reset(new sha256_message_schedule_gadget(pb, new_block, packed_W, FMT(this->annotation_prefix, " message_schedule"))); - - /* initalize */ - round_a.push_back(pb_linear_combination_array(prev_output.rbegin() + 7*32, prev_output.rbegin() + 8*32)); - round_b.push_back(pb_linear_combination_array(prev_output.rbegin() + 6*32, prev_output.rbegin() + 7*32)); - round_c.push_back(pb_linear_combination_array(prev_output.rbegin() + 5*32, prev_output.rbegin() + 6*32)); - round_d.push_back(pb_linear_combination_array(prev_output.rbegin() + 4*32, prev_output.rbegin() + 5*32)); - round_e.push_back(pb_linear_combination_array(prev_output.rbegin() + 3*32, prev_output.rbegin() + 4*32)); - round_f.push_back(pb_linear_combination_array(prev_output.rbegin() + 2*32, prev_output.rbegin() + 3*32)); - round_g.push_back(pb_linear_combination_array(prev_output.rbegin() + 1*32, prev_output.rbegin() + 2*32)); - round_h.push_back(pb_linear_combination_array(prev_output.rbegin() + 0*32, prev_output.rbegin() + 1*32)); - - /* do the rounds */ - for (size_t i = 0; i < 64; ++i) - { - round_h.push_back(round_g[i]); - round_g.push_back(round_f[i]); - round_f.push_back(round_e[i]); - round_d.push_back(round_c[i]); - round_c.push_back(round_b[i]); - round_b.push_back(round_a[i]); - - pb_variable_array new_round_a_variables; - new_round_a_variables.allocate(pb, 32, FMT(this->annotation_prefix, " new_round_a_variables_%zu", i+1)); - round_a.emplace_back(new_round_a_variables); - - pb_variable_array new_round_e_variables; - new_round_e_variables.allocate(pb, 32, FMT(this->annotation_prefix, " new_round_e_variables_%zu", i+1)); - round_e.emplace_back(new_round_e_variables); - - round_functions.push_back(sha256_round_function_gadget(pb, - round_a[i], round_b[i], round_c[i], round_d[i], - round_e[i], round_f[i], round_g[i], round_h[i], - packed_W[i], SHA256_K[i], round_a[i+1], round_e[i+1], - FMT(this->annotation_prefix, " round_functions_%zu", i))); - } - - /* finalize */ - unreduced_output.allocate(pb, 8, FMT(this->annotation_prefix, " unreduced_output")); - reduced_output.allocate(pb, 8, FMT(this->annotation_prefix, " reduced_output")); - for (size_t i = 0; i < 8; ++i) - { - reduce_output.push_back(lastbits_gadget(pb, - unreduced_output[i], - 32+1, - reduced_output[i], - pb_variable_array(output.bits.rbegin() + (7-i) * 32, output.bits.rbegin() + (8-i) * 32), - FMT(this->annotation_prefix, " reduce_output_%zu", i))); - } -} - -template -void sha256_compression_function_gadget::generate_r1cs_constraints() -{ - message_schedule->generate_r1cs_constraints(); - for (size_t i = 0; i < 64; ++i) - { - round_functions[i].generate_r1cs_constraints(); - } - - for (size_t i = 0; i < 4; ++i) - { - this->pb.add_r1cs_constraint(r1cs_constraint(1, - round_functions[3-i].packed_d + round_functions[63-i].packed_new_a, - unreduced_output[i]), - FMT(this->annotation_prefix, " unreduced_output_%zu", i)); - - this->pb.add_r1cs_constraint(r1cs_constraint(1, - round_functions[3-i].packed_h + round_functions[63-i].packed_new_e, - unreduced_output[4+i]), - FMT(this->annotation_prefix, " unreduced_output_%zu", 4+i)); - } - - for (size_t i = 0; i < 8; ++i) - { - reduce_output[i].generate_r1cs_constraints(); - } -} - -template -void sha256_compression_function_gadget::generate_r1cs_witness() -{ - message_schedule->generate_r1cs_witness(); - -#ifdef DEBUG - printf("Input:\n"); - for (size_t j = 0; j < 16; ++j) - { - printf("%lx ", this->pb.val(packed_W[j]).as_uint64()); - } - printf("\n"); -#endif - - for (size_t i = 0; i < 64; ++i) - { - round_functions[i].generate_r1cs_witness(); - } - - for (size_t i = 0; i < 4; ++i) - { - this->pb.val(unreduced_output[i]) = this->pb.val(round_functions[3-i].packed_d) + this->pb.val(round_functions[63-i].packed_new_a); - this->pb.val(unreduced_output[4+i]) = this->pb.val(round_functions[3-i].packed_h) + this->pb.val(round_functions[63-i].packed_new_e); - } - - for (size_t i = 0; i < 8; ++i) - { - reduce_output[i].generate_r1cs_witness(); - } - -#ifdef DEBUG - printf("Output:\n"); - for (size_t j = 0; j < 8; ++j) - { - printf("%lx ", this->pb.val(reduced_output[j]).as_uint64()); - } - printf("\n"); -#endif -} - -template -sha256_two_to_one_hash_gadget::sha256_two_to_one_hash_gadget(protoboard &pb, - const digest_variable &left, - const digest_variable &right, - const digest_variable &output, - const std::string &annotation_prefix) : - gadget(pb, annotation_prefix) -{ - /* concatenate block = left || right */ - pb_variable_array block; - block.insert(block.end(), left.bits.begin(), left.bits.end()); - block.insert(block.end(), right.bits.begin(), right.bits.end()); - - /* compute the hash itself */ - f.reset(new sha256_compression_function_gadget(pb, SHA256_default_IV(pb), block, output, FMT(this->annotation_prefix, " f"))); -} - -template -sha256_two_to_one_hash_gadget::sha256_two_to_one_hash_gadget(protoboard &pb, - const size_t block_length, - const block_variable &input_block, - const digest_variable &output, - const std::string &annotation_prefix) : - gadget(pb, annotation_prefix) -{ - assert(block_length == SHA256_block_size); - assert(input_block.bits.size() == block_length); - f.reset(new sha256_compression_function_gadget(pb, SHA256_default_IV(pb), input_block.bits, output, FMT(this->annotation_prefix, " f"))); -} - -template -void sha256_two_to_one_hash_gadget::generate_r1cs_constraints(const bool ensure_output_bitness) -{ - UNUSED(ensure_output_bitness); - f->generate_r1cs_constraints(); -} - -template -void sha256_two_to_one_hash_gadget::generate_r1cs_witness() -{ - f->generate_r1cs_witness(); -} - -template -size_t sha256_two_to_one_hash_gadget::get_block_len() -{ - return SHA256_block_size; -} - -template -size_t sha256_two_to_one_hash_gadget::get_digest_len() -{ - return SHA256_digest_size; -} - -template -bit_vector sha256_two_to_one_hash_gadget::get_hash(const bit_vector &input) -{ - protoboard pb; - - block_variable input_variable(pb, SHA256_block_size, "input"); - digest_variable output_variable(pb, SHA256_digest_size, "output"); - sha256_two_to_one_hash_gadget f(pb, SHA256_block_size, input_variable, output_variable, "f"); - - input_variable.generate_r1cs_witness(input); - f.generate_r1cs_witness(); - - return output_variable.get_digest(); -} - -template -size_t sha256_two_to_one_hash_gadget::expected_constraints(const bool ensure_output_bitness) -{ - UNUSED(ensure_output_bitness); - return 27280; /* hardcoded for now */ -} - -} // libsnark - -#endif // SHA256_GADGET_TCC_ diff --git a/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/tests/generate_sha256_gadget_tests.py b/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/tests/generate_sha256_gadget_tests.py deleted file mode 100644 index 452317ffb40..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/tests/generate_sha256_gadget_tests.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python -## -# @author This file is part of libsnark, developed by SCIPR Lab -# and contributors (see AUTHORS). -# @copyright MIT license (see LICENSE file) - -import random -import pypy_sha256 # PyPy's implementation of SHA256 compression function; see copyright and authorship notice within. - -BLOCK_LEN = 512 -BLOCK_BYTES = BLOCK_LEN // 8 -HASH_LEN = 256 -HASH_BYTES = HASH_LEN // 8 - -def gen_random_bytes(n): - return [random.randint(0, 255) for i in xrange(n)] - -def words_to_bytes(arr): - return sum(([x >> 24, (x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff] for x in arr), []) - -def bytes_to_words(arr): - l = len(arr) - assert l % 4 == 0 - return [(arr[i*4 + 3] << 24) + (arr[i*4+2] << 16) + (arr[i*4+1] << 8) + arr[i*4] for i in xrange(l//4)] - -def cpp_val(s, log_radix=32): - if log_radix == 8: - hexfmt = '0x%02x' - elif log_radix == 32: - hexfmt = '0x%08x' - s = bytes_to_words(s) - else: - raise - return 'int_list_to_bits({%s}, %d)' % (', '.join(hexfmt % x for x in s), log_radix) - -def H_bytes(x): - assert len(x) == BLOCK_BYTES - state = pypy_sha256.sha_init() - state['data'] = words_to_bytes(bytes_to_words(x)) - pypy_sha256.sha_transform(state) - return words_to_bytes(bytes_to_words(words_to_bytes(state['digest']))) - -def generate_sha256_gadget_tests(): - left = gen_random_bytes(HASH_BYTES) - right = gen_random_bytes(HASH_BYTES) - hash = H_bytes(left + right) - - print "const bit_vector left_bv = %s;" % cpp_val(left) - print "const bit_vector right_bv = %s;" % cpp_val(right) - print "const bit_vector hash_bv = %s;" % cpp_val(hash) - -if __name__ == '__main__': - random.seed(0) # for reproducibility - generate_sha256_gadget_tests() - diff --git a/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/tests/pypy_sha256.py b/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/tests/pypy_sha256.py deleted file mode 100644 index 496989c117c..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/tests/pypy_sha256.py +++ /dev/null @@ -1,263 +0,0 @@ -#!/usr/bin/env python -# -# SHA256 compression function implementation below is a verbatim copy of PyPy's implementation from -# https://bitbucket.org/pypy/pypy/raw/f1f064b3faf1e012f7a9a9ab08f18074637ebe8a/lib_pypy/_sha256.py . -# -# It is licensed under the MIT license and copyright PyPy Copyright holders 2003-2015 -# See https://bitbucket.org/pypy/pypy/src/tip/LICENSE for the full copyright notice. -# - -SHA_BLOCKSIZE = 64 -SHA_DIGESTSIZE = 32 - - -def new_shaobject(): - return { - 'digest': [0]*8, - 'count_lo': 0, - 'count_hi': 0, - 'data': [0]* SHA_BLOCKSIZE, - 'local': 0, - 'digestsize': 0 - } - -ROR = lambda x, y: (((x & 0xffffffff) >> (y & 31)) | (x << (32 - (y & 31)))) & 0xffffffff -Ch = lambda x, y, z: (z ^ (x & (y ^ z))) -Maj = lambda x, y, z: (((x | y) & z) | (x & y)) -S = lambda x, n: ROR(x, n) -R = lambda x, n: (x & 0xffffffff) >> n -Sigma0 = lambda x: (S(x, 2) ^ S(x, 13) ^ S(x, 22)) -Sigma1 = lambda x: (S(x, 6) ^ S(x, 11) ^ S(x, 25)) -Gamma0 = lambda x: (S(x, 7) ^ S(x, 18) ^ R(x, 3)) -Gamma1 = lambda x: (S(x, 17) ^ S(x, 19) ^ R(x, 10)) - -def sha_transform(sha_info): - W = [] - - d = sha_info['data'] - for i in range(0,16): - W.append( (d[4*i]<<24) + (d[4*i+1]<<16) + (d[4*i+2]<<8) + d[4*i+3]) - - for i in range(16,64): - W.append( (Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]) & 0xffffffff ) - - ss = sha_info['digest'][:] - - def RND(a,b,c,d,e,f,g,h,i,ki): - t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; - t1 = Sigma0(a) + Maj(a, b, c); - d += t0; - h = t0 + t1; - return d & 0xffffffff, h & 0xffffffff - - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],0,0x428a2f98); - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],1,0x71374491); - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],2,0xb5c0fbcf); - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],3,0xe9b5dba5); - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],4,0x3956c25b); - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],5,0x59f111f1); - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],6,0x923f82a4); - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],7,0xab1c5ed5); - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],8,0xd807aa98); - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],9,0x12835b01); - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],10,0x243185be); - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],11,0x550c7dc3); - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],12,0x72be5d74); - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],13,0x80deb1fe); - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],14,0x9bdc06a7); - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],15,0xc19bf174); - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],16,0xe49b69c1); - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],17,0xefbe4786); - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],18,0x0fc19dc6); - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],19,0x240ca1cc); - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],20,0x2de92c6f); - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],21,0x4a7484aa); - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],22,0x5cb0a9dc); - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],23,0x76f988da); - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],24,0x983e5152); - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],25,0xa831c66d); - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],26,0xb00327c8); - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],27,0xbf597fc7); - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],28,0xc6e00bf3); - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],29,0xd5a79147); - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],30,0x06ca6351); - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],31,0x14292967); - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],32,0x27b70a85); - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],33,0x2e1b2138); - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],34,0x4d2c6dfc); - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],35,0x53380d13); - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],36,0x650a7354); - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],37,0x766a0abb); - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],38,0x81c2c92e); - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],39,0x92722c85); - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],40,0xa2bfe8a1); - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],41,0xa81a664b); - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],42,0xc24b8b70); - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],43,0xc76c51a3); - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],44,0xd192e819); - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],45,0xd6990624); - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],46,0xf40e3585); - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],47,0x106aa070); - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],48,0x19a4c116); - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],49,0x1e376c08); - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],50,0x2748774c); - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],51,0x34b0bcb5); - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],52,0x391c0cb3); - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],53,0x4ed8aa4a); - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],54,0x5b9cca4f); - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],55,0x682e6ff3); - ss[3], ss[7] = RND(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],56,0x748f82ee); - ss[2], ss[6] = RND(ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],57,0x78a5636f); - ss[1], ss[5] = RND(ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],58,0x84c87814); - ss[0], ss[4] = RND(ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],ss[4],59,0x8cc70208); - ss[7], ss[3] = RND(ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],ss[3],60,0x90befffa); - ss[6], ss[2] = RND(ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],ss[2],61,0xa4506ceb); - ss[5], ss[1] = RND(ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],ss[1],62,0xbef9a3f7); - ss[4], ss[0] = RND(ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[0],63,0xc67178f2); - - dig = [] - for i, x in enumerate(sha_info['digest']): - dig.append( (x + ss[i]) & 0xffffffff ) - sha_info['digest'] = dig - -def sha_init(): - sha_info = new_shaobject() - sha_info['digest'] = [0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19] - sha_info['count_lo'] = 0 - sha_info['count_hi'] = 0 - sha_info['local'] = 0 - sha_info['digestsize'] = 32 - return sha_info - -def sha224_init(): - sha_info = new_shaobject() - sha_info['digest'] = [0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4] - sha_info['count_lo'] = 0 - sha_info['count_hi'] = 0 - sha_info['local'] = 0 - sha_info['digestsize'] = 28 - return sha_info - -def sha_update(sha_info, buffer): - if isinstance(buffer, str): - raise TypeError("Unicode strings must be encoded before hashing") - count = len(buffer) - buffer_idx = 0 - clo = (sha_info['count_lo'] + (count << 3)) & 0xffffffff - if clo < sha_info['count_lo']: - sha_info['count_hi'] += 1 - sha_info['count_lo'] = clo - - sha_info['count_hi'] += (count >> 29) - - if sha_info['local']: - i = SHA_BLOCKSIZE - sha_info['local'] - if i > count: - i = count - - # copy buffer - sha_info['data'][sha_info['local']:sha_info['local']+i] = buffer[buffer_idx:buffer_idx+i] - - count -= i - buffer_idx += i - - sha_info['local'] += i - if sha_info['local'] == SHA_BLOCKSIZE: - sha_transform(sha_info) - sha_info['local'] = 0 - else: - return - - while count >= SHA_BLOCKSIZE: - # copy buffer - sha_info['data'] = list(buffer[buffer_idx:buffer_idx + SHA_BLOCKSIZE]) - count -= SHA_BLOCKSIZE - buffer_idx += SHA_BLOCKSIZE - sha_transform(sha_info) - - - # copy buffer - pos = sha_info['local'] - sha_info['data'][pos:pos+count] = buffer[buffer_idx:buffer_idx + count] - sha_info['local'] = count - -def sha_final(sha_info): - lo_bit_count = sha_info['count_lo'] - hi_bit_count = sha_info['count_hi'] - count = (lo_bit_count >> 3) & 0x3f - sha_info['data'][count] = 0x80; - count += 1 - if count > SHA_BLOCKSIZE - 8: - # zero the bytes in data after the count - sha_info['data'] = sha_info['data'][:count] + ([0] * (SHA_BLOCKSIZE - count)) - sha_transform(sha_info) - # zero bytes in data - sha_info['data'] = [0] * SHA_BLOCKSIZE - else: - sha_info['data'] = sha_info['data'][:count] + ([0] * (SHA_BLOCKSIZE - count)) - - sha_info['data'][56] = (hi_bit_count >> 24) & 0xff - sha_info['data'][57] = (hi_bit_count >> 16) & 0xff - sha_info['data'][58] = (hi_bit_count >> 8) & 0xff - sha_info['data'][59] = (hi_bit_count >> 0) & 0xff - sha_info['data'][60] = (lo_bit_count >> 24) & 0xff - sha_info['data'][61] = (lo_bit_count >> 16) & 0xff - sha_info['data'][62] = (lo_bit_count >> 8) & 0xff - sha_info['data'][63] = (lo_bit_count >> 0) & 0xff - - sha_transform(sha_info) - - dig = [] - for i in sha_info['digest']: - dig.extend([ ((i>>24) & 0xff), ((i>>16) & 0xff), ((i>>8) & 0xff), (i & 0xff) ]) - return ''.join([chr(i) for i in dig]) - -class sha256(object): - digest_size = digestsize = SHA_DIGESTSIZE - block_size = SHA_BLOCKSIZE - - def __init__(self, s=None): - self._sha = sha_init() - if s: - sha_update(self._sha, s) - - def update(self, s): - sha_update(self._sha, s) - - def digest(self): - return sha_final(self._sha.copy())[:self._sha['digestsize']] - - def hexdigest(self): - return ''.join(['%.2x' % ord(i) for i in self.digest()]) - - def copy(self): - new = sha256.__new__(sha256) - new._sha = self._sha.copy() - return new - -class sha224(sha256): - digest_size = digestsize = 28 - - def __init__(self, s=None): - self._sha = sha224_init() - if s: - sha_update(self._sha, s) - - def copy(self): - new = sha224.__new__(sha224) - new._sha = self._sha.copy() - return new - -def test(): - a_str = "just a test string" - - assert 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' == sha256().hexdigest() - assert 'd7b553c6f09ac85d142415f857c5310f3bbbe7cdd787cce4b985acedd585266f' == sha256(a_str).hexdigest() - assert '8113ebf33c97daa9998762aacafe750c7cefc2b2f173c90c59663a57fe626f21' == sha256(a_str*7).hexdigest() - - s = sha256(a_str) - s.update(a_str) - assert '03d9963e05a094593190b6fc794cb1a3e1ac7d7883f0b5855268afeccc70d461' == s.hexdigest() - -if __name__ == "__main__": - test() diff --git a/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/tests/test_sha256_gadget.cpp b/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/tests/test_sha256_gadget.cpp deleted file mode 100644 index 0bfaf3a125f..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/hashes/sha256/tests/test_sha256_gadget.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#include "common/default_types/ec_pp.hpp" -#include "common/utils.hpp" -#include "common/profiling.hpp" -#include "gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp" - -#include - -using namespace libsnark; - -template -void test_two_to_one() -{ - protoboard pb; - - digest_variable left(pb, SHA256_digest_size, "left"); - digest_variable right(pb, SHA256_digest_size, "right"); - digest_variable output(pb, SHA256_digest_size, "output"); - - sha256_two_to_one_hash_gadget f(pb, left, right, output, "f"); - f.generate_r1cs_constraints(); - printf("Number of constraints for sha256_two_to_one_hash_gadget: %zu\n", pb.num_constraints()); - - const bit_vector left_bv = int_list_to_bits({0x426bc2d8, 0x4dc86782, 0x81e8957a, 0x409ec148, 0xe6cffbe8, 0xafe6ba4f, 0x9c6f1978, 0xdd7af7e9}, 32); - const bit_vector right_bv = int_list_to_bits({0x038cce42, 0xabd366b8, 0x3ede7e00, 0x9130de53, 0x72cdf73d, 0xee825114, 0x8cb48d1b, 0x9af68ad0}, 32); - const bit_vector hash_bv = int_list_to_bits({0xeffd0b7f, 0x1ccba116, 0x2ee816f7, 0x31c62b48, 0x59305141, 0x990e5c0a, 0xce40d33d, 0x0b1167d1}, 32); - - left.generate_r1cs_witness(left_bv); - right.generate_r1cs_witness(right_bv); - - f.generate_r1cs_witness(); - output.generate_r1cs_witness(hash_bv); - - EXPECT_TRUE(pb.is_satisfied()); -} - -TEST(gadgetlib1, sha256) -{ - start_profiling(); - default_ec_pp::init_public_params(); - test_two_to_one >(); -} diff --git a/src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.hpp b/src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.hpp deleted file mode 100644 index 0efa7cf4d23..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/** - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef MERKLE_AUTHENTICATION_PATH_VARIABLE_HPP_ -#define MERKLE_AUTHENTICATION_PATH_VARIABLE_HPP_ - -#include "common/data_structures/merkle_tree.hpp" -#include "gadgetlib1/gadget.hpp" -#include "gadgetlib1/gadgets/hashes/hash_io.hpp" - -namespace libsnark { - -template -class merkle_authentication_path_variable : public gadget { -public: - - const size_t tree_depth; - std::vector > left_digests; - std::vector > right_digests; - - merkle_authentication_path_variable(protoboard &pb, - const size_t tree_depth, - const std::string &annotation_prefix); - - void generate_r1cs_constraints(); - void generate_r1cs_witness(const size_t address, const merkle_authentication_path &path); - merkle_authentication_path get_authentication_path(const size_t address) const; -}; - -} // libsnark - -#include "gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.tcc" - -#endif // MERKLE_AUTHENTICATION_PATH_VARIABLE_HPP diff --git a/src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.tcc b/src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.tcc deleted file mode 100644 index b3d805d8edb..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.tcc +++ /dev/null @@ -1,76 +0,0 @@ -/** - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef MERKLE_AUTHENTICATION_PATH_VARIABLE_TCC_ -#define MERKLE_AUTHENTICATION_PATH_VARIABLE_TCC_ - -namespace libsnark { - -template -merkle_authentication_path_variable::merkle_authentication_path_variable(protoboard &pb, - const size_t tree_depth, - const std::string &annotation_prefix) : - gadget(pb, annotation_prefix), - tree_depth(tree_depth) -{ - for (size_t i = 0; i < tree_depth; ++i) - { - left_digests.emplace_back(digest_variable(pb, HashT::get_digest_len(), FMT(annotation_prefix, " left_digests_%zu", i))); - right_digests.emplace_back(digest_variable(pb, HashT::get_digest_len(), FMT(annotation_prefix, " right_digests_%zu", i))); - } -} - -template -void merkle_authentication_path_variable::generate_r1cs_constraints() -{ - for (size_t i = 0; i < tree_depth; ++i) - { - left_digests[i].generate_r1cs_constraints(); - right_digests[i].generate_r1cs_constraints(); - } -} - -template -void merkle_authentication_path_variable::generate_r1cs_witness(const size_t address, const merkle_authentication_path &path) -{ - assert(path.size() == tree_depth); - - for (size_t i = 0; i < tree_depth; ++i) - { - if (address & (UINT64_C(1) << (tree_depth-1-i))) - { - left_digests[i].generate_r1cs_witness(path[i]); - } - else - { - right_digests[i].generate_r1cs_witness(path[i]); - } - } -} - -template -merkle_authentication_path merkle_authentication_path_variable::get_authentication_path(const size_t address) const -{ - merkle_authentication_path result; - for (size_t i = 0; i < tree_depth; ++i) - { - if (address & (UINT64_C(1) << (tree_depth-1-i))) - { - result.emplace_back(left_digests[i].get_digest()); - } - else - { - result.emplace_back(right_digests[i].get_digest()); - } - } - - return result; -} - -} // libsnark - -#endif // MERKLE_AUTHENTICATION_PATH_VARIABLE_TCC diff --git a/src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.hpp b/src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.hpp deleted file mode 100644 index b1e3a4f053a..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.hpp +++ /dev/null @@ -1,73 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for the Merkle tree check read gadget. - - The gadget checks the following: given a root R, address A, value V, and - authentication path P, check that P is a valid authentication path for the - value V as the A-th leaf in a Merkle tree with root R. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef MERKLE_TREE_CHECK_READ_GADGET_HPP_ -#define MERKLE_TREE_CHECK_READ_GADGET_HPP_ - -#include "common/data_structures/merkle_tree.hpp" -#include "gadgetlib1/gadget.hpp" -#include "gadgetlib1/gadgets/hashes/hash_io.hpp" -#include "gadgetlib1/gadgets/hashes/digest_selector_gadget.hpp" -#include "gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.hpp" - -namespace libsnark { - -template -class merkle_tree_check_read_gadget : public gadget { -private: - - std::vector hashers; - std::vector > hasher_inputs; - std::vector > propagators; - std::vector > internal_output; - - std::shared_ptr > computed_root; - std::shared_ptr > check_root; - -public: - - const size_t digest_size; - const size_t tree_depth; - pb_linear_combination_array address_bits; - digest_variable leaf; - digest_variable root; - merkle_authentication_path_variable path; - pb_linear_combination read_successful; - - merkle_tree_check_read_gadget(protoboard &pb, - const size_t tree_depth, - const pb_linear_combination_array &address_bits, - const digest_variable &leaf_digest, - const digest_variable &root_digest, - const merkle_authentication_path_variable &path, - const pb_linear_combination &read_successful, - const std::string &annotation_prefix); - - void generate_r1cs_constraints(); - void generate_r1cs_witness(); - - static size_t root_size_in_bits(); - /* for debugging purposes */ - static size_t expected_constraints(const size_t tree_depth); -}; - -template -void test_merkle_tree_check_read_gadget(); - -} // libsnark - -#include "gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.tcc" - -#endif // MERKLE_TREE_CHECK_READ_GADGET_HPP_ diff --git a/src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.tcc b/src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.tcc deleted file mode 100644 index 29ce1b8ac1d..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.tcc +++ /dev/null @@ -1,196 +0,0 @@ -/** @file - ***************************************************************************** - - Implementation of interfaces for the Merkle tree check read. - - See merkle_tree_check_read_gadget.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef MERKLE_TREE_CHECK_READ_GADGET_TCC_ -#define MERKLE_TREE_CHECK_READ_GADGET_TCC_ - -namespace libsnark { - -template -merkle_tree_check_read_gadget::merkle_tree_check_read_gadget(protoboard &pb, - const size_t tree_depth, - const pb_linear_combination_array &address_bits, - const digest_variable &leaf, - const digest_variable &root, - const merkle_authentication_path_variable &path, - const pb_linear_combination &read_successful, - const std::string &annotation_prefix) : - gadget(pb, annotation_prefix), - digest_size(HashT::get_digest_len()), - tree_depth(tree_depth), - address_bits(address_bits), - leaf(leaf), - root(root), - path(path), - read_successful(read_successful) -{ - /* - The tricky part here is ordering. For Merkle tree - authentication paths, path[0] corresponds to one layer below - the root (and path[tree_depth-1] corresponds to the layer - containing the leaf), while address_bits has the reverse order: - address_bits[0] is LSB, and corresponds to layer containing the - leaf, and address_bits[tree_depth-1] is MSB, and corresponds to - the subtree directly under the root. - */ - assert(tree_depth > 0); - assert(tree_depth == address_bits.size()); - - for (size_t i = 0; i < tree_depth-1; ++i) - { - internal_output.emplace_back(digest_variable(pb, digest_size, FMT(this->annotation_prefix, " internal_output_%zu", i))); - } - - computed_root.reset(new digest_variable(pb, digest_size, FMT(this->annotation_prefix, " computed_root"))); - - for (size_t i = 0; i < tree_depth; ++i) - { - block_variable inp(pb, path.left_digests[i], path.right_digests[i], FMT(this->annotation_prefix, " inp_%zu", i)); - hasher_inputs.emplace_back(inp); - hashers.emplace_back(HashT(pb, 2*digest_size, inp, (i == 0 ? *computed_root : internal_output[i-1]), - FMT(this->annotation_prefix, " load_hashers_%zu", i))); - } - - for (size_t i = 0; i < tree_depth; ++i) - { - /* - The propagators take a computed hash value (or leaf in the - base case) and propagate it one layer up, either in the left - or the right slot of authentication_path_variable. - */ - propagators.emplace_back(digest_selector_gadget(pb, digest_size, i < tree_depth - 1 ? internal_output[i] : leaf, - address_bits[tree_depth-1-i], path.left_digests[i], path.right_digests[i], - FMT(this->annotation_prefix, " digest_selector_%zu", i))); - } - - check_root.reset(new bit_vector_copy_gadget(pb, computed_root->bits, root.bits, read_successful, FieldT::capacity(), FMT(annotation_prefix, " check_root"))); -} - -template -void merkle_tree_check_read_gadget::generate_r1cs_constraints() -{ - /* ensure correct hash computations */ - for (size_t i = 0; i < tree_depth; ++i) - { - // Note that we check root outside and have enforced booleanity of path.left_digests/path.right_digests outside in path.generate_r1cs_constraints - hashers[i].generate_r1cs_constraints(false); - } - - /* ensure consistency of path.left_digests/path.right_digests with internal_output */ - for (size_t i = 0; i < tree_depth; ++i) - { - propagators[i].generate_r1cs_constraints(); - } - - check_root->generate_r1cs_constraints(false, false); -} - -template -void merkle_tree_check_read_gadget::generate_r1cs_witness() -{ - /* do the hash computations bottom-up */ - for (int i = tree_depth-1; i >= 0; --i) - { - /* propagate previous input */ - propagators[i].generate_r1cs_witness(); - - /* compute hash */ - hashers[i].generate_r1cs_witness(); - } - - check_root->generate_r1cs_witness(); -} - -template -size_t merkle_tree_check_read_gadget::root_size_in_bits() -{ - return HashT::get_digest_len(); -} - -template -size_t merkle_tree_check_read_gadget::expected_constraints(const size_t tree_depth) -{ - /* NB: this includes path constraints */ - const size_t hasher_constraints = tree_depth * HashT::expected_constraints(false); - const size_t propagator_constraints = tree_depth * HashT::get_digest_len(); - const size_t authentication_path_constraints = 2 * tree_depth * HashT::get_digest_len(); - const size_t check_root_constraints = 3 * div_ceil(HashT::get_digest_len(), FieldT::capacity()); - - return hasher_constraints + propagator_constraints + authentication_path_constraints + check_root_constraints; -} - -template -void test_merkle_tree_check_read_gadget() -{ - /* prepare test */ - const size_t digest_len = HashT::get_digest_len(); - const size_t tree_depth = 16; - std::vector path(tree_depth); - - bit_vector prev_hash(digest_len); - std::generate(prev_hash.begin(), prev_hash.end(), [&]() { return std::rand() % 2; }); - bit_vector leaf = prev_hash; - - bit_vector address_bits; - - size_t address = 0; - for (int64_t level = tree_depth-1; level >= 0; --level) - { - const bool computed_is_right = (std::rand() % 2); - address |= (computed_is_right ? UINT64_C(1) << (tree_depth-1-level) : 0); - address_bits.push_back(computed_is_right); - bit_vector other(digest_len); - std::generate(other.begin(), other.end(), [&]() { return std::rand() % 2; }); - - bit_vector block = prev_hash; - block.insert(computed_is_right ? block.begin() : block.end(), other.begin(), other.end()); - bit_vector h = HashT::get_hash(block); - - path[level] = other; - - prev_hash = h; - } - bit_vector root = prev_hash; - - /* execute test */ - protoboard pb; - pb_variable_array address_bits_va; - address_bits_va.allocate(pb, tree_depth, "address_bits"); - digest_variable leaf_digest(pb, digest_len, "input_block"); - digest_variable root_digest(pb, digest_len, "output_digest"); - merkle_authentication_path_variable path_var(pb, tree_depth, "path_var"); - merkle_tree_check_read_gadget ml(pb, tree_depth, address_bits_va, leaf_digest, root_digest, path_var, ONE, "ml"); - - path_var.generate_r1cs_constraints(); - ml.generate_r1cs_constraints(); - - address_bits_va.fill_with_bits(pb, address_bits); - assert(address_bits_va.get_field_element_from_bits(pb).as_uint64() == address); - leaf_digest.generate_r1cs_witness(leaf); - path_var.generate_r1cs_witness(address, path); - ml.generate_r1cs_witness(); - - /* make sure that read checker didn't accidentally overwrite anything */ - address_bits_va.fill_with_bits(pb, address_bits); - leaf_digest.generate_r1cs_witness(leaf); - root_digest.generate_r1cs_witness(root); - assert(pb.is_satisfied()); - - const size_t num_constraints = pb.num_constraints(); - const size_t expected_constraints = merkle_tree_check_read_gadget::expected_constraints(tree_depth); - assert(num_constraints == expected_constraints); -} - -} // libsnark - -#endif // MERKLE_TREE_CHECK_READ_GADGET_TCC_ diff --git a/src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.hpp b/src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.hpp deleted file mode 100644 index 6ec0ca11ff6..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.hpp +++ /dev/null @@ -1,90 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for the Merkle tree check read gadget. - - The gadget checks the following: given two roots R1 and R2, address A, two - values V1 and V2, and authentication path P, check that - - P is a valid authentication path for the value V1 as the A-th leaf in a Merkle tree with root R1, and - - P is a valid authentication path for the value V2 as the A-th leaf in a Merkle tree with root R2. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef MERKLE_TREE_CHECK_UPDATE_GADGET_HPP_ -#define MERKLE_TREE_CHECK_UPDATE_GADGET_HPP_ - -#include "common/data_structures/merkle_tree.hpp" -#include "gadgetlib1/gadget.hpp" -#include "gadgetlib1/gadgets/hashes/hash_io.hpp" -#include "gadgetlib1/gadgets/hashes/digest_selector_gadget.hpp" -#include "gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.hpp" - -namespace libsnark { - -template -class merkle_tree_check_update_gadget : public gadget { -private: - - std::vector prev_hashers; - std::vector > prev_hasher_inputs; - std::vector > prev_propagators; - std::vector > prev_internal_output; - - std::vector next_hashers; - std::vector > next_hasher_inputs; - std::vector > next_propagators; - std::vector > next_internal_output; - - std::shared_ptr > computed_next_root; - std::shared_ptr > check_next_root; - -public: - - const size_t digest_size; - const size_t tree_depth; - - pb_variable_array address_bits; - digest_variable prev_leaf_digest; - digest_variable prev_root_digest; - merkle_authentication_path_variable prev_path; - digest_variable next_leaf_digest; - digest_variable next_root_digest; - merkle_authentication_path_variable next_path; - pb_linear_combination update_successful; - - /* Note that while it is necessary to generate R1CS constraints - for prev_path, it is not necessary to do so for next_path. See - comment in the implementation of generate_r1cs_constraints() */ - - merkle_tree_check_update_gadget(protoboard &pb, - const size_t tree_depth, - const pb_variable_array &address_bits, - const digest_variable &prev_leaf_digest, - const digest_variable &prev_root_digest, - const merkle_authentication_path_variable &prev_path, - const digest_variable &next_leaf_digest, - const digest_variable &next_root_digest, - const merkle_authentication_path_variable &next_path, - const pb_linear_combination &update_successful, - const std::string &annotation_prefix); - - void generate_r1cs_constraints(); - void generate_r1cs_witness(); - - static size_t root_size_in_bits(); - /* for debugging purposes */ - static size_t expected_constraints(const size_t tree_depth); -}; - -template -void test_merkle_tree_check_update_gadget(); - -} // libsnark - -#include "gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.tcc" - -#endif // MERKLE_TREE_CHECK_UPDATE_GADGET_HPP_ diff --git a/src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.tcc b/src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.tcc deleted file mode 100644 index 507c7526d96..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.tcc +++ /dev/null @@ -1,265 +0,0 @@ -/** @file - ***************************************************************************** - - Implementation of interfaces for the Merkle tree check update gadget. - - See merkle_tree_check_update_gadget.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef MERKLE_TREE_CHECK_UPDATE_GADGET_TCC_ -#define MERKLE_TREE_CHECK_UPDATE_GADGET_TCC_ - -namespace libsnark { - -template -merkle_tree_check_update_gadget::merkle_tree_check_update_gadget(protoboard &pb, - const size_t tree_depth, - const pb_variable_array &address_bits, - const digest_variable &prev_leaf_digest, - const digest_variable &prev_root_digest, - const merkle_authentication_path_variable &prev_path, - const digest_variable &next_leaf_digest, - const digest_variable &next_root_digest, - const merkle_authentication_path_variable &next_path, - const pb_linear_combination &update_successful, - const std::string &annotation_prefix) : - gadget(pb, annotation_prefix), - digest_size(HashT::get_digest_len()), - tree_depth(tree_depth), - address_bits(address_bits), - prev_leaf_digest(prev_leaf_digest), - prev_root_digest(prev_root_digest), - prev_path(prev_path), - next_leaf_digest(next_leaf_digest), - next_root_digest(next_root_digest), - next_path(next_path), - update_successful(update_successful) -{ - assert(tree_depth > 0); - assert(tree_depth == address_bits.size()); - - for (size_t i = 0; i < tree_depth-1; ++i) - { - prev_internal_output.emplace_back(digest_variable(pb, digest_size, FMT(this->annotation_prefix, " prev_internal_output_%zu", i))); - next_internal_output.emplace_back(digest_variable(pb, digest_size, FMT(this->annotation_prefix, " next_internal_output_%zu", i))); - } - - computed_next_root.reset(new digest_variable(pb, digest_size, FMT(this->annotation_prefix, " computed_root"))); - - for (size_t i = 0; i < tree_depth; ++i) - { - block_variable prev_inp(pb, prev_path.left_digests[i], prev_path.right_digests[i], FMT(this->annotation_prefix, " prev_inp_%zu", i)); - prev_hasher_inputs.emplace_back(prev_inp); - prev_hashers.emplace_back(HashT(pb, 2*digest_size, prev_inp, (i == 0 ? prev_root_digest : prev_internal_output[i-1]), - FMT(this->annotation_prefix, " prev_hashers_%zu", i))); - - block_variable next_inp(pb, next_path.left_digests[i], next_path.right_digests[i], FMT(this->annotation_prefix, " next_inp_%zu", i)); - next_hasher_inputs.emplace_back(next_inp); - next_hashers.emplace_back(HashT(pb, 2*digest_size, next_inp, (i == 0 ? *computed_next_root : next_internal_output[i-1]), - FMT(this->annotation_prefix, " next_hashers_%zu", i))); - } - - for (size_t i = 0; i < tree_depth; ++i) - { - prev_propagators.emplace_back(digest_selector_gadget(pb, digest_size, i < tree_depth -1 ? prev_internal_output[i] : prev_leaf_digest, - address_bits[tree_depth-1-i], prev_path.left_digests[i], prev_path.right_digests[i], - FMT(this->annotation_prefix, " prev_propagators_%zu", i))); - next_propagators.emplace_back(digest_selector_gadget(pb, digest_size, i < tree_depth -1 ? next_internal_output[i] : next_leaf_digest, - address_bits[tree_depth-1-i], next_path.left_digests[i], next_path.right_digests[i], - FMT(this->annotation_prefix, " next_propagators_%zu", i))); - } - - check_next_root.reset(new bit_vector_copy_gadget(pb, computed_next_root->bits, next_root_digest.bits, update_successful, FieldT::capacity(), FMT(annotation_prefix, " check_next_root"))); -} - -template -void merkle_tree_check_update_gadget::generate_r1cs_constraints() -{ - /* ensure correct hash computations */ - for (size_t i = 0; i < tree_depth; ++i) - { - prev_hashers[i].generate_r1cs_constraints(false); // we check root outside and prev_left/prev_right above - next_hashers[i].generate_r1cs_constraints(true); // however we must check right side hashes - } - - /* ensure consistency of internal_left/internal_right with internal_output */ - for (size_t i = 0; i < tree_depth; ++i) - { - prev_propagators[i].generate_r1cs_constraints(); - next_propagators[i].generate_r1cs_constraints(); - } - - /* ensure that prev auxiliary input and next auxiliary input match */ - for (size_t i = 0; i < tree_depth; ++i) - { - for (size_t j = 0; j < digest_size; ++j) - { - /* - addr * (prev_left - next_left) + (1 - addr) * (prev_right - next_right) = 0 - addr * (prev_left - next_left - prev_right + next_right) = next_right - prev_right - */ - this->pb.add_r1cs_constraint(r1cs_constraint(address_bits[tree_depth-1-i], - prev_path.left_digests[i].bits[j] - next_path.left_digests[i].bits[j] - prev_path.right_digests[i].bits[j] + next_path.right_digests[i].bits[j], - next_path.right_digests[i].bits[j] - prev_path.right_digests[i].bits[j]), - FMT(this->annotation_prefix, " aux_check_%zu_%zu", i, j)); - } - } - - /* Note that while it is necessary to generate R1CS constraints - for prev_path, it is not necessary to do so for next_path. - - This holds, because { next_path.left_inputs[i], - next_path.right_inputs[i] } is a pair { hash_output, - auxiliary_input }. The bitness for hash_output is enforced - above by next_hashers[i].generate_r1cs_constraints. - - Because auxiliary input is the same for prev_path and next_path - (enforced above), we have that auxiliary_input part is also - constrained to be boolean, because prev_path is *all* - constrained to be all boolean. */ - - check_next_root->generate_r1cs_constraints(false, false); -} - -template -void merkle_tree_check_update_gadget::generate_r1cs_witness() -{ - /* do the hash computations bottom-up */ - for (int i = tree_depth-1; i >= 0; --i) - { - /* ensure consistency of prev_path and next_path */ - if (this->pb.val(address_bits[tree_depth-1-i]) == FieldT::one()) - { - next_path.left_digests[i].generate_r1cs_witness(prev_path.left_digests[i].get_digest()); - } - else - { - next_path.right_digests[i].generate_r1cs_witness(prev_path.right_digests[i].get_digest()); - } - - /* propagate previous input */ - prev_propagators[i].generate_r1cs_witness(); - next_propagators[i].generate_r1cs_witness(); - - /* compute hash */ - prev_hashers[i].generate_r1cs_witness(); - next_hashers[i].generate_r1cs_witness(); - } - - check_next_root->generate_r1cs_witness(); -} - -template -size_t merkle_tree_check_update_gadget::root_size_in_bits() -{ - return HashT::get_digest_len(); -} - -template -size_t merkle_tree_check_update_gadget::expected_constraints(const size_t tree_depth) -{ - /* NB: this includes path constraints */ - const size_t prev_hasher_constraints = tree_depth * HashT::expected_constraints(false); - const size_t next_hasher_constraints = tree_depth * HashT::expected_constraints(true); - const size_t prev_authentication_path_constraints = 2 * tree_depth * HashT::get_digest_len(); - const size_t prev_propagator_constraints = tree_depth * HashT::get_digest_len(); - const size_t next_propagator_constraints = tree_depth * HashT::get_digest_len(); - const size_t check_next_root_constraints = 3 * div_ceil(HashT::get_digest_len(), FieldT::capacity()); - const size_t aux_equality_constraints = tree_depth * HashT::get_digest_len(); - - return (prev_hasher_constraints + next_hasher_constraints + prev_authentication_path_constraints + - prev_propagator_constraints + next_propagator_constraints + check_next_root_constraints + - aux_equality_constraints); -} - -template -void test_merkle_tree_check_update_gadget() -{ - /* prepare test */ - const size_t digest_len = HashT::get_digest_len(); - - const size_t tree_depth = 16; - std::vector prev_path(tree_depth); - - bit_vector prev_load_hash(digest_len); - std::generate(prev_load_hash.begin(), prev_load_hash.end(), [&]() { return std::rand() % 2; }); - bit_vector prev_store_hash(digest_len); - std::generate(prev_store_hash.begin(), prev_store_hash.end(), [&]() { return std::rand() % 2; }); - - bit_vector loaded_leaf = prev_load_hash; - bit_vector stored_leaf = prev_store_hash; - - bit_vector address_bits; - - size_t address = 0; - for (int64_t level = tree_depth-1; level >= 0; --level) - { - const bool computed_is_right = (std::rand() % 2); - address |= (computed_is_right ? UINT64_C(1) << (tree_depth-1-level) : 0); - address_bits.push_back(computed_is_right); - bit_vector other(digest_len); - std::generate(other.begin(), other.end(), [&]() { return std::rand() % 2; }); - - bit_vector load_block = prev_load_hash; - load_block.insert(computed_is_right ? load_block.begin() : load_block.end(), other.begin(), other.end()); - bit_vector store_block = prev_store_hash; - store_block.insert(computed_is_right ? store_block.begin() : store_block.end(), other.begin(), other.end()); - - bit_vector load_h = HashT::get_hash(load_block); - bit_vector store_h = HashT::get_hash(store_block); - - prev_path[level] = other; - - prev_load_hash = load_h; - prev_store_hash = store_h; - } - - bit_vector load_root = prev_load_hash; - bit_vector store_root = prev_store_hash; - - /* execute the test */ - protoboard pb; - pb_variable_array address_bits_va; - address_bits_va.allocate(pb, tree_depth, "address_bits"); - digest_variable prev_leaf_digest(pb, digest_len, "prev_leaf_digest"); - digest_variable prev_root_digest(pb, digest_len, "prev_root_digest"); - merkle_authentication_path_variable prev_path_var(pb, tree_depth, "prev_path_var"); - digest_variable next_leaf_digest(pb, digest_len, "next_leaf_digest"); - digest_variable next_root_digest(pb, digest_len, "next_root_digest"); - merkle_authentication_path_variable next_path_var(pb, tree_depth, "next_path_var"); - merkle_tree_check_update_gadget mls(pb, tree_depth, address_bits_va, - prev_leaf_digest, prev_root_digest, prev_path_var, - next_leaf_digest, next_root_digest, next_path_var, ONE, "mls"); - - prev_path_var.generate_r1cs_constraints(); - mls.generate_r1cs_constraints(); - - address_bits_va.fill_with_bits(pb, address_bits); - assert(address_bits_va.get_field_element_from_bits(pb).as_uint64() == address); - prev_leaf_digest.generate_r1cs_witness(loaded_leaf); - prev_path_var.generate_r1cs_witness(address, prev_path); - next_leaf_digest.generate_r1cs_witness(stored_leaf); - address_bits_va.fill_with_bits(pb, address_bits); - mls.generate_r1cs_witness(); - - /* make sure that update check will check for the right things */ - prev_leaf_digest.generate_r1cs_witness(loaded_leaf); - next_leaf_digest.generate_r1cs_witness(stored_leaf); - prev_root_digest.generate_r1cs_witness(load_root); - next_root_digest.generate_r1cs_witness(store_root); - address_bits_va.fill_with_bits(pb, address_bits); - assert(pb.is_satisfied()); - - const size_t num_constraints = pb.num_constraints(); - const size_t expected_constraints = merkle_tree_check_update_gadget::expected_constraints(tree_depth); - assert(num_constraints == expected_constraints); -} - -} // libsnark - -#endif // MERKLE_TREE_CHECK_UPDATE_GADGET_TCC_ diff --git a/src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/tests/test_merkle_tree_gadgets.cpp b/src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/tests/test_merkle_tree_gadgets.cpp deleted file mode 100644 index 27b52f9ec29..00000000000 --- a/src/snark/libsnark/gadgetlib1/gadgets/merkle_tree/tests/test_merkle_tree_gadgets.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp" -#ifdef CURVE_BN128 -#include "algebra/curves/bn128/bn128_pp.hpp" -#endif -#include "gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.hpp" -#include "gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.hpp" -#include "gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp" - -#include - -using namespace libsnark; - -template -void test_all_merkle_tree_gadgets() -{ - typedef Fr FieldT; - test_merkle_tree_check_read_gadget >(); - - test_merkle_tree_check_update_gadget >(); -} - -TEST(gadgetlib1, merkle_tree) -{ - start_profiling(); - - alt_bn128_pp::init_public_params(); - test_all_merkle_tree_gadgets(); - -#ifdef CURVE_BN128 // BN128 has fancy dependencies so it may be disabled - bn128_pp::init_public_params(); - test_all_merkle_tree_gadgets(); -#endif -} diff --git a/src/snark/libsnark/gadgetlib1/pb_variable.hpp b/src/snark/libsnark/gadgetlib1/pb_variable.hpp deleted file mode 100644 index caa44cec181..00000000000 --- a/src/snark/libsnark/gadgetlib1/pb_variable.hpp +++ /dev/null @@ -1,144 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef PB_VARIABLE_HPP_ -#define PB_VARIABLE_HPP_ - -#include -#include -#include -#include "common/utils.hpp" -#include "relations/variable.hpp" - -namespace libsnark { - -typedef size_t lc_index_t; - -template -class protoboard; - -template -class pb_variable : public variable { -public: - pb_variable(const var_index_t index = 0) : variable(index) {}; - - void allocate(protoboard &pb, const std::string &annotation=""); -}; - -template -class pb_variable_array : private std::vector > -{ - typedef std::vector > contents; -public: - using typename contents::iterator; - using typename contents::const_iterator; - using typename contents::reverse_iterator; - using typename contents::const_reverse_iterator; - - using contents::begin; - using contents::end; - using contents::rbegin; - using contents::rend; - using contents::emplace_back; - using contents::insert; - using contents::reserve; - using contents::size; - using contents::empty; - using contents::operator[]; - using contents::resize; - - pb_variable_array() : contents() {}; - pb_variable_array(size_t count, const pb_variable &value) : contents(count, value) {}; - pb_variable_array(typename contents::const_iterator first, typename contents::const_iterator last) : contents(first, last) {}; - pb_variable_array(typename contents::const_reverse_iterator first, typename contents::const_reverse_iterator last) : contents(first, last) {}; - void allocate(protoboard &pb, const size_t n, const std::string &annotation_prefix=""); - - void fill_with_field_elements(protoboard &pb, const std::vector& vals) const; - void fill_with_bits(protoboard &pb, const bit_vector& bits) const; - void fill_with_bits_of_uint64(protoboard &pb, const uint64_t i) const; - void fill_with_bits_of_field_element(protoboard &pb, const FieldT &r) const; - - std::vector get_vals(const protoboard &pb) const; - bit_vector get_bits(const protoboard &pb) const; - - FieldT get_field_element_from_bits(const protoboard &pb) const; -}; - -/* index 0 corresponds to the constant term (used in legacy code) */ -#define ONE pb_variable(0) - -template -class pb_linear_combination : public linear_combination { -public: - bool is_variable; - lc_index_t index; - - pb_linear_combination(); - pb_linear_combination(const pb_variable &var); - - void assign(protoboard &pb, const linear_combination &lc); - void evaluate(protoboard &pb) const; - - bool is_constant() const; - FieldT constant_term() const; -}; - -template -class pb_linear_combination_array : private std::vector > -{ - typedef std::vector > contents; -public: - using typename contents::iterator; - using typename contents::const_iterator; - using typename contents::reverse_iterator; - using typename contents::const_reverse_iterator; - - using contents::begin; - using contents::end; - using contents::rbegin; - using contents::rend; - using contents::emplace_back; - using contents::insert; - using contents::reserve; - using contents::size; - using contents::empty; - using contents::operator[]; - using contents::resize; - - pb_linear_combination_array() : contents() {}; - pb_linear_combination_array(const pb_variable_array &arr) { for (auto &v : arr) this->emplace_back(pb_linear_combination(v)); }; - pb_linear_combination_array(size_t count) : contents(count) {}; - pb_linear_combination_array(size_t count, const pb_linear_combination &value) : contents(count, value) {}; - pb_linear_combination_array(typename contents::const_iterator first, typename contents::const_iterator last) : contents(first, last) {}; - pb_linear_combination_array(typename contents::const_reverse_iterator first, typename contents::const_reverse_iterator last) : contents(first, last) {}; - - void evaluate(protoboard &pb) const; - - void fill_with_field_elements(protoboard &pb, const std::vector& vals) const; - void fill_with_bits(protoboard &pb, const bit_vector& bits) const; - void fill_with_bits_of_uint64(protoboard &pb, const uint64_t i) const; - void fill_with_bits_of_field_element(protoboard &pb, const FieldT &r) const; - - std::vector get_vals(const protoboard &pb) const; - bit_vector get_bits(const protoboard &pb) const; - - FieldT get_field_element_from_bits(const protoboard &pb) const; -}; - -template -linear_combination pb_sum(const pb_linear_combination_array &v); - -template -linear_combination pb_packing_sum(const pb_linear_combination_array &v); - -template -linear_combination pb_coeff_sum(const pb_linear_combination_array &v, const std::vector &coeffs); - -} // libsnark -#include "gadgetlib1/pb_variable.tcc" - -#endif // PB_VARIABLE_HPP_ diff --git a/src/snark/libsnark/gadgetlib1/pb_variable.tcc b/src/snark/libsnark/gadgetlib1/pb_variable.tcc deleted file mode 100644 index b4c6ad4f9ad..00000000000 --- a/src/snark/libsnark/gadgetlib1/pb_variable.tcc +++ /dev/null @@ -1,330 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef PB_VARIABLE_TCC_ -#define PB_VARIABLE_TCC_ -#include -#include "gadgetlib1/protoboard.hpp" -#include "common/utils.hpp" - -namespace libsnark { - -template -void pb_variable::allocate(protoboard &pb, const std::string &annotation) -{ - this->index = pb.allocate_var_index(annotation); -} - -/* allocates pb_variable array in MSB->LSB order */ -template -void pb_variable_array::allocate(protoboard &pb, const size_t n, const std::string &annotation_prefix) -{ -#ifdef DEBUG - assert(annotation_prefix != ""); -#endif - (*this).resize(n); - - for (size_t i = 0; i < n; ++i) - { - (*this)[i].allocate(pb, FMT(annotation_prefix, "_%zu", i)); - } -} - -template -void pb_variable_array::fill_with_field_elements(protoboard &pb, const std::vector& vals) const -{ - assert(this->size() == vals.size()); - for (size_t i = 0; i < vals.size(); ++i) - { - pb.val((*this)[i]) = vals[i]; - } -} - -template -void pb_variable_array::fill_with_bits(protoboard &pb, const bit_vector& bits) const -{ - assert(this->size() == bits.size()); - for (size_t i = 0; i < bits.size(); ++i) - { - pb.val((*this)[i]) = (bits[i] ? FieldT::one() : FieldT::zero()); - } -} - -template -void pb_variable_array::fill_with_bits_of_field_element(protoboard &pb, const FieldT &r) const -{ - const bigint rint = r.as_bigint(); - for (size_t i = 0; i < this->size(); ++i) - { - pb.val((*this)[i]) = rint.test_bit(i) ? FieldT::one() : FieldT::zero(); - } -} - -template -void pb_variable_array::fill_with_bits_of_uint64(protoboard &pb, const uint64_t i) const -{ - this->fill_with_bits_of_field_element(pb, FieldT(i, true)); -} - -template -std::vector pb_variable_array::get_vals(const protoboard &pb) const -{ - std::vector result(this->size()); - for (size_t i = 0; i < this->size(); ++i) - { - result[i] = pb.val((*this)[i]); - } - return result; -} - -template -bit_vector pb_variable_array::get_bits(const protoboard &pb) const -{ - bit_vector result; - for (size_t i = 0; i < this->size(); ++i) - { - const FieldT v = pb.val((*this)[i]); - assert(v == FieldT::zero() || v == FieldT::one()); - result.push_back(v == FieldT::one()); - } - return result; -} - -template -FieldT pb_variable_array::get_field_element_from_bits(const protoboard &pb) const -{ - FieldT result = FieldT::zero(); - - for (size_t i = 0; i < this->size(); ++i) - { - /* push in the new bit */ - const FieldT v = pb.val((*this)[this->size()-1-i]); - assert(v == FieldT::zero() || v == FieldT::one()); - result += result + v; - } - - return result; -} - -template -pb_linear_combination::pb_linear_combination() -{ - this->is_variable = false; - this->index = 0; -} - -template -pb_linear_combination::pb_linear_combination(const pb_variable &var) -{ - this->is_variable = true; - this->index = var.index; - this->terms.emplace_back(linear_term(var)); -} - -template -void pb_linear_combination::assign(protoboard &pb, const linear_combination &lc) -{ - assert(this->is_variable == false); - this->index = pb.allocate_lc_index(); - this->terms = lc.terms; -} - -template -void pb_linear_combination::evaluate(protoboard &pb) const -{ - if (this->is_variable) - { - return; // do nothing - } - - FieldT sum = 0; - for (auto term : this->terms) - { - sum += term.coeff * pb.val(pb_variable(term.index)); - } - - pb.lc_val(*this) = sum; -} - -template -bool pb_linear_combination::is_constant() const -{ - if (is_variable) - { - return (index == 0); - } - else - { - for (auto term : this->terms) - { - if (term.index != 0) - { - return false; - } - } - - return true; - } -} - -template -FieldT pb_linear_combination::constant_term() const -{ - if (is_variable) - { - return (index == 0 ? FieldT::one() : FieldT::zero()); - } - else - { - FieldT result = FieldT::zero(); - for (auto term : this->terms) - { - if (term.index == 0) - { - result += term.coeff; - } - } - return result; - } -} - -template -void pb_linear_combination_array::evaluate(protoboard &pb) const -{ - for (size_t i = 0; i < this->size(); ++i) - { - (*this)[i].evaluate(pb); - } -} - -template -void pb_linear_combination_array::fill_with_field_elements(protoboard &pb, const std::vector& vals) const -{ - assert(this->size() == vals.size()); - for (size_t i = 0; i < vals.size(); ++i) - { - pb.lc_val((*this)[i]) = vals[i]; - } -} - -template -void pb_linear_combination_array::fill_with_bits(protoboard &pb, const bit_vector& bits) const -{ - assert(this->size() == bits.size()); - for (size_t i = 0; i < bits.size(); ++i) - { - pb.lc_val((*this)[i]) = (bits[i] ? FieldT::one() : FieldT::zero()); - } -} - -template -void pb_linear_combination_array::fill_with_bits_of_field_element(protoboard &pb, const FieldT &r) const -{ - const bigint rint = r.as_bigint(); - for (size_t i = 0; i < this->size(); ++i) - { - pb.lc_val((*this)[i]) = rint.test_bit(i) ? FieldT::one() : FieldT::zero(); - } -} - -template -void pb_linear_combination_array::fill_with_bits_of_uint64(protoboard &pb, const uint64_t i) const -{ - this->fill_with_bits_of_field_element(pb, FieldT(i)); -} - -template -std::vector pb_linear_combination_array::get_vals(const protoboard &pb) const -{ - std::vector result(this->size()); - for (size_t i = 0; i < this->size(); ++i) - { - result[i] = pb.lc_val((*this)[i]); - } - return result; -} - -template -bit_vector pb_linear_combination_array::get_bits(const protoboard &pb) const -{ - bit_vector result; - for (size_t i = 0; i < this->size(); ++i) - { - const FieldT v = pb.lc_val((*this)[i]); - assert(v == FieldT::zero() || v == FieldT::one()); - result.push_back(v == FieldT::one()); - } - return result; -} - -template -FieldT pb_linear_combination_array::get_field_element_from_bits(const protoboard &pb) const -{ - FieldT result = FieldT::zero(); - - for (size_t i = 0; i < this->size(); ++i) - { - /* push in the new bit */ - const FieldT v = pb.lc_val((*this)[this->size()-1-i]); - assert(v == FieldT::zero() || v == FieldT::one()); - result += result + v; - } - - return result; -} - -template -linear_combination pb_sum(const pb_linear_combination_array &v) -{ - linear_combination result; - for (auto &term : v) - { - result = result + term; - } - - return result; -} - -template -linear_combination pb_packing_sum(const pb_linear_combination_array &v) -{ - FieldT twoi = FieldT::one(); // will hold 2^i entering each iteration - std::vector > all_terms; - for (auto &lc : v) - { - for (auto &term : lc.terms) - { - all_terms.emplace_back(twoi * term); - } - twoi += twoi; - } - - return linear_combination(all_terms); -} - -template -linear_combination pb_coeff_sum(const pb_linear_combination_array &v, const std::vector &coeffs) -{ - assert(v.size() == coeffs.size()); - std::vector > all_terms; - - auto coeff_it = coeffs.begin(); - for (auto &lc : v) - { - for (auto &term : lc.terms) - { - all_terms.emplace_back((*coeff_it) * term); - } - ++coeff_it; - } - - return linear_combination(all_terms); -} - - -} // libsnark -#endif // PB_VARIABLE_TCC diff --git a/src/snark/libsnark/gadgetlib1/protoboard.hpp b/src/snark/libsnark/gadgetlib1/protoboard.hpp deleted file mode 100644 index a910a6df92d..00000000000 --- a/src/snark/libsnark/gadgetlib1/protoboard.hpp +++ /dev/null @@ -1,75 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef PROTOBOARD_HPP_ -#define PROTOBOARD_HPP_ - -#include -#include -#include -#include -#include -#include "gadgetlib1/pb_variable.hpp" -#include "relations/constraint_satisfaction_problems/r1cs/r1cs.hpp" -#include "common/utils.hpp" - -namespace libsnark { - -template -class r1cs_constraint; - -template -class r1cs_constraint_system; - -template -class protoboard { -private: - FieldT constant_term; /* only here, because pb.val() needs to be able to return reference to the constant 1 term */ - r1cs_variable_assignment values; /* values[0] will hold the value of the first allocated variable of the protoboard, *NOT* constant 1 */ - var_index_t next_free_var; - lc_index_t next_free_lc; - std::vector lc_values; -public: - r1cs_constraint_system constraint_system; - - protoboard(); - - void clear_values(); - - FieldT& val(const pb_variable &var); - FieldT val(const pb_variable &var) const; - - FieldT& lc_val(const pb_linear_combination &lc); - FieldT lc_val(const pb_linear_combination &lc) const; - - void add_r1cs_constraint(const r1cs_constraint &constr, const std::string &annotation=""); - void augment_variable_annotation(const pb_variable &v, const std::string &postfix); - bool is_satisfied() const; - void dump_variables() const; - - size_t num_constraints() const; - size_t num_inputs() const; - size_t num_variables() const; - - void set_input_sizes(const size_t primary_input_size); - - r1cs_variable_assignment full_variable_assignment() const; - r1cs_primary_input primary_input() const; - r1cs_auxiliary_input auxiliary_input() const; - r1cs_constraint_system get_constraint_system() const; - - friend class pb_variable; - friend class pb_linear_combination; - -private: - var_index_t allocate_var_index(const std::string &annotation=""); - lc_index_t allocate_lc_index(); -}; - -} // libsnark -#include "gadgetlib1/protoboard.tcc" -#endif // PROTOBOARD_HPP_ diff --git a/src/snark/libsnark/gadgetlib1/protoboard.tcc b/src/snark/libsnark/gadgetlib1/protoboard.tcc deleted file mode 100644 index 882af28e60b..00000000000 --- a/src/snark/libsnark/gadgetlib1/protoboard.tcc +++ /dev/null @@ -1,189 +0,0 @@ -/** @file - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef PROTOBOARD_TCC_ -#define PROTOBOARD_TCC_ - -#include -#include -#include "common/profiling.hpp" - -namespace libsnark { - -template -protoboard::protoboard() -{ - constant_term = FieldT::one(); - -#ifdef DEBUG - constraint_system.variable_annotations[0] = "ONE"; -#endif - - next_free_var = 1; /* to account for constant 1 term */ - next_free_lc = 0; -} - -template -void protoboard::clear_values() -{ - std::fill(values.begin(), values.end(), FieldT::zero()); -} - -template -var_index_t protoboard::allocate_var_index(const std::string &annotation) -{ -#ifdef DEBUG - assert(annotation != ""); - constraint_system.variable_annotations[next_free_var] = annotation; -#else - UNUSED(annotation); -#endif - ++constraint_system.auxiliary_input_size; - values.emplace_back(FieldT::zero()); - return next_free_var++; -} - -template -lc_index_t protoboard::allocate_lc_index() -{ - lc_values.emplace_back(FieldT::zero()); - return next_free_lc++; -} - -template -FieldT& protoboard::val(const pb_variable &var) -{ - assert(var.index <= values.size()); - return (var.index == 0 ? constant_term : values[var.index-1]); -} - -template -FieldT protoboard::val(const pb_variable &var) const -{ - assert(var.index <= values.size()); - return (var.index == 0 ? constant_term : values[var.index-1]); -} - -template -FieldT& protoboard::lc_val(const pb_linear_combination &lc) -{ - if (lc.is_variable) - { - return this->val(pb_variable(lc.index)); - } - else - { - assert(lc.index < lc_values.size()); - return lc_values[lc.index]; - } -} - -template -FieldT protoboard::lc_val(const pb_linear_combination &lc) const -{ - if (lc.is_variable) - { - return this->val(pb_variable(lc.index)); - } - else - { - assert(lc.index < lc_values.size()); - return lc_values[lc.index]; - } -} - -template -void protoboard::add_r1cs_constraint(const r1cs_constraint &constr, const std::string &annotation) -{ -#ifdef DEBUG - assert(annotation != ""); - constraint_system.constraint_annotations[constraint_system.constraints.size()] = annotation; -#else - UNUSED(annotation); -#endif - constraint_system.constraints.emplace_back(constr); -} - -template -void protoboard::augment_variable_annotation(const pb_variable &v, const std::string &postfix) -{ -#ifdef DEBUG - auto it = constraint_system.variable_annotations.find(v.index); - constraint_system.variable_annotations[v.index] = (it == constraint_system.variable_annotations.end() ? "" : it->second + " ") + postfix; -#endif -} - -template -bool protoboard::is_satisfied() const -{ - return constraint_system.is_satisfied(primary_input(), auxiliary_input()); -} - -template -void protoboard::dump_variables() const -{ -#ifdef DEBUG - for (size_t i = 0; i < constraint_system.num_variables; ++i) - { - printf("%-40s --> ", constraint_system.variable_annotations[i].c_str()); - values[i].as_bigint().print_hex(); - } -#endif -} - -template -size_t protoboard::num_constraints() const -{ - return constraint_system.num_constraints(); -} - -template -size_t protoboard::num_inputs() const -{ - return constraint_system.num_inputs(); -} - -template -size_t protoboard::num_variables() const -{ - return next_free_var - 1; -} - -template -void protoboard::set_input_sizes(const size_t primary_input_size) -{ - assert(primary_input_size <= num_variables()); - constraint_system.primary_input_size = primary_input_size; - constraint_system.auxiliary_input_size = num_variables() - primary_input_size; -} - -template -r1cs_variable_assignment protoboard::full_variable_assignment() const -{ - return values; -} - -template -r1cs_primary_input protoboard::primary_input() const -{ - return r1cs_primary_input(values.begin(), values.begin() + num_inputs()); -} - -template -r1cs_auxiliary_input protoboard::auxiliary_input() const -{ - return r1cs_primary_input(values.begin() + num_inputs(), values.end()); -} - -template -r1cs_constraint_system protoboard::get_constraint_system() const -{ - return constraint_system; -} - -} // libsnark -#endif // PROTOBOARD_TCC_ diff --git a/src/snark/libsnark/gtests.cpp b/src/snark/libsnark/gtests.cpp deleted file mode 100644 index 74c66bdada6..00000000000 --- a/src/snark/libsnark/gtests.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include - -#include "common/profiling.hpp" - -int main(int argc, char **argv) { - libsnark::inhibit_profiling_info = true; - libsnark::inhibit_profiling_counters = true; - - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} - diff --git a/src/snark/libsnark/reductions/r1cs_to_qap/r1cs_to_qap.hpp b/src/snark/libsnark/reductions/r1cs_to_qap/r1cs_to_qap.hpp deleted file mode 100644 index 86831cb1dab..00000000000 --- a/src/snark/libsnark/reductions/r1cs_to_qap/r1cs_to_qap.hpp +++ /dev/null @@ -1,70 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for a R1CS-to-QAP reduction, that is, constructing - a QAP ("Quadratic Arithmetic Program") from a R1CS ("Rank-1 Constraint System"). - - QAPs are defined in \[GGPR13], and constructed for R1CS also in \[GGPR13]. - - The implementation of the reduction follows, extends, and optimizes - the efficient approach described in Appendix E of \[BCGTV13]. - - References: - - \[BCGTV13] - "SNARKs for C: Verifying Program Executions Succinctly and in Zero Knowledge", - Eli Ben-Sasson, Alessandro Chiesa, Daniel Genkin, Eran Tromer, Madars Virza, - CRYPTO 2013, - - - \[GGPR13]: - "Quadratic span programs and succinct NIZKs without PCPs", - Rosario Gennaro, Craig Gentry, Bryan Parno, Mariana Raykova, - EUROCRYPT 2013, - - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef R1CS_TO_QAP_HPP_ -#define R1CS_TO_QAP_HPP_ - -#include "relations/arithmetic_programs/qap/qap.hpp" -#include "relations/constraint_satisfaction_problems/r1cs/r1cs.hpp" - -namespace libsnark { - -/** - * Instance map for the R1CS-to-QAP reduction. - */ -template -qap_instance r1cs_to_qap_instance_map(const r1cs_constraint_system &cs); - -/** - * Instance map for the R1CS-to-QAP reduction followed by evaluation of the resulting QAP instance. - */ -template -qap_instance_evaluation r1cs_to_qap_instance_map_with_evaluation(const r1cs_constraint_system &cs, - const FieldT &t); - -/** - * Witness map for the R1CS-to-QAP reduction. - * - * The witness map takes zero knowledge into account when d1,d2,d3 are random. - */ -template -qap_witness r1cs_to_qap_witness_map(const r1cs_constraint_system &cs, - const r1cs_primary_input &primary_input, - const r1cs_auxiliary_input &auxiliary_input, - const FieldT &d1, - const FieldT &d2, - const FieldT &d3); - -} // libsnark - -#include "reductions/r1cs_to_qap/r1cs_to_qap.tcc" - -#endif // R1CS_TO_QAP_HPP_ diff --git a/src/snark/libsnark/reductions/r1cs_to_qap/r1cs_to_qap.tcc b/src/snark/libsnark/reductions/r1cs_to_qap/r1cs_to_qap.tcc deleted file mode 100644 index 3d0bee27337..00000000000 --- a/src/snark/libsnark/reductions/r1cs_to_qap/r1cs_to_qap.tcc +++ /dev/null @@ -1,338 +0,0 @@ -/** @file - ***************************************************************************** - - Implementation of interfaces for a R1CS-to-QAP reduction. - - See r1cs_to_qap.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef R1CS_TO_QAP_TCC_ -#define R1CS_TO_QAP_TCC_ - -#include "common/profiling.hpp" -#include "common/utils.hpp" -#include "algebra/evaluation_domain/evaluation_domain.hpp" - -namespace libsnark { - -/** - * Instance map for the R1CS-to-QAP reduction. - * - * Namely, given a R1CS constraint system cs, construct a QAP instance for which: - * A := (A_0(z),A_1(z),...,A_m(z)) - * B := (B_0(z),B_1(z),...,B_m(z)) - * C := (C_0(z),C_1(z),...,C_m(z)) - * where - * m = number of variables of the QAP - * and - * each A_i,B_i,C_i is expressed in the Lagrange basis. - */ -template -qap_instance r1cs_to_qap_instance_map(const r1cs_constraint_system &cs) -{ - enter_block("Call to r1cs_to_qap_instance_map"); - - const std::shared_ptr > domain = get_evaluation_domain(cs.num_constraints() + cs.num_inputs() + 1); - - std::vector > A_in_Lagrange_basis(cs.num_variables()+1); - std::vector > B_in_Lagrange_basis(cs.num_variables()+1); - std::vector > C_in_Lagrange_basis(cs.num_variables()+1); - - enter_block("Compute polynomials A, B, C in Lagrange basis"); - /** - * add and process the constraints - * input_i * 0 = 0 - * to ensure soundness of input consistency - */ - for (size_t i = 0; i <= cs.num_inputs(); ++i) - { - A_in_Lagrange_basis[i][cs.num_constraints() + i] = FieldT::one(); - } - /* process all other constraints */ - for (size_t i = 0; i < cs.num_constraints(); ++i) - { - for (size_t j = 0; j < cs.constraints[i].a.terms.size(); ++j) - { - A_in_Lagrange_basis[cs.constraints[i].a.terms[j].index][i] += - cs.constraints[i].a.terms[j].coeff; - } - - for (size_t j = 0; j < cs.constraints[i].b.terms.size(); ++j) - { - B_in_Lagrange_basis[cs.constraints[i].b.terms[j].index][i] += - cs.constraints[i].b.terms[j].coeff; - } - - for (size_t j = 0; j < cs.constraints[i].c.terms.size(); ++j) - { - C_in_Lagrange_basis[cs.constraints[i].c.terms[j].index][i] += - cs.constraints[i].c.terms[j].coeff; - } - } - leave_block("Compute polynomials A, B, C in Lagrange basis"); - - leave_block("Call to r1cs_to_qap_instance_map"); - - return qap_instance(domain, - cs.num_variables(), - domain->m, - cs.num_inputs(), - std::move(A_in_Lagrange_basis), - std::move(B_in_Lagrange_basis), - std::move(C_in_Lagrange_basis)); -} - -/** - * Instance map for the R1CS-to-QAP reduction followed by evaluation of the resulting QAP instance. - * - * Namely, given a R1CS constraint system cs and a field element t, construct - * a QAP instance (evaluated at t) for which: - * At := (A_0(t),A_1(t),...,A_m(t)) - * Bt := (B_0(t),B_1(t),...,B_m(t)) - * Ct := (C_0(t),C_1(t),...,C_m(t)) - * Ht := (1,t,t^2,...,t^n) - * Zt := Z(t) = "vanishing polynomial of a certain set S, evaluated at t" - * where - * m = number of variables of the QAP - * n = degree of the QAP - */ -template -qap_instance_evaluation r1cs_to_qap_instance_map_with_evaluation(const r1cs_constraint_system &cs, - const FieldT &t) -{ - enter_block("Call to r1cs_to_qap_instance_map_with_evaluation"); - - const std::shared_ptr > domain = get_evaluation_domain(cs.num_constraints() + cs.num_inputs() + 1); - - std::vector At, Bt, Ct, Ht; - - At.resize(cs.num_variables()+1, FieldT::zero()); - Bt.resize(cs.num_variables()+1, FieldT::zero()); - Ct.resize(cs.num_variables()+1, FieldT::zero()); - Ht.reserve(domain->m+1); - - const FieldT Zt = domain->compute_Z(t); - - enter_block("Compute evaluations of A, B, C, H at t"); - const std::vector u = domain->lagrange_coeffs(t); - /** - * add and process the constraints - * input_i * 0 = 0 - * to ensure soundness of input consistency - */ - for (size_t i = 0; i <= cs.num_inputs(); ++i) - { - At[i] = u[cs.num_constraints() + i]; - } - /* process all other constraints */ - for (size_t i = 0; i < cs.num_constraints(); ++i) - { - for (size_t j = 0; j < cs.constraints[i].a.terms.size(); ++j) - { - At[cs.constraints[i].a.terms[j].index] += - u[i]*cs.constraints[i].a.terms[j].coeff; - } - - for (size_t j = 0; j < cs.constraints[i].b.terms.size(); ++j) - { - Bt[cs.constraints[i].b.terms[j].index] += - u[i]*cs.constraints[i].b.terms[j].coeff; - } - - for (size_t j = 0; j < cs.constraints[i].c.terms.size(); ++j) - { - Ct[cs.constraints[i].c.terms[j].index] += - u[i]*cs.constraints[i].c.terms[j].coeff; - } - } - - FieldT ti = FieldT::one(); - for (size_t i = 0; i < domain->m+1; ++i) - { - Ht.emplace_back(ti); - ti *= t; - } - leave_block("Compute evaluations of A, B, C, H at t"); - - leave_block("Call to r1cs_to_qap_instance_map_with_evaluation"); - - return qap_instance_evaluation(domain, - cs.num_variables(), - domain->m, - cs.num_inputs(), - t, - std::move(At), - std::move(Bt), - std::move(Ct), - std::move(Ht), - Zt); -} - -/** - * Witness map for the R1CS-to-QAP reduction. - * - * The witness map takes zero knowledge into account when d1,d2,d3 are random. - * - * More precisely, compute the coefficients - * h_0,h_1,...,h_n - * of the polynomial - * H(z) := (A(z)*B(z)-C(z))/Z(z) - * where - * A(z) := A_0(z) + \sum_{k=1}^{m} w_k A_k(z) + d1 * Z(z) - * B(z) := B_0(z) + \sum_{k=1}^{m} w_k B_k(z) + d2 * Z(z) - * C(z) := C_0(z) + \sum_{k=1}^{m} w_k C_k(z) + d3 * Z(z) - * Z(z) := "vanishing polynomial of set S" - * and - * m = number of variables of the QAP - * n = degree of the QAP - * - * This is done as follows: - * (1) compute evaluations of A,B,C on S = {sigma_1,...,sigma_n} - * (2) compute coefficients of A,B,C - * (3) compute evaluations of A,B,C on T = "coset of S" - * (4) compute evaluation of H on T - * (5) compute coefficients of H - * (6) patch H to account for d1,d2,d3 (i.e., add coefficients of the polynomial (A d2 + B d1 - d3) + d1*d2*Z ) - * - * The code below is not as simple as the above high-level description due to - * some reshuffling to save space. - */ -template -qap_witness r1cs_to_qap_witness_map(const r1cs_constraint_system &cs, - const r1cs_primary_input &primary_input, - const r1cs_auxiliary_input &auxiliary_input, - const FieldT &d1, - const FieldT &d2, - const FieldT &d3) -{ - enter_block("Call to r1cs_to_qap_witness_map"); - - /* sanity check */ - assert(cs.is_satisfied(primary_input, auxiliary_input)); - - const std::shared_ptr > domain = get_evaluation_domain(cs.num_constraints() + cs.num_inputs() + 1); - - r1cs_variable_assignment full_variable_assignment = primary_input; - full_variable_assignment.insert(full_variable_assignment.end(), auxiliary_input.begin(), auxiliary_input.end()); - - enter_block("Compute evaluation of polynomials A, B on set S"); - std::vector aA(domain->m, FieldT::zero()), aB(domain->m, FieldT::zero()); - - /* account for the additional constraints input_i * 0 = 0 */ - for (size_t i = 0; i <= cs.num_inputs(); ++i) - { - aA[i+cs.num_constraints()] = (i > 0 ? full_variable_assignment[i-1] : FieldT::one()); - } - /* account for all other constraints */ - for (size_t i = 0; i < cs.num_constraints(); ++i) - { - aA[i] += cs.constraints[i].a.evaluate(full_variable_assignment); - aB[i] += cs.constraints[i].b.evaluate(full_variable_assignment); - } - leave_block("Compute evaluation of polynomials A, B on set S"); - - enter_block("Compute coefficients of polynomial A"); - domain->iFFT(aA); - leave_block("Compute coefficients of polynomial A"); - - enter_block("Compute coefficients of polynomial B"); - domain->iFFT(aB); - leave_block("Compute coefficients of polynomial B"); - - enter_block("Compute ZK-patch"); - std::vector coefficients_for_H(domain->m+1, FieldT::zero()); -#ifdef MULTICORE -#pragma omp parallel for -#endif - /* add coefficients of the polynomial (d2*A + d1*B - d3) + d1*d2*Z */ - for (size_t i = 0; i < domain->m; ++i) - { - coefficients_for_H[i] = d2*aA[i] + d1*aB[i]; - } - coefficients_for_H[0] -= d3; - domain->add_poly_Z(d1*d2, coefficients_for_H); - leave_block("Compute ZK-patch"); - - enter_block("Compute evaluation of polynomial A on set T"); - domain->cosetFFT(aA, FieldT::multiplicative_generator); - leave_block("Compute evaluation of polynomial A on set T"); - - enter_block("Compute evaluation of polynomial B on set T"); - domain->cosetFFT(aB, FieldT::multiplicative_generator); - leave_block("Compute evaluation of polynomial B on set T"); - - enter_block("Compute evaluation of polynomial H on set T"); - std::vector &H_tmp = aA; // can overwrite aA because it is not used later -#ifdef MULTICORE -#pragma omp parallel for -#endif - for (size_t i = 0; i < domain->m; ++i) - { - H_tmp[i] = aA[i]*aB[i]; - } - std::vector().swap(aB); // destroy aB - - enter_block("Compute evaluation of polynomial C on set S"); - std::vector aC(domain->m, FieldT::zero()); - for (size_t i = 0; i < cs.num_constraints(); ++i) - { - aC[i] += cs.constraints[i].c.evaluate(full_variable_assignment); - } - leave_block("Compute evaluation of polynomial C on set S"); - - enter_block("Compute coefficients of polynomial C"); - domain->iFFT(aC); - leave_block("Compute coefficients of polynomial C"); - - enter_block("Compute evaluation of polynomial C on set T"); - domain->cosetFFT(aC, FieldT::multiplicative_generator); - leave_block("Compute evaluation of polynomial C on set T"); - -#ifdef MULTICORE -#pragma omp parallel for -#endif - for (size_t i = 0; i < domain->m; ++i) - { - H_tmp[i] = (H_tmp[i]-aC[i]); - } - - enter_block("Divide by Z on set T"); - domain->divide_by_Z_on_coset(H_tmp); - leave_block("Divide by Z on set T"); - - leave_block("Compute evaluation of polynomial H on set T"); - - enter_block("Compute coefficients of polynomial H"); - domain->icosetFFT(H_tmp, FieldT::multiplicative_generator); - leave_block("Compute coefficients of polynomial H"); - - enter_block("Compute sum of H and ZK-patch"); -#ifdef MULTICORE -#pragma omp parallel for -#endif - for (size_t i = 0; i < domain->m; ++i) - { - coefficients_for_H[i] += H_tmp[i]; - } - leave_block("Compute sum of H and ZK-patch"); - - leave_block("Call to r1cs_to_qap_witness_map"); - - return qap_witness(cs.num_variables(), - domain->m, - cs.num_inputs(), - d1, - d2, - d3, - full_variable_assignment, - std::move(coefficients_for_H)); -} - -} // libsnark - -#endif // R1CS_TO_QAP_TCC_ diff --git a/src/snark/libsnark/relations/arithmetic_programs/qap/qap.hpp b/src/snark/libsnark/relations/arithmetic_programs/qap/qap.hpp deleted file mode 100644 index 4991d203b36..00000000000 --- a/src/snark/libsnark/relations/arithmetic_programs/qap/qap.hpp +++ /dev/null @@ -1,193 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for a QAP ("Quadratic Arithmetic Program"). - - QAPs are defined in \[GGPR13]. - - References: - - \[GGPR13]: - "Quadratic span programs and succinct NIZKs without PCPs", - Rosario Gennaro, Craig Gentry, Bryan Parno, Mariana Raykova, - EUROCRYPT 2013, - - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef QAP_HPP_ -#define QAP_HPP_ - -#include "algebra/evaluation_domain/evaluation_domain.hpp" - -namespace libsnark { - -/* forward declaration */ -template -class qap_witness; - -/** - * A QAP instance. - * - * Specifically, the datastructure stores: - * - a choice of domain (corresponding to a certain subset of the field); - * - the number of variables, the degree, and the number of inputs; and - * - coefficients of the A,B,C polynomials in the Lagrange basis. - * - * There is no need to store the Z polynomial because it is uniquely - * determined by the domain (as Z is its vanishing polynomial). - */ -template -class qap_instance { -private: - size_t num_variables_; - size_t degree_; - size_t num_inputs_; - -public: - std::shared_ptr > domain; - - std::vector > A_in_Lagrange_basis; - std::vector > B_in_Lagrange_basis; - std::vector > C_in_Lagrange_basis; - - qap_instance(const std::shared_ptr > &domain, - const size_t num_variables, - const size_t degree, - const size_t num_inputs, - const std::vector > &A_in_Lagrange_basis, - const std::vector > &B_in_Lagrange_basis, - const std::vector > &C_in_Lagrange_basis); - - qap_instance(const std::shared_ptr > &domain, - const size_t num_variables, - const size_t degree, - const size_t num_inputs, - std::vector > &&A_in_Lagrange_basis, - std::vector > &&B_in_Lagrange_basis, - std::vector > &&C_in_Lagrange_basis); - - qap_instance(const qap_instance &other) = default; - qap_instance(qap_instance &&other) = default; - qap_instance& operator=(const qap_instance &other) = default; - qap_instance& operator=(qap_instance &&other) = default; - - size_t num_variables() const; - size_t degree() const; - size_t num_inputs() const; - - bool is_satisfied(const qap_witness &witness) const; -}; - -/** - * A QAP instance evaluation is a QAP instance that is evaluated at a field element t. - * - * Specifically, the datastructure stores: - * - a choice of domain (corresponding to a certain subset of the field); - * - the number of variables, the degree, and the number of inputs; - * - a field element t; - * - evaluations of the A,B,C (and Z) polynomials at t; - * - evaluations of all monomials of t; - * - counts about how many of the above evaluations are in fact non-zero. - */ -template -class qap_instance_evaluation { -private: - size_t num_variables_; - size_t degree_; - size_t num_inputs_; -public: - std::shared_ptr > domain; - - FieldT t; - - std::vector At, Bt, Ct, Ht; - - FieldT Zt; - - qap_instance_evaluation(const std::shared_ptr > &domain, - const size_t num_variables, - const size_t degree, - const size_t num_inputs, - const FieldT &t, - const std::vector &At, - const std::vector &Bt, - const std::vector &Ct, - const std::vector &Ht, - const FieldT &Zt); - qap_instance_evaluation(const std::shared_ptr > &domain, - const size_t num_variables, - const size_t degree, - const size_t num_inputs, - const FieldT &t, - std::vector &&At, - std::vector &&Bt, - std::vector &&Ct, - std::vector &&Ht, - const FieldT &Zt); - - qap_instance_evaluation(const qap_instance_evaluation &other) = default; - qap_instance_evaluation(qap_instance_evaluation &&other) = default; - qap_instance_evaluation& operator=(const qap_instance_evaluation &other) = default; - qap_instance_evaluation& operator=(qap_instance_evaluation &&other) = default; - - size_t num_variables() const; - size_t degree() const; - size_t num_inputs() const; - - bool is_satisfied(const qap_witness &witness) const; -}; - -/** - * A QAP witness. - */ -template -class qap_witness { -private: - size_t num_variables_; - size_t degree_; - size_t num_inputs_; - -public: - FieldT d1, d2, d3; - - std::vector coefficients_for_ABCs; - std::vector coefficients_for_H; - - qap_witness(const size_t num_variables, - const size_t degree, - const size_t num_inputs, - const FieldT &d1, - const FieldT &d2, - const FieldT &d3, - const std::vector &coefficients_for_ABCs, - const std::vector &coefficients_for_H); - - qap_witness(const size_t num_variables, - const size_t degree, - const size_t num_inputs, - const FieldT &d1, - const FieldT &d2, - const FieldT &d3, - const std::vector &coefficients_for_ABCs, - std::vector &&coefficients_for_H); - - qap_witness(const qap_witness &other) = default; - qap_witness(qap_witness &&other) = default; - qap_witness& operator=(const qap_witness &other) = default; - qap_witness& operator=(qap_witness &&other) = default; - - size_t num_variables() const; - size_t degree() const; - size_t num_inputs() const; -}; - -} // libsnark - -#include "relations/arithmetic_programs/qap/qap.tcc" - -#endif // QAP_HPP_ diff --git a/src/snark/libsnark/relations/arithmetic_programs/qap/qap.tcc b/src/snark/libsnark/relations/arithmetic_programs/qap/qap.tcc deleted file mode 100644 index a4a3c96a25d..00000000000 --- a/src/snark/libsnark/relations/arithmetic_programs/qap/qap.tcc +++ /dev/null @@ -1,324 +0,0 @@ -/** @file -***************************************************************************** - -Implementation of interfaces for a QAP ("Quadratic Arithmetic Program"). - -See qap.hpp . - -***************************************************************************** -* @author This file is part of libsnark, developed by SCIPR Lab -* and contributors (see AUTHORS). -* @copyright MIT license (see LICENSE file) -*****************************************************************************/ - -#ifndef QAP_TCC_ -#define QAP_TCC_ - -#include "common/profiling.hpp" -#include "common/utils.hpp" -#include "algebra/evaluation_domain/evaluation_domain.hpp" -#include "algebra/scalar_multiplication/multiexp.hpp" - -namespace libsnark { - -template -qap_instance::qap_instance(const std::shared_ptr > &domain, - const size_t num_variables, - const size_t degree, - const size_t num_inputs, - const std::vector > &A_in_Lagrange_basis, - const std::vector > &B_in_Lagrange_basis, - const std::vector > &C_in_Lagrange_basis) : - num_variables_(num_variables), - degree_(degree), - num_inputs_(num_inputs), - domain(domain), - A_in_Lagrange_basis(A_in_Lagrange_basis), - B_in_Lagrange_basis(B_in_Lagrange_basis), - C_in_Lagrange_basis(C_in_Lagrange_basis) -{ -} - -template -qap_instance::qap_instance(const std::shared_ptr > &domain, - const size_t num_variables, - const size_t degree, - const size_t num_inputs, - std::vector > &&A_in_Lagrange_basis, - std::vector > &&B_in_Lagrange_basis, - std::vector > &&C_in_Lagrange_basis) : - num_variables_(num_variables), - degree_(degree), - num_inputs_(num_inputs), - domain(domain), - A_in_Lagrange_basis(std::move(A_in_Lagrange_basis)), - B_in_Lagrange_basis(std::move(B_in_Lagrange_basis)), - C_in_Lagrange_basis(std::move(C_in_Lagrange_basis)) -{ -} - -template -size_t qap_instance::num_variables() const -{ - return num_variables_; -} - -template -size_t qap_instance::degree() const -{ - return degree_; -} - -template -size_t qap_instance::num_inputs() const -{ - return num_inputs_; -} - -template -bool qap_instance::is_satisfied(const qap_witness &witness) const -{ - const FieldT t = FieldT::random_element(); - - std::vector At(this->num_variables()+1, FieldT::zero()); - std::vector Bt(this->num_variables()+1, FieldT::zero()); - std::vector Ct(this->num_variables()+1, FieldT::zero()); - std::vector Ht(this->degree()+1); - - const FieldT Zt = this->domain->compute_Z(t); - - const std::vector u = this->domain->lagrange_coeffs(t); - - for (size_t i = 0; i < this->num_variables()+1; ++i) - { - for (auto &el : A_in_Lagrange_basis[i]) - { - At[i] += u[el.first] * el.second; - } - - for (auto &el : B_in_Lagrange_basis[i]) - { - Bt[i] += u[el.first] * el.second; - } - - for (auto &el : C_in_Lagrange_basis[i]) - { - Ct[i] += u[el.first] * el.second; - } - } - - FieldT ti = FieldT::one(); - for (size_t i = 0; i < this->degree()+1; ++i) - { - Ht[i] = ti; - ti *= t; - } - - const qap_instance_evaluation eval_qap_inst(this->domain, - this->num_variables(), - this->degree(), - this->num_inputs(), - t, - std::move(At), - std::move(Bt), - std::move(Ct), - std::move(Ht), - Zt); - return eval_qap_inst.is_satisfied(witness); -} - -template -qap_instance_evaluation::qap_instance_evaluation(const std::shared_ptr > &domain, - const size_t num_variables, - const size_t degree, - const size_t num_inputs, - const FieldT &t, - const std::vector &At, - const std::vector &Bt, - const std::vector &Ct, - const std::vector &Ht, - const FieldT &Zt) : - num_variables_(num_variables), - degree_(degree), - num_inputs_(num_inputs), - domain(domain), - t(t), - At(At), - Bt(Bt), - Ct(Ct), - Ht(Ht), - Zt(Zt) -{ -} - -template -qap_instance_evaluation::qap_instance_evaluation(const std::shared_ptr > &domain, - const size_t num_variables, - const size_t degree, - const size_t num_inputs, - const FieldT &t, - std::vector &&At, - std::vector &&Bt, - std::vector &&Ct, - std::vector &&Ht, - const FieldT &Zt) : - num_variables_(num_variables), - degree_(degree), - num_inputs_(num_inputs), - domain(domain), - t(t), - At(std::move(At)), - Bt(std::move(Bt)), - Ct(std::move(Ct)), - Ht(std::move(Ht)), - Zt(Zt) -{ -} - -template -size_t qap_instance_evaluation::num_variables() const -{ - return num_variables_; -} - -template -size_t qap_instance_evaluation::degree() const -{ - return degree_; -} - -template -size_t qap_instance_evaluation::num_inputs() const -{ - return num_inputs_; -} - -template -bool qap_instance_evaluation::is_satisfied(const qap_witness &witness) const -{ - - if (this->num_variables() != witness.num_variables()) - { - return false; - } - - if (this->degree() != witness.degree()) - { - return false; - } - - if (this->num_inputs() != witness.num_inputs()) - { - return false; - } - - if (this->num_variables() != witness.coefficients_for_ABCs.size()) - { - return false; - } - - if (this->degree()+1 != witness.coefficients_for_H.size()) - { - return false; - } - - if (this->At.size() != this->num_variables()+1 || this->Bt.size() != this->num_variables()+1 || this->Ct.size() != this->num_variables()+1) - { - return false; - } - - if (this->Ht.size() != this->degree()+1) - { - return false; - } - - if (this->Zt != this->domain->compute_Z(this->t)) - { - return false; - } - - FieldT ans_A = this->At[0] + witness.d1*this->Zt; - FieldT ans_B = this->Bt[0] + witness.d2*this->Zt; - FieldT ans_C = this->Ct[0] + witness.d3*this->Zt; - FieldT ans_H = FieldT::zero(); - - ans_A = ans_A + naive_plain_exp(this->At.begin()+1, this->At.begin()+1+this->num_variables(), - witness.coefficients_for_ABCs.begin(), witness.coefficients_for_ABCs.begin()+this->num_variables()); - ans_B = ans_B + naive_plain_exp(this->Bt.begin()+1, this->Bt.begin()+1+this->num_variables(), - witness.coefficients_for_ABCs.begin(), witness.coefficients_for_ABCs.begin()+this->num_variables()); - ans_C = ans_C + naive_plain_exp(this->Ct.begin()+1, this->Ct.begin()+1+this->num_variables(), - witness.coefficients_for_ABCs.begin(), witness.coefficients_for_ABCs.begin()+this->num_variables()); - ans_H = ans_H + naive_plain_exp(this->Ht.begin(), this->Ht.begin()+this->degree()+1, - witness.coefficients_for_H.begin(), witness.coefficients_for_H.begin()+this->degree()+1); - - if (ans_A * ans_B - ans_C != ans_H * this->Zt) - { - return false; - } - - return true; -} - -template -qap_witness::qap_witness(const size_t num_variables, - const size_t degree, - const size_t num_inputs, - const FieldT &d1, - const FieldT &d2, - const FieldT &d3, - const std::vector &coefficients_for_ABCs, - const std::vector &coefficients_for_H) : - num_variables_(num_variables), - degree_(degree), - num_inputs_(num_inputs), - d1(d1), - d2(d2), - d3(d3), - coefficients_for_ABCs(coefficients_for_ABCs), - coefficients_for_H(coefficients_for_H) -{ -} - -template -qap_witness::qap_witness(const size_t num_variables, - const size_t degree, - const size_t num_inputs, - const FieldT &d1, - const FieldT &d2, - const FieldT &d3, - const std::vector &coefficients_for_ABCs, - std::vector &&coefficients_for_H) : - num_variables_(num_variables), - degree_(degree), - num_inputs_(num_inputs), - d1(d1), - d2(d2), - d3(d3), - coefficients_for_ABCs(coefficients_for_ABCs), - coefficients_for_H(std::move(coefficients_for_H)) -{ -} - - -template -size_t qap_witness::num_variables() const -{ - return num_variables_; -} - -template -size_t qap_witness::degree() const -{ - return degree_; -} - -template -size_t qap_witness::num_inputs() const -{ - return num_inputs_; -} - - -} // libsnark - -#endif // QAP_TCC_ diff --git a/src/snark/libsnark/relations/arithmetic_programs/qap/tests/test_qap.cpp b/src/snark/libsnark/relations/arithmetic_programs/qap/tests/test_qap.cpp deleted file mode 100644 index 3c7b8705712..00000000000 --- a/src/snark/libsnark/relations/arithmetic_programs/qap/tests/test_qap.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/** - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ -#include -#include -#include -#include -#include - -#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp" -#include "algebra/fields/field_utils.hpp" -#include "common/profiling.hpp" -#include "common/utils.hpp" -#include "reductions/r1cs_to_qap/r1cs_to_qap.hpp" -#include "relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.hpp" - -#include - -using namespace libsnark; - -template -void test_qap(const size_t qap_degree, const size_t num_inputs, const bool binary_input) -{ - /* - We construct an instance where the QAP degree is qap_degree. - So we generate an instance of R1CS where the number of constraints qap_degree - num_inputs - 1. - See the transformation from R1CS to QAP for why this is the case. - So we need that qap_degree >= num_inputs + 1. - */ - ASSERT_LE(num_inputs + 1, qap_degree); - enter_block("Call to test_qap"); - - const size_t num_constraints = qap_degree - num_inputs - 1; - - print_indent(); printf("* QAP degree: %zu\n", qap_degree); - print_indent(); printf("* Number of inputs: %zu\n", num_inputs); - print_indent(); printf("* Number of R1CS constraints: %zu\n", num_constraints); - print_indent(); printf("* Input type: %s\n", binary_input ? "binary" : "field"); - - enter_block("Generate constraint system and assignment"); - r1cs_example example; - if (binary_input) - { - example = generate_r1cs_example_with_binary_input(num_constraints, num_inputs); - } - else - { - example = generate_r1cs_example_with_field_input(num_constraints, num_inputs); - } - leave_block("Generate constraint system and assignment"); - - enter_block("Check satisfiability of constraint system"); - EXPECT_TRUE(example.constraint_system.is_satisfied(example.primary_input, example.auxiliary_input)); - leave_block("Check satisfiability of constraint system"); - - const FieldT t = FieldT::random_element(), - d1 = FieldT::random_element(), - d2 = FieldT::random_element(), - d3 = FieldT::random_element(); - - enter_block("Compute QAP instance 1"); - qap_instance qap_inst_1 = r1cs_to_qap_instance_map(example.constraint_system); - leave_block("Compute QAP instance 1"); - - enter_block("Compute QAP instance 2"); - qap_instance_evaluation qap_inst_2 = r1cs_to_qap_instance_map_with_evaluation(example.constraint_system, t); - leave_block("Compute QAP instance 2"); - - enter_block("Compute QAP witness"); - qap_witness qap_wit = r1cs_to_qap_witness_map(example.constraint_system, example.primary_input, example.auxiliary_input, d1, d2, d3); - leave_block("Compute QAP witness"); - - enter_block("Check satisfiability of QAP instance 1"); - EXPECT_TRUE(qap_inst_1.is_satisfied(qap_wit)); - leave_block("Check satisfiability of QAP instance 1"); - - enter_block("Check satisfiability of QAP instance 2"); - EXPECT_TRUE(qap_inst_2.is_satisfied(qap_wit)); - leave_block("Check satisfiability of QAP instance 2"); - - leave_block("Call to test_qap"); -} - -TEST(relations, qap) -{ - start_profiling(); - - const size_t num_inputs = 10; - - enter_block("Test QAP with binary input"); - - test_qap >(UINT64_C(1) << 21, num_inputs, true); - - leave_block("Test QAP with binary input"); - - enter_block("Test QAP with field input"); - - test_qap >(UINT64_C(1) << 21, num_inputs, false); - - leave_block("Test QAP with field input"); -} diff --git a/src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.hpp b/src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.hpp deleted file mode 100644 index 47003e95938..00000000000 --- a/src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.hpp +++ /dev/null @@ -1,73 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for a R1CS example, as well as functions to sample - R1CS examples with prescribed parameters (according to some distribution). - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef R1CS_EXAMPLES_HPP_ -#define R1CS_EXAMPLES_HPP_ - -#include "relations/constraint_satisfaction_problems/r1cs/r1cs.hpp" - -namespace libsnark { - -/** - * A R1CS example comprises a R1CS constraint system, R1CS input, and R1CS witness. - */ -template -struct r1cs_example { - r1cs_constraint_system constraint_system; - r1cs_primary_input primary_input; - r1cs_auxiliary_input auxiliary_input; - - r1cs_example() = default; - r1cs_example(const r1cs_example &other) = default; - r1cs_example(const r1cs_constraint_system &constraint_system, - const r1cs_primary_input &primary_input, - const r1cs_auxiliary_input &auxiliary_input) : - constraint_system(constraint_system), - primary_input(primary_input), - auxiliary_input(auxiliary_input) - {}; - r1cs_example(r1cs_constraint_system &&constraint_system, - r1cs_primary_input &&primary_input, - r1cs_auxiliary_input &&auxiliary_input) : - constraint_system(std::move(constraint_system)), - primary_input(std::move(primary_input)), - auxiliary_input(std::move(auxiliary_input)) - {}; -}; - -/** - * Generate a R1CS example such that: - * - the number of constraints of the R1CS constraint system is num_constraints; - * - the number of variables of the R1CS constraint system is (approximately) num_constraints; - * - the number of inputs of the R1CS constraint system is num_inputs; - * - the R1CS input consists of ``full'' field elements (typically require the whole log|Field| bits to represent). - */ -template -r1cs_example generate_r1cs_example_with_field_input(const size_t num_constraints, - const size_t num_inputs); - -/** - * Generate a R1CS example such that: - * - the number of constraints of the R1CS constraint system is num_constraints; - * - the number of variables of the R1CS constraint system is (approximately) num_constraints; - * - the number of inputs of the R1CS constraint system is num_inputs; - * - the R1CS input consists of binary values (as opposed to ``full'' field elements). - */ -template -r1cs_example generate_r1cs_example_with_binary_input(const size_t num_constraints, - const size_t num_inputs); - -} // libsnark - -#include "relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.tcc" - -#endif // R1CS_EXAMPLES_HPP_ diff --git a/src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.tcc b/src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.tcc deleted file mode 100644 index defa0772173..00000000000 --- a/src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.tcc +++ /dev/null @@ -1,164 +0,0 @@ -/** @file - ***************************************************************************** - - Implementation of functions to sample R1CS examples with prescribed parameters - (according to some distribution). - - See r1cs_examples.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef R1CS_EXAMPLES_TCC_ -#define R1CS_EXAMPLES_TCC_ - -#include - -#include "common/utils.hpp" - -namespace libsnark { - -template -r1cs_example generate_r1cs_example_with_field_input(const size_t num_constraints, - const size_t num_inputs) -{ - enter_block("Call to generate_r1cs_example_with_field_input"); - - assert(num_inputs <= num_constraints + 2); - - r1cs_constraint_system cs; - cs.primary_input_size = num_inputs; - cs.auxiliary_input_size = 2 + num_constraints - num_inputs; // TODO: explain this - - r1cs_variable_assignment full_variable_assignment; - FieldT a = FieldT::random_element(); - FieldT b = FieldT::random_element(); - full_variable_assignment.push_back(a); - full_variable_assignment.push_back(b); - - for (size_t i = 0; i < num_constraints-1; ++i) - { - linear_combination A, B, C; - - if (i % 2) - { - // a * b = c - A.add_term(i+1, 1); - B.add_term(i+2, 1); - C.add_term(i+3, 1); - FieldT tmp = a*b; - full_variable_assignment.push_back(tmp); - a = b; b = tmp; - } - else - { - // a + b = c - B.add_term(0, 1); - A.add_term(i+1, 1); - A.add_term(i+2, 1); - C.add_term(i+3, 1); - FieldT tmp = a+b; - full_variable_assignment.push_back(tmp); - a = b; b = tmp; - } - - cs.add_constraint(r1cs_constraint(A, B, C)); - } - - linear_combination A, B, C; - FieldT fin = FieldT::zero(); - for (size_t i = 1; i < cs.num_variables(); ++i) - { - A.add_term(i, 1); - B.add_term(i, 1); - fin = fin + full_variable_assignment[i-1]; - } - C.add_term(cs.num_variables(), 1); - cs.add_constraint(r1cs_constraint(A, B, C)); - full_variable_assignment.push_back(fin.squared()); - - /* split variable assignment */ - r1cs_primary_input primary_input(full_variable_assignment.begin(), full_variable_assignment.begin() + num_inputs); - r1cs_primary_input auxiliary_input(full_variable_assignment.begin() + num_inputs, full_variable_assignment.end()); - - /* sanity checks */ - assert(cs.num_variables() == full_variable_assignment.size()); - assert(cs.num_variables() >= num_inputs); - assert(cs.num_inputs() == num_inputs); - assert(cs.num_constraints() == num_constraints); - assert(cs.is_satisfied(primary_input, auxiliary_input)); - - leave_block("Call to generate_r1cs_example_with_field_input"); - - return r1cs_example(std::move(cs), std::move(primary_input), std::move(auxiliary_input)); -} - -template -r1cs_example generate_r1cs_example_with_binary_input(const size_t num_constraints, - const size_t num_inputs) -{ - enter_block("Call to generate_r1cs_example_with_binary_input"); - - assert(num_inputs >= 1); - - r1cs_constraint_system cs; - cs.primary_input_size = num_inputs; - cs.auxiliary_input_size = num_constraints; /* we will add one auxiliary variable per constraint */ - - r1cs_variable_assignment full_variable_assignment; - for (size_t i = 0; i < num_inputs; ++i) - { - full_variable_assignment.push_back(FieldT(std::rand() % 2)); - } - - size_t lastvar = num_inputs-1; - for (size_t i = 0; i < num_constraints; ++i) - { - ++lastvar; - const size_t u = (i == 0 ? std::rand() % num_inputs : std::rand() % i); - const size_t v = (i == 0 ? std::rand() % num_inputs : std::rand() % i); - - /* chose two random bits and XOR them together: - res = u + v - 2 * u * v - 2 * u * v = u + v - res - */ - linear_combination A, B, C; - A.add_term(u+1, 2); - B.add_term(v+1, 1); - if (u == v) - { - C.add_term(u+1, 2); - } - else - { - C.add_term(u+1, 1); - C.add_term(v+1, 1); - } - C.add_term(lastvar+1, -FieldT::one()); - - cs.add_constraint(r1cs_constraint(A, B, C)); - full_variable_assignment.push_back(full_variable_assignment[u] + full_variable_assignment[v] - full_variable_assignment[u] * full_variable_assignment[v] - full_variable_assignment[u] * full_variable_assignment[v]); - } - - /* split variable assignment */ - r1cs_primary_input primary_input(full_variable_assignment.begin(), full_variable_assignment.begin() + num_inputs); - r1cs_primary_input auxiliary_input(full_variable_assignment.begin() + num_inputs, full_variable_assignment.end()); - - /* sanity checks */ - assert(cs.num_variables() == full_variable_assignment.size()); - assert(cs.num_variables() >= num_inputs); - assert(cs.num_inputs() == num_inputs); - assert(cs.num_constraints() == num_constraints); - assert(cs.is_satisfied(primary_input, auxiliary_input)); - - leave_block("Call to generate_r1cs_example_with_binary_input"); - - return r1cs_example(std::move(cs), std::move(primary_input), std::move(auxiliary_input)); -} - -} // libsnark - -#endif // R1CS_EXAMPLES_TCC diff --git a/src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/r1cs.hpp b/src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/r1cs.hpp deleted file mode 100644 index ca3acb3a9e6..00000000000 --- a/src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/r1cs.hpp +++ /dev/null @@ -1,153 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for: - - a R1CS constraint, - - a R1CS variable assignment, and - - a R1CS constraint system. - - Above, R1CS stands for "Rank-1 Constraint System". - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef R1CS_HPP_ -#define R1CS_HPP_ - -#include -#include -#include -#include -#include - -#include "relations/variable.hpp" - -namespace libsnark { - -/************************* R1CS constraint ***********************************/ - -template -class r1cs_constraint; - -template -std::ostream& operator<<(std::ostream &out, const r1cs_constraint &c); - -template -std::istream& operator>>(std::istream &in, r1cs_constraint &c); - -/** - * A R1CS constraint is a formal expression of the form - * - * < A , X > * < B , X > = < C , X > , - * - * where X = (x_0,x_1,...,x_m) is a vector of formal variables and A,B,C each - * consist of 1+m elements in . - * - * A R1CS constraint is used to construct a R1CS constraint system (see below). - */ -template -class r1cs_constraint { -public: - - linear_combination a, b, c; - - r1cs_constraint() {}; - r1cs_constraint(const linear_combination &a, - const linear_combination &b, - const linear_combination &c); - - r1cs_constraint(const std::initializer_list > &A, - const std::initializer_list > &B, - const std::initializer_list > &C); - - bool operator==(const r1cs_constraint &other) const; - - friend std::ostream& operator<< (std::ostream &out, const r1cs_constraint &c); - friend std::istream& operator>> (std::istream &in, r1cs_constraint &c); -}; - -/************************* R1CS variable assignment **************************/ - -/** - * A R1CS variable assignment is a vector of elements that represents - * a candidate solution to a R1CS constraint system (see below). - */ - -/* TODO: specify that it does *NOT* include the constant 1 */ -template -using r1cs_primary_input = std::vector; - -template -using r1cs_auxiliary_input = std::vector; - -template -using r1cs_variable_assignment = std::vector; /* note the changed name! (TODO: remove this comment after primary_input transition is complete) */ - -/************************* R1CS constraint system ****************************/ - -template -class r1cs_constraint_system; - -template -std::ostream& operator<<(std::ostream &out, const r1cs_constraint_system &cs); - -template -std::istream& operator>>(std::istream &in, r1cs_constraint_system &cs); - -/** - * A system of R1CS constraints looks like - * - * { < A_k , X > * < B_k , X > = < C_k , X > }_{k=1}^{n} . - * - * In other words, the system is satisfied if and only if there exist a - * USCS variable assignment for which each R1CS constraint is satisfied. - * - * NOTE: - * The 0-th variable (i.e., "x_{0}") always represents the constant 1. - * Thus, the 0-th variable is not included in num_variables. - */ -template -class r1cs_constraint_system { -public: - size_t primary_input_size; - size_t auxiliary_input_size; - - std::vector > constraints; - - r1cs_constraint_system() : primary_input_size(0), auxiliary_input_size(0) {} - - size_t num_inputs() const; - size_t num_variables() const; - size_t num_constraints() const; - -#ifdef DEBUG - std::map constraint_annotations; - std::map variable_annotations; -#endif - - bool is_valid() const; - bool is_satisfied(const r1cs_primary_input &primary_input, - const r1cs_auxiliary_input &auxiliary_input) const; - - void add_constraint(const r1cs_constraint &c); - void add_constraint(const r1cs_constraint &c, const std::string &annotation); - - void swap_AB_if_beneficial(); - - bool operator==(const r1cs_constraint_system &other) const; - - friend std::ostream& operator<< (std::ostream &out, const r1cs_constraint_system &cs); - friend std::istream& operator>> (std::istream &in, r1cs_constraint_system &cs); - - void report_linear_constraint_statistics() const; -}; - - -} // libsnark - -#include "relations/constraint_satisfaction_problems/r1cs/r1cs.tcc" - -#endif // R1CS_HPP_ diff --git a/src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/r1cs.tcc b/src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/r1cs.tcc deleted file mode 100644 index 0faa56a87f1..00000000000 --- a/src/snark/libsnark/relations/constraint_satisfaction_problems/r1cs/r1cs.tcc +++ /dev/null @@ -1,310 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for: - - a R1CS constraint, - - a R1CS variable assignment, and - - a R1CS constraint system. - - See r1cs.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef R1CS_TCC_ -#define R1CS_TCC_ - -#include -#include -#include -#include "common/utils.hpp" -#include "common/profiling.hpp" -#include "algebra/fields/bigint.hpp" - -namespace libsnark { - -template -r1cs_constraint::r1cs_constraint(const linear_combination &a, - const linear_combination &b, - const linear_combination &c) : - a(a), b(b), c(c) -{ -} - -template -r1cs_constraint::r1cs_constraint(const std::initializer_list > &A, - const std::initializer_list > &B, - const std::initializer_list > &C) -{ - for (auto lc_A : A) - { - a.terms.insert(a.terms.end(), lc_A.terms.begin(), lc_A.terms.end()); - } - for (auto lc_B : B) - { - b.terms.insert(b.terms.end(), lc_B.terms.begin(), lc_B.terms.end()); - } - for (auto lc_C : C) - { - c.terms.insert(c.terms.end(), lc_C.terms.begin(), lc_C.terms.end()); - } -} - -template -bool r1cs_constraint::operator==(const r1cs_constraint &other) const -{ - return (this->a == other.a && - this->b == other.b && - this->c == other.c); -} - -template -std::ostream& operator<<(std::ostream &out, const r1cs_constraint &c) -{ - out << c.a; - out << c.b; - out << c.c; - - return out; -} - -template -std::istream& operator>>(std::istream &in, r1cs_constraint &c) -{ - in >> c.a; - in >> c.b; - in >> c.c; - - return in; -} - -template -size_t r1cs_constraint_system::num_inputs() const -{ - return primary_input_size; -} - -template -size_t r1cs_constraint_system::num_variables() const -{ - return primary_input_size + auxiliary_input_size; -} - - -template -size_t r1cs_constraint_system::num_constraints() const -{ - return constraints.size(); -} - -template -bool r1cs_constraint_system::is_valid() const -{ - if (this->num_inputs() > this->num_variables()) return false; - - for (size_t c = 0; c < constraints.size(); ++c) - { - if (!(constraints[c].a.is_valid(this->num_variables()) && - constraints[c].b.is_valid(this->num_variables()) && - constraints[c].c.is_valid(this->num_variables()))) - { - return false; - } - } - - return true; -} - -template -void dump_r1cs_constraint(const r1cs_constraint &constraint, - const r1cs_variable_assignment &full_variable_assignment, - const std::map &variable_annotations) -{ - printf("terms for a:\n"); constraint.a.print_with_assignment(full_variable_assignment, variable_annotations); - printf("terms for b:\n"); constraint.b.print_with_assignment(full_variable_assignment, variable_annotations); - printf("terms for c:\n"); constraint.c.print_with_assignment(full_variable_assignment, variable_annotations); -} - -template -bool r1cs_constraint_system::is_satisfied(const r1cs_primary_input &primary_input, - const r1cs_auxiliary_input &auxiliary_input) const -{ - assert(primary_input.size() == num_inputs()); - assert(primary_input.size() + auxiliary_input.size() == num_variables()); - - r1cs_variable_assignment full_variable_assignment = primary_input; - full_variable_assignment.insert(full_variable_assignment.end(), auxiliary_input.begin(), auxiliary_input.end()); - - for (size_t c = 0; c < constraints.size(); ++c) - { - const FieldT ares = constraints[c].a.evaluate(full_variable_assignment); - const FieldT bres = constraints[c].b.evaluate(full_variable_assignment); - const FieldT cres = constraints[c].c.evaluate(full_variable_assignment); - - if (!(ares*bres == cres)) - { -#ifdef DEBUG - auto it = constraint_annotations.find(c); - printf("constraint %zu (%s) unsatisfied\n", c, (it == constraint_annotations.end() ? "no annotation" : it->second.c_str())); - printf(" = "); ares.print(); - printf(" = "); bres.print(); - printf(" = "); cres.print(); - printf("constraint was:\n"); - dump_r1cs_constraint(constraints[c], full_variable_assignment, variable_annotations); -#endif // DEBUG - return false; - } - } - - return true; -} - -template -void r1cs_constraint_system::add_constraint(const r1cs_constraint &c) -{ - constraints.emplace_back(c); -} - -template -void r1cs_constraint_system::add_constraint(const r1cs_constraint &c, const std::string &annotation) -{ -#ifdef DEBUG - constraint_annotations[constraints.size()] = annotation; -#endif - constraints.emplace_back(c); -} - -template -void r1cs_constraint_system::swap_AB_if_beneficial() -{ - enter_block("Call to r1cs_constraint_system::swap_AB_if_beneficial"); - - enter_block("Estimate densities"); - bit_vector touched_by_A(this->num_variables() + 1, false), touched_by_B(this->num_variables() + 1, false); - - for (size_t i = 0; i < this->constraints.size(); ++i) - { - for (size_t j = 0; j < this->constraints[i].a.terms.size(); ++j) - { - touched_by_A[this->constraints[i].a.terms[j].index] = true; - } - - for (size_t j = 0; j < this->constraints[i].b.terms.size(); ++j) - { - touched_by_B[this->constraints[i].b.terms[j].index] = true; - } - } - - size_t non_zero_A_count = 0, non_zero_B_count = 0; - for (size_t i = 0; i < this->num_variables() + 1; ++i) - { - non_zero_A_count += touched_by_A[i] ? 1 : 0; - non_zero_B_count += touched_by_B[i] ? 1 : 0; - } - - if (!inhibit_profiling_info) - { - print_indent(); printf("* Non-zero A-count (estimate): %zu\n", non_zero_A_count); - print_indent(); printf("* Non-zero B-count (estimate): %zu\n", non_zero_B_count); - } - leave_block("Estimate densities"); - - if (non_zero_B_count > non_zero_A_count) - { - enter_block("Perform the swap"); - for (size_t i = 0; i < this->constraints.size(); ++i) - { - std::swap(this->constraints[i].a, this->constraints[i].b); - } - leave_block("Perform the swap"); - } - else - { - print_indent(); printf("Swap is not beneficial, not performing\n"); - } - - leave_block("Call to r1cs_constraint_system::swap_AB_if_beneficial"); -} - -template -bool r1cs_constraint_system::operator==(const r1cs_constraint_system &other) const -{ - return (this->constraints == other.constraints && - this->primary_input_size == other.primary_input_size && - this->auxiliary_input_size == other.auxiliary_input_size); -} - -template -std::ostream& operator<<(std::ostream &out, const r1cs_constraint_system &cs) -{ - out << cs.primary_input_size << "\n"; - out << cs.auxiliary_input_size << "\n"; - - out << cs.num_constraints() << "\n"; - for (const r1cs_constraint& c : cs.constraints) - { - out << c; - } - - return out; -} - -template -std::istream& operator>>(std::istream &in, r1cs_constraint_system &cs) -{ - in >> cs.primary_input_size; - in >> cs.auxiliary_input_size; - - cs.constraints.clear(); - - size_t s; - in >> s; - - char b; - in.read(&b, 1); - - cs.constraints.reserve(s); - - for (size_t i = 0; i < s; ++i) - { - r1cs_constraint c; - in >> c; - cs.constraints.emplace_back(c); - } - - return in; -} - -template -void r1cs_constraint_system::report_linear_constraint_statistics() const -{ -#ifdef DEBUG - for (size_t i = 0; i < constraints.size(); ++i) - { - auto &constr = constraints[i]; - bool a_is_const = true; - for (auto &t : constr.a.terms) - { - a_is_const = a_is_const && (t.index == 0); - } - - bool b_is_const = true; - for (auto &t : constr.b.terms) - { - b_is_const = b_is_const && (t.index == 0); - } - - if (a_is_const || b_is_const) - { - auto it = constraint_annotations.find(i); - printf("%s\n", (it == constraint_annotations.end() ? FORMAT("", "constraint_%zu", i) : it->second).c_str()); - } - } -#endif -} - -} // libsnark -#endif // R1CS_TCC_ diff --git a/src/snark/libsnark/relations/variable.hpp b/src/snark/libsnark/relations/variable.hpp deleted file mode 100644 index 84c65e810d8..00000000000 --- a/src/snark/libsnark/relations/variable.hpp +++ /dev/null @@ -1,213 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for: - - a variable (i.e., x_i), - - a linear term (i.e., a_i * x_i), and - - a linear combination (i.e., sum_i a_i * x_i). - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef VARIABLE_HPP_ -#define VARIABLE_HPP_ - -#include -#include -#include -#include - -namespace libsnark { - -/** - * Mnemonic typedefs. - */ -typedef size_t var_index_t; -typedef int64_t integer_coeff_t; - -/** - * Forward declaration. - */ -template -class linear_term; - -/** - * Forward declaration. - */ -template -class linear_combination; - -/********************************* Variable **********************************/ - -/** - * A variable represents a formal expression of the form "x_{index}". - */ -template -class variable { -public: - - var_index_t index; - - variable(const var_index_t index = 0) : index(index) {}; - - linear_term operator*(const integer_coeff_t int_coeff) const; - linear_term operator*(const FieldT &field_coeff) const; - - linear_combination operator+(const linear_combination &other) const; - linear_combination operator-(const linear_combination &other) const; - - linear_term operator-() const; - - bool operator==(const variable &other) const; -}; - -template -linear_term operator*(const integer_coeff_t int_coeff, const variable &var); - -template -linear_term operator*(const FieldT &field_coeff, const variable &var); - -template -linear_combination operator+(const integer_coeff_t int_coeff, const variable &var); - -template -linear_combination operator+(const FieldT &field_coeff, const variable &var); - -template -linear_combination operator-(const integer_coeff_t int_coeff, const variable &var); - -template -linear_combination operator-(const FieldT &field_coeff, const variable &var); - - -/****************************** Linear term **********************************/ - -/** - * A linear term represents a formal expression of the form "coeff * x_{index}". - */ -template -class linear_term { -public: - - var_index_t index = 0; - FieldT coeff; - - linear_term() {}; - linear_term(const variable &var); - linear_term(const variable &var, const integer_coeff_t int_coeff); - linear_term(const variable &var, const FieldT &field_coeff); - - linear_term operator*(const integer_coeff_t int_coeff) const; - linear_term operator*(const FieldT &field_coeff) const; - - linear_combination operator+(const linear_combination &other) const; - linear_combination operator-(const linear_combination &other) const; - - linear_term operator-() const; - - bool operator==(const linear_term &other) const; -}; - -template -linear_term operator*(const integer_coeff_t int_coeff, const linear_term <); - -template -linear_term operator*(const FieldT &field_coeff, const linear_term <); - -template -linear_combination operator+(const integer_coeff_t int_coeff, const linear_term <); - -template -linear_combination operator+(const FieldT &field_coeff, const linear_term <); - -template -linear_combination operator-(const integer_coeff_t int_coeff, const linear_term <); - -template -linear_combination operator-(const FieldT &field_coeff, const linear_term <); - - -/***************************** Linear combination ****************************/ - -template -class linear_combination; - -template -std::ostream& operator<<(std::ostream &out, const linear_combination &lc); - -template -std::istream& operator>>(std::istream &in, linear_combination &lc); - -/** - * A linear combination represents a formal expression of the form "sum_i coeff_i * x_{index_i}". - */ -template -class linear_combination { -public: - - std::vector > terms; - - linear_combination() {}; - linear_combination(const integer_coeff_t int_coeff); - linear_combination(const FieldT &field_coeff); - linear_combination(const variable &var); - linear_combination(const linear_term <); - linear_combination(const std::vector > &all_terms); - - /* for supporting range-based for loops over linear_combination */ - typename std::vector >::const_iterator begin() const; - typename std::vector >::const_iterator end() const; - - void add_term(const variable &var); - void add_term(const variable &var, const integer_coeff_t int_coeff); - void add_term(const variable &var, const FieldT &field_coeff); - - void add_term(const linear_term <); - - FieldT evaluate(const std::vector &assignment) const; - - linear_combination operator*(const integer_coeff_t int_coeff) const; - linear_combination operator*(const FieldT &field_coeff) const; - - linear_combination operator+(const linear_combination &other) const; - - linear_combination operator-(const linear_combination &other) const; - linear_combination operator-() const; - - bool operator==(const linear_combination &other) const; - - bool is_valid(const size_t num_variables) const; - - void print(const std::map &variable_annotations = std::map()) const; - void print_with_assignment(const std::vector &full_assignment, const std::map &variable_annotations = std::map()) const; - - friend std::ostream& operator<< (std::ostream &out, const linear_combination &lc); - friend std::istream& operator>> (std::istream &in, linear_combination &lc); -}; - -template -linear_combination operator*(const integer_coeff_t int_coeff, const linear_combination &lc); - -template -linear_combination operator*(const FieldT &field_coeff, const linear_combination &lc); - -template -linear_combination operator+(const integer_coeff_t int_coeff, const linear_combination &lc); - -template -linear_combination operator+(const FieldT &field_coeff, const linear_combination &lc); - -template -linear_combination operator-(const integer_coeff_t int_coeff, const linear_combination &lc); - -template -linear_combination operator-(const FieldT &field_coeff, const linear_combination &lc); - -} // libsnark - -#include "relations/variable.tcc" - -#endif // VARIABLE_HPP_ diff --git a/src/snark/libsnark/relations/variable.tcc b/src/snark/libsnark/relations/variable.tcc deleted file mode 100644 index 4c4cab97f59..00000000000 --- a/src/snark/libsnark/relations/variable.tcc +++ /dev/null @@ -1,512 +0,0 @@ -/** @file - ***************************************************************************** - - Implementation of interfaces for: - - a variable (i.e., x_i), - - a linear term (i.e., a_i * x_i), and - - a linear combination (i.e., sum_i a_i * x_i). - - See variabe.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef VARIABLE_TCC_ -#define VARIABLE_TCC_ - -#include -#include - -#include "algebra/fields/bigint.hpp" - -namespace libsnark { - -template -linear_term variable::operator*(const integer_coeff_t int_coeff) const -{ - return linear_term(*this, int_coeff); -} - -template -linear_term variable::operator*(const FieldT &field_coeff) const -{ - return linear_term(*this, field_coeff); -} - -template -linear_combination variable::operator+(const linear_combination &other) const -{ - linear_combination result; - - result.add_term(*this); - result.terms.insert(result.terms.begin(), other.terms.begin(), other.terms.end()); - - return result; -} - -template -linear_combination variable::operator-(const linear_combination &other) const -{ - return (*this) + (-other); -} - -template -linear_term variable::operator-() const -{ - return linear_term(*this, -FieldT::one()); -} - -template -bool variable::operator==(const variable &other) const -{ - return (this->index == other.index); -} - -template -linear_term operator*(const integer_coeff_t int_coeff, const variable &var) -{ - return linear_term(var, int_coeff); -} - -template -linear_term operator*(const FieldT &field_coeff, const variable &var) -{ - return linear_term(var, field_coeff); -} - -template -linear_combination operator+(const integer_coeff_t int_coeff, const variable &var) -{ - return linear_combination(int_coeff) + var; -} - -template -linear_combination operator+(const FieldT &field_coeff, const variable &var) -{ - return linear_combination(field_coeff) + var; -} - -template -linear_combination operator-(const integer_coeff_t int_coeff, const variable &var) -{ - return linear_combination(int_coeff) - var; -} - -template -linear_combination operator-(const FieldT &field_coeff, const variable &var) -{ - return linear_combination(field_coeff) - var; -} - -template -linear_term::linear_term(const variable &var) : - index(var.index), coeff(FieldT::one()) -{ -} - -template -linear_term::linear_term(const variable &var, const integer_coeff_t int_coeff) : - index(var.index), coeff(FieldT(int_coeff)) -{ -} - -template -linear_term::linear_term(const variable &var, const FieldT &coeff) : - index(var.index), coeff(coeff) -{ -} - -template -linear_term linear_term::operator*(const integer_coeff_t int_coeff) const -{ - return (this->operator*(FieldT(int_coeff))); -} - -template -linear_term linear_term::operator*(const FieldT &field_coeff) const -{ - return linear_term(this->index, field_coeff * this->coeff); -} - -template -linear_combination operator+(const integer_coeff_t int_coeff, const linear_term <) -{ - return linear_combination(int_coeff) + lt; -} - -template -linear_combination operator+(const FieldT &field_coeff, const linear_term <) -{ - return linear_combination(field_coeff) + lt; -} - -template -linear_combination operator-(const integer_coeff_t int_coeff, const linear_term <) -{ - return linear_combination(int_coeff) - lt; -} - -template -linear_combination operator-(const FieldT &field_coeff, const linear_term <) -{ - return linear_combination(field_coeff) - lt; -} - -template -linear_combination linear_term::operator+(const linear_combination &other) const -{ - return linear_combination(*this) + other; -} - -template -linear_combination linear_term::operator-(const linear_combination &other) const -{ - return (*this) + (-other); -} - -template -linear_term linear_term::operator-() const -{ - return linear_term(this->index, -this->coeff); -} - -template -bool linear_term::operator==(const linear_term &other) const -{ - return (this->index == other.index && - this->coeff == other.coeff); -} - -template -linear_term operator*(const integer_coeff_t int_coeff, const linear_term <) -{ - return FieldT(int_coeff) * lt; -} - -template -linear_term operator*(const FieldT &field_coeff, const linear_term <) -{ - return linear_term(lt.index, field_coeff * lt.coeff); -} - -template -linear_combination::linear_combination(const integer_coeff_t int_coeff) -{ - this->add_term(linear_term(0, int_coeff)); -} - -template -linear_combination::linear_combination(const FieldT &field_coeff) -{ - this->add_term(linear_term(0, field_coeff)); -} - -template -linear_combination::linear_combination(const variable &var) -{ - this->add_term(var); -} - -template -linear_combination::linear_combination(const linear_term <) -{ - this->add_term(lt); -} - -template -typename std::vector >::const_iterator linear_combination::begin() const -{ - return terms.begin(); -} - -template -typename std::vector >::const_iterator linear_combination::end() const -{ - return terms.end(); -} - -template -void linear_combination::add_term(const variable &var) -{ - this->terms.emplace_back(linear_term(var.index, FieldT::one())); -} - -template -void linear_combination::add_term(const variable &var, const integer_coeff_t int_coeff) -{ - this->terms.emplace_back(linear_term(var.index, int_coeff)); -} - -template -void linear_combination::add_term(const variable &var, const FieldT &coeff) -{ - this->terms.emplace_back(linear_term(var.index, coeff)); -} - -template -void linear_combination::add_term(const linear_term &other) -{ - this->terms.emplace_back(other); -} - -template -linear_combination linear_combination::operator*(const integer_coeff_t int_coeff) const -{ - return (*this) * FieldT(int_coeff); -} - -template -FieldT linear_combination::evaluate(const std::vector &assignment) const -{ - FieldT acc = FieldT::zero(); - for (auto < : terms) - { - acc += (lt.index == 0 ? FieldT::one() : assignment[lt.index-1]) * lt.coeff; - } - return acc; -} - -template -linear_combination linear_combination::operator*(const FieldT &field_coeff) const -{ - linear_combination result; - result.terms.reserve(this->terms.size()); - for (const linear_term < : this->terms) - { - result.terms.emplace_back(lt * field_coeff); - } - return result; -} - -template -linear_combination linear_combination::operator+(const linear_combination &other) const -{ - linear_combination result; - - auto it1 = this->terms.begin(); - auto it2 = other.terms.begin(); - - /* invariant: it1 and it2 always point to unprocessed items in the corresponding linear combinations */ - while (it1 != this->terms.end() && it2 != other.terms.end()) - { - if (it1->index < it2->index) - { - result.terms.emplace_back(*it1); - ++it1; - } - else if (it1->index > it2->index) - { - result.terms.emplace_back(*it2); - ++it2; - } - else - { - /* it1->index == it2->index */ - result.terms.emplace_back(linear_term(variable(it1->index), it1->coeff + it2->coeff)); - ++it1; - ++it2; - } - } - - if (it1 != this->terms.end()) - { - result.terms.insert(result.terms.end(), it1, this->terms.end()); - } - else - { - result.terms.insert(result.terms.end(), it2, other.terms.end()); - } - - return result; -} - -template -linear_combination linear_combination::operator-(const linear_combination &other) const -{ - return (*this) + (-other); -} - -template -linear_combination linear_combination::operator-() const -{ - return (*this) * (-FieldT::one()); -} - -template -bool linear_combination::operator==(const linear_combination &other) const -{ - return (this->terms == other.terms); -} - -template -bool linear_combination::is_valid(const size_t num_variables) const -{ - /* check that all terms in linear combination are sorted */ - for (size_t i = 1; i < terms.size(); ++i) - { - if (terms[i-1].index >= terms[i].index) - { - return false; - } - } - - /* check that the variables are in proper range. as the variables - are sorted, it suffices to check the last term */ - if ((--terms.end())->index >= num_variables) - { - return false; - } - - return true; -} - -template -void linear_combination::print(const std::map &variable_annotations) const -{ - for (auto < : terms) - { - if (lt.index == 0) - { - printf(" 1 * "); - lt.coeff.print(); - } - else - { - auto it = variable_annotations.find(lt.index); - printf(" x_%zu (%s) * ", lt.index, (it == variable_annotations.end() ? "no annotation" : it->second.c_str())); - lt.coeff.print(); - } - } -} - -template -void linear_combination::print_with_assignment(const std::vector &full_assignment, const std::map &variable_annotations) const -{ - for (auto < : terms) - { - if (lt.index == 0) - { - printf(" 1 * "); - lt.coeff.print(); - } - else - { - printf(" x_%zu * ", lt.index); - lt.coeff.print(); - - auto it = variable_annotations.find(lt.index); - printf(" where x_%zu (%s) was assigned value ", lt.index, - (it == variable_annotations.end() ? "no annotation" : it->second.c_str())); - full_assignment[lt.index-1].print(); - printf(" i.e. negative of "); - (-full_assignment[lt.index-1]).print(); - } - } -} - -template -std::ostream& operator<<(std::ostream &out, const linear_combination &lc) -{ - out << lc.terms.size() << "\n"; - for (const linear_term& lt : lc.terms) - { - out << lt.index << "\n"; - out << lt.coeff << OUTPUT_NEWLINE; - } - - return out; -} - -template -std::istream& operator>>(std::istream &in, linear_combination &lc) -{ - lc.terms.clear(); - - size_t s; - in >> s; - - consume_newline(in); - - lc.terms.reserve(s); - - for (size_t i = 0; i < s; ++i) - { - linear_term lt; - in >> lt.index; - consume_newline(in); - in >> lt.coeff; - consume_OUTPUT_NEWLINE(in); - lc.terms.emplace_back(lt); - } - - return in; -} - -template -linear_combination operator*(const integer_coeff_t int_coeff, const linear_combination &lc) -{ - return lc * int_coeff; -} - -template -linear_combination operator*(const FieldT &field_coeff, const linear_combination &lc) -{ - return lc * field_coeff; -} - -template -linear_combination operator+(const integer_coeff_t int_coeff, const linear_combination &lc) -{ - return linear_combination(int_coeff) + lc; -} - -template -linear_combination operator+(const FieldT &field_coeff, const linear_combination &lc) -{ - return linear_combination(field_coeff) + lc; -} - -template -linear_combination operator-(const integer_coeff_t int_coeff, const linear_combination &lc) -{ - return linear_combination(int_coeff) - lc; -} - -template -linear_combination operator-(const FieldT &field_coeff, const linear_combination &lc) -{ - return linear_combination(field_coeff) - lc; -} - -template -linear_combination::linear_combination(const std::vector > &all_terms) -{ - if (all_terms.empty()) - { - return; - } - - terms = all_terms; - std::sort(terms.begin(), terms.end(), [](linear_term a, linear_term b) { return a.index < b.index; }); - - auto result_it = terms.begin(); - for (auto it = ++terms.begin(); it != terms.end(); ++it) - { - if (it->index == result_it->index) - { - result_it->coeff += it->coeff; - } - else - { - *(++result_it) = *it; - } - } - terms.resize((result_it - terms.begin()) + 1); -} - -} // libsnark - -#endif // VARIABLE_TCC diff --git a/src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.hpp b/src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.hpp deleted file mode 100644 index fcd28abf3bd..00000000000 --- a/src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of functionality that runs the R1CS ppzkSNARK for - a given R1CS example. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef RUN_R1CS_PPZKSNARK_HPP_ -#define RUN_R1CS_PPZKSNARK_HPP_ - -#include "relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.hpp" - -namespace libsnark { - -/** - * Runs the ppzkSNARK (generator, prover, and verifier) for a given - * R1CS example (specified by a constraint system, input, and witness). - * - * Optionally, also test the serialization routines for keys and proofs. - * (This takes additional time.) - */ -template -bool run_r1cs_ppzksnark(const r1cs_example > &example, - const bool test_serialization); - -} // libsnark - -#include "zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.tcc" - -#endif // RUN_R1CS_PPZKSNARK_HPP_ diff --git a/src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.tcc b/src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.tcc deleted file mode 100644 index 00af6fe25e3..00000000000 --- a/src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.tcc +++ /dev/null @@ -1,114 +0,0 @@ -/** @file - ***************************************************************************** - - Implementation of functionality that runs the R1CS ppzkSNARK for - a given R1CS example. - - See run_r1cs_ppzksnark.hpp . - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef RUN_R1CS_PPZKSNARK_TCC_ -#define RUN_R1CS_PPZKSNARK_TCC_ - -#include "zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp" - -#include -#include - -#include "common/profiling.hpp" - -namespace libsnark { - -template -typename std::enable_if::type -test_affine_verifier(const r1cs_ppzksnark_verification_key &vk, - const r1cs_ppzksnark_primary_input &primary_input, - const r1cs_ppzksnark_proof &proof, - const bool expected_answer) -{ - print_header("R1CS ppzkSNARK Affine Verifier"); - const bool answer = r1cs_ppzksnark_affine_verifier_weak_IC(vk, primary_input, proof); - assert(answer == expected_answer); -} - -template -typename std::enable_if::type -test_affine_verifier(const r1cs_ppzksnark_verification_key &vk, - const r1cs_ppzksnark_primary_input &primary_input, - const r1cs_ppzksnark_proof &proof, - const bool expected_answer) -{ - UNUSED(vk, primary_input, proof, expected_answer); - print_header("R1CS ppzkSNARK Affine Verifier"); - printf("Affine verifier is not supported; not testing anything.\n"); -} - -/** - * The code below provides an example of all stages of running a R1CS ppzkSNARK. - * - * Of course, in a real-life scenario, we would have three distinct entities, - * mangled into one in the demonstration below. The three entities are as follows. - * (1) The "generator", which runs the ppzkSNARK generator on input a given - * constraint system CS to create a proving and a verification key for CS. - * (2) The "prover", which runs the ppzkSNARK prover on input the proving key, - * a primary input for CS, and an auxiliary input for CS. - * (3) The "verifier", which runs the ppzkSNARK verifier on input the verification key, - * a primary input for CS, and a proof. - */ -template -bool run_r1cs_ppzksnark(const r1cs_example > &example, - const bool test_serialization) -{ - enter_block("Call to run_r1cs_ppzksnark"); - - print_header("R1CS ppzkSNARK Generator"); - r1cs_ppzksnark_keypair keypair = r1cs_ppzksnark_generator(example.constraint_system); - printf("\n"); print_indent(); print_mem("after generator"); - - print_header("Preprocess verification key"); - r1cs_ppzksnark_processed_verification_key pvk = r1cs_ppzksnark_verifier_process_vk(keypair.vk); - - if (test_serialization) - { - enter_block("Test serialization of keys"); - keypair.pk = reserialize >(keypair.pk); - keypair.vk = reserialize >(keypair.vk); - pvk = reserialize >(pvk); - leave_block("Test serialization of keys"); - } - - print_header("R1CS ppzkSNARK Prover"); - r1cs_ppzksnark_proof proof = r1cs_ppzksnark_prover(keypair.pk, example.primary_input, example.auxiliary_input, example.constraint_system); - printf("\n"); print_indent(); print_mem("after prover"); - - if (test_serialization) - { - enter_block("Test serialization of proof"); - proof = reserialize >(proof); - leave_block("Test serialization of proof"); - } - - print_header("R1CS ppzkSNARK Verifier"); - const bool ans = r1cs_ppzksnark_verifier_strong_IC(keypair.vk, example.primary_input, proof); - printf("\n"); print_indent(); print_mem("after verifier"); - printf("* The verification result is: %s\n", (ans ? "PASS" : "FAIL")); - - print_header("R1CS ppzkSNARK Online Verifier"); - const bool ans2 = r1cs_ppzksnark_online_verifier_strong_IC(pvk, example.primary_input, proof); - assert(ans == ans2); - - test_affine_verifier(keypair.vk, example.primary_input, proof, ans); - - leave_block("Call to run_r1cs_ppzksnark"); - - return ans; -} - -} // libsnark - -#endif // RUN_R1CS_PPZKSNARK_TCC_ diff --git a/src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/profiling/profile_r1cs_ppzksnark.cpp b/src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/profiling/profile_r1cs_ppzksnark.cpp deleted file mode 100644 index 5c54150289e..00000000000 --- a/src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/profiling/profile_r1cs_ppzksnark.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/** @file - ***************************************************************************** - Profiling program that exercises the ppzkSNARK (first generator, then prover, - then verifier) on a synthetic R1CS instance. - - The command - - $ src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/profiling/profile_r1cs_ppzksnark 1000 10 Fr - - exercises the ppzkSNARK (first generator, then prover, then verifier) on an R1CS instance with 1000 equations and an input consisting of 10 field elements. - - (If you get the error `zmInit ERR:can't protect`, see the discussion [above](#elliptic-curve-choices).) - - The command - - $ src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/profiling/profile_r1cs_ppzksnark 1000 10 bytes - - does the same but now the input consists of 10 bytes. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ -#include -#include - -#include "common/default_types/r1cs_ppzksnark_pp.hpp" -#include "common/profiling.hpp" -#include "common/utils.hpp" -#include "relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.hpp" -#include "zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.hpp" - -using namespace libsnark; - -int main(int argc, const char * argv[]) -{ - default_r1cs_ppzksnark_pp::init_public_params(); - start_profiling(); - - if (argc == 2 && strcmp(argv[1], "-v") == 0) - { - print_compilation_info(); - return 0; - } - - if (argc != 3 && argc != 4) - { - printf("usage: %s num_constraints input_size [Fr|bytes]\n", argv[0]); - return 1; - } - const int num_constraints = atoi(argv[1]); - int input_size = atoi(argv[2]); - if (argc == 4) - { - assert(strcmp(argv[3], "Fr") == 0 || strcmp(argv[3], "bytes") == 0); - if (strcmp(argv[3], "bytes") == 0) - { - input_size = div_ceil(8 * input_size, Fr::capacity()); - } - } - - enter_block("Generate R1CS example"); - r1cs_example > example = generate_r1cs_example_with_field_input >(num_constraints, input_size); - leave_block("Generate R1CS example"); - - print_header("(enter) Profile R1CS ppzkSNARK"); - const bool test_serialization = true; - run_r1cs_ppzksnark(example, test_serialization); - print_header("(leave) Profile R1CS ppzkSNARK"); -} diff --git a/src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp b/src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp deleted file mode 100644 index 6095d6a08cb..00000000000 --- a/src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp +++ /dev/null @@ -1,486 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of interfaces for a ppzkSNARK for R1CS. - - This includes: - - class for proving key - - class for verification key - - class for processed verification key - - class for key pair (proving key & verification key) - - class for proof - - generator algorithm - - prover algorithm - - verifier algorithm (with strong or weak input consistency) - - online verifier algorithm (with strong or weak input consistency) - - The implementation instantiates (a modification of) the protocol of \[PGHR13], - by following extending, and optimizing the approach described in \[BCTV14]. - - - Acronyms: - - - R1CS = "Rank-1 Constraint Systems" - - ppzkSNARK = "PreProcessing Zero-Knowledge Succinct Non-interactive ARgument of Knowledge" - - References: - - \[BCTV14]: - "Succinct Non-Interactive Zero Knowledge for a von Neumann Architecture", - Eli Ben-Sasson, Alessandro Chiesa, Eran Tromer, Madars Virza, - USENIX Security 2014, - - - \[PGHR13]: - "Pinocchio: Nearly practical verifiable computation", - Bryan Parno, Craig Gentry, Jon Howell, Mariana Raykova, - IEEE S&P 2013, - - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef R1CS_PPZKSNARK_HPP_ -#define R1CS_PPZKSNARK_HPP_ - -#include - -#include "algebra/curves/public_params.hpp" -#include "common/data_structures/accumulation_vector.hpp" -#include "algebra/knowledge_commitment/knowledge_commitment.hpp" -#include "relations/constraint_satisfaction_problems/r1cs/r1cs.hpp" -#include "zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark_params.hpp" - -namespace libsnark { - -/******************************** Proving key ********************************/ - -template -class r1cs_ppzksnark_proving_key; - -template -std::ostream& operator<<(std::ostream &out, const r1cs_ppzksnark_proving_key &pk); - -template -std::istream& operator>>(std::istream &in, r1cs_ppzksnark_proving_key &pk); - -/** - * A proving key for the R1CS ppzkSNARK. - */ -template -class r1cs_ppzksnark_proving_key { -public: - knowledge_commitment_vector, G1 > A_query; - knowledge_commitment_vector, G1 > B_query; - knowledge_commitment_vector, G1 > C_query; - G1_vector H_query; - G1_vector K_query; - - r1cs_ppzksnark_proving_key() {}; - r1cs_ppzksnark_proving_key& operator=(const r1cs_ppzksnark_proving_key &other) = default; - r1cs_ppzksnark_proving_key(const r1cs_ppzksnark_proving_key &other) = default; - r1cs_ppzksnark_proving_key(r1cs_ppzksnark_proving_key &&other) = default; - r1cs_ppzksnark_proving_key(knowledge_commitment_vector, G1 > &&A_query, - knowledge_commitment_vector, G1 > &&B_query, - knowledge_commitment_vector, G1 > &&C_query, - G1_vector &&H_query, - G1_vector &&K_query) : - A_query(std::move(A_query)), - B_query(std::move(B_query)), - C_query(std::move(C_query)), - H_query(std::move(H_query)), - K_query(std::move(K_query)) - {}; - - size_t G1_size() const - { - return 2*(A_query.domain_size() + C_query.domain_size()) + B_query.domain_size() + H_query.size() + K_query.size(); - } - - size_t G2_size() const - { - return B_query.domain_size(); - } - - size_t G1_sparse_size() const - { - return 2*(A_query.size() + C_query.size()) + B_query.size() + H_query.size() + K_query.size(); - } - - size_t G2_sparse_size() const - { - return B_query.size(); - } - - size_t size_in_bits() const - { - return A_query.size_in_bits() + B_query.size_in_bits() + C_query.size_in_bits() + libsnark::size_in_bits(H_query) + libsnark::size_in_bits(K_query); - } - - void print_size() const - { - print_indent(); printf("* G1 elements in PK: %zu\n", this->G1_size()); - print_indent(); printf("* Non-zero G1 elements in PK: %zu\n", this->G1_sparse_size()); - print_indent(); printf("* G2 elements in PK: %zu\n", this->G2_size()); - print_indent(); printf("* Non-zero G2 elements in PK: %zu\n", this->G2_sparse_size()); - print_indent(); printf("* PK size in bits: %zu\n", this->size_in_bits()); - } - - bool operator==(const r1cs_ppzksnark_proving_key &other) const; - friend std::ostream& operator<< (std::ostream &out, const r1cs_ppzksnark_proving_key &pk); - friend std::istream& operator>> (std::istream &in, r1cs_ppzksnark_proving_key &pk); -}; - - -/******************************* Verification key ****************************/ - -template -class r1cs_ppzksnark_verification_key; - -template -std::ostream& operator<<(std::ostream &out, const r1cs_ppzksnark_verification_key &vk); - -template -std::istream& operator>>(std::istream &in, r1cs_ppzksnark_verification_key &vk); - -/** - * A verification key for the R1CS ppzkSNARK. - */ -template -class r1cs_ppzksnark_verification_key { -public: - G2 alphaA_g2; - G1 alphaB_g1; - G2 alphaC_g2; - G2 gamma_g2; - G1 gamma_beta_g1; - G2 gamma_beta_g2; - G2 rC_Z_g2; - - accumulation_vector > encoded_IC_query; - - r1cs_ppzksnark_verification_key() = default; - r1cs_ppzksnark_verification_key(const G2 &alphaA_g2, - const G1 &alphaB_g1, - const G2 &alphaC_g2, - const G2 &gamma_g2, - const G1 &gamma_beta_g1, - const G2 &gamma_beta_g2, - const G2 &rC_Z_g2, - const accumulation_vector > &eIC) : - alphaA_g2(alphaA_g2), - alphaB_g1(alphaB_g1), - alphaC_g2(alphaC_g2), - gamma_g2(gamma_g2), - gamma_beta_g1(gamma_beta_g1), - gamma_beta_g2(gamma_beta_g2), - rC_Z_g2(rC_Z_g2), - encoded_IC_query(eIC) - {}; - - size_t G1_size() const - { - return 2 + encoded_IC_query.size(); - } - - size_t G2_size() const - { - return 5; - } - - size_t size_in_bits() const - { - return (2 * G1::size_in_bits() + encoded_IC_query.size_in_bits() + 5 * G2::size_in_bits()); - } - - void print_size() const - { - print_indent(); printf("* G1 elements in VK: %zu\n", this->G1_size()); - print_indent(); printf("* G2 elements in VK: %zu\n", this->G2_size()); - print_indent(); printf("* VK size in bits: %zu\n", this->size_in_bits()); - } - - bool operator==(const r1cs_ppzksnark_verification_key &other) const; - friend std::ostream& operator<< (std::ostream &out, const r1cs_ppzksnark_verification_key &vk); - friend std::istream& operator>> (std::istream &in, r1cs_ppzksnark_verification_key &vk); - - static r1cs_ppzksnark_verification_key dummy_verification_key(const size_t input_size); -}; - - -/************************ Processed verification key *************************/ - -template -class r1cs_ppzksnark_processed_verification_key; - -template -std::ostream& operator<<(std::ostream &out, const r1cs_ppzksnark_processed_verification_key &pvk); - -template -std::istream& operator>>(std::istream &in, r1cs_ppzksnark_processed_verification_key &pvk); - -/** - * A processed verification key for the R1CS ppzkSNARK. - * - * Compared to a (non-processed) verification key, a processed verification key - * contains a small constant amount of additional pre-computed information that - * enables a faster verification time. - */ -template -class r1cs_ppzksnark_processed_verification_key { -public: - G2_precomp pp_G2_one_precomp; - G2_precomp vk_alphaA_g2_precomp; - G1_precomp vk_alphaB_g1_precomp; - G2_precomp vk_alphaC_g2_precomp; - G2_precomp vk_rC_Z_g2_precomp; - G2_precomp vk_gamma_g2_precomp; - G1_precomp vk_gamma_beta_g1_precomp; - G2_precomp vk_gamma_beta_g2_precomp; - - accumulation_vector > encoded_IC_query; - - bool operator==(const r1cs_ppzksnark_processed_verification_key &other) const; - friend std::ostream& operator<< (std::ostream &out, const r1cs_ppzksnark_processed_verification_key &pvk); - friend std::istream& operator>> (std::istream &in, r1cs_ppzksnark_processed_verification_key &pvk); -}; - - -/********************************** Key pair *********************************/ - -/** - * A key pair for the R1CS ppzkSNARK, which consists of a proving key and a verification key. - */ -template -class r1cs_ppzksnark_keypair { -public: - r1cs_ppzksnark_proving_key pk; - r1cs_ppzksnark_verification_key vk; - - r1cs_ppzksnark_keypair() = default; - r1cs_ppzksnark_keypair(const r1cs_ppzksnark_keypair &other) = default; - r1cs_ppzksnark_keypair(r1cs_ppzksnark_proving_key &&pk, - r1cs_ppzksnark_verification_key &&vk) : - pk(std::move(pk)), - vk(std::move(vk)) - {} - - r1cs_ppzksnark_keypair(r1cs_ppzksnark_keypair &&other) = default; -}; - - -/*********************************** Proof ***********************************/ - -template -class r1cs_ppzksnark_proof; - -template -std::ostream& operator<<(std::ostream &out, const r1cs_ppzksnark_proof &proof); - -template -std::istream& operator>>(std::istream &in, r1cs_ppzksnark_proof &proof); - -/** - * A proof for the R1CS ppzkSNARK. - * - * While the proof has a structure, externally one merely opaquely produces, - * serializes/deserializes, and verifies proofs. We only expose some information - * about the structure for statistics purposes. - */ -template -class r1cs_ppzksnark_proof { -public: - knowledge_commitment, G1 > g_A; - knowledge_commitment, G1 > g_B; - knowledge_commitment, G1 > g_C; - G1 g_H; - G1 g_K; - - r1cs_ppzksnark_proof() - { - // invalid proof with valid curve points - this->g_A.g = G1 ::one(); - this->g_A.h = G1::one(); - this->g_B.g = G2 ::one(); - this->g_B.h = G1::one(); - this->g_C.g = G1 ::one(); - this->g_C.h = G1::one(); - this->g_H = G1::one(); - this->g_K = G1::one(); - } - r1cs_ppzksnark_proof(knowledge_commitment, G1 > &&g_A, - knowledge_commitment, G1 > &&g_B, - knowledge_commitment, G1 > &&g_C, - G1 &&g_H, - G1 &&g_K) : - g_A(std::move(g_A)), - g_B(std::move(g_B)), - g_C(std::move(g_C)), - g_H(std::move(g_H)), - g_K(std::move(g_K)) - {}; - - size_t G1_size() const - { - return 7; - } - - size_t G2_size() const - { - return 1; - } - - size_t size_in_bits() const - { - return G1_size() * G1::size_in_bits() + G2_size() * G2::size_in_bits(); - } - - void print_size() const - { - print_indent(); printf("* G1 elements in proof: %zu\n", this->G1_size()); - print_indent(); printf("* G2 elements in proof: %zu\n", this->G2_size()); - print_indent(); printf("* Proof size in bits: %zu\n", this->size_in_bits()); - } - - bool is_well_formed() const - { - return (g_A.g.is_well_formed() && g_A.h.is_well_formed() && - g_B.g.is_well_formed() && g_B.h.is_well_formed() && - g_C.g.is_well_formed() && g_C.h.is_well_formed() && - g_H.is_well_formed() && - g_K.is_well_formed()); - } - - bool operator==(const r1cs_ppzksnark_proof &other) const; - friend std::ostream& operator<< (std::ostream &out, const r1cs_ppzksnark_proof &proof); - friend std::istream& operator>> (std::istream &in, r1cs_ppzksnark_proof &proof); -}; - - -/***************************** Main algorithms *******************************/ - -/** - * A generator algorithm for the R1CS ppzkSNARK. - * - * Given a R1CS constraint system CS, this algorithm produces proving and verification keys for CS. - */ -template -r1cs_ppzksnark_keypair r1cs_ppzksnark_generator(const r1cs_ppzksnark_constraint_system &cs); - -template -r1cs_ppzksnark_keypair r1cs_ppzksnark_generator( - const r1cs_ppzksnark_constraint_system &cs, - const Fr& t, - const Fr& alphaA, - const Fr& alphaB, - const Fr& alphaC, - const Fr& rA, - const Fr& rB, - const Fr& beta, - const Fr& gamma -); - -/** - * A prover algorithm for the R1CS ppzkSNARK. - * - * Given a R1CS primary input X and a R1CS auxiliary input Y, this algorithm - * produces a proof (of knowledge) that attests to the following statement: - * ``there exists Y such that CS(X,Y)=0''. - * Above, CS is the R1CS constraint system that was given as input to the generator algorithm. - */ -template -r1cs_ppzksnark_proof r1cs_ppzksnark_prover(const r1cs_ppzksnark_proving_key &pk, - const r1cs_ppzksnark_primary_input &primary_input, - const r1cs_ppzksnark_auxiliary_input &auxiliary_input, - const r1cs_ppzksnark_constraint_system &constraint_system); - -template -r1cs_ppzksnark_proof r1cs_ppzksnark_prover_streaming(std::ifstream &proving_key_file, - const r1cs_ppzksnark_primary_input &primary_input, - const r1cs_ppzksnark_auxiliary_input &auxiliary_input, - const r1cs_ppzksnark_constraint_system &constraint_system); - -/* - Below are four variants of verifier algorithm for the R1CS ppzkSNARK. - - These are the four cases that arise from the following two choices: - - (1) The verifier accepts a (non-processed) verification key or, instead, a processed verification key. - In the latter case, we call the algorithm an "online verifier". - - (2) The verifier checks for "weak" input consistency or, instead, "strong" input consistency. - Strong input consistency requires that |primary_input| = CS.num_inputs, whereas - weak input consistency requires that |primary_input| <= CS.num_inputs (and - the primary input is implicitly padded with zeros up to length CS.num_inputs). - */ - -/** - * A verifier algorithm for the R1CS ppzkSNARK that: - * (1) accepts a non-processed verification key, and - * (2) has weak input consistency. - */ -template -bool r1cs_ppzksnark_verifier_weak_IC(const r1cs_ppzksnark_verification_key &vk, - const r1cs_ppzksnark_primary_input &primary_input, - const r1cs_ppzksnark_proof &proof); - -/** - * A verifier algorithm for the R1CS ppzkSNARK that: - * (1) accepts a non-processed verification key, and - * (2) has strong input consistency. - */ -template -bool r1cs_ppzksnark_verifier_strong_IC(const r1cs_ppzksnark_verification_key &vk, - const r1cs_ppzksnark_primary_input &primary_input, - const r1cs_ppzksnark_proof &proof); - -/** - * Convert a (non-processed) verification key into a processed verification key. - */ -template -r1cs_ppzksnark_processed_verification_key r1cs_ppzksnark_verifier_process_vk(const r1cs_ppzksnark_verification_key &vk); - -/** - * A verifier algorithm for the R1CS ppzkSNARK that: - * (1) accepts a processed verification key, and - * (2) has weak input consistency. - */ -template -bool r1cs_ppzksnark_online_verifier_weak_IC(const r1cs_ppzksnark_processed_verification_key &pvk, - const r1cs_ppzksnark_primary_input &input, - const r1cs_ppzksnark_proof &proof); - -/** - * A verifier algorithm for the R1CS ppzkSNARK that: - * (1) accepts a processed verification key, and - * (2) has strong input consistency. - */ -template -bool r1cs_ppzksnark_online_verifier_strong_IC(const r1cs_ppzksnark_processed_verification_key &pvk, - const r1cs_ppzksnark_primary_input &primary_input, - const r1cs_ppzksnark_proof &proof); - -/****************************** Miscellaneous ********************************/ - -/** - * For debugging purposes (of r1cs_ppzksnark_r1cs_ppzksnark_verifier_gadget): - * - * A verifier algorithm for the R1CS ppzkSNARK that: - * (1) accepts a non-processed verification key, - * (2) has weak input consistency, and - * (3) uses affine coordinates for elliptic-curve computations. - */ -template -bool r1cs_ppzksnark_affine_verifier_weak_IC(const r1cs_ppzksnark_verification_key &vk, - const r1cs_ppzksnark_primary_input &primary_input, - const r1cs_ppzksnark_proof &proof); - - -} // libsnark - -#include "zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.tcc" - -#endif // R1CS_PPZKSNARK_HPP_ diff --git a/src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.tcc b/src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.tcc deleted file mode 100644 index 9cc392e534a..00000000000 --- a/src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.tcc +++ /dev/null @@ -1,886 +0,0 @@ -/** @file -***************************************************************************** - -Implementation of interfaces for a ppzkSNARK for R1CS. - -See r1cs_ppzksnark.hpp . - -***************************************************************************** -* @author This file is part of libsnark, developed by SCIPR Lab -* and contributors (see AUTHORS). -* @copyright MIT license (see LICENSE file) -*****************************************************************************/ - -#ifndef R1CS_PPZKSNARK_TCC_ -#define R1CS_PPZKSNARK_TCC_ - -#include -#include -#include -#include -#include - -#include "common/profiling.hpp" -#include "common/utils.hpp" -#include "algebra/scalar_multiplication/multiexp.hpp" -#include "algebra/scalar_multiplication/kc_multiexp.hpp" -#include "reductions/r1cs_to_qap/r1cs_to_qap.hpp" - -namespace libsnark { - -template -bool r1cs_ppzksnark_proving_key::operator==(const r1cs_ppzksnark_proving_key &other) const -{ - return (this->A_query == other.A_query && - this->B_query == other.B_query && - this->C_query == other.C_query && - this->H_query == other.H_query && - this->K_query == other.K_query); -} - -template -std::ostream& operator<<(std::ostream &out, const r1cs_ppzksnark_proving_key &pk) -{ - out << pk.A_query; - out << pk.B_query; - out << pk.C_query; - out << pk.H_query; - out << pk.K_query; - - return out; -} - -template -std::istream& operator>>(std::istream &in, r1cs_ppzksnark_proving_key &pk) -{ - in >> pk.A_query; - in >> pk.B_query; - in >> pk.C_query; - in >> pk.H_query; - in >> pk.K_query; - - return in; -} - -template -bool r1cs_ppzksnark_verification_key::operator==(const r1cs_ppzksnark_verification_key &other) const -{ - return (this->alphaA_g2 == other.alphaA_g2 && - this->alphaB_g1 == other.alphaB_g1 && - this->alphaC_g2 == other.alphaC_g2 && - this->gamma_g2 == other.gamma_g2 && - this->gamma_beta_g1 == other.gamma_beta_g1 && - this->gamma_beta_g2 == other.gamma_beta_g2 && - this->rC_Z_g2 == other.rC_Z_g2 && - this->encoded_IC_query == other.encoded_IC_query); -} - -template -std::ostream& operator<<(std::ostream &out, const r1cs_ppzksnark_verification_key &vk) -{ - out << vk.alphaA_g2 << OUTPUT_NEWLINE; - out << vk.alphaB_g1 << OUTPUT_NEWLINE; - out << vk.alphaC_g2 << OUTPUT_NEWLINE; - out << vk.gamma_g2 << OUTPUT_NEWLINE; - out << vk.gamma_beta_g1 << OUTPUT_NEWLINE; - out << vk.gamma_beta_g2 << OUTPUT_NEWLINE; - out << vk.rC_Z_g2 << OUTPUT_NEWLINE; - out << vk.encoded_IC_query << OUTPUT_NEWLINE; - - return out; -} - -template -std::istream& operator>>(std::istream &in, r1cs_ppzksnark_verification_key &vk) -{ - in >> vk.alphaA_g2; - consume_OUTPUT_NEWLINE(in); - in >> vk.alphaB_g1; - consume_OUTPUT_NEWLINE(in); - in >> vk.alphaC_g2; - consume_OUTPUT_NEWLINE(in); - in >> vk.gamma_g2; - consume_OUTPUT_NEWLINE(in); - in >> vk.gamma_beta_g1; - consume_OUTPUT_NEWLINE(in); - in >> vk.gamma_beta_g2; - consume_OUTPUT_NEWLINE(in); - in >> vk.rC_Z_g2; - consume_OUTPUT_NEWLINE(in); - in >> vk.encoded_IC_query; - consume_OUTPUT_NEWLINE(in); - - return in; -} - -template -bool r1cs_ppzksnark_processed_verification_key::operator==(const r1cs_ppzksnark_processed_verification_key &other) const -{ - return (this->pp_G2_one_precomp == other.pp_G2_one_precomp && - this->vk_alphaA_g2_precomp == other.vk_alphaA_g2_precomp && - this->vk_alphaB_g1_precomp == other.vk_alphaB_g1_precomp && - this->vk_alphaC_g2_precomp == other.vk_alphaC_g2_precomp && - this->vk_rC_Z_g2_precomp == other.vk_rC_Z_g2_precomp && - this->vk_gamma_g2_precomp == other.vk_gamma_g2_precomp && - this->vk_gamma_beta_g1_precomp == other.vk_gamma_beta_g1_precomp && - this->vk_gamma_beta_g2_precomp == other.vk_gamma_beta_g2_precomp && - this->encoded_IC_query == other.encoded_IC_query); -} - -template -std::ostream& operator<<(std::ostream &out, const r1cs_ppzksnark_processed_verification_key &pvk) -{ - out << pvk.pp_G2_one_precomp << OUTPUT_NEWLINE; - out << pvk.vk_alphaA_g2_precomp << OUTPUT_NEWLINE; - out << pvk.vk_alphaB_g1_precomp << OUTPUT_NEWLINE; - out << pvk.vk_alphaC_g2_precomp << OUTPUT_NEWLINE; - out << pvk.vk_rC_Z_g2_precomp << OUTPUT_NEWLINE; - out << pvk.vk_gamma_g2_precomp << OUTPUT_NEWLINE; - out << pvk.vk_gamma_beta_g1_precomp << OUTPUT_NEWLINE; - out << pvk.vk_gamma_beta_g2_precomp << OUTPUT_NEWLINE; - out << pvk.encoded_IC_query << OUTPUT_NEWLINE; - - return out; -} - -template -std::istream& operator>>(std::istream &in, r1cs_ppzksnark_processed_verification_key &pvk) -{ - in >> pvk.pp_G2_one_precomp; - consume_OUTPUT_NEWLINE(in); - in >> pvk.vk_alphaA_g2_precomp; - consume_OUTPUT_NEWLINE(in); - in >> pvk.vk_alphaB_g1_precomp; - consume_OUTPUT_NEWLINE(in); - in >> pvk.vk_alphaC_g2_precomp; - consume_OUTPUT_NEWLINE(in); - in >> pvk.vk_rC_Z_g2_precomp; - consume_OUTPUT_NEWLINE(in); - in >> pvk.vk_gamma_g2_precomp; - consume_OUTPUT_NEWLINE(in); - in >> pvk.vk_gamma_beta_g1_precomp; - consume_OUTPUT_NEWLINE(in); - in >> pvk.vk_gamma_beta_g2_precomp; - consume_OUTPUT_NEWLINE(in); - in >> pvk.encoded_IC_query; - consume_OUTPUT_NEWLINE(in); - - return in; -} - -template -bool r1cs_ppzksnark_proof::operator==(const r1cs_ppzksnark_proof &other) const -{ - return (this->g_A == other.g_A && - this->g_B == other.g_B && - this->g_C == other.g_C && - this->g_H == other.g_H && - this->g_K == other.g_K); -} - -template -std::ostream& operator<<(std::ostream &out, const r1cs_ppzksnark_proof &proof) -{ - out << proof.g_A << OUTPUT_NEWLINE; - out << proof.g_B << OUTPUT_NEWLINE; - out << proof.g_C << OUTPUT_NEWLINE; - out << proof.g_H << OUTPUT_NEWLINE; - out << proof.g_K << OUTPUT_NEWLINE; - - return out; -} - -template -std::istream& operator>>(std::istream &in, r1cs_ppzksnark_proof &proof) -{ - in >> proof.g_A; - consume_OUTPUT_NEWLINE(in); - in >> proof.g_B; - consume_OUTPUT_NEWLINE(in); - in >> proof.g_C; - consume_OUTPUT_NEWLINE(in); - in >> proof.g_H; - consume_OUTPUT_NEWLINE(in); - in >> proof.g_K; - consume_OUTPUT_NEWLINE(in); - - return in; -} - -template -r1cs_ppzksnark_verification_key r1cs_ppzksnark_verification_key::dummy_verification_key(const size_t input_size) -{ - r1cs_ppzksnark_verification_key result; - result.alphaA_g2 = Fr::random_element() * G2::one(); - result.alphaB_g1 = Fr::random_element() * G1::one(); - result.alphaC_g2 = Fr::random_element() * G2::one(); - result.gamma_g2 = Fr::random_element() * G2::one(); - result.gamma_beta_g1 = Fr::random_element() * G1::one(); - result.gamma_beta_g2 = Fr::random_element() * G2::one(); - result.rC_Z_g2 = Fr::random_element() * G2::one(); - - G1 base = Fr::random_element() * G1::one(); - G1_vector v; - for (size_t i = 0; i < input_size; ++i) - { - v.emplace_back(Fr::random_element() * G1::one()); - } - - result.encoded_IC_query = accumulation_vector >(std::move(base), std::move(v)); - - return result; -} - -template -r1cs_ppzksnark_keypair r1cs_ppzksnark_generator(const r1cs_ppzksnark_constraint_system &cs) -{ - /* draw random element at which the QAP is evaluated */ - const Fr t = Fr::random_element(); - - const Fr alphaA = Fr::random_element(), - alphaB = Fr::random_element(), - alphaC = Fr::random_element(), - rA = Fr::random_element(), - rB = Fr::random_element(), - beta = Fr::random_element(), - gamma = Fr::random_element(); - - return r1cs_ppzksnark_generator(cs, t, alphaA, alphaB, alphaC, rA, rB, beta, gamma); -} - -template -r1cs_ppzksnark_keypair r1cs_ppzksnark_generator( - const r1cs_ppzksnark_constraint_system &cs, - const Fr& t, - const Fr& alphaA, - const Fr& alphaB, - const Fr& alphaC, - const Fr& rA, - const Fr& rB, - const Fr& beta, - const Fr& gamma -) -{ - enter_block("Call to r1cs_ppzksnark_generator"); - - /* make the B_query "lighter" if possible */ - r1cs_ppzksnark_constraint_system cs_copy(cs); - cs_copy.swap_AB_if_beneficial(); - - qap_instance_evaluation > qap_inst = r1cs_to_qap_instance_map_with_evaluation(cs_copy, t); - - print_indent(); printf("* QAP number of variables: %zu\n", qap_inst.num_variables()); - print_indent(); printf("* QAP pre degree: %zu\n", cs_copy.constraints.size()); - print_indent(); printf("* QAP degree: %zu\n", qap_inst.degree()); - print_indent(); printf("* QAP number of input variables: %zu\n", qap_inst.num_inputs()); - - enter_block("Compute query densities"); - size_t non_zero_At = 0, non_zero_Bt = 0, non_zero_Ct = 0, non_zero_Ht = 0; - for (size_t i = 0; i < qap_inst.num_variables()+1; ++i) - { - if (!qap_inst.At[i].is_zero()) - { - ++non_zero_At; - } - if (!qap_inst.Bt[i].is_zero()) - { - ++non_zero_Bt; - } - if (!qap_inst.Ct[i].is_zero()) - { - ++non_zero_Ct; - } - } - for (size_t i = 0; i < qap_inst.degree()+1; ++i) - { - if (!qap_inst.Ht[i].is_zero()) - { - ++non_zero_Ht; - } - } - leave_block("Compute query densities"); - - Fr_vector At = std::move(qap_inst.At); // qap_inst.At is now in unspecified state, but we do not use it later - Fr_vector Bt = std::move(qap_inst.Bt); // qap_inst.Bt is now in unspecified state, but we do not use it later - Fr_vector Ct = std::move(qap_inst.Ct); // qap_inst.Ct is now in unspecified state, but we do not use it later - Fr_vector Ht = std::move(qap_inst.Ht); // qap_inst.Ht is now in unspecified state, but we do not use it later - - /* append Zt to At,Bt,Ct with */ - At.emplace_back(qap_inst.Zt); - Bt.emplace_back(qap_inst.Zt); - Ct.emplace_back(qap_inst.Zt); - - const Fr rC = rA * rB; - - // construct the same-coefficient-check query (must happen before zeroing out the prefix of At) - Fr_vector Kt; - Kt.reserve(qap_inst.num_variables()+4); - for (size_t i = 0; i < qap_inst.num_variables()+1; ++i) - { - Kt.emplace_back( beta * (rA * At[i] + rB * Bt[i] + rC * Ct[i] ) ); - } - Kt.emplace_back(beta * rA * qap_inst.Zt); - Kt.emplace_back(beta * rB * qap_inst.Zt); - Kt.emplace_back(beta * rC * qap_inst.Zt); - - /* zero out prefix of At and stick it into IC coefficients */ - Fr_vector IC_coefficients; - IC_coefficients.reserve(qap_inst.num_inputs() + 1); - for (size_t i = 0; i < qap_inst.num_inputs() + 1; ++i) - { - IC_coefficients.emplace_back(At[i]); - assert(!IC_coefficients[i].is_zero()); - At[i] = Fr::zero(); - } - - const size_t g1_exp_count = 2*(non_zero_At - qap_inst.num_inputs() + non_zero_Ct) + non_zero_Bt + non_zero_Ht + Kt.size(); - const size_t g2_exp_count = non_zero_Bt; - - size_t g1_window = get_exp_window_size >(g1_exp_count); - size_t g2_window = get_exp_window_size >(g2_exp_count); - print_indent(); printf("* G1 window: %zu\n", g1_window); - print_indent(); printf("* G2 window: %zu\n", g2_window); - -#ifdef MULTICORE - const size_t chunks = omp_get_max_threads(); // to override, set OMP_NUM_THREADS env var or call omp_set_num_threads() -#else - const size_t chunks = 1; -#endif - - enter_block("Generating G1 multiexp table"); - window_table > g1_table = get_window_table(Fr::size_in_bits(), g1_window, G1::one()); - leave_block("Generating G1 multiexp table"); - - enter_block("Generating G2 multiexp table"); - window_table > g2_table = get_window_table(Fr::size_in_bits(), g2_window, G2::one()); - leave_block("Generating G2 multiexp table"); - - enter_block("Generate R1CS proving key"); - - enter_block("Generate knowledge commitments"); - enter_block("Compute the A-query", false); - knowledge_commitment_vector, G1 > A_query = kc_batch_exp(Fr::size_in_bits(), g1_window, g1_window, g1_table, g1_table, rA, rA*alphaA, At, chunks); - leave_block("Compute the A-query", false); - - enter_block("Compute the B-query", false); - knowledge_commitment_vector, G1 > B_query = kc_batch_exp(Fr::size_in_bits(), g2_window, g1_window, g2_table, g1_table, rB, rB*alphaB, Bt, chunks); - leave_block("Compute the B-query", false); - - enter_block("Compute the C-query", false); - knowledge_commitment_vector, G1 > C_query = kc_batch_exp(Fr::size_in_bits(), g1_window, g1_window, g1_table, g1_table, rC, rC*alphaC, Ct, chunks); - leave_block("Compute the C-query", false); - - enter_block("Compute the H-query", false); - G1_vector H_query = batch_exp(Fr::size_in_bits(), g1_window, g1_table, Ht); - leave_block("Compute the H-query", false); - - enter_block("Compute the K-query", false); - G1_vector K_query = batch_exp(Fr::size_in_bits(), g1_window, g1_table, Kt); -#ifdef USE_MIXED_ADDITION - batch_to_special >(K_query); -#endif - leave_block("Compute the K-query", false); - - leave_block("Generate knowledge commitments"); - - leave_block("Generate R1CS proving key"); - - enter_block("Generate R1CS verification key"); - G2 alphaA_g2 = alphaA * G2::one(); - G1 alphaB_g1 = alphaB * G1::one(); - G2 alphaC_g2 = alphaC * G2::one(); - G2 gamma_g2 = gamma * G2::one(); - G1 gamma_beta_g1 = (gamma * beta) * G1::one(); - G2 gamma_beta_g2 = (gamma * beta) * G2::one(); - G2 rC_Z_g2 = (rC * qap_inst.Zt) * G2::one(); - - enter_block("Encode IC query for R1CS verification key"); - G1 encoded_IC_base = (rA * IC_coefficients[0]) * G1::one(); - Fr_vector multiplied_IC_coefficients; - multiplied_IC_coefficients.reserve(qap_inst.num_inputs()); - for (size_t i = 1; i < qap_inst.num_inputs() + 1; ++i) - { - multiplied_IC_coefficients.emplace_back(rA * IC_coefficients[i]); - } - G1_vector encoded_IC_values = batch_exp(Fr::size_in_bits(), g1_window, g1_table, multiplied_IC_coefficients); - - leave_block("Encode IC query for R1CS verification key"); - leave_block("Generate R1CS verification key"); - - leave_block("Call to r1cs_ppzksnark_generator"); - - accumulation_vector > encoded_IC_query(std::move(encoded_IC_base), std::move(encoded_IC_values)); - - r1cs_ppzksnark_verification_key vk = r1cs_ppzksnark_verification_key(alphaA_g2, - alphaB_g1, - alphaC_g2, - gamma_g2, - gamma_beta_g1, - gamma_beta_g2, - rC_Z_g2, - encoded_IC_query); - r1cs_ppzksnark_proving_key pk = r1cs_ppzksnark_proving_key(std::move(A_query), - std::move(B_query), - std::move(C_query), - std::move(H_query), - std::move(K_query)); - - pk.print_size(); - vk.print_size(); - - return r1cs_ppzksnark_keypair(std::move(pk), std::move(vk)); -} - -template -knowledge_commitment r1cs_compute_proof_kc(const qap_witness > &qap_wit, - const knowledge_commitment_vector &kcv, - const Fr &zk_shift) -{ - knowledge_commitment returnval = kcv[0] + (zk_shift * kcv[qap_wit.num_variables()+1]); - -#ifdef DEBUG - assert(kcv.domain_size() == qap_wit.num_variables()+2); -#endif - -#ifdef MULTICORE - const size_t chunks = omp_get_max_threads(); // to override, set OMP_NUM_THREADS env var or call omp_set_num_threads() -#else - const size_t chunks = 1; -#endif - - returnval = returnval + kc_multi_exp_with_mixed_addition >( - kcv, - 1, - 1 + qap_wit.num_variables(), - qap_wit.coefficients_for_ABCs.begin(), - qap_wit.coefficients_for_ABCs.begin()+qap_wit.num_variables(), - chunks, - true - ); - - return returnval; -} - - - -template -G1 r1cs_compute_proof_K(const qap_witness> &qap_wit, const G1_vector &K_query, const G1 &zk_shift) -{ -#ifdef DEBUG - assert(K_query.size() == qap_wit.num_variables()+4); -#endif - -#ifdef MULTICORE - const size_t chunks = omp_get_max_threads(); // to override, set OMP_NUM_THREADS env var or call omp_set_num_threads() -#else - const size_t chunks = 1; -#endif - - G1 g_K = K_query[0] + zk_shift; - g_K = g_K + multi_exp_with_mixed_addition, Fr >( - K_query.begin()+1, - K_query.begin()+1+qap_wit.num_variables(), - qap_wit.coefficients_for_ABCs.begin(), - qap_wit.coefficients_for_ABCs.begin()+qap_wit.num_variables(), - chunks, - true - ); - - return g_K; -} - - -template -G1 r1cs_compute_proof_H(const qap_witness > &qap_wit, const G1_vector &H_query) -{ - G1 g_H = G1::zero(); - -#ifdef DEBUG - assert(H_query.size() == qap_wit.degree()+1); -#endif - -#ifdef MULTICORE - const size_t chunks = omp_get_max_threads(); // to override, set OMP_NUM_THREADS env var or call omp_set_num_threads() -#else - const size_t chunks = 1; -#endif - - g_H = g_H + multi_exp, Fr >( - H_query.begin(), - H_query.begin()+qap_wit.degree()+1, - qap_wit.coefficients_for_H.begin(), - qap_wit.coefficients_for_H.begin()+qap_wit.degree()+1, - chunks, - true - ); - - return g_H; -} - -template -r1cs_ppzksnark_proof r1cs_ppzksnark_prover(const r1cs_ppzksnark_proving_key &pk, - const r1cs_ppzksnark_primary_input &primary_input, - const r1cs_ppzksnark_auxiliary_input &auxiliary_input, - const r1cs_ppzksnark_constraint_system &constraint_system) -{ - enter_block("Call to r1cs_ppzksnark_prover"); - -#ifdef DEBUG - assert(constraint_system.is_satisfied(primary_input, auxiliary_input)); -#endif - - const Fr d1 = Fr::random_element(), - d2 = Fr::random_element(), - d3 = Fr::random_element(); - - enter_block("Compute the polynomial H"); - const qap_witness > qap_wit = r1cs_to_qap_witness_map(constraint_system, primary_input, auxiliary_input, d1, d2, d3); - leave_block("Compute the polynomial H"); - -#ifdef DEBUG - const Fr t = Fr::random_element(); - qap_instance_evaluation > qap_inst = r1cs_to_qap_instance_map_with_evaluation(constraint_system, t); - assert(qap_inst.is_satisfied(qap_wit)); -#endif - -#ifdef DEBUG - for (size_t i = 0; i < qap_wit.num_inputs() + 1; ++i) - { - assert(pk.A_query[i].g == G1::zero()); - } -#endif - - enter_block("Compute the proof"); - - enter_block("Compute answer to A-query", false); - auto g_A = r1cs_compute_proof_kc, G1 >(qap_wit, pk.A_query, qap_wit.d1); - leave_block("Compute answer to A-query", false); - - enter_block("Compute answer to B-query", false); - auto g_B = r1cs_compute_proof_kc, G1 >(qap_wit, pk.B_query, qap_wit.d2); - leave_block("Compute answer to B-query", false); - - enter_block("Compute answer to C-query", false); - auto g_C = r1cs_compute_proof_kc, G1 >(qap_wit, pk.C_query, qap_wit.d3); - leave_block("Compute answer to C-query", false); - - enter_block("Compute answer to H-query", false); - auto g_H = r1cs_compute_proof_H(qap_wit, pk.H_query); - leave_block("Compute answer to H-query", false); - - enter_block("Compute answer to K-query", false); - G1 zk_shift = qap_wit.d1*pk.K_query[qap_wit.num_variables()+1] + - qap_wit.d2*pk.K_query[qap_wit.num_variables()+2] + - qap_wit.d3*pk.K_query[qap_wit.num_variables()+3]; - G1 g_K = r1cs_compute_proof_K(qap_wit, pk.K_query, zk_shift); - leave_block("Compute answer to K-query", false); - - leave_block("Compute the proof"); - - leave_block("Call to r1cs_ppzksnark_prover"); - - r1cs_ppzksnark_proof proof = r1cs_ppzksnark_proof(std::move(g_A), std::move(g_B), std::move(g_C), std::move(g_H), std::move(g_K)); - - return proof; -} - -template -r1cs_ppzksnark_proof r1cs_ppzksnark_prover_streaming(std::ifstream &proving_key_file, - const r1cs_ppzksnark_primary_input &primary_input, - const r1cs_ppzksnark_auxiliary_input &auxiliary_input, - const r1cs_ppzksnark_constraint_system &constraint_system) -{ - enter_block("Call to r1cs_ppzksnark_prover_streaming"); - - const Fr d1 = Fr::random_element(), - d2 = Fr::random_element(), - d3 = Fr::random_element(); - - enter_block("Compute the polynomial H"); - const qap_witness > qap_wit = r1cs_to_qap_witness_map(constraint_system, primary_input, auxiliary_input, d1, d2, d3); - leave_block("Compute the polynomial H"); - - enter_block("Compute the proof"); - - r1cs_ppzksnark_proof proof; - - enter_block("Compute answer to A-query", false); - { - knowledge_commitment_vector, G1 > A_query; - proving_key_file >> A_query; - proof.g_A = r1cs_compute_proof_kc, G1 >(qap_wit, A_query, qap_wit.d1); - } - leave_block("Compute answer to A-query", false); - - enter_block("Compute answer to B-query", false); - { - knowledge_commitment_vector, G1 > B_query; - proving_key_file >> B_query; - proof.g_B = r1cs_compute_proof_kc, G1 >(qap_wit, B_query, qap_wit.d2); - } - leave_block("Compute answer to B-query", false); - - enter_block("Compute answer to C-query", false); - { - knowledge_commitment_vector, G1 > C_query; - proving_key_file >> C_query; - proof.g_C = r1cs_compute_proof_kc, G1 >(qap_wit, C_query, qap_wit.d3); - } - leave_block("Compute answer to C-query", false); - - enter_block("Compute answer to H-query", false); - { - G1_vector H_query; - proving_key_file >> H_query; - proof.g_H = r1cs_compute_proof_H(qap_wit, H_query); - } - leave_block("Compute answer to H-query", false); - - enter_block("Compute answer to K-query", false); - { - G1_vector K_query; - proving_key_file >> K_query; - G1 zk_shift = qap_wit.d1*K_query[qap_wit.num_variables()+1] + - qap_wit.d2*K_query[qap_wit.num_variables()+2] + - qap_wit.d3*K_query[qap_wit.num_variables()+3]; - proof.g_K = r1cs_compute_proof_K(qap_wit, K_query, zk_shift); - } - leave_block("Compute answer to K-query", false); - - leave_block("Compute the proof"); - - leave_block("Call to r1cs_ppzksnark_prover_streaming"); - - return proof; -} - -template -r1cs_ppzksnark_processed_verification_key r1cs_ppzksnark_verifier_process_vk(const r1cs_ppzksnark_verification_key &vk) -{ - enter_block("Call to r1cs_ppzksnark_verifier_process_vk"); - - r1cs_ppzksnark_processed_verification_key pvk; - pvk.pp_G2_one_precomp = ppT::precompute_G2(G2::one()); - pvk.vk_alphaA_g2_precomp = ppT::precompute_G2(vk.alphaA_g2); - pvk.vk_alphaB_g1_precomp = ppT::precompute_G1(vk.alphaB_g1); - pvk.vk_alphaC_g2_precomp = ppT::precompute_G2(vk.alphaC_g2); - pvk.vk_rC_Z_g2_precomp = ppT::precompute_G2(vk.rC_Z_g2); - pvk.vk_gamma_g2_precomp = ppT::precompute_G2(vk.gamma_g2); - pvk.vk_gamma_beta_g1_precomp = ppT::precompute_G1(vk.gamma_beta_g1); - pvk.vk_gamma_beta_g2_precomp = ppT::precompute_G2(vk.gamma_beta_g2); - - pvk.encoded_IC_query = vk.encoded_IC_query; - - leave_block("Call to r1cs_ppzksnark_verifier_process_vk"); - - return pvk; -} - -template -bool r1cs_ppzksnark_online_verifier_weak_IC(const r1cs_ppzksnark_processed_verification_key &pvk, - const r1cs_ppzksnark_primary_input &primary_input, - const r1cs_ppzksnark_proof &proof) -{ - assert(pvk.encoded_IC_query.domain_size() >= primary_input.size()); - - const accumulation_vector > accumulated_IC = pvk.encoded_IC_query.template accumulate_chunk >(primary_input.begin(), primary_input.end(), 0); - const G1 &acc = accumulated_IC.first; - - if (!proof.is_well_formed()) - { - return false; - } - - G1_precomp proof_g_A_g_precomp = ppT::precompute_G1(proof.g_A.g); - G1_precomp proof_g_A_h_precomp = ppT::precompute_G1(proof.g_A.h); - Fqk kc_A_1 = ppT::miller_loop(proof_g_A_g_precomp, pvk.vk_alphaA_g2_precomp); - Fqk kc_A_2 = ppT::miller_loop(proof_g_A_h_precomp, pvk.pp_G2_one_precomp); - GT kc_A = ppT::final_exponentiation(kc_A_1 * kc_A_2.unitary_inverse()); - if (kc_A != GT::one()) - { - return false; - } - - G2_precomp proof_g_B_g_precomp = ppT::precompute_G2(proof.g_B.g); - G1_precomp proof_g_B_h_precomp = ppT::precompute_G1(proof.g_B.h); - Fqk kc_B_1 = ppT::miller_loop(pvk.vk_alphaB_g1_precomp, proof_g_B_g_precomp); - Fqk kc_B_2 = ppT::miller_loop(proof_g_B_h_precomp, pvk.pp_G2_one_precomp); - GT kc_B = ppT::final_exponentiation(kc_B_1 * kc_B_2.unitary_inverse()); - if (kc_B != GT::one()) - { - return false; - } - - G1_precomp proof_g_C_g_precomp = ppT::precompute_G1(proof.g_C.g); - G1_precomp proof_g_C_h_precomp = ppT::precompute_G1(proof.g_C.h); - Fqk kc_C_1 = ppT::miller_loop(proof_g_C_g_precomp, pvk.vk_alphaC_g2_precomp); - Fqk kc_C_2 = ppT::miller_loop(proof_g_C_h_precomp, pvk.pp_G2_one_precomp); - GT kc_C = ppT::final_exponentiation(kc_C_1 * kc_C_2.unitary_inverse()); - if (kc_C != GT::one()) - { - return false; - } - - // check that g^((A+acc)*B)=g^(H*\Prod(t-\sigma)+C) - // equivalently, via pairings, that e(g^(A+acc), g^B) = e(g^H, g^Z) + e(g^C, g^1) - G1_precomp proof_g_A_g_acc_precomp = ppT::precompute_G1(proof.g_A.g + acc); - G1_precomp proof_g_H_precomp = ppT::precompute_G1(proof.g_H); - Fqk QAP_1 = ppT::miller_loop(proof_g_A_g_acc_precomp, proof_g_B_g_precomp); - Fqk QAP_23 = ppT::double_miller_loop(proof_g_H_precomp, pvk.vk_rC_Z_g2_precomp, proof_g_C_g_precomp, pvk.pp_G2_one_precomp); - GT QAP = ppT::final_exponentiation(QAP_1 * QAP_23.unitary_inverse()); - if (QAP != GT::one()) - { - return false; - } - - G1_precomp proof_g_K_precomp = ppT::precompute_G1(proof.g_K); - G1_precomp proof_g_A_g_acc_C_precomp = ppT::precompute_G1((proof.g_A.g + acc) + proof.g_C.g); - Fqk K_1 = ppT::miller_loop(proof_g_K_precomp, pvk.vk_gamma_g2_precomp); - Fqk K_23 = ppT::double_miller_loop(proof_g_A_g_acc_C_precomp, pvk.vk_gamma_beta_g2_precomp, pvk.vk_gamma_beta_g1_precomp, proof_g_B_g_precomp); - GT K = ppT::final_exponentiation(K_1 * K_23.unitary_inverse()); - if (K != GT::one()) - { - return false; - } - - return true; -} - -template -bool r1cs_ppzksnark_verifier_weak_IC(const r1cs_ppzksnark_verification_key &vk, - const r1cs_ppzksnark_primary_input &primary_input, - const r1cs_ppzksnark_proof &proof) -{ - enter_block("Call to r1cs_ppzksnark_verifier_weak_IC"); - r1cs_ppzksnark_processed_verification_key pvk = r1cs_ppzksnark_verifier_process_vk(vk); - bool result = r1cs_ppzksnark_online_verifier_weak_IC(pvk, primary_input, proof); - leave_block("Call to r1cs_ppzksnark_verifier_weak_IC"); - return result; -} - -template -bool r1cs_ppzksnark_online_verifier_strong_IC(const r1cs_ppzksnark_processed_verification_key &pvk, - const r1cs_ppzksnark_primary_input &primary_input, - const r1cs_ppzksnark_proof &proof) -{ - bool result = true; - enter_block("Call to r1cs_ppzksnark_online_verifier_strong_IC"); - - if (pvk.encoded_IC_query.domain_size() != primary_input.size()) - { - print_indent(); printf("Input length differs from expected (got %zu, expected %zu).\n", primary_input.size(), pvk.encoded_IC_query.domain_size()); - result = false; - } - else - { - result = r1cs_ppzksnark_online_verifier_weak_IC(pvk, primary_input, proof); - } - - leave_block("Call to r1cs_ppzksnark_online_verifier_strong_IC"); - return result; -} - -template -bool r1cs_ppzksnark_verifier_strong_IC(const r1cs_ppzksnark_verification_key &vk, - const r1cs_ppzksnark_primary_input &primary_input, - const r1cs_ppzksnark_proof &proof) -{ - enter_block("Call to r1cs_ppzksnark_verifier_strong_IC"); - r1cs_ppzksnark_processed_verification_key pvk = r1cs_ppzksnark_verifier_process_vk(vk); - bool result = r1cs_ppzksnark_online_verifier_strong_IC(pvk, primary_input, proof); - leave_block("Call to r1cs_ppzksnark_verifier_strong_IC"); - return result; -} - -template -bool r1cs_ppzksnark_affine_verifier_weak_IC(const r1cs_ppzksnark_verification_key &vk, - const r1cs_ppzksnark_primary_input &primary_input, - const r1cs_ppzksnark_proof &proof) -{ - enter_block("Call to r1cs_ppzksnark_affine_verifier_weak_IC"); - assert(vk.encoded_IC_query.domain_size() >= primary_input.size()); - - affine_ate_G2_precomp pvk_pp_G2_one_precomp = ppT::affine_ate_precompute_G2(G2::one()); - affine_ate_G2_precomp pvk_vk_alphaA_g2_precomp = ppT::affine_ate_precompute_G2(vk.alphaA_g2); - affine_ate_G1_precomp pvk_vk_alphaB_g1_precomp = ppT::affine_ate_precompute_G1(vk.alphaB_g1); - affine_ate_G2_precomp pvk_vk_alphaC_g2_precomp = ppT::affine_ate_precompute_G2(vk.alphaC_g2); - affine_ate_G2_precomp pvk_vk_rC_Z_g2_precomp = ppT::affine_ate_precompute_G2(vk.rC_Z_g2); - affine_ate_G2_precomp pvk_vk_gamma_g2_precomp = ppT::affine_ate_precompute_G2(vk.gamma_g2); - affine_ate_G1_precomp pvk_vk_gamma_beta_g1_precomp = ppT::affine_ate_precompute_G1(vk.gamma_beta_g1); - affine_ate_G2_precomp pvk_vk_gamma_beta_g2_precomp = ppT::affine_ate_precompute_G2(vk.gamma_beta_g2); - - enter_block("Compute input-dependent part of A"); - const accumulation_vector > accumulated_IC = vk.encoded_IC_query.template accumulate_chunk >(primary_input.begin(), primary_input.end(), 0); - assert(accumulated_IC.is_fully_accumulated()); - const G1 &acc = accumulated_IC.first; - leave_block("Compute input-dependent part of A"); - - bool result = true; - enter_block("Check knowledge commitment for A is valid"); - affine_ate_G1_precomp proof_g_A_g_precomp = ppT::affine_ate_precompute_G1(proof.g_A.g); - affine_ate_G1_precomp proof_g_A_h_precomp = ppT::affine_ate_precompute_G1(proof.g_A.h); - Fqk kc_A_miller = ppT::affine_ate_e_over_e_miller_loop(proof_g_A_g_precomp, pvk_vk_alphaA_g2_precomp, proof_g_A_h_precomp, pvk_pp_G2_one_precomp); - GT kc_A = ppT::final_exponentiation(kc_A_miller); - - if (kc_A != GT::one()) - { - print_indent(); printf("Knowledge commitment for A query incorrect.\n"); - result = false; - } - leave_block("Check knowledge commitment for A is valid"); - - enter_block("Check knowledge commitment for B is valid"); - affine_ate_G2_precomp proof_g_B_g_precomp = ppT::affine_ate_precompute_G2(proof.g_B.g); - affine_ate_G1_precomp proof_g_B_h_precomp = ppT::affine_ate_precompute_G1(proof.g_B.h); - Fqk kc_B_miller = ppT::affine_ate_e_over_e_miller_loop(pvk_vk_alphaB_g1_precomp, proof_g_B_g_precomp, proof_g_B_h_precomp, pvk_pp_G2_one_precomp); - GT kc_B = ppT::final_exponentiation(kc_B_miller); - if (kc_B != GT::one()) - { - print_indent(); printf("Knowledge commitment for B query incorrect.\n"); - result = false; - } - leave_block("Check knowledge commitment for B is valid"); - - enter_block("Check knowledge commitment for C is valid"); - affine_ate_G1_precomp proof_g_C_g_precomp = ppT::affine_ate_precompute_G1(proof.g_C.g); - affine_ate_G1_precomp proof_g_C_h_precomp = ppT::affine_ate_precompute_G1(proof.g_C.h); - Fqk kc_C_miller = ppT::affine_ate_e_over_e_miller_loop(proof_g_C_g_precomp, pvk_vk_alphaC_g2_precomp, proof_g_C_h_precomp, pvk_pp_G2_one_precomp); - GT kc_C = ppT::final_exponentiation(kc_C_miller); - if (kc_C != GT::one()) - { - print_indent(); printf("Knowledge commitment for C query incorrect.\n"); - result = false; - } - leave_block("Check knowledge commitment for C is valid"); - - enter_block("Check QAP divisibility"); - affine_ate_G1_precomp proof_g_A_g_acc_precomp = ppT::affine_ate_precompute_G1(proof.g_A.g + acc); - affine_ate_G1_precomp proof_g_H_precomp = ppT::affine_ate_precompute_G1(proof.g_H); - Fqk QAP_miller = ppT::affine_ate_e_times_e_over_e_miller_loop(proof_g_H_precomp, pvk_vk_rC_Z_g2_precomp, proof_g_C_g_precomp, pvk_pp_G2_one_precomp, proof_g_A_g_acc_precomp, proof_g_B_g_precomp); - GT QAP = ppT::final_exponentiation(QAP_miller); - if (QAP != GT::one()) - { - print_indent(); printf("QAP divisibility check failed.\n"); - result = false; - } - leave_block("Check QAP divisibility"); - - enter_block("Check same coefficients were used"); - affine_ate_G1_precomp proof_g_K_precomp = ppT::affine_ate_precompute_G1(proof.g_K); - affine_ate_G1_precomp proof_g_A_g_acc_C_precomp = ppT::affine_ate_precompute_G1((proof.g_A.g + acc) + proof.g_C.g); - Fqk K_miller = ppT::affine_ate_e_times_e_over_e_miller_loop(proof_g_A_g_acc_C_precomp, pvk_vk_gamma_beta_g2_precomp, pvk_vk_gamma_beta_g1_precomp, proof_g_B_g_precomp, proof_g_K_precomp, pvk_vk_gamma_g2_precomp); - GT K = ppT::final_exponentiation(K_miller); - if (K != GT::one()) - { - print_indent(); printf("Same-coefficient check failed.\n"); - result = false; - } - leave_block("Check same coefficients were used"); - - leave_block("Call to r1cs_ppzksnark_affine_verifier_weak_IC"); - - return result; -} - -} // libsnark -#endif // R1CS_PPZKSNARK_TCC_ diff --git a/src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark_params.hpp b/src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark_params.hpp deleted file mode 100644 index 4054b8e3b2f..00000000000 --- a/src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark_params.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/** @file - ***************************************************************************** - - Declaration of public-parameter selector for the R1CS ppzkSNARK. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#ifndef R1CS_PPZKSNARK_PARAMS_HPP_ -#define R1CS_PPZKSNARK_PARAMS_HPP_ - -#include "relations/constraint_satisfaction_problems/r1cs/r1cs.hpp" - -namespace libsnark { - -/** - * Below are various template aliases (used for convenience). - */ - -template -using r1cs_ppzksnark_constraint_system = r1cs_constraint_system >; - -template -using r1cs_ppzksnark_primary_input = r1cs_primary_input >; - -template -using r1cs_ppzksnark_auxiliary_input = r1cs_auxiliary_input >; - -} // libsnark - -#endif // R1CS_PPZKSNARK_PARAMS_HPP_ diff --git a/src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/tests/test_r1cs_ppzksnark.cpp b/src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/tests/test_r1cs_ppzksnark.cpp deleted file mode 100644 index 6c6e51857f5..00000000000 --- a/src/snark/libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/tests/test_r1cs_ppzksnark.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/** @file - ***************************************************************************** - Test program that exercises the ppzkSNARK (first generator, then - prover, then verifier) on a synthetic R1CS instance. - - ***************************************************************************** - * @author This file is part of libsnark, developed by SCIPR Lab - * and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ -#include -#include - -#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp" -#include "common/profiling.hpp" -#include "common/utils.hpp" -#include "relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.hpp" -#include "zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.hpp" - -#include - -using namespace libsnark; - -template -void test_r1cs_ppzksnark(size_t num_constraints, - size_t input_size) -{ - print_header("(enter) Test R1CS ppzkSNARK"); - - const bool test_serialization = true; - r1cs_example > example = generate_r1cs_example_with_binary_input >(num_constraints, input_size); - example.constraint_system.swap_AB_if_beneficial(); - const bool bit = run_r1cs_ppzksnark(example, test_serialization); - EXPECT_TRUE(bit); - - print_header("(leave) Test R1CS ppzkSNARK"); -} - -TEST(zk_proof_systems, r1cs_ppzksnark) -{ - start_profiling(); - - test_r1cs_ppzksnark(1000, 20); -} From 2a47986a0024931b13484365f7779a728db5489d Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 25 Jun 2019 17:29:32 +0200 Subject: [PATCH 261/395] Remove libgmp --- configure.ac | 14 ++------------ contrib/debian/copyright | 4 ---- depends/packages/libgmp.mk | 19 ------------------- depends/packages/packages.mk | 2 +- 4 files changed, 3 insertions(+), 36 deletions(-) delete mode 100644 depends/packages/libgmp.mk diff --git a/configure.ac b/configure.ac index d3aec4aa2d9..8766729625f 100644 --- a/configure.ac +++ b/configure.ac @@ -693,7 +693,7 @@ if test x$use_pkgconfig = xyes; then ) else # BUG: Fix this: - echo 'BUG: configure does not yet check for the following dependencies if pkg-config is not on the system: libcrypto++, libgmp' + echo 'BUG: configure does not yet check for the following dependencies if pkg-config is not on the system: libcrypto++' AC_CHECK_HEADER([openssl/crypto.h],,AC_MSG_ERROR(libcrypto headers missing)) AC_CHECK_LIB([crypto], [main],CRYPTO_LIBS=-lcrypto, AC_MSG_ERROR(libcrypto missing)) @@ -733,14 +733,6 @@ else fi fi -# These packages don't provide pkgconfig config files across all -# platforms, so we use older autoconf detection mechanisms: -AC_CHECK_HEADER([gmp.h],,AC_MSG_ERROR(libgmp headers missing)) -AC_CHECK_LIB([gmp],[[__gmpn_sub_n]],GMP_LIBS=-lgmp, [AC_MSG_ERROR(libgmp missing)]) - -AC_CHECK_HEADER([gmpxx.h],,AC_MSG_ERROR(libgmpxx headers missing)) -AC_CHECK_LIB([gmpxx],[main],GMPXX_LIBS=-lgmpxx, [AC_MSG_ERROR(libgmpxx missing)]) - RUST_LIBS="-lrustzcash" case $host in *mingw*) @@ -755,7 +747,7 @@ AX_CHECK_COMPILE_FLAG([-fwrapv],[CXXFLAGS="$CXXFLAGS -fwrapv"]) AX_CHECK_COMPILE_FLAG([-fno-strict-aliasing],[CXXFLAGS="$CXXFLAGS -fno-strict-aliasing"]) AX_CHECK_COMPILE_FLAG([-Wno-builtin-declaration-mismatch],[CXXFLAGS="$CXXFLAGS -Wno-builtin-declaration-mismatch"],,[[$CXXFLAG_WERROR]]) -LIBZCASH_LIBS="-lgmp -lgmpxx $BOOST_SYSTEM_LIB -lcrypto -lsodium $RUST_LIBS" +LIBZCASH_LIBS="$BOOST_SYSTEM_LIB -lcrypto -lsodium $RUST_LIBS" AC_MSG_CHECKING([whether to build bitcoind]) AM_CONDITIONAL([BUILD_BITCOIND], [test x$build_bitcoind = xyes]) @@ -885,8 +877,6 @@ AC_SUBST(SSL_LIBS) AC_SUBST(EVENT_LIBS) AC_SUBST(EVENT_PTHREADS_LIBS) AC_SUBST(ZMQ_LIBS) -AC_SUBST(GMP_LIBS) -AC_SUBST(GMPXX_LIBS) AC_SUBST(LIBZCASH_LIBS) AC_SUBST(PROTON_LIBS) AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile src/test/buildenv.py]) diff --git a/contrib/debian/copyright b/contrib/debian/copyright index a0442449939..34b08239e8f 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -109,10 +109,6 @@ Files: depends/sources/libsodium-*.tar.gz Copyright: 2013-2016 Frank Denis License: ISC -Files: depends/sources/gmp-*.tar.bz2 -Copyright: 1991, 1996, 1999, 2000, 2007 Free Software Foundation, Inc. -License: LGPL - Files: depends/sources/boost_*.tar.gz Copyright: 2008 Beman Dawes License: Boost-Software-License-1.0 diff --git a/depends/packages/libgmp.mk b/depends/packages/libgmp.mk deleted file mode 100644 index 2e55b05f61a..00000000000 --- a/depends/packages/libgmp.mk +++ /dev/null @@ -1,19 +0,0 @@ -package=libgmp -$(package)_version=6.1.1 -$(package)_download_path=https://gmplib.org/download/gmp/ -$(package)_file_name=gmp-$($(package)_version).tar.bz2 -$(package)_sha256_hash=a8109865f2893f1373b0a8ed5ff7429de8db696fc451b1036bd7bdf95bbeffd6 -$(package)_dependencies= -$(package)_config_opts=--enable-cxx --disable-shared - -define $(package)_config_cmds - $($(package)_autoconf) --host=$(host) --build=$(build) -endef - -define $(package)_build_cmds - $(MAKE) CPPFLAGS='-fPIC' -endef - -define $(package)_stage_cmds - $(MAKE) DESTDIR=$($(package)_staging_dir) install ; echo '=== staging find for $(package):' ; find $($(package)_staging_dir) -endef diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index e88bbd44183..b67c11e995b 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -34,7 +34,7 @@ rust_crates := \ crate_winapi_x86_64_pc_windows_gnu rust_packages := rust $(rust_crates) librustzcash proton_packages := proton -zcash_packages := libgmp libsodium +zcash_packages := libsodium packages := boost openssl libevent zeromq $(zcash_packages) googletest native_packages := native_ccache From 1f38ad2536dcd8faa6276e3af288b5ad733969b6 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 25 Jun 2019 22:15:40 +0200 Subject: [PATCH 262/395] Remove libsnark unit tests from full test suite --- qa/zcash/full_test_suite.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/qa/zcash/full_test_suite.py b/qa/zcash/full_test_suite.py index 0e8605cc3f1..fcbdf0cd828 100755 --- a/qa/zcash/full_test_suite.py +++ b/qa/zcash/full_test_suite.py @@ -138,7 +138,6 @@ def util_test(): 'no-dot-so', 'util-test', 'secp256k1', - 'libsnark', 'univalue', 'rpc', ] @@ -150,7 +149,6 @@ def util_test(): 'no-dot-so': ensure_no_dot_so_in_depends, 'util-test': util_test, 'secp256k1': ['make', '-C', repofile('src/secp256k1'), 'check'], - 'libsnark': ['make', '-C', repofile('src'), 'libsnark-tests'], 'univalue': ['make', '-C', repofile('src/univalue'), 'check'], 'rpc': [repofile('qa/pull-tester/rpc-tests.sh')], } From 3019c0be14536d59f334b25b083a241e115b6635 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 18 Jul 2019 12:10:07 +0200 Subject: [PATCH 263/395] test: Require minimum of Sapling for all RPC tests --- qa/rpc-tests/test_framework/util.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index ef933f5460c..6e992d5ace7 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -98,6 +98,10 @@ def initialize_chain(test_dir): for i in range(4): datadir=initialize_datadir("cache", i) args = [ os.getenv("BITCOIND", "bitcoind"), "-keypool=1", "-datadir="+datadir, "-discover=0" ] + args.extend([ + '-nuparams=5ba81b19:1', # Overwinter + '-nuparams=76b809bb:1', # Sapling + ]) if i > 0: args.append("-connect=127.0.0.1:"+str(p2p_port(0))) bitcoind_processes[i] = subprocess.Popen(args) @@ -183,6 +187,10 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary= if binary is None: binary = os.getenv("BITCOIND", "bitcoind") args = [ binary, "-datadir="+datadir, "-keypool=1", "-discover=0", "-rest" ] + args.extend([ + '-nuparams=5ba81b19:1', # Overwinter + '-nuparams=76b809bb:1', # Sapling + ]) if extra_args is not None: args.extend(extra_args) bitcoind_processes[i] = subprocess.Popen(args) devnull = open("/dev/null", "w+") From 0097df5c7aa6d4b47913059ea0e86ce9d12a29df Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 19 Jul 2019 14:07:43 +0200 Subject: [PATCH 264/395] test: Add Sapling v4 transactions to mininode framework --- qa/rpc-tests/test_framework/mininode.py | 104 +++++++++++++++++++++++- 1 file changed, 100 insertions(+), 4 deletions(-) diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 89b7ecf40b4..afe04410d8a 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -359,6 +359,70 @@ def __repr__(self): % (self.nVersion, repr(self.vHave)) +class SpendDescription(object): + def __init__(self): + self.cv = None + self.anchor = None + self.nullifier = None + self.rk = None + self.zkproof = None + self.spendAuthSig = None + + def deserialize(self, f): + self.cv = deser_uint256(f) + self.anchor = deser_uint256(f) + self.nullifier = deser_uint256(f) + self.rk = deser_uint256(f) + self.zkproof = f.read(192) + self.spendAuthSig = f.read(64) + + def serialize(self): + r = "" + r += ser_uint256(self.cv) + r += ser_uint256(self.anchor) + r += ser_uint256(self.nullifier) + r += ser_uint256(self.rk) + r += self.zkproof + r += self.spendAuthSig + return r + + def __repr__(self): + return "SpendDescription(cv=%064x, anchor=%064x, nullifier=%064x, rk=%064x, zkproof=%064x, spendAuthSig=%064x)" \ + % (self.cv, self.anchor, self.nullifier, self.rk, self.zkproof, self.spendauthsig) + + +class OutputDescription(object): + def __init__(self): + self.cv = None + self.cmu = None + self.ephemeralKey = None + self.encCiphertext = None + self.outCiphertext = None + self.zkproof = None + + def deserialize(self, f): + self.cv = deser_uint256(f) + self.cmu = deser_uint256(f) + self.ephemeralKey = deser_uint256(f) + self.encCiphertext = f.read(580) + self.outCiphertext = f.read(80) + self.zkproof = f.read(192) + + def serialize(self): + r = "" + r += ser_uint256(self.cv) + r += ser_uint256(self.cmu) + r += ser_uint256(self.ephemeralKey) + r += self.encCiphertext + r += self.outCiphertext + r += self.zkproof + return r + + def __repr__(self): + return "OutputDescription(cv=%064x, cmu=%064x, ephemeralKey=%064x, encCiphertext=%064x, outCiphertext=%064x, zkproof=%064x)" \ + % (self.cv, self.cmu, self.ephemeralKey, self.encCiphertext, self.outCiphertext, self.zkproof) + + G1_PREFIX_MASK = 0x02 G2_PREFIX_MASK = 0x0a @@ -585,9 +649,13 @@ def __init__(self, tx=None): self.vout = [] self.nLockTime = 0 self.nExpiryHeight = 0 + self.valueBalance = 0 + self.shieldedSpends = [] + self.shieldedOutputs = [] self.vJoinSplit = [] self.joinSplitPubKey = None self.joinSplitSig = None + self.bindingSig = None self.sha256 = None self.hash = None else: @@ -598,9 +666,13 @@ def __init__(self, tx=None): self.vout = copy.deepcopy(tx.vout) self.nLockTime = tx.nLockTime self.nExpiryHeight = tx.nExpiryHeight + self.valueBalance = tx.valueBalance + self.shieldedSpends = copy.deepcopy(tx.shieldedSpends) + self.shieldedOutputs = copy.deepcopy(tx.shieldedOutputs) self.vJoinSplit = copy.deepcopy(tx.vJoinSplit) self.joinSplitPubKey = tx.joinSplitPubKey self.joinSplitSig = tx.joinSplitSig + self.bindingSig = tx.bindingSig self.sha256 = None self.hash = None @@ -614,19 +686,30 @@ def deserialize(self, f): isOverwinterV3 = (self.fOverwintered and self.nVersionGroupId == OVERWINTER_VERSION_GROUP_ID and self.nVersion == 3) + isSaplingV4 = (self.fOverwintered and + self.nVersionGroupId == SAPLING_VERSION_GROUP_ID and + self.nVersion == 4) self.vin = deser_vector(f, CTxIn) self.vout = deser_vector(f, CTxOut) self.nLockTime = struct.unpack("= 2: self.vJoinSplit = deser_vector(f, JSDescription) if len(self.vJoinSplit) > 0: self.joinSplitPubKey = deser_uint256(f) self.joinSplitSig = f.read(64) + if isSaplingV4 and not (len(self.shieldedSpends) == 0 and len(self.shieldedOutputs) == 0): + self.bindingSig = f.read(64) + self.sha256 = None self.hash = None @@ -635,6 +718,9 @@ def serialize(self): isOverwinterV3 = (self.fOverwintered and self.nVersionGroupId == OVERWINTER_VERSION_GROUP_ID and self.nVersion == 3) + isSaplingV4 = (self.fOverwintered and + self.nVersionGroupId == SAPLING_VERSION_GROUP_ID and + self.nVersion == 4) r = "" r += struct.pack("= 2: r += ser_vector(self.vJoinSplit) if len(self.vJoinSplit) > 0: r += ser_uint256(self.joinSplitPubKey) r += self.joinSplitSig + if isSaplingV4 and not (len(self.shieldedSpends) == 0 and len(self.shieldedOutputs) == 0): + r += self.bindingSig return r def rehash(self): @@ -670,14 +762,18 @@ def is_valid(self): def __repr__(self): r = ("CTransaction(fOverwintered=%r nVersion=%i nVersionGroupId=0x%08x " - "vin=%s vout=%s nLockTime=%i nExpiryHeight=%i" + "vin=%s vout=%s nLockTime=%i nExpiryHeight=%i valueBalance=%i " + "shieldedSpends=%s shieldedOutputs=%s" % (self.fOverwintered, self.nVersion, self.nVersionGroupId, - repr(self.vin), repr(self.vout), self.nLockTime, self.nExpiryHeight)) + repr(self.vin), repr(self.vout), self.nLockTime, self.nExpiryHeight, + self.valueBalance, repr(self.shieldedSpends), repr(self.shieldedOutputs))) if self.nVersion >= 2: r += " vJoinSplit=%s" % repr(self.vJoinSplit) if len(self.vJoinSplit) > 0: r += " joinSplitPubKey=%064x joinSplitSig=%064x" \ (self.joinSplitPubKey, self.joinSplitSig) + if len(self.shieldedSpends) > 0 or len(self.shieldedOutputs) > 0: + r += " bindingSig=%064x" % self.bindingSig r += ")" return r From d7d4dd8a0f4a7fce35163c237ffeafb5320be767 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 19 Jul 2019 14:08:00 +0200 Subject: [PATCH 265/395] test: Add hashFinalSaplingProxy to create_block --- qa/rpc-tests/test_framework/blocktools.py | 4 +++- qa/rpc-tests/test_framework/mininode.py | 18 +++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/qa/rpc-tests/test_framework/blocktools.py b/qa/rpc-tests/test_framework/blocktools.py index 3a679f14e37..0f744d31e89 100644 --- a/qa/rpc-tests/test_framework/blocktools.py +++ b/qa/rpc-tests/test_framework/blocktools.py @@ -8,7 +8,7 @@ from script import CScript, OP_0, OP_EQUAL, OP_HASH160 # Create a block (with regtest difficulty) -def create_block(hashprev, coinbase, nTime=None, nBits=None): +def create_block(hashprev, coinbase, nTime=None, nBits=None, hashFinalSaplingRoot=None): block = CBlock() if nTime is None: import time @@ -16,6 +16,8 @@ def create_block(hashprev, coinbase, nTime=None, nBits=None): else: block.nTime = nTime block.hashPrevBlock = hashprev + if hashFinalSaplingRoot is not None: + block.hashFinalSaplingRoot = hashFinalSaplingRoot if nBits is None: block.nBits = 0x200f0f0f # Will break after a difficulty adjustment... else: diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index afe04410d8a..208a53db361 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -786,7 +786,7 @@ def __init__(self, header=None): self.nVersion = header.nVersion self.hashPrevBlock = header.hashPrevBlock self.hashMerkleRoot = header.hashMerkleRoot - self.hashReserved = header.hashReserved + self.hashFinalSaplingRoot = header.hashFinalSaplingRoot self.nTime = header.nTime self.nBits = header.nBits self.nNonce = header.nNonce @@ -799,7 +799,7 @@ def set_null(self): self.nVersion = 4 self.hashPrevBlock = 0 self.hashMerkleRoot = 0 - self.hashReserved = 0 + self.hashFinalSaplingRoot = 0 self.nTime = 0 self.nBits = 0 self.nNonce = 0 @@ -811,7 +811,7 @@ def deserialize(self, f): self.nVersion = struct.unpack(" Date: Fri, 19 Jul 2019 14:10:13 +0200 Subject: [PATCH 266/395] test: Update RPC tests to use a minimum of Sapling The p2p_nu_peer_management and rewind_index RPC tests still start from Sprout, because they are explicitly (and only) testing network behaviour across network upgrades. The mempool_tx_input_limit test is removed because the flag has been ignored since Sapling activation, and will be removed at some point in the near future. --- qa/pull-tester/rpc-tests.sh | 1 - qa/rpc-tests/bip65-cltv-p2p.py | 7 +- qa/rpc-tests/bipdersig-p2p.py | 7 +- qa/rpc-tests/finalsaplingroot.py | 3 - qa/rpc-tests/fundrawtransaction.py | 4 +- qa/rpc-tests/mempool_nu_activation.py | 99 ++++++++------- qa/rpc-tests/mempool_reorg.py | 4 +- qa/rpc-tests/mempool_tx_expiry.py | 24 +--- qa/rpc-tests/mempool_tx_input_limit.py | 139 --------------------- qa/rpc-tests/mergetoaddress_helper.py | 17 +-- qa/rpc-tests/mergetoaddress_mixednotes.py | 2 - qa/rpc-tests/mergetoaddress_sapling.py | 7 +- qa/rpc-tests/mergetoaddress_sprout.py | 4 +- qa/rpc-tests/p2p_node_bloom.py | 14 +-- qa/rpc-tests/p2p_txexpiringsoon.py | 11 +- qa/rpc-tests/p2p_txexpiry_dos.py | 13 +- qa/rpc-tests/rawtransactions.py | 2 +- qa/rpc-tests/regtest_signrawtransaction.py | 10 +- qa/rpc-tests/rewind_index.py | 12 +- qa/rpc-tests/signrawtransaction_offline.py | 6 +- qa/rpc-tests/sprout_sapling_migration.py | 7 +- qa/rpc-tests/test_framework/mininode.py | 8 +- qa/rpc-tests/turnstile.py | 7 +- qa/rpc-tests/wallet.py | 45 ++----- qa/rpc-tests/wallet_addresses.py | 40 +----- qa/rpc-tests/wallet_listnotes.py | 28 ++--- qa/rpc-tests/wallet_listreceived.py | 8 +- qa/rpc-tests/wallet_overwintertx.py | 87 +++++++------ qa/rpc-tests/wallet_persistence.py | 12 +- qa/rpc-tests/wallet_sapling.py | 48 ------- qa/rpc-tests/wallet_shieldcoinbase.py | 32 +---- 31 files changed, 194 insertions(+), 514 deletions(-) delete mode 100755 qa/rpc-tests/mempool_tx_input_limit.py diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index d7035144486..ca26c82a8b4 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -43,7 +43,6 @@ testScripts=( 'rest.py' 'mempool_spendcoinbase.py' 'mempool_reorg.py' - 'mempool_tx_input_limit.py' 'mempool_nu_activation.py' 'mempool_tx_expiry.py' 'httpbasics.py' diff --git a/qa/rpc-tests/bip65-cltv-p2p.py b/qa/rpc-tests/bip65-cltv-p2p.py index 1867ce284bb..c2091cc0c08 100755 --- a/qa/rpc-tests/bip65-cltv-p2p.py +++ b/qa/rpc-tests/bip65-cltv-p2p.py @@ -66,7 +66,9 @@ def invalidate_transaction(self, tx): def get_tests(self): self.coinbase_blocks = self.nodes[0].generate(1) self.nodes[0].generate(100) - self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0) + hashTip = self.nodes[0].getbestblockhash() + hashFinalSaplingRoot = int("0x" + self.nodes[0].getblock(hashTip)['finalsaplingroot'] + "L", 0) + self.tip = int ("0x" + hashTip + "L", 0) self.nodeaddress = self.nodes[0].getnewaddress() '''Check that the rules are enforced.''' @@ -83,7 +85,8 @@ def get_tests(self): self.block_bits = int("0x" + gbt["bits"], 0) block = create_block(self.tip, create_coinbase(101), - self.block_time, self.block_bits) + self.block_time, self.block_bits, + hashFinalSaplingRoot) block.nVersion = 4 block.vtx.append(spendtx) block.hashMerkleRoot = block.calc_merkle_root() diff --git a/qa/rpc-tests/bipdersig-p2p.py b/qa/rpc-tests/bipdersig-p2p.py index 404e10e3c28..ab0bed14396 100755 --- a/qa/rpc-tests/bipdersig-p2p.py +++ b/qa/rpc-tests/bipdersig-p2p.py @@ -73,7 +73,9 @@ def invalidate_transaction(self, tx): def get_tests(self): self.coinbase_blocks = self.nodes[0].generate(1) self.nodes[0].generate(100) - self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0) + hashTip = self.nodes[0].getbestblockhash() + hashFinalSaplingRoot = int("0x" + self.nodes[0].getblock(hashTip)['finalsaplingroot'] + "L", 0) + self.tip = int ("0x" + hashTip + "L", 0) self.nodeaddress = self.nodes[0].getnewaddress() '''Check that the rules are enforced.''' @@ -90,7 +92,8 @@ def get_tests(self): self.block_bits = int("0x" + gbt["bits"], 0) block = create_block(self.tip, create_coinbase(101), - self.block_time, self.block_bits) + self.block_time, self.block_bits, + hashFinalSaplingRoot) block.nVersion = 4 block.vtx.append(spendtx) block.hashMerkleRoot = block.calc_merkle_root() diff --git a/qa/rpc-tests/finalsaplingroot.py b/qa/rpc-tests/finalsaplingroot.py index 6d66cd83a14..1f3ac8e26b7 100755 --- a/qa/rpc-tests/finalsaplingroot.py +++ b/qa/rpc-tests/finalsaplingroot.py @@ -30,8 +30,6 @@ def setup_chain(self): def setup_network(self, split=False): self.nodes = start_nodes(4, self.options.tmpdir, extra_args=[[ - '-nuparams=5ba81b19:100', # Overwinter - '-nuparams=76b809bb:200', # Sapling '-txindex' # Avoid JSONRPC error: No information available about transaction ]] * 4 ) connect_nodes_bi(self.nodes,0,1) @@ -42,7 +40,6 @@ def setup_network(self, split=False): self.sync_all() def run_test(self): - # Activate Overwinter and Sapling self.nodes[0].generate(200) self.sync_all() diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index b17947dd2ec..45b999051d4 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -180,8 +180,8 @@ def run_test(self): outputs = { self.nodes[0].getnewaddress() : 1.0 } rawtx = self.nodes[2].createrawtransaction(inputs, outputs) - # 4-byte version + 1-byte vin count + 36-byte prevout then script_len - rawtx = rawtx[:82] + "0100" + rawtx[84:] + # 4-byte version + 4-byte versionGroupId + 1-byte vin count + 36-byte prevout then script_len + rawtx = rawtx[:90] + "0100" + rawtx[92:] dec_tx = self.nodes[2].decoderawtransaction(rawtx) assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) diff --git a/qa/rpc-tests/mempool_nu_activation.py b/qa/rpc-tests/mempool_nu_activation.py index 8a88deed125..c8f02b2c723 100755 --- a/qa/rpc-tests/mempool_nu_activation.py +++ b/qa/rpc-tests/mempool_nu_activation.py @@ -11,7 +11,6 @@ start_node, connect_nodes, wait_and_assert_operationid_status, get_coinbase_address ) -from test_framework.authproxy import JSONRPCException from decimal import Decimal @@ -22,9 +21,7 @@ class MempoolUpgradeActivationTest(BitcoinTestFramework): def setup_network(self): args = ["-checkmempool", "-debug=mempool", "-blockmaxsize=4000", - "-nuparams=5ba81b19:200", # Overwinter - "-nuparams=76b809bb:210", # Sapling - "-nuparams=2bb40e60:220", # Blossom + "-nuparams=2bb40e60:200", # Blossom ] self.nodes = [] self.nodes.append(start_node(0, self.options.tmpdir, args)) @@ -43,23 +40,24 @@ def run_test(self): # Mine 97 blocks. After this, nodes[1] blocks # 1 to 97 are spend-able. - self.nodes[0].generate(97) + self.nodes[0].generate(94) self.sync_all() # Shield some ZEC node1_taddr = get_coinbase_address(self.nodes[1]) - node0_zaddr = self.nodes[0].z_getnewaddress('sprout') + node0_zaddr = self.nodes[0].z_getnewaddress('sapling') recipients = [{'address': node0_zaddr, 'amount': Decimal('10')}] myopid = self.nodes[1].z_sendmany(node1_taddr, recipients, 1, Decimal('0')) print wait_and_assert_operationid_status(self.nodes[1], myopid) self.sync_all() + self.nodes[0].generate(1) + self.sync_all() # Mempool checks for activation of upgrade Y at height H on base X def nu_activation_checks(): - # Mine block H - 2. After this, the mempool expects - # block H - 1, which is the last X block. - self.nodes[0].generate(1) - self.sync_all() + # Start at block H - 5. After this, the mempool expects block H - 4, which is + # the last height at which we can create transactions for X blocks (due to the + # expiring-soon restrictions). # Mempool should be empty. assert_equal(set(self.nodes[0].getrawmempool()), set()) @@ -67,39 +65,64 @@ def nu_activation_checks(): # Check node 0 shielded balance assert_equal(self.nodes[0].z_getbalance(node0_zaddr), Decimal('10')) - # Fill the mempool with twice as many transactions as can fit into blocks + # Fill the mempool with more transactions than can fit into 4 blocks node0_taddr = self.nodes[0].getnewaddress() x_txids = [] - info = self.nodes[0].getblockchaininfo() - chaintip_branchid = info["consensus"]["chaintip"] - while self.nodes[1].getmempoolinfo()['bytes'] < 2 * 4000: - try: - x_txids.append(self.nodes[1].sendtoaddress(node0_taddr, Decimal('0.001'))) - except JSONRPCException: - # This fails due to expiring soon threshold, which applies from Overwinter onwards. - upgrade_name = info["upgrades"][chaintip_branchid]["name"] - assert_true(upgrade_name in ("Overwinter", "Sapling"), upgrade_name) - break + while self.nodes[1].getmempoolinfo()['bytes'] < 8 * 4000: + x_txids.append(self.nodes[1].sendtoaddress(node0_taddr, Decimal('0.001'))) self.sync_all() # Spends should be in the mempool x_mempool = set(self.nodes[0].getrawmempool()) assert_equal(x_mempool, set(x_txids)) + assert_equal(set(self.nodes[1].getrawmempool()), set(x_txids)) + + blocks = [] + + # Mine block H - 4. After this, the mempool expects + # block H - 3, which is an X block. + self.nodes[0].generate(1) + self.sync_all() + blocks.append(self.nodes[0].getblock(self.nodes[0].getbestblockhash())['tx']) + + # mempool should not be empty. + assert_true(len(set(self.nodes[0].getrawmempool())) > 0) + assert_true(len(set(self.nodes[1].getrawmempool())) > 0) + + # Mine block H - 3. After this, the mempool expects + # block H - 2, which is an X block. + self.nodes[0].generate(1) + self.sync_all() + blocks.append(self.nodes[0].getblock(self.nodes[0].getbestblockhash())['tx']) + + # mempool should not be empty. + assert_true(len(set(self.nodes[0].getrawmempool())) > 0) + assert_true(len(set(self.nodes[1].getrawmempool())) > 0) + + # Mine block H - 2. After this, the mempool expects + # block H - 1, which is an X block. + self.nodes[0].generate(1) + self.sync_all() + blocks.append(self.nodes[0].getblock(self.nodes[0].getbestblockhash())['tx']) + + # mempool should not be empty. + assert_true(len(set(self.nodes[0].getrawmempool())) > 0) + assert_true(len(set(self.nodes[1].getrawmempool())) > 0) # Mine block H - 1. After this, the mempool expects # block H, which is the first Y block. self.nodes[0].generate(1) self.sync_all() + blocks.append(self.nodes[0].getblock(self.nodes[0].getbestblockhash())['tx']) # mempool should be empty. assert_equal(set(self.nodes[0].getrawmempool()), set()) + assert_equal(set(self.nodes[1].getrawmempool()), set()) - # When transitioning from Sprout to Overwinter, where expiring soon threshold does not apply: - # Block H - 1 should contain a subset of the original mempool + # Blocks [H - 4..H - 1] should contain a subset of the original mempool # (with all other transactions having been dropped) - block_txids = self.nodes[0].getblock(self.nodes[0].getbestblockhash())['tx'] - if chaintip_branchid is "00000000": - assert(len(block_txids) < len(x_txids)) + assert(sum([len(block_txids) for block_txids in blocks]) < len(x_txids)) + for block_txids in blocks: for txid in block_txids[1:]: # Exclude coinbase assert(txid in x_txids) @@ -117,6 +140,7 @@ def nu_activation_checks(): # Spends should be in the mempool assert_equal(set(self.nodes[0].getrawmempool()), set(y_txids)) + assert_equal(set(self.nodes[1].getrawmempool()), set(y_txids)) # Node 0 note should be unspendable assert_equal(self.nodes[0].z_getbalance(node0_zaddr), Decimal('0')) @@ -135,6 +159,9 @@ def nu_activation_checks(): #assert_equal(set(self.nodes[0].getrawmempool()), set(block_txids[1:])) assert_equal(set(self.nodes[0].getrawmempool()), set()) + # Node 1's mempool is unaffected because it still considers block H - 1 valid. + assert_equal(set(self.nodes[1].getrawmempool()), set(y_txids)) + # Node 0 note should be spendable again assert_equal(self.nodes[0].z_getbalance(node0_zaddr), Decimal('10')) @@ -146,26 +173,10 @@ def nu_activation_checks(): self.nodes[1].generate(6) self.sync_all() - print('Testing Sprout -> Overwinter activation boundary') - # Current height = 197 - nu_activation_checks() - # Current height = 205 - - self.nodes[0].generate(2) - self.sync_all() - - print('Testing Overwinter -> Sapling activation boundary') - # Current height = 207 - nu_activation_checks() - # Current height = 215 - - self.nodes[0].generate(2) - self.sync_all() - print('Testing Sapling -> Blossom activation boundary') - # Current height = 217 + # Current height = 195 nu_activation_checks() - # Current height = 225 + # Current height = 205 if __name__ == '__main__': MempoolUpgradeActivationTest().main() diff --git a/qa/rpc-tests/mempool_reorg.py b/qa/rpc-tests/mempool_reorg.py index e37e39babf9..431c3716cb6 100755 --- a/qa/rpc-tests/mempool_reorg.py +++ b/qa/rpc-tests/mempool_reorg.py @@ -60,9 +60,9 @@ def run_test(self): # Create a block-height-locked transaction which will be invalid after reorg timelock_tx = self.nodes[0].createrawtransaction([{"txid": coinbase_txids[0], "vout": 0}], {node0_address: 10}) - # Set the time lock + # Set the time lock, ensuring we don't clobber the rest of the Sapling v4 tx format timelock_tx = timelock_tx.replace("ffffffff", "11111111", 1) - timelock_tx = timelock_tx[:-8] + hex(self.nodes[0].getblockcount() + 2)[2:] + "000000" + timelock_tx = timelock_tx[:-38] + hex(self.nodes[0].getblockcount() + 2)[2:] + "000000" + timelock_tx[-30:] timelock_tx = self.nodes[0].signrawtransaction(timelock_tx)["hex"] assert_raises(JSONRPCException, self.nodes[0].sendrawtransaction, timelock_tx) diff --git a/qa/rpc-tests/mempool_tx_expiry.py b/qa/rpc-tests/mempool_tx_expiry.py index 7d66fd0e986..12eabb2ac73 100755 --- a/qa/rpc-tests/mempool_tx_expiry.py +++ b/qa/rpc-tests/mempool_tx_expiry.py @@ -4,7 +4,7 @@ # file COPYING or https://www.opensource.org/licenses/mit-license.php . # -# Test proper expiry for transactions >= version 3 +# Test proper expiry for transactions >= version 4 # import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." @@ -17,7 +17,6 @@ from decimal import Decimal -SAPLING_ACTIVATION_HEIGHT = 300 TX_EXPIRING_SOON_THRESHOLD = 3 TX_EXPIRY_DELTA = 10 @@ -26,8 +25,6 @@ class MempoolTxExpiryTest(BitcoinTestFramework): def setup_nodes(self): return start_nodes(4, self.options.tmpdir, [[ - "-nuparams=5ba81b19:205", # Overwinter - "-nuparams=76b809bb:%d" % SAPLING_ACTIVATION_HEIGHT, # Sapling "-txexpirydelta=%d" % TX_EXPIRY_DELTA, "-debug=mempool" ]] * 4) @@ -40,22 +37,13 @@ def run_test(self): bob = self.nodes[2].getnewaddress() z_bob = self.nodes[2].z_getnewaddress('sapling') - # When Overwinter not yet activated, no expiryheight in tx - tx = self.nodes[0].sendtoaddress(bob, 0.01) - rawtx = self.nodes[0].getrawtransaction(tx, 1) - assert_equal(rawtx["overwintered"], False) - assert("expiryheight" not in rawtx) - - self.nodes[0].generate(6) - self.sync_all() - print "Splitting network..." self.split_network() - # When Overwinter is activated, test dependent txs + # Test dependent txs firstTx = self.nodes[0].sendtoaddress(alice, 0.1) firstTxInfo = self.nodes[0].getrawtransaction(firstTx, 1) - assert_equal(firstTxInfo["version"], 3) + assert_equal(firstTxInfo["version"], 4) assert_equal(firstTxInfo["overwintered"], True) assert("expiryheight" in firstTxInfo) print "First tx expiry height:", firstTxInfo['expiryheight'] @@ -88,12 +76,6 @@ def run_test(self): assert_equal(set(self.nodes[0].getrawmempool()), set()) assert_equal(set(self.nodes[2].getrawmempool()), set()) - # Activate Sapling - n = SAPLING_ACTIVATION_HEIGHT - self.nodes[0].getblockcount() - assert(n > 0) - self.nodes[0].generate(n) - self.sync_all() - ## Shield one of Alice's coinbase funds to her zaddr res = self.nodes[0].z_shieldcoinbase("*", z_alice, 0.0001, 1) wait_and_assert_operationid_status(self.nodes[0], res['opid']) diff --git a/qa/rpc-tests/mempool_tx_input_limit.py b/qa/rpc-tests/mempool_tx_input_limit.py deleted file mode 100755 index 66cccff35e4..00000000000 --- a/qa/rpc-tests/mempool_tx_input_limit.py +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2017 The Zcash developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or https://www.opensource.org/licenses/mit-license.php . - -import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." - -from test_framework.test_framework import BitcoinTestFramework -from test_framework.authproxy import JSONRPCException -from test_framework.util import assert_equal, initialize_chain_clean, \ - start_node, connect_nodes, wait_and_assert_operationid_status, \ - get_coinbase_address - -from decimal import Decimal - -# Test -mempooltxinputlimit -class MempoolTxInputLimitTest(BitcoinTestFramework): - - alert_filename = None # Set by setup_network - - def setup_network(self): - args = ["-checkmempool", "-debug=mempool", "-mempooltxinputlimit=2", "-nuparams=5ba81b19:110"] - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, args)) - self.nodes.append(start_node(1, self.options.tmpdir, args)) - connect_nodes(self.nodes[1], 0) - self.is_network_split = False - self.sync_all - - def setup_chain(self): - print "Initializing test directory "+self.options.tmpdir - initialize_chain_clean(self.options.tmpdir, 2) - - def call_z_sendmany(self, from_addr, to_addr, amount): - recipients = [] - recipients.append({"address": to_addr, "amount": amount}) - myopid = self.nodes[0].z_sendmany(from_addr, recipients) - return wait_and_assert_operationid_status(self.nodes[0], myopid) - - def run_test(self): - self.nodes[0].generate(100) - self.sync_all() - # Mine three blocks. After this, nodes[0] blocks - # 1, 2, and 3 are spend-able. - self.nodes[1].generate(3) - self.sync_all() - - # Check 1: z_sendmany is limited by -mempooltxinputlimit - - # Add zaddr to node 0 - node0_zaddr = self.nodes[0].z_getnewaddress('sprout') - - # Send three inputs from node 0 taddr to zaddr to get out of coinbase - node0_taddr = get_coinbase_address(self.nodes[0]) - recipients = [] - recipients.append({"address":node0_zaddr, "amount":Decimal('30.0')-Decimal('0.0001')}) # utxo amount less fee - myopid = self.nodes[0].z_sendmany(node0_taddr, recipients) - - # Spend should fail due to -mempooltxinputlimit - wait_and_assert_operationid_status(self.nodes[0], myopid, "failed", "Too many transparent inputs 3 > limit 2", 120) - - # Mempool should be empty. - assert_equal(set(self.nodes[0].getrawmempool()), set()) - - # Reduce amount to only use two inputs - spend_zaddr_amount = Decimal('20.0') - Decimal('0.0001') - spend_zaddr_id = self.call_z_sendmany(node0_taddr, node0_zaddr, spend_zaddr_amount) # utxo amount less fee - self.sync_all() - - # Spend should be in the mempool - assert_equal(set(self.nodes[0].getrawmempool()), set([ spend_zaddr_id ])) - - self.nodes[0].generate(1) - self.sync_all() - - # mempool should be empty. - assert_equal(set(self.nodes[0].getrawmempool()), set()) - - # Check 2: sendfrom is limited by -mempooltxinputlimit - recipients = [] - spend_taddr_amount = spend_zaddr_amount - Decimal('0.0001') - spend_taddr_output = Decimal('8') - - # Create three outputs - recipients.append({"address":self.nodes[1].getnewaddress(), "amount": spend_taddr_output}) - recipients.append({"address":self.nodes[1].getnewaddress(), "amount": spend_taddr_output}) - recipients.append({"address":self.nodes[1].getnewaddress(), "amount": spend_taddr_amount - spend_taddr_output - spend_taddr_output}) - - myopid = self.nodes[0].z_sendmany(node0_zaddr, recipients) - wait_and_assert_operationid_status(self.nodes[0], myopid) - self.sync_all() - self.nodes[1].generate(1) - self.sync_all() - - # Should use three UTXOs and fail - try: - self.nodes[1].sendfrom("", node0_taddr, spend_taddr_amount - Decimal('1')) - assert(False) - except JSONRPCException,e: - msg = e.error['message'] - assert_equal("Too many transparent inputs 3 > limit 2", msg) - - # mempool should be empty. - assert_equal(set(self.nodes[1].getrawmempool()), set()) - - # Should use two UTXOs and succeed - spend_taddr_id2 = self.nodes[1].sendfrom("", node0_taddr, spend_taddr_output + spend_taddr_output - Decimal('1')) - - # Spend should be in the mempool - assert_equal(set(self.nodes[1].getrawmempool()), set([ spend_taddr_id2 ])) - - # Mine three blocks - self.nodes[1].generate(3) - self.sync_all() - # The next block to be mined, 109, is the last Sprout block - bci = self.nodes[0].getblockchaininfo() - assert_equal(bci['consensus']['chaintip'], '00000000') - assert_equal(bci['consensus']['nextblock'], '00000000') - - # z_sendmany should be limited by -mempooltxinputlimit - recipients = [] - recipients.append({"address":node0_zaddr, "amount":Decimal('30.0')-Decimal('0.0001')}) # utxo amount less fee - myopid = self.nodes[0].z_sendmany(node0_taddr, recipients) - wait_and_assert_operationid_status(self.nodes[0], myopid, 'failed', 'Too many transparent inputs 3 > limit 2') - - # Mine one block - self.nodes[1].generate(1) - self.sync_all() - # The next block to be mined, 110, is the first Overwinter block - bci = self.nodes[0].getblockchaininfo() - assert_equal(bci['consensus']['chaintip'], '00000000') - assert_equal(bci['consensus']['nextblock'], '5ba81b19') - - # z_sendmany should no longer be limited by -mempooltxinputlimit - myopid = self.nodes[0].z_sendmany(node0_taddr, recipients) - wait_and_assert_operationid_status(self.nodes[0], myopid) - -if __name__ == '__main__': - MempoolTxInputLimitTest().main() diff --git a/qa/rpc-tests/mergetoaddress_helper.py b/qa/rpc-tests/mergetoaddress_helper.py index 97380010478..653a2882f8b 100755 --- a/qa/rpc-tests/mergetoaddress_helper.py +++ b/qa/rpc-tests/mergetoaddress_helper.py @@ -27,7 +27,7 @@ def assert_mergetoaddress_exception(expected_error_msg, merge_to_address_lambda) class MergeToAddressHelper: - def __init__(self, addr_type, any_zaddr, utxos_to_generate, utxos_in_tx1, utxos_in_tx2, test_mempooltxinputlimit): + def __init__(self, addr_type, any_zaddr, utxos_to_generate, utxos_in_tx1, utxos_in_tx2): self.addr_type = addr_type self.any_zaddr = [any_zaddr] self.any_zaddr_or_utxo = [any_zaddr, "ANY_TADDR"] @@ -35,7 +35,6 @@ def __init__(self, addr_type, any_zaddr, utxos_to_generate, utxos_in_tx1, utxos_ self.utxos_to_generate = utxos_to_generate self.utxos_in_tx1 = utxos_in_tx1 self.utxos_in_tx2 = utxos_in_tx2 - self.test_mempooltxinputlimit = test_mempooltxinputlimit def setup_chain(self, test): print("Initializing test directory "+test.options.tmpdir) @@ -282,16 +281,10 @@ def run_test(self, test): test.nodes[1].generate(1) test.sync_all() - # Verify maximum number of UTXOs which node 2 can shield is limited by option -mempooltxinputlimit - # This option is used when the limit parameter is set to 0. - - # -mempooltxinputlimit is not used after overwinter activation - if self.test_mempooltxinputlimit: - expected_to_merge = 7 - expected_remaining = 13 - else: - expected_to_merge = 20 - expected_remaining = 0 + # Verify maximum number of UTXOs which node 2 can shield is not limited + # when the limit parameter is set to 0. + expected_to_merge = 20 + expected_remaining = 0 result = test.nodes[2].z_mergetoaddress([n2taddr], myzaddr, Decimal('0.0001'), 0) assert_equal(result["mergingUTXOs"], expected_to_merge) diff --git a/qa/rpc-tests/mergetoaddress_mixednotes.py b/qa/rpc-tests/mergetoaddress_mixednotes.py index 3e06e42e28d..be78d144487 100755 --- a/qa/rpc-tests/mergetoaddress_mixednotes.py +++ b/qa/rpc-tests/mergetoaddress_mixednotes.py @@ -15,8 +15,6 @@ class MergeToAddressMixedNotes(BitcoinTestFramework): def setup_nodes(self): return start_nodes(4, self.options.tmpdir, [[ - '-nuparams=5ba81b19:100', # Overwinter - '-nuparams=76b809bb:100', # Sapling '-experimentalfeatures', '-zmergetoaddress' ]] * 4) diff --git a/qa/rpc-tests/mergetoaddress_sapling.py b/qa/rpc-tests/mergetoaddress_sapling.py index 72ca6929aba..9c3c96e13f2 100755 --- a/qa/rpc-tests/mergetoaddress_sapling.py +++ b/qa/rpc-tests/mergetoaddress_sapling.py @@ -12,16 +12,13 @@ class MergeToAddressSapling (BitcoinTestFramework): # 13505 would be the maximum number of utxos based on the transaction size limits for Sapling # but testing this causes the test to take an indeterminately long time to run. - helper = MergeToAddressHelper('sapling', 'ANY_SAPLING', 800, 800, 0, False) + helper = MergeToAddressHelper('sapling', 'ANY_SAPLING', 800, 800, 0) def setup_chain(self): self.helper.setup_chain(self) def setup_network(self, split=False): - self.helper.setup_network(self, [ - '-nuparams=5ba81b19:100', # Overwinter - '-nuparams=76b809bb:100', # Sapling - ]) + self.helper.setup_network(self) def run_test(self): self.helper.run_test(self) diff --git a/qa/rpc-tests/mergetoaddress_sprout.py b/qa/rpc-tests/mergetoaddress_sprout.py index 8d3e2cbec83..669606c1eb3 100755 --- a/qa/rpc-tests/mergetoaddress_sprout.py +++ b/qa/rpc-tests/mergetoaddress_sprout.py @@ -10,7 +10,9 @@ class MergeToAddressSprout (BitcoinTestFramework): - helper = MergeToAddressHelper('sprout', 'ANY_SPROUT', 800, 662, 138, True) + # 13505 would be the maximum number of utxos based on the transaction size limits for Sapling + # but testing this causes the test to take an indeterminately long time to run. + helper = MergeToAddressHelper('sprout', 'ANY_SPROUT', 800, 800, 0) def setup_chain(self): self.helper.setup_chain(self) diff --git a/qa/rpc-tests/p2p_node_bloom.py b/qa/rpc-tests/p2p_node_bloom.py index dd8709c046e..7c5a07b23ba 100755 --- a/qa/rpc-tests/p2p_node_bloom.py +++ b/qa/rpc-tests/p2p_node_bloom.py @@ -6,7 +6,7 @@ import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." from test_framework.mininode import NodeConn, NodeConnCB, NetworkThread, \ - msg_filteradd, msg_filterclear, mininode_lock, SPROUT_PROTO_VERSION + msg_filteradd, msg_filterclear, mininode_lock, SAPLING_PROTO_VERSION from test_framework.test_framework import BitcoinTestFramework from test_framework.util import initialize_chain_clean, start_nodes, \ p2p_port, assert_equal @@ -74,10 +74,10 @@ def run_test(self): # Verify mininodes are connected to zcashd nodes peerinfo = self.nodes[0].getpeerinfo() versions = [x["version"] for x in peerinfo] - assert_equal(1, versions.count(SPROUT_PROTO_VERSION)) + assert_equal(1, versions.count(SAPLING_PROTO_VERSION)) peerinfo = self.nodes[1].getpeerinfo() versions = [x["version"] for x in peerinfo] - assert_equal(1, versions.count(SPROUT_PROTO_VERSION)) + assert_equal(1, versions.count(SAPLING_PROTO_VERSION)) # Mininodes send filterclear message to zcashd node. nobf_node.send_message(msg_filterclear()) @@ -88,10 +88,10 @@ def run_test(self): # Verify mininodes are still connected to zcashd nodes peerinfo = self.nodes[0].getpeerinfo() versions = [x["version"] for x in peerinfo] - assert_equal(1, versions.count(SPROUT_PROTO_VERSION)) + assert_equal(1, versions.count(SAPLING_PROTO_VERSION)) peerinfo = self.nodes[1].getpeerinfo() versions = [x["version"] for x in peerinfo] - assert_equal(1, versions.count(SPROUT_PROTO_VERSION)) + assert_equal(1, versions.count(SAPLING_PROTO_VERSION)) # Mininodes send filteradd message to zcashd node. nobf_node.send_message(msg_filteradd()) @@ -102,10 +102,10 @@ def run_test(self): # Verify NoBF mininode has been dropped, and BF mininode is still connected. peerinfo = self.nodes[0].getpeerinfo() versions = [x["version"] for x in peerinfo] - assert_equal(0, versions.count(SPROUT_PROTO_VERSION)) + assert_equal(0, versions.count(SAPLING_PROTO_VERSION)) peerinfo = self.nodes[1].getpeerinfo() versions = [x["version"] for x in peerinfo] - assert_equal(1, versions.count(SPROUT_PROTO_VERSION)) + assert_equal(1, versions.count(SAPLING_PROTO_VERSION)) [ c.disconnect_node() for c in connections ] diff --git a/qa/rpc-tests/p2p_txexpiringsoon.py b/qa/rpc-tests/p2p_txexpiringsoon.py index bd631a5adb7..01fd907683a 100755 --- a/qa/rpc-tests/p2p_txexpiringsoon.py +++ b/qa/rpc-tests/p2p_txexpiringsoon.py @@ -7,7 +7,7 @@ from test_framework.authproxy import JSONRPCException from test_framework.mininode import NodeConn, NetworkThread, CInv, \ - msg_mempool, msg_getdata, msg_tx, mininode_lock, OVERWINTER_PROTO_VERSION + msg_mempool, msg_getdata, msg_tx, mininode_lock, SAPLING_PROTO_VERSION from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, connect_nodes_bi, fail, \ initialize_chain_clean, p2p_port, start_nodes, sync_blocks, sync_mempools @@ -23,8 +23,7 @@ def setup_chain(self): initialize_chain_clean(self.options.tmpdir, 3) def setup_network(self): - self.nodes = start_nodes(3, self.options.tmpdir, - extra_args=[['-nuparams=5ba81b19:10']] * 3) + self.nodes = start_nodes(3, self.options.tmpdir) connect_nodes_bi(self.nodes, 0, 1) # We don't connect node 2 @@ -85,7 +84,7 @@ def run_test(self): testnode0 = TestNode() connections = [] connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], - testnode0, "regtest", OVERWINTER_PROTO_VERSION)) + testnode0, "regtest", SAPLING_PROTO_VERSION)) testnode0.add_connection(connections[0]) # Start up network handling in another thread @@ -95,7 +94,7 @@ def run_test(self): # Verify mininodes are connected to zcashd nodes peerinfo = self.nodes[0].getpeerinfo() versions = [x["version"] for x in peerinfo] - assert_equal(1, versions.count(OVERWINTER_PROTO_VERSION)) + assert_equal(1, versions.count(SAPLING_PROTO_VERSION)) assert_equal(0, peerinfo[0]["banscore"]) # Mine some blocks so we can spend @@ -150,7 +149,7 @@ def run_test(self): # Set up test node for node 2 testnode2 = TestNode() connections.append(NodeConn('127.0.0.1', p2p_port(2), self.nodes[2], - testnode2, "regtest", OVERWINTER_PROTO_VERSION)) + testnode2, "regtest", SAPLING_PROTO_VERSION)) testnode2.add_connection(connections[-1]) # Verify block count diff --git a/qa/rpc-tests/p2p_txexpiry_dos.py b/qa/rpc-tests/p2p_txexpiry_dos.py index e51bf2cb6db..633f00284aa 100755 --- a/qa/rpc-tests/p2p_txexpiry_dos.py +++ b/qa/rpc-tests/p2p_txexpiry_dos.py @@ -6,7 +6,7 @@ import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." from test_framework.mininode import NodeConn, NetworkThread, \ - msg_tx, OVERWINTER_PROTO_VERSION + msg_tx, SAPLING_PROTO_VERSION from test_framework.test_framework import BitcoinTestFramework from test_framework.util import initialize_chain_clean, start_nodes, \ p2p_port, assert_equal @@ -22,15 +22,14 @@ def setup_chain(self): initialize_chain_clean(self.options.tmpdir, 1) def setup_network(self): - self.nodes = start_nodes(1, self.options.tmpdir, - extra_args=[['-nuparams=5ba81b19:10']]) + self.nodes = start_nodes(1, self.options.tmpdir) def run_test(self): test_node = TestNode() connections = [] connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], - test_node, "regtest", OVERWINTER_PROTO_VERSION)) + test_node, "regtest", SAPLING_PROTO_VERSION)) test_node.add_connection(connections[0]) # Start up network handling in another thread @@ -41,7 +40,7 @@ def run_test(self): # Verify mininodes are connected to zcashd nodes peerinfo = self.nodes[0].getpeerinfo() versions = [x["version"] for x in peerinfo] - assert_equal(1, versions.count(OVERWINTER_PROTO_VERSION)) + assert_equal(1, versions.count(SAPLING_PROTO_VERSION)) assert_equal(0, peerinfo[0]["banscore"]) coinbase_blocks = self.nodes[0].generate(1) @@ -62,7 +61,7 @@ def run_test(self): # and still has a banscore of 0. peerinfo = self.nodes[0].getpeerinfo() versions = [x["version"] for x in peerinfo] - assert_equal(1, versions.count(OVERWINTER_PROTO_VERSION)) + assert_equal(1, versions.count(SAPLING_PROTO_VERSION)) assert_equal(0, peerinfo[0]["banscore"]) # Mine a block and resend the transaction @@ -75,7 +74,7 @@ def run_test(self): # but has a banscore of 10. peerinfo = self.nodes[0].getpeerinfo() versions = [x["version"] for x in peerinfo] - assert_equal(1, versions.count(OVERWINTER_PROTO_VERSION)) + assert_equal(1, versions.count(SAPLING_PROTO_VERSION)) assert_equal(10, peerinfo[0]["banscore"]) [c.disconnect_node() for c in connections] diff --git a/qa/rpc-tests/rawtransactions.py b/qa/rpc-tests/rawtransactions.py index 43768695784..0efd9e93709 100755 --- a/qa/rpc-tests/rawtransactions.py +++ b/qa/rpc-tests/rawtransactions.py @@ -132,7 +132,7 @@ def run_test(self): break; bal = self.nodes[0].getbalance() - inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex']}] + inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "amount" : vout['value']}] outputs = { self.nodes[0].getnewaddress() : 2.199 } rawTx = self.nodes[2].createrawtransaction(inputs, outputs) rawTxPartialSigned = self.nodes[1].signrawtransaction(rawTx, inputs) diff --git a/qa/rpc-tests/regtest_signrawtransaction.py b/qa/rpc-tests/regtest_signrawtransaction.py index 4b2b524bcad..acdba0397e6 100755 --- a/qa/rpc-tests/regtest_signrawtransaction.py +++ b/qa/rpc-tests/regtest_signrawtransaction.py @@ -6,16 +6,10 @@ import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import start_nodes, wait_and_assert_operationid_status +from test_framework.util import wait_and_assert_operationid_status class RegtestSignrawtransactionTest (BitcoinTestFramework): - def setup_nodes(self): - return start_nodes(4, self.options.tmpdir, [[ - "-nuparams=5ba81b19:200", # Overwinter - "-nuparams=76b809bb:206", # Sapling - ]] * 4) - def run_test(self): self.nodes[0].generate(1) self.sync_all() @@ -26,7 +20,7 @@ def run_test(self): self.nodes[0].generate(1) self.sync_all() - # Create and sign Overwinter transaction. + # Create and sign Sapling transaction. # If the incorrect consensus branch id is selected, there will be a signing error. opid = self.nodes[1].z_sendmany(taddr, [{'address': zaddr1, 'amount': 1}]) diff --git a/qa/rpc-tests/rewind_index.py b/qa/rpc-tests/rewind_index.py index 9a30f393ca9..14ad3f86abe 100755 --- a/qa/rpc-tests/rewind_index.py +++ b/qa/rpc-tests/rewind_index.py @@ -11,6 +11,8 @@ import time +FAKE_SPROUT = ['-nuparams=5ba81b19:210', '-nuparams=76b809bb:220'] +FAKE_OVERWINTER = ['-nuparams=5ba81b19:10', '-nuparams=76b809bb:220'] class RewindBlockIndexTest (BitcoinTestFramework): @@ -22,7 +24,11 @@ def setup_network(self, split=False): # Node 0 - Overwinter, then Sprout, then Overwinter again # Node 1 - Sprout # Node 2 - Overwinter - self.nodes = start_nodes(3, self.options.tmpdir, extra_args=[['-nuparams=5ba81b19:10'], [], ['-nuparams=5ba81b19:10']]) + self.nodes = start_nodes(3, self.options.tmpdir, extra_args=[ + FAKE_OVERWINTER, + FAKE_SPROUT, + FAKE_OVERWINTER, + ]) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) @@ -52,7 +58,7 @@ def run_test (self): print("Switching node 0 from Overwinter to Sprout") self.nodes[0].stop() bitcoind_processes[0].wait() - self.nodes[0] = start_node(0,self.options.tmpdir) + self.nodes[0] = start_node(0, self.options.tmpdir, extra_args=FAKE_SPROUT) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) @@ -69,7 +75,7 @@ def run_test (self): print("Switching node 0 from Sprout to Overwinter") self.nodes[0].stop() bitcoind_processes[0].wait() - self.nodes[0] = start_node(0,self.options.tmpdir, extra_args=['-nuparams=5ba81b19:10']) + self.nodes[0] = start_node(0, self.options.tmpdir, extra_args=FAKE_OVERWINTER) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) diff --git a/qa/rpc-tests/signrawtransaction_offline.py b/qa/rpc-tests/signrawtransaction_offline.py index a4478c3c482..0f3942bff1a 100755 --- a/qa/rpc-tests/signrawtransaction_offline.py +++ b/qa/rpc-tests/signrawtransaction_offline.py @@ -13,7 +13,7 @@ def setup_chain(self): initialize_chain_clean(self.options.tmpdir, 2) def setup_network(self): - self.nodes = [ start_node(0, self.options.tmpdir, ["-nuparams=5ba81b19:10"]) ] + self.nodes = [ start_node(0, self.options.tmpdir, ["-nuparams=2bb40e60:10"]) ] self.is_network_split = False self.sync_all() @@ -22,7 +22,7 @@ def run_test(self): print "Mining blocks..." self.nodes[0].generate(101) - offline_node = start_node(1, self.options.tmpdir, ["-maxconnections=0", "-nuparams=5ba81b19:10"]) + offline_node = start_node(1, self.options.tmpdir, ["-maxconnections=0", "-nuparams=2bb40e60:10"]) self.nodes.append(offline_node) assert_equal(0, len(offline_node.getpeerinfo())) # make sure node 1 has no peers @@ -49,7 +49,7 @@ def run_test(self): pass # Passing in the consensus branch id resolves the issue for offline regtest nodes. - signed_tx = offline_node.signrawtransaction(create_hex, sign_inputs, privkeys, "ALL", "5ba81b19") + signed_tx = offline_node.signrawtransaction(create_hex, sign_inputs, privkeys, "ALL", "2bb40e60") # If we return the transaction hash, then we have have not thrown an error (success) online_tx_hash = self.nodes[0].sendrawtransaction(signed_tx['hex']) diff --git a/qa/rpc-tests/sprout_sapling_migration.py b/qa/rpc-tests/sprout_sapling_migration.py index 57c8534c83e..40d6ab196b9 100755 --- a/qa/rpc-tests/sprout_sapling_migration.py +++ b/qa/rpc-tests/sprout_sapling_migration.py @@ -52,10 +52,7 @@ def check_migration_status(node, destination_address, migration_state): class SproutSaplingMigration(BitcoinTestFramework): def setup_nodes(self): - # Activate overwinter/sapling on all nodes extra_args = [[ - '-nuparams=5ba81b19:100', # Overwinter - '-nuparams=76b809bb:100', # Sapling ]] * 4 # Add migration parameters to nodes[0] extra_args[0] = extra_args[0] + [ @@ -63,8 +60,8 @@ def setup_nodes(self): '-migrationdestaddress=' + SAPLING_ADDR, '-debug=zrpcunsafe' ] - assert_equal(5, len(extra_args[0])) - assert_equal(2, len(extra_args[1])) + assert_equal(3, len(extra_args[0])) + assert_equal(0, len(extra_args[1])) return start_nodes(4, self.options.tmpdir, extra_args) def setup_chain(self): diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 208a53db361..9b75eb514ca 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -642,9 +642,9 @@ def __repr__(self): class CTransaction(object): def __init__(self, tx=None): if tx is None: - self.fOverwintered = False - self.nVersion = 1 - self.nVersionGroupId = 0 + self.fOverwintered = True + self.nVersion = 4 + self.nVersionGroupId = SAPLING_VERSION_GROUP_ID self.vin = [] self.vout = [] self.nLockTime = 0 @@ -1517,7 +1517,7 @@ class NodeConn(asyncore.dispatcher): "regtest": "\xaa\xe8\x3f\x5f" # regtest } - def __init__(self, dstaddr, dstport, rpc, callback, net="regtest", protocol_version=SPROUT_PROTO_VERSION): + def __init__(self, dstaddr, dstport, rpc, callback, net="regtest", protocol_version=SAPLING_PROTO_VERSION): asyncore.dispatcher.__init__(self, map=mininode_socket_map) self.log = logging.getLogger("NodeConn(%s:%d)" % (dstaddr, dstport)) self.dstaddr = dstaddr diff --git a/qa/rpc-tests/turnstile.py b/qa/rpc-tests/turnstile.py index 129a91ee50b..31451d116b2 100755 --- a/qa/rpc-tests/turnstile.py +++ b/qa/rpc-tests/turnstile.py @@ -40,8 +40,6 @@ ) from decimal import Decimal -NUPARAMS_ARGS = ['-nuparams=5ba81b19:100', # Overwinter - '-nuparams=76b809bb:101'] # Sapling TURNSTILE_ARGS = ['-experimentalfeatures', '-developersetpoolsizezero'] @@ -52,8 +50,7 @@ def setup_chain(self): initialize_chain_clean(self.options.tmpdir, 3) def setup_network(self, split=False): - self.nodes = start_nodes(3, self.options.tmpdir, - extra_args=[NUPARAMS_ARGS] * 3) + self.nodes = start_nodes(3, self.options.tmpdir) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) self.is_network_split=False @@ -70,7 +67,7 @@ def assert_pool_balance(self, node, name, balance): # Helper method to start a single node with extra args and sync to the network def start_and_sync_node(self, index, args=[]): - self.nodes[index] = start_node(index, self.options.tmpdir, extra_args=NUPARAMS_ARGS + args) + self.nodes[index] = start_node(index, self.options.tmpdir, extra_args=args) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index 8d5e3d62ccb..8d6cab67a1a 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -92,7 +92,7 @@ def run_test (self): # Catch an attempt to send a transaction with an absurdly high fee. # Send 1.0 from an utxo of value 10.0 but don't specify a change output, so then - # the change of 9.0 becomes the fee, which is greater than estimated fee of 0.0019. + # the change of 9.0 becomes the fee, which is greater than estimated fee of 0.0021. inputs = [] outputs = {} for utxo in node2utxos: @@ -108,7 +108,7 @@ def run_test (self): except JSONRPCException,e: errorString = e.error['message'] assert("absurdly high fees" in errorString) - assert("900000000 > 190000" in errorString) + assert("900000000 > 210000" in errorString) # create both transactions txns_to_send = [] @@ -286,12 +286,16 @@ def run_test (self): myzaddr = self.nodes[0].z_getnewaddress('sprout') recipients = [] - num_t_recipients = 3000 + num_t_recipients = 1000 + num_z_recipients = 2100 amount_per_recipient = Decimal('0.00000001') errorString = '' for i in xrange(0,num_t_recipients): newtaddr = self.nodes[2].getnewaddress() recipients.append({"address":newtaddr, "amount":amount_per_recipient}) + for i in xrange(0,num_z_recipients): + newzaddr = self.nodes[2].z_getnewaddress('sprout') + recipients.append({"address":newzaddr, "amount":amount_per_recipient}) # Issue #2759 Workaround START # HTTP connection to node 0 may fall into a state, during the few minutes it takes to process @@ -302,47 +306,12 @@ def run_test (self): self.nodes[0].getinfo() # Issue #2759 Workaround END - try: - self.nodes[0].z_sendmany(myzaddr, recipients) - except JSONRPCException,e: - errorString = e.error['message'] - assert("Too many outputs, size of raw transaction" in errorString) - - recipients = [] - num_t_recipients = 2000 - num_z_recipients = 50 - amount_per_recipient = Decimal('0.00000001') - errorString = '' - for i in xrange(0,num_t_recipients): - newtaddr = self.nodes[2].getnewaddress() - recipients.append({"address":newtaddr, "amount":amount_per_recipient}) - for i in xrange(0,num_z_recipients): - newzaddr = self.nodes[2].z_getnewaddress('sprout') - recipients.append({"address":newzaddr, "amount":amount_per_recipient}) - - # Issue #2759 Workaround START - self.nodes[0].getinfo() - # Issue #2759 Workaround END - try: self.nodes[0].z_sendmany(myzaddr, recipients) except JSONRPCException,e: errorString = e.error['message'] assert("size of raw transaction would be larger than limit" in errorString) - recipients = [] - num_z_recipients = 100 - amount_per_recipient = Decimal('0.00000001') - errorString = '' - for i in xrange(0,num_z_recipients): - newzaddr = self.nodes[2].z_getnewaddress('sprout') - recipients.append({"address":newzaddr, "amount":amount_per_recipient}) - try: - self.nodes[0].z_sendmany(myzaddr, recipients) - except JSONRPCException,e: - errorString = e.error['message'] - assert("Invalid parameter, too many zaddr outputs" in errorString) - # add zaddr to node 2 myzaddr = self.nodes[2].z_getnewaddress('sprout') diff --git a/qa/rpc-tests/wallet_addresses.py b/qa/rpc-tests/wallet_addresses.py index c9a6ab7c30a..897c7cc5a2f 100755 --- a/qa/rpc-tests/wallet_addresses.py +++ b/qa/rpc-tests/wallet_addresses.py @@ -6,17 +6,11 @@ import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal, start_nodes +from test_framework.util import assert_equal # Test wallet address behaviour across network upgradesa\ class WalletAddressesTest(BitcoinTestFramework): - def setup_nodes(self): - return start_nodes(4, self.options.tmpdir, [[ - '-nuparams=5ba81b19:202', # Overwinter - '-nuparams=76b809bb:204', # Sapling - ]] * 4) - def run_test(self): def addr_checks(default_type): # Check default type, as well as explicit types @@ -38,41 +32,17 @@ def addr_checks(default_type): # Sanity-check the test harness assert_equal(self.nodes[0].getblockcount(), 200) - # Current height = 200 -> Sprout - # Default address type is Sapling - print "Testing height 200 (Sprout)" - addr_checks('sapling') - - self.nodes[0].generate(1) - self.sync_all() - - # Current height = 201 -> Sprout - # Default address type is Sapling - print "Testing height 201 (Sprout)" - addr_checks('sapling') - - self.nodes[0].generate(1) - self.sync_all() - - # Current height = 202 -> Overwinter - # Default address type is Sapling - print "Testing height 202 (Overwinter)" - addr_checks('sapling') - - self.nodes[0].generate(1) - self.sync_all() - - # Current height = 203 -> Overwinter + # Current height = 200 -> Sapling # Default address type is Sapling - print "Testing height 203 (Overwinter)" + print "Testing height 200 (Sapling)" addr_checks('sapling') self.nodes[0].generate(1) self.sync_all() - # Current height = 204 -> Sapling + # Current height = 201 -> Sapling # Default address type is Sapling - print "Testing height 204 (Sapling)" + print "Testing height 201 (Sapling)" addr_checks('sapling') if __name__ == '__main__': diff --git a/qa/rpc-tests/wallet_listnotes.py b/qa/rpc-tests/wallet_listnotes.py index 9f9b0993727..169d4be569d 100755 --- a/qa/rpc-tests/wallet_listnotes.py +++ b/qa/rpc-tests/wallet_listnotes.py @@ -9,7 +9,6 @@ from test_framework.util import ( assert_equal, get_coinbase_address, - start_nodes, wait_and_assert_operationid_status, ) @@ -18,29 +17,21 @@ # Test wallet z_listunspent behaviour across network upgrades class WalletListNotes(BitcoinTestFramework): - def setup_nodes(self): - return start_nodes(4, self.options.tmpdir, [[ - '-nuparams=5ba81b19:202', # Overwinter - '-nuparams=76b809bb:214', # Sapling - ]] * 4) - def run_test(self): - # Current height = 200 -> Sprout + # Current height = 200 assert_equal(200, self.nodes[0].getblockcount()) sproutzaddr = self.nodes[0].z_getnewaddress('sprout') - - # test that we can create a sapling zaddr before sapling activates saplingzaddr = self.nodes[0].z_getnewaddress('sapling') # we've got lots of coinbase (taddr) but no shielded funds yet assert_equal(0, Decimal(self.nodes[0].z_gettotalbalance()['private'])) - - # Set current height to 201 -> Sprout + + # Set current height to 201 self.nodes[0].generate(1) self.sync_all() assert_equal(201, self.nodes[0].getblockcount()) - # Shield coinbase funds (must be a multiple of 10, no change allowed pre-sapling) + # Shield coinbase funds (must be a multiple of 10, no change allowed) receive_amount_10 = Decimal('10.0') - Decimal('0.0001') recipients = [{"address":sproutzaddr, "amount":receive_amount_10}] myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients) @@ -70,8 +61,8 @@ def run_test(self): # Generate a block to confirm shield coinbase tx self.nodes[0].generate(1) self.sync_all() - - # Current height = 202 -> Overwinter. Default address type remains Sprout + + # Current height = 202 assert_equal(202, self.nodes[0].getblockcount()) # Send 1.0 (actually 0.9999) from sproutzaddr to a new zaddr @@ -108,12 +99,7 @@ def run_test(self): unspent_tx_filter = self.nodes[0].z_listunspent(0, 9999, False, [sproutzaddr]) assert_equal(1, len(unspent_tx_filter)) assert_equal(unspent_tx[1], unspent_tx_filter[0]) - - # Set current height to 204 -> Sapling - self.nodes[0].generate(12) - self.sync_all() - assert_equal(214, self.nodes[0].getblockcount()) - + # No funds in saplingzaddr yet assert_equal(0, len(self.nodes[0].z_listunspent(0, 9999, False, [saplingzaddr]))) diff --git a/qa/rpc-tests/wallet_listreceived.py b/qa/rpc-tests/wallet_listreceived.py index 16b384ab855..526a3e6cd99 100755 --- a/qa/rpc-tests/wallet_listreceived.py +++ b/qa/rpc-tests/wallet_listreceived.py @@ -7,7 +7,7 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, assert_true, assert_false -from test_framework.util import start_nodes, wait_and_assert_operationid_status +from test_framework.util import wait_and_assert_operationid_status from decimal import Decimal my_memo = 'c0ffee' # stay awake @@ -19,12 +19,6 @@ class ListReceivedTest (BitcoinTestFramework): - def setup_nodes(self): - return start_nodes(4, self.options.tmpdir, [[ - "-nuparams=5ba81b19:201", # Overwinter - "-nuparams=76b809bb:214", # Sapling - ]] * 4) - def generate_and_sync(self, new_height): current_height = self.nodes[0].getblockcount() assert(new_height > current_height) diff --git a/qa/rpc-tests/wallet_overwintertx.py b/qa/rpc-tests/wallet_overwintertx.py index 8915789bba4..92b14d78f19 100755 --- a/qa/rpc-tests/wallet_overwintertx.py +++ b/qa/rpc-tests/wallet_overwintertx.py @@ -6,9 +6,15 @@ import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal, initialize_chain_clean, \ - start_nodes, connect_nodes_bi, wait_and_assert_operationid_status, \ - assert_greater_than, get_coinbase_address +from test_framework.util import ( + assert_equal, + assert_greater_than, + connect_nodes_bi, + get_coinbase_address, + initialize_chain_clean, + start_nodes, + wait_and_assert_operationid_status, +) from test_framework.authproxy import JSONRPCException from decimal import Decimal @@ -20,7 +26,11 @@ def setup_chain(self): initialize_chain_clean(self.options.tmpdir, 4) def setup_network(self, split=False): - self.nodes = start_nodes(4, self.options.tmpdir, extra_args=[["-nuparams=5ba81b19:200", "-debug=zrpcunsafe", "-txindex"]] * 4 ) + self.nodes = start_nodes(4, self.options.tmpdir, extra_args=[[ + "-nuparams=2bb40e60:200", + "-debug=zrpcunsafe", + "-txindex", + ]] * 4 ) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) @@ -31,9 +41,9 @@ def setup_network(self, split=False): def run_test (self): self.nodes[0].generate(100) self.sync_all() - self.nodes[1].generate(98) + self.nodes[1].generate(95) self.sync_all() - # Node 0 has reward from blocks 1 to 98 which are spendable. + # Node 0 has reward from blocks 1 to 95 which are spendable. taddr0 = get_coinbase_address(self.nodes[0]) taddr1 = self.nodes[1].getnewaddress() @@ -43,19 +53,12 @@ def run_test (self): zaddr3 = self.nodes[3].z_getnewaddress('sprout') # - # Currently at block 198. The next block to be mined 199 is a Sprout block + # Currently at block 195. The next block to be mined 196 is a Sapling block # bci = self.nodes[0].getblockchaininfo() - assert_equal(bci['consensus']['chaintip'], '00000000') - assert_equal(bci['consensus']['nextblock'], '00000000') - assert_equal(bci['upgrades']['5ba81b19']['status'], 'pending') - - # Cannot use the expiryheight parameter of createrawtransaction if Overwinter is not active in the next block - try: - self.nodes[0].createrawtransaction([], {}, 0, 99) - except JSONRPCException,e: - errorString = e.error['message'] - assert_equal("Invalid parameter, expiryheight can only be used if Overwinter is active when the transaction is mined" in errorString, True) + assert_equal(bci['consensus']['chaintip'], '76b809bb') + assert_equal(bci['consensus']['nextblock'], '76b809bb') + assert_equal(bci['upgrades']['2bb40e60']['status'], 'pending') # Node 0 sends transparent funds to Node 2 tsendamount = Decimal('1.0') @@ -75,8 +78,10 @@ def run_test (self): myopid = self.nodes[0].z_sendmany(taddr0, recipients) txid_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid) + # Skip over the three blocks prior to activation; no transactions can be mined + # in them due to the nearly-expiring restrictions. self.sync_all() - self.nodes[0].generate(1) + self.nodes[0].generate(4) self.sync_all() # Verify balance @@ -84,26 +89,26 @@ def run_test (self): assert_equal(self.nodes[2].getbalance(), Decimal('0.4999')) assert_equal(self.nodes[2].z_getbalance(zaddr2), zsendamount) - # Verify transaction versions are 1 or 2 (intended for Sprout) + # Verify transaction version is 4 (intended for Sapling+) result = self.nodes[0].getrawtransaction(txid_transparent, 1) - assert_equal(result["version"], 1) - assert_equal(result["overwintered"], False) + assert_equal(result["version"], 4) + assert_equal(result["overwintered"], True) result = self.nodes[0].getrawtransaction(txid_zsendmany, 1) - assert_equal(result["version"], 1) - assert_equal(result["overwintered"], False) + assert_equal(result["version"], 4) + assert_equal(result["overwintered"], True) result = self.nodes[0].getrawtransaction(txid_shielded, 1) - assert_equal(result["version"], 2) - assert_equal(result["overwintered"], False) + assert_equal(result["version"], 4) + assert_equal(result["overwintered"], True) # - # Currently at block 199. The next block to be mined 200 is an Overwinter block + # Currently at block 199. The next block to be mined 200 is a Blossom block # bci = self.nodes[0].getblockchaininfo() - assert_equal(bci['consensus']['chaintip'], '00000000') - assert_equal(bci['consensus']['nextblock'], '5ba81b19') - assert_equal(bci['upgrades']['5ba81b19']['status'], 'pending') + assert_equal(bci['consensus']['chaintip'], '76b809bb') + assert_equal(bci['consensus']['nextblock'], '2bb40e60') + assert_equal(bci['upgrades']['2bb40e60']['status'], 'pending') - # Test using expiryheight parameter of createrawtransaction when Overwinter is active in the next block + # Test using expiryheight parameter of createrawtransaction when Blossom is active in the next block errorString = "" try: self.nodes[0].createrawtransaction([], {}, 0, 499999999) @@ -144,7 +149,7 @@ def run_test (self): myopid = self.nodes[0].z_sendmany(taddr0, recipients) txid_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid) - # Mine the first Overwinter block + # Mine the first Blossom block self.sync_all() self.nodes[0].generate(1) self.sync_all() @@ -153,28 +158,28 @@ def run_test (self): # size_on_disk should be > 0 assert_greater_than(bci['size_on_disk'], 0) - assert_equal(bci['consensus']['chaintip'], '5ba81b19') - assert_equal(bci['consensus']['nextblock'], '5ba81b19') - assert_equal(bci['upgrades']['5ba81b19']['status'], 'active') + assert_equal(bci['consensus']['chaintip'], '2bb40e60') + assert_equal(bci['consensus']['nextblock'], '2bb40e60') + assert_equal(bci['upgrades']['2bb40e60']['status'], 'active') # Verify balance assert_equal(self.nodes[1].z_getbalance(taddr1), Decimal('1.0')) assert_equal(self.nodes[3].getbalance(), Decimal('0.4999')) assert_equal(self.nodes[3].z_getbalance(zaddr3), zsendamount) - # Verify transaction version is 3 (intended for Overwinter) + # Verify transaction version is 4 (intended for Sapling+) result = self.nodes[0].getrawtransaction(txid_transparent, 1) - assert_equal(result["version"], 3) + assert_equal(result["version"], 4) assert_equal(result["overwintered"], True) - assert_equal(result["versiongroupid"], "03c48270") + assert_equal(result["versiongroupid"], "892f2085") result = self.nodes[0].getrawtransaction(txid_zsendmany, 1) - assert_equal(result["version"], 3) + assert_equal(result["version"], 4) assert_equal(result["overwintered"], True) - assert_equal(result["versiongroupid"], "03c48270") + assert_equal(result["versiongroupid"], "892f2085") result = self.nodes[0].getrawtransaction(txid_shielded, 1) - assert_equal(result["version"], 3) + assert_equal(result["version"], 4) assert_equal(result["overwintered"], True) - assert_equal(result["versiongroupid"], "03c48270") + assert_equal(result["versiongroupid"], "892f2085") if __name__ == '__main__': WalletOverwinterTxTest().main() diff --git a/qa/rpc-tests/wallet_persistence.py b/qa/rpc-tests/wallet_persistence.py index ed34f416b0c..3ffaf591b82 100755 --- a/qa/rpc-tests/wallet_persistence.py +++ b/qa/rpc-tests/wallet_persistence.py @@ -22,11 +22,7 @@ def setup_chain(self): initialize_chain_clean(self.options.tmpdir, 3) def setup_network(self, split=False): - self.nodes = start_nodes(3, self.options.tmpdir, - extra_args=[[ - '-nuparams=5ba81b19:100', # Overwinter - '-nuparams=76b809bb:201', # Sapling - ]] * 3) + self.nodes = start_nodes(3, self.options.tmpdir) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) self.is_network_split=False @@ -38,7 +34,7 @@ def run_test(self): assert_equal(self.nodes[0].getblockcount(), 200) self.sync_all() - # Verify Sapling address is persisted in wallet (even when Sapling is not yet active) + # Verify Sapling address is persisted in wallet sapling_addr = self.nodes[0].z_getnewaddress('sapling') # Make sure the node has the addresss @@ -54,10 +50,6 @@ def run_test(self): addresses = self.nodes[0].z_listaddresses() assert_true(sapling_addr in addresses, "Should contain address after restart") - # Activate Sapling - self.nodes[0].generate(1) - self.sync_all() - # Node 0 shields funds to Sapling address taddr0 = get_coinbase_address(self.nodes[0]) recipients = [] diff --git a/qa/rpc-tests/wallet_sapling.py b/qa/rpc-tests/wallet_sapling.py index fed4fe25648..ca42893dd30 100755 --- a/qa/rpc-tests/wallet_sapling.py +++ b/qa/rpc-tests/wallet_sapling.py @@ -21,8 +21,6 @@ class WalletSaplingTest(BitcoinTestFramework): def setup_nodes(self): return start_nodes(4, self.options.tmpdir, [[ - '-nuparams=5ba81b19:201', # Overwinter - '-nuparams=76b809bb:203', # Sapling '-experimentalfeatures', '-zmergetoaddress', ]] * 4) @@ -30,52 +28,6 @@ def run_test(self): # Sanity-check the test harness assert_equal(self.nodes[0].getblockcount(), 200) - # Activate Overwinter - self.nodes[2].generate(1) - self.sync_all() - - # Verify RPCs disallow Sapling value transfer if Sapling is not active - tmp_taddr = get_coinbase_address(self.nodes[3]) - tmp_zaddr = self.nodes[3].z_getnewaddress('sapling') - try: - recipients = [] - recipients.append({"address": tmp_zaddr, "amount": Decimal('10')}) - self.nodes[3].z_sendmany(tmp_taddr, recipients, 1, 0) - raise AssertionError("Should have thrown an exception") - except JSONRPCException as e: - assert_equal("Invalid parameter, Sapling has not activated", e.error['message']) - try: - recipients = [] - recipients.append({"address": tmp_taddr, "amount": Decimal('10')}) - self.nodes[3].z_sendmany(tmp_zaddr, recipients, 1, 0) - raise AssertionError("Should have thrown an exception") - except JSONRPCException as e: - assert_equal("Invalid parameter, Sapling has not activated", e.error['message']) - try: - self.nodes[3].z_shieldcoinbase(tmp_taddr, tmp_zaddr) - raise AssertionError("Should have thrown an exception") - except JSONRPCException as e: - assert_equal("Invalid parameter, Sapling has not activated", e.error['message']) - - # Verify z_mergetoaddress RPC does not support Sapling yet - try: - self.nodes[3].z_mergetoaddress([tmp_taddr], tmp_zaddr) - raise AssertionError("Should have thrown an exception") - except JSONRPCException as e: - assert_equal("Invalid parameter, Sapling has not activated", e.error['message']) - try: - self.nodes[3].z_mergetoaddress([tmp_zaddr], tmp_taddr) - raise AssertionError("Should have thrown an exception") - except JSONRPCException as e: - # When sending from a zaddr we check for sapling activation only if - # we find notes belonging to that address. Since sapling is not active - # none can be generated and none will be found. - assert_equal("Could not find any funds to merge.", e.error['message']) - - # Activate Sapling - self.nodes[2].generate(2) - self.sync_all() - taddr1 = self.nodes[1].getnewaddress() saplingAddr0 = self.nodes[0].z_getnewaddress('sapling') saplingAddr1 = self.nodes[1].z_getnewaddress('sapling') diff --git a/qa/rpc-tests/wallet_shieldcoinbase.py b/qa/rpc-tests/wallet_shieldcoinbase.py index 804915f681f..212f096193e 100755 --- a/qa/rpc-tests/wallet_shieldcoinbase.py +++ b/qa/rpc-tests/wallet_shieldcoinbase.py @@ -24,18 +24,10 @@ def setup_chain(self): def setup_network(self, split=False): args = ['-regtestprotectcoinbase', '-debug=zrpcunsafe'] - args2 = ['-regtestprotectcoinbase', '-debug=zrpcunsafe', "-mempooltxinputlimit=7"] - if self.addr_type != 'sprout': - nu = [ - '-nuparams=5ba81b19:0', # Overwinter - '-nuparams=76b809bb:1', # Sapling - ] - args.extend(nu) - args2 = args self.nodes = [] self.nodes.append(start_node(0, self.options.tmpdir, args)) self.nodes.append(start_node(1, self.options.tmpdir, args)) - self.nodes.append(start_node(2, self.options.tmpdir, args2)) + self.nodes.append(start_node(2, self.options.tmpdir, args)) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) @@ -164,14 +156,8 @@ def verify_locking(first, second, limit): wait_and_assert_operationid_status(self.nodes[0], opid1) wait_and_assert_operationid_status(self.nodes[0], opid2) - if self.addr_type == 'sprout': - # Shielding the 800 utxos will occur over two transactions, since max tx size is 100,000 bytes. - # We don't verify shieldingValue as utxos are not selected in any specific order, so value can change on each test run. - # We set an unrealistically high limit parameter of 99999, to verify that max tx size will constrain the number of utxos. - verify_locking('662', '138', 99999) - else: - # Shield the 800 utxos over two transactions - verify_locking('500', '300', 500) + # Shield the 800 utxos over two transactions + verify_locking('500', '300', 500) # sync_all() invokes sync_mempool() but node 2's mempool limit will cause tx1 and tx2 to be rejected. # So instead, we sync on blocks and mempool for node 0 and node 1, and after a new block is generated @@ -181,18 +167,6 @@ def verify_locking(first, second, limit): self.nodes[1].generate(1) self.sync_all() - if self.addr_type == 'sprout': - # Verify maximum number of utxos which node 2 can shield is limited by option -mempooltxinputlimit - # This option is used when the limit parameter is set to 0. - mytaddr = get_coinbase_address(self.nodes[2], 20) - result = self.nodes[2].z_shieldcoinbase(mytaddr, myzaddr, Decimal('0.0001'), 0) - assert_equal(result["shieldingUTXOs"], Decimal('7')) - assert_equal(result["remainingUTXOs"], Decimal('13')) - wait_and_assert_operationid_status(self.nodes[2], result['opid']) - self.sync_all() - self.nodes[1].generate(1) - self.sync_all() - # Verify maximum number of utxos which node 0 can shield is set by default limit parameter of 50 self.nodes[0].generate(200) self.sync_all() From 9cbd2889bef8f711671d297478a6ef81b57bd186 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 29 Jul 2019 11:54:51 +0100 Subject: [PATCH 267/395] rpc: Use Sapling transactions in zc_raw_joinsplit --- src/wallet/rpcwallet.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 436696ea592..aa610ff56ff 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3046,10 +3046,11 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp) crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey); CMutableTransaction mtx(tx); - mtx.nVersion = 2; + mtx.nVersion = 4; + mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID; mtx.joinSplitPubKey = joinSplitPubKey; - JSDescription jsdesc(false, + JSDescription jsdesc(true, *pzcashParams, joinSplitPubKey, anchor, From 210c46c21d98c95880fa0fa7e1a6d7fe7a46218f Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Sat, 24 Aug 2019 19:05:10 -0600 Subject: [PATCH 268/395] #4114 don't call error() from GetSpentIndex() --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 9318deaf74a..241bc47cccc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1633,7 +1633,7 @@ bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value) { AssertLockHeld(cs_main); if (!fSpentIndex) - return error("spent index not enabled"); + return false; if (mempool.getSpentIndex(key, value)) return true; return pblocktree->ReadSpentIndex(key, value); From 7d5de93518d687f995297fe30c456e15c1b861cf Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Mon, 26 Aug 2019 17:37:53 +0100 Subject: [PATCH 269/395] Add intended rewind for Blossom on testnet. Signed-off-by: Daira Hopwood --- src/main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 9318deaf74a..9f7d77fbd67 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4636,7 +4636,9 @@ bool RewindBlockIndex(const CChainParams& chainparams, bool& clearWitnessCaches) // This is true when we intend to do a long rewind. bool intendedRewind = (networkID == "test" && nHeight == 252500 && *phashFirstInsufValidated == - uint256S("0018bd16a9c6f15795a754c498d2b2083ab78f14dae44a66a8d0e90ba8464d9c")); + uint256S("0018bd16a9c6f15795a754c498d2b2083ab78f14dae44a66a8d0e90ba8464d9c")) || + (networkID == "test" && nHeight == 584000 && *phashFirstInsufValidated == + uint256S("002e1d6daf4ab7b296e7df839dc1bee9d615583bb4bc34b1926ce78307532852")); clearWitnessCaches = (rewindLength > MAX_REORG_LENGTH && intendedRewind); From e83168b8c87463c66dc4a961f5857e9ecb0cfb89 Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Tue, 27 Aug 2019 08:37:42 -0600 Subject: [PATCH 270/395] better fix: make GetSpentIndex() consistent with others... but don't call it if insight explorer isn't enabled --- src/main.cpp | 9 +++++++-- src/rpc/rawtransaction.cpp | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 241bc47cccc..49b315e4b96 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1633,10 +1633,15 @@ bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value) { AssertLockHeld(cs_main); if (!fSpentIndex) - return false; + return error("Spent index not enabled"); + if (mempool.getSpentIndex(key, value)) return true; - return pblocktree->ReadSpentIndex(key, value); + + if (!pblocktree->ReadSpentIndex(key, value)) + return error("Unable to get spent index information"); + + return true; } bool GetAddressIndex(const uint160& addressHash, int type, diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index ece1a09e94c..7d20f101749 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -176,7 +176,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) // Add address and value info if spentindex enabled CSpentIndexValue spentInfo; CSpentIndexKey spentKey(txin.prevout.hash, txin.prevout.n); - if (GetSpentIndex(spentKey, spentInfo)) { + if (fSpentIndex && GetSpentIndex(spentKey, spentInfo)) { in.push_back(Pair("value", ValueFromAmount(spentInfo.satoshis))); in.push_back(Pair("valueSat", spentInfo.satoshis)); @@ -206,7 +206,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) // Add spent information if spentindex is enabled CSpentIndexValue spentInfo; CSpentIndexKey spentKey(txid, i); - if (GetSpentIndex(spentKey, spentInfo)) { + if (fSpentIndex && GetSpentIndex(spentKey, spentInfo)) { out.push_back(Pair("spentTxId", spentInfo.txid.GetHex())); out.push_back(Pair("spentIndex", (int)spentInfo.inputIndex)); out.push_back(Pair("spentHeight", spentInfo.blockHeight)); From df8fd9ef808c464f435d09b6505d4ab3515ac41d Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 28 Aug 2019 10:55:24 -0600 Subject: [PATCH 271/395] Notable changes for v2.0.7-1 --- doc/release-notes.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index a29094b5174..791634613ae 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,3 +4,9 @@ release-notes at release time) Notable changes =============== +Testnet Blossom Rewind +---------------------- +The warning that users of testnet got to upgrade for Blossom was somewhat +short. Users who were running a pre-2.0.7 version of zcashd at testnet Blossom +activation may now be on the wrong branch. We have added an "intended rewind" +to prevent having to having to reindex when reconnecting to the correct chain. From aca5af4b83208d4450aa6a50592bdd7405d81d1e Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 28 Aug 2019 11:18:22 -0600 Subject: [PATCH 272/395] fix typo Co-Authored-By: Daira Hopwood --- doc/release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index 791634613ae..22f8616ddf1 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -9,4 +9,4 @@ Testnet Blossom Rewind The warning that users of testnet got to upgrade for Blossom was somewhat short. Users who were running a pre-2.0.7 version of zcashd at testnet Blossom activation may now be on the wrong branch. We have added an "intended rewind" -to prevent having to having to reindex when reconnecting to the correct chain. +to prevent having to manually reindex when reconnecting to the correct chain. From 8e4c13c14c48c891ae35b64a9e02ce0cb477b8b8 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 28 Aug 2019 19:32:35 -0600 Subject: [PATCH 273/395] Add note about logging fix --- doc/release-notes.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index 22f8616ddf1..b0e7274d683 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -10,3 +10,8 @@ The warning that users of testnet got to upgrade for Blossom was somewhat short. Users who were running a pre-2.0.7 version of zcashd at testnet Blossom activation may now be on the wrong branch. We have added an "intended rewind" to prevent having to manually reindex when reconnecting to the correct chain. + + +Insight Explorer Logging Fix +---------------------------- +Fixed an issue where `ERROR: spent index not enabled` would be logged unnecessarily. From e588ab1a990132c78c1e397f8de4507acb67de12 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Thu, 29 Aug 2019 09:38:40 -0600 Subject: [PATCH 274/395] Better wording in release notes Co-authored-by: LarryRuane --- doc/release-notes.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index b0e7274d683..f65b98552b9 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -6,10 +6,11 @@ Notable changes Testnet Blossom Rewind ---------------------- -The warning that users of testnet got to upgrade for Blossom was somewhat -short. Users who were running a pre-2.0.7 version of zcashd at testnet Blossom -activation may now be on the wrong branch. We have added an "intended rewind" -to prevent having to manually reindex when reconnecting to the correct chain. +Testnet users needed to upgrade to 2.0.7 before Blossom activated. The amount +of notice given to these users was brief, so many were not able to upgrade in +time. These users may now be on the wrong branch. v2.0.7-1 adds an "intended +rewind" to prevent having to manually reindex when reconnecting to the correct +chain. Insight Explorer Logging Fix From 75b8f0f8b40d0eef3a3d86271f4032aebb0d5531 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Thu, 29 Aug 2019 18:46:37 +0100 Subject: [PATCH 275/395] Remove copyright entries for Autoconf macros that have been deleted. Signed-off-by: Daira Hopwood --- COPYING | 4 ---- contrib/debian/copyright | 25 ------------------------- 2 files changed, 29 deletions(-) diff --git a/COPYING b/COPYING index 2f0bae0b25c..090c06efdf3 100644 --- a/COPYING +++ b/COPYING @@ -46,8 +46,4 @@ following files in build-aux/m4 (see https://github.com/zcash/zcash/issues/2827) * ax_check_compile_flag.m4 * ax_check_link_flag.m4 * ax_check_preproc_flag.m4 - * ax_compiler_vendor.m4 - * ax_gcc_archflag.m4 - * ax_gcc_x86_cpuid.m4 - * ax_openmp.m4 * ax_pthread.m4 diff --git a/contrib/debian/copyright b/contrib/debian/copyright index 34b08239e8f..493e3f4784d 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -71,31 +71,6 @@ Copyright: 2008, Guido U. Draheim 2011, Maarten Bosmans License: GPLv3-or-later-with-Autoconf-exception -Files: build-aux/m4/ax_compiler_vendor.m4 -Copyright: 2008, Steven G. Johnson - 2008, Matteo Frigo - 2018-19, John Zaitseff -License: GPLv3-or-later-with-Autoconf-exception - -Files: build-aux/m4/ax_gcc_archflag.m4 -Copyright: 2008, Steven G. Johnson - 2008, Matteo Frigo - 2014, Tsukasa Oi - 2017-2018, Alexey Kopytov -License: GPLv3-or-later-with-Autoconf-exception - -Files: build-aux/m4/ax_gcc_x86_cpuid.m4 -Copyright: 2008, Steven G. Johnson - 2008, Matteo Frigo - 2015, Michael Petch -License: GPLv3-or-later-with-Autoconf-exception - -Files: build-aux/m4/ax_openmp.m4 -Copyright: 2008, Steven G. Johnson - 2015, John W. Peterson - 2016, Nick R. Papior -License: GPLv3-or-later-with-Autoconf-exception - Files: build-aux/m4/ax_pthread.m4 Copyright: 2008, Steven G. Johnson 2011, Daniel Richard G. From c05652b8d976859026e1e2cfec83b4d16bd5da98 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Thu, 29 Aug 2019 12:58:35 -0600 Subject: [PATCH 276/395] make-release.py: Versioning changes for 2.0.7-1. --- README.md | 2 +- configure.ac | 2 +- contrib/gitian-descriptors/gitian-linux.yml | 2 +- src/clientversion.h | 2 +- src/deprecation.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 5fcb48e7ed5..91a12fbad69 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Zcash 2.0.7 +Zcash 2.0.7-1 =========== diff --git a/configure.ac b/configure.ac index 90dd4e44500..1be5bd991e5 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 2) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_REVISION, 7) -define(_CLIENT_VERSION_BUILD, 50) +define(_CLIENT_VERSION_BUILD, 51) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 335365667c1..b1f39c95990 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "zcash-2.0.7" +name: "zcash-2.0.7-1" enable_cache: true distro: "debian" suites: diff --git a/src/clientversion.h b/src/clientversion.h index 0c5e47fd823..dc83538342f 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -18,7 +18,7 @@ #define CLIENT_VERSION_MAJOR 2 #define CLIENT_VERSION_MINOR 0 #define CLIENT_VERSION_REVISION 7 -#define CLIENT_VERSION_BUILD 50 +#define CLIENT_VERSION_BUILD 51 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/deprecation.h b/src/deprecation.h index 10bb3195d80..53089969e7c 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -8,7 +8,7 @@ // Deprecation policy: // * Shut down 16 weeks' worth of blocks after the estimated release block height. // * A warning is shown during the 2 weeks' worth of blocks prior to shut down. -static const int APPROX_RELEASE_HEIGHT = 588500; +static const int APPROX_RELEASE_HEIGHT = 594500; static const int WEEKS_UNTIL_DEPRECATION = 16; static const int DEPRECATION_HEIGHT = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 24); From f98365e47eb568b3954c0250f9f3852b84771929 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Thu, 29 Aug 2019 13:07:52 -0600 Subject: [PATCH 277/395] make-release.py: Updated manpages for 2.0.7-1. --- doc/man/zcash-cli.1 | 6 +++--- doc/man/zcash-tx.1 | 6 +++--- doc/man/zcashd.1 | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/man/zcash-cli.1 b/doc/man/zcash-cli.1 index 777624816ac..2a63f8f5227 100644 --- a/doc/man/zcash-cli.1 +++ b/doc/man/zcash-cli.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-CLI "1" "August 2019" "zcash-cli v2.0.7" "User Commands" +.TH ZCASH-CLI "1" "August 2019" "zcash-cli v2.0.7-1" "User Commands" .SH NAME -zcash-cli \- manual page for zcash-cli v2.0.7 +zcash-cli \- manual page for zcash-cli v2.0.7-1 .SH DESCRIPTION -Zcash RPC client version v2.0.7 +Zcash RPC client version v2.0.7\-1 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . diff --git a/doc/man/zcash-tx.1 b/doc/man/zcash-tx.1 index 16df92b2f50..039858dd41d 100644 --- a/doc/man/zcash-tx.1 +++ b/doc/man/zcash-tx.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-TX "1" "August 2019" "zcash-tx v2.0.7" "User Commands" +.TH ZCASH-TX "1" "August 2019" "zcash-tx v2.0.7-1" "User Commands" .SH NAME -zcash-tx \- manual page for zcash-tx v2.0.7 +zcash-tx \- manual page for zcash-tx v2.0.7-1 .SH DESCRIPTION -Zcash zcash\-tx utility version v2.0.7 +Zcash zcash\-tx utility version v2.0.7\-1 .SS "Usage:" .TP zcash\-tx [options] [commands] diff --git a/doc/man/zcashd.1 b/doc/man/zcashd.1 index b0c77f3c546..4e52e251a80 100644 --- a/doc/man/zcashd.1 +++ b/doc/man/zcashd.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASHD "1" "August 2019" "zcashd v2.0.7" "User Commands" +.TH ZCASHD "1" "August 2019" "zcashd v2.0.7-1" "User Commands" .SH NAME -zcashd \- manual page for zcashd v2.0.7 +zcashd \- manual page for zcashd v2.0.7-1 .SH DESCRIPTION -Zcash Daemon version v2.0.7 +Zcash Daemon version v2.0.7\-1 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . From eaac9a92dd504f3c3b3b836d16bf58311813e2c7 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Thu, 29 Aug 2019 13:07:52 -0600 Subject: [PATCH 278/395] make-release.py: Updated release notes and changelog for 2.0.7-1. --- contrib/debian/changelog | 6 ++++ doc/authors.md | 7 ++-- doc/release-notes.md | 12 ------- doc/release-notes/release-notes-2.0.7-1.md | 38 ++++++++++++++++++++++ 4 files changed, 48 insertions(+), 15 deletions(-) create mode 100644 doc/release-notes/release-notes-2.0.7-1.md diff --git a/contrib/debian/changelog b/contrib/debian/changelog index fda4225518f..89ca5da0865 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,9 @@ +zcash (2.0.7+1) stable; urgency=medium + + * 2.0.7-1 release. + + -- Electric Coin Company Thu, 29 Aug 2019 13:07:52 -0600 + zcash (2.0.7) stable; urgency=medium * 2.0.7 release. diff --git a/doc/authors.md b/doc/authors.md index 68291ff73eb..603ac10cd72 100644 --- a/doc/authors.md +++ b/doc/authors.md @@ -4,8 +4,8 @@ Zcash Contributors Jack Grigg (874) Simon Liu (459) Sean Bowe (278) -Eirik Ogilvie-Wigley (160) -Daira Hopwood (135) +Eirik Ogilvie-Wigley (166) +Daira Hopwood (136) Jay Graber (89) Wladimir J. van der Laan (82) Taylor Hornby (73) @@ -14,7 +14,7 @@ Nathan Wilcox (56) Pieter Wuille (54) Kevin Gallagher (38) Cory Fields (35) -Larry Ruane (29) +Larry Ruane (31) Marshall Gaucher (22) Jonathan "Duke" Leto (17) syd (15) @@ -76,6 +76,7 @@ Gavin Andresen (2) Brad Miller (2) Bjorn Hjortsberg (2) Amgad Abdelhafez (2) +Alex Tsankov (2) zathras-crypto (1) unsystemizer (1) tpantin (1) diff --git a/doc/release-notes.md b/doc/release-notes.md index f65b98552b9..a29094b5174 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,15 +4,3 @@ release-notes at release time) Notable changes =============== -Testnet Blossom Rewind ----------------------- -Testnet users needed to upgrade to 2.0.7 before Blossom activated. The amount -of notice given to these users was brief, so many were not able to upgrade in -time. These users may now be on the wrong branch. v2.0.7-1 adds an "intended -rewind" to prevent having to manually reindex when reconnecting to the correct -chain. - - -Insight Explorer Logging Fix ----------------------------- -Fixed an issue where `ERROR: spent index not enabled` would be logged unnecessarily. diff --git a/doc/release-notes/release-notes-2.0.7-1.md b/doc/release-notes/release-notes-2.0.7-1.md new file mode 100644 index 00000000000..997d4b9f4ee --- /dev/null +++ b/doc/release-notes/release-notes-2.0.7-1.md @@ -0,0 +1,38 @@ +Notable changes +=============== + +Testnet Blossom Rewind +---------------------- +Testnet users needed to upgrade to 2.0.7 before Blossom activated. The amount +of notice given to these users was brief, so many were not able to upgrade in +time. These users may now be on the wrong branch. v2.0.7-1 adds an "intended +rewind" to prevent having to manually reindex when reconnecting to the correct +chain. + + +Insight Explorer Logging Fix +---------------------------- +Fixed an issue where `ERROR: spent index not enabled` would be logged unnecessarily. + +Changelog +========= + +Alex Tsankov (2): + Update INSTALL + Typo Fix + +Daira Hopwood (1): + Add intended rewind for Blossom on testnet. + +Eirik Ogilvie-Wigley (6): + Notable changes for v2.0.7-1 + fix typo + Add note about logging fix + Better wording in release notes + make-release.py: Versioning changes for 2.0.7-1. + make-release.py: Updated manpages for 2.0.7-1. + +Larry Ruane (2): + #4114 don't call error() from GetSpentIndex() + better fix: make GetSpentIndex() consistent with others... + From 7b91ba89303f0e6ee4d9bc4e67f76f2c3fad4b67 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Thu, 29 Aug 2019 20:09:17 +0100 Subject: [PATCH 279/395] Remove copyright entry for libsnark. Signed-off-by: Daira Hopwood --- contrib/debian/copyright | 5 ----- 1 file changed, 5 deletions(-) diff --git a/contrib/debian/copyright b/contrib/debian/copyright index 493e3f4784d..5121d906009 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -133,11 +133,6 @@ Copyright: 2011, The LevelDB Authors License: BSD-3clause-Google Comment: The LevelDB Authors are listed in src/leveldb/AUTHORS. -Files src/snark/* -Copyright: 2012-2019, SCIPR Lab and contributors -License: Expat -Comment: The contributors are listed in src/snark/AUTHORS. - License: Boost-Software-License-1.0 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by From 419cf654b85ddf401a4238fe3c1939c240e0ed23 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 30 Aug 2019 15:04:16 -0600 Subject: [PATCH 280/395] Notable changes for v2.0.7-2 --- doc/release-notes.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index a29094b5174..28607e12169 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,3 +4,21 @@ release-notes at release time) Notable changes =============== + +Pre-Blossom EOS Halt +-------------------- +v2.0.7-2 contains a shortened EOS halt so that is in alignment with v2.0.7. + + +Testnet Blossom Rewind +---------------------- +Testnet users needed to upgrade to 2.0.7 before Blossom activated. The amount +of notice given to these users was brief, so many were not able to upgrade in +time. These users may now be on the wrong branch. v2.0.7-2 adds an "intended +rewind" to prevent having to manually reindex when reconnecting to the correct +chain. + + +Insight Explorer Logging Fix +---------------------------- +Fixed an issue where `ERROR: spent index not enabled` would be logged unnecessarily. From 72d2ab918dc94b7236e8cdffd6ff60ffdc15b0ae Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 30 Aug 2019 17:38:50 -0600 Subject: [PATCH 281/395] make-release.py: Versioning changes for 2.0.7-2. --- README.md | 2 +- configure.ac | 2 +- contrib/gitian-descriptors/gitian-linux.yml | 2 +- src/clientversion.h | 2 +- src/deprecation.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 91a12fbad69..4ab6f3513c6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Zcash 2.0.7-1 +Zcash 2.0.7-2 =========== diff --git a/configure.ac b/configure.ac index 1be5bd991e5..5c0ee02060f 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 2) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_REVISION, 7) -define(_CLIENT_VERSION_BUILD, 51) +define(_CLIENT_VERSION_BUILD, 52) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index b1f39c95990..57de597b67c 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "zcash-2.0.7-1" +name: "zcash-2.0.7-2" enable_cache: true distro: "debian" suites: diff --git a/src/clientversion.h b/src/clientversion.h index dc83538342f..0d5c394de32 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -18,7 +18,7 @@ #define CLIENT_VERSION_MAJOR 2 #define CLIENT_VERSION_MINOR 0 #define CLIENT_VERSION_REVISION 7 -#define CLIENT_VERSION_BUILD 51 +#define CLIENT_VERSION_BUILD 52 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/deprecation.h b/src/deprecation.h index 53089969e7c..10bb3195d80 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -8,7 +8,7 @@ // Deprecation policy: // * Shut down 16 weeks' worth of blocks after the estimated release block height. // * A warning is shown during the 2 weeks' worth of blocks prior to shut down. -static const int APPROX_RELEASE_HEIGHT = 594500; +static const int APPROX_RELEASE_HEIGHT = 588500; static const int WEEKS_UNTIL_DEPRECATION = 16; static const int DEPRECATION_HEIGHT = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 24); From 6271f7b8a6139a077e0a2ab0df24ff2358373c6f Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 30 Aug 2019 17:47:52 -0600 Subject: [PATCH 282/395] make-release.py: Updated manpages for 2.0.7-2. --- doc/man/zcash-cli.1 | 6 +++--- doc/man/zcash-tx.1 | 6 +++--- doc/man/zcashd.1 | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/man/zcash-cli.1 b/doc/man/zcash-cli.1 index 2a63f8f5227..3f187e49cee 100644 --- a/doc/man/zcash-cli.1 +++ b/doc/man/zcash-cli.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-CLI "1" "August 2019" "zcash-cli v2.0.7-1" "User Commands" +.TH ZCASH-CLI "1" "August 2019" "zcash-cli v2.0.7-2" "User Commands" .SH NAME -zcash-cli \- manual page for zcash-cli v2.0.7-1 +zcash-cli \- manual page for zcash-cli v2.0.7-2 .SH DESCRIPTION -Zcash RPC client version v2.0.7\-1 +Zcash RPC client version v2.0.7\-2 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . diff --git a/doc/man/zcash-tx.1 b/doc/man/zcash-tx.1 index 039858dd41d..89ac04d28f6 100644 --- a/doc/man/zcash-tx.1 +++ b/doc/man/zcash-tx.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-TX "1" "August 2019" "zcash-tx v2.0.7-1" "User Commands" +.TH ZCASH-TX "1" "August 2019" "zcash-tx v2.0.7-2" "User Commands" .SH NAME -zcash-tx \- manual page for zcash-tx v2.0.7-1 +zcash-tx \- manual page for zcash-tx v2.0.7-2 .SH DESCRIPTION -Zcash zcash\-tx utility version v2.0.7\-1 +Zcash zcash\-tx utility version v2.0.7\-2 .SS "Usage:" .TP zcash\-tx [options] [commands] diff --git a/doc/man/zcashd.1 b/doc/man/zcashd.1 index 4e52e251a80..0c3aaf84eeb 100644 --- a/doc/man/zcashd.1 +++ b/doc/man/zcashd.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASHD "1" "August 2019" "zcashd v2.0.7-1" "User Commands" +.TH ZCASHD "1" "August 2019" "zcashd v2.0.7-2" "User Commands" .SH NAME -zcashd \- manual page for zcashd v2.0.7-1 +zcashd \- manual page for zcashd v2.0.7-2 .SH DESCRIPTION -Zcash Daemon version v2.0.7\-1 +Zcash Daemon version v2.0.7\-2 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . From 7c7b6625cf6f469201814d7035b8d4708c608726 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 30 Aug 2019 17:47:52 -0600 Subject: [PATCH 283/395] make-release.py: Updated release notes and changelog for 2.0.7-2. --- contrib/debian/changelog | 6 +++++ doc/authors.md | 2 +- doc/release-notes.md | 18 ------------- doc/release-notes/release-notes-2.0.7-2.md | 30 ++++++++++++++++++++++ 4 files changed, 37 insertions(+), 19 deletions(-) create mode 100644 doc/release-notes/release-notes-2.0.7-2.md diff --git a/contrib/debian/changelog b/contrib/debian/changelog index 89ca5da0865..ba3a2a2942c 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,9 @@ +zcash (2.0.7+2) stable; urgency=medium + + * 2.0.7-2 release. + + -- Electric Coin Company Fri, 30 Aug 2019 17:47:52 -0600 + zcash (2.0.7+1) stable; urgency=medium * 2.0.7-1 release. diff --git a/doc/authors.md b/doc/authors.md index 603ac10cd72..1583fd014b1 100644 --- a/doc/authors.md +++ b/doc/authors.md @@ -4,7 +4,7 @@ Zcash Contributors Jack Grigg (874) Simon Liu (459) Sean Bowe (278) -Eirik Ogilvie-Wigley (166) +Eirik Ogilvie-Wigley (169) Daira Hopwood (136) Jay Graber (89) Wladimir J. van der Laan (82) diff --git a/doc/release-notes.md b/doc/release-notes.md index 28607e12169..a29094b5174 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,21 +4,3 @@ release-notes at release time) Notable changes =============== - -Pre-Blossom EOS Halt --------------------- -v2.0.7-2 contains a shortened EOS halt so that is in alignment with v2.0.7. - - -Testnet Blossom Rewind ----------------------- -Testnet users needed to upgrade to 2.0.7 before Blossom activated. The amount -of notice given to these users was brief, so many were not able to upgrade in -time. These users may now be on the wrong branch. v2.0.7-2 adds an "intended -rewind" to prevent having to manually reindex when reconnecting to the correct -chain. - - -Insight Explorer Logging Fix ----------------------------- -Fixed an issue where `ERROR: spent index not enabled` would be logged unnecessarily. diff --git a/doc/release-notes/release-notes-2.0.7-2.md b/doc/release-notes/release-notes-2.0.7-2.md new file mode 100644 index 00000000000..f135ad7337a --- /dev/null +++ b/doc/release-notes/release-notes-2.0.7-2.md @@ -0,0 +1,30 @@ +Notable changes +=============== + + +Pre-Blossom EOS Halt +-------------------- +v2.0.7-2 contains a shortened EOS halt so that is in alignment with v2.0.7. + + +Testnet Blossom Rewind +---------------------- +Testnet users needed to upgrade to 2.0.7 before Blossom activated. The amount +of notice given to these users was brief, so many were not able to upgrade in +time. These users may now be on the wrong branch. v2.0.7-2 adds an "intended +rewind" to prevent having to manually reindex when reconnecting to the correct +chain. + + +Insight Explorer Logging Fix +---------------------------- +Fixed an issue where `ERROR: spent index not enabled` would be logged unnecessarily. + +Changelog +========= + +Eirik Ogilvie-Wigley (3): + Notable changes for v2.0.7-2 + make-release.py: Versioning changes for 2.0.7-2. + make-release.py: Updated manpages for 2.0.7-2. + From f3ec4534ee89d6562d96b03a3a5378d30d3ec1fc Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 29 Oct 2018 11:57:10 +1300 Subject: [PATCH 284/395] depends: Fix crate vendoring path --- depends/funcs.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/depends/funcs.mk b/depends/funcs.mk index f17b246a4c8..877f8060ca3 100644 --- a/depends/funcs.mk +++ b/depends/funcs.mk @@ -40,7 +40,7 @@ endef define vendor_crate_source mkdir -p $($(1)_staging_prefix_dir)/$(CRATE_REGISTRY) && \ -cp -r $($(1)_extract_dir) $($(1)_staging_prefix_dir)/$(CRATE_REGISTRY)/$($(1)_crate_name) && \ +cp -r $($(1)_extract_dir) $($(1)_staging_prefix_dir)/$(CRATE_REGISTRY)/$($(1)_crate_versioned_name) && \ cd $($(1)_staging_prefix_dir)/$(CRATE_REGISTRY)/$($(1)_crate_versioned_name) && \ rm -r `basename $($(1)_patch_dir)` .stamp_* .$($(1)_file_name).hash endef From 8c1f5fa7292cc2e2ef9c90c4d143dacd45e30036 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 30 Oct 2018 14:50:45 +1300 Subject: [PATCH 285/395] depends: Helper for vendoring new crates --- depends/packages/vendorcrate.mk | 15 +++++++++++++++ depends/packages/vendorcrate.sh | 12 ++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 depends/packages/vendorcrate.mk create mode 100755 depends/packages/vendorcrate.sh diff --git a/depends/packages/vendorcrate.mk b/depends/packages/vendorcrate.mk new file mode 100644 index 00000000000..728eb71b5ad --- /dev/null +++ b/depends/packages/vendorcrate.mk @@ -0,0 +1,15 @@ +package=crate_CRATEFILE +$(package)_crate_name=CRATENAME +$(package)_version=CRATEVER +$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) +$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate +$(package)_sha256_hash=CRATEHASH +$(package)_crate_versioned_name=$($(package)_crate_name) + +define $(package)_preprocess_cmds + $(call generate_crate_checksum,$(package)) +endef + +define $(package)_stage_cmds + $(call vendor_crate_source,$(package)) +endef diff --git a/depends/packages/vendorcrate.sh b/depends/packages/vendorcrate.sh new file mode 100755 index 00000000000..b76521ae451 --- /dev/null +++ b/depends/packages/vendorcrate.sh @@ -0,0 +1,12 @@ +pkgdir=$(dirname $0) + +cratefile=$(echo "$1" | tr '-' '_') +cratename=$1 +cratever=$2 +cratehash=$(curl "https://static.crates.io/crates/$cratename/$cratename-$cratever.crate" | sha256sum | awk '{print $1}') + +cat "$pkgdir/vendorcrate.mk" | +sed "s/CRATEFILE/$cratefile/g" | +sed "s/CRATENAME/$cratename/g" | +sed "s/CRATEVER/$cratever/g" | +sed "s/CRATEHASH/$cratehash/g" > "$pkgdir/crate_$cratefile.mk" From 1822eb333f07a63475b0e79569627ae5e1aa0096 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 7 Sep 2019 04:05:56 -0400 Subject: [PATCH 286/395] depends: Add flag for building with a local librustzcash repo Usage: $ ./zcutil/build.sh LIBRUSTZCASH_OVERRIDE=/path/to/librustzcash --- depends/Makefile | 2 ++ depends/README.md | 1 + depends/packages/librustzcash.mk | 34 ++++++++++++++++++++++++++++++-- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/depends/Makefile b/depends/Makefile index aa07755f0d9..b4aeda76139 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -15,6 +15,8 @@ DOWNLOAD_CONNECT_TIMEOUT:=10 DOWNLOAD_RETRIES:=3 CRATE_REGISTRY:=vendored-sources +LIBRUSTZCASH_OVERRIDE ?= + host:=$(BUILD) ifneq ($(HOST),) host:=$(HOST) diff --git a/depends/README.md b/depends/README.md index 41898de1a37..1b976af7ebb 100644 --- a/depends/README.md +++ b/depends/README.md @@ -36,6 +36,7 @@ The following can be set when running make: make FOO=bar PRIORITY_DOWNLOAD_PATH: Try fetching source files from here before using their own URLs NO_WALLET: Don't download/build/cache libs needed to enable the wallet DEBUG: disable some optimizations and enable more runtime checking + LIBRUSTZCASH_OVERRIDE: Path to a local librustzcash repository If some packages are not built, for example `make NO_WALLET=1`, the appropriate options will be passed to bitcoin's configure. In this case, `--disable-wallet`. diff --git a/depends/packages/librustzcash.mk b/depends/packages/librustzcash.mk index 9bc8ee543ec..8dee7b9a690 100644 --- a/depends/packages/librustzcash.mk +++ b/depends/packages/librustzcash.mk @@ -5,8 +5,11 @@ $(package)_file_name=$(package)-$($(package)_git_commit).tar.gz $(package)_download_file=$($(package)_git_commit).tar.gz $(package)_sha256_hash=9909ec59fa7a411c2071d6237b3363a0bc6e5e42358505cf64b7da0f58a7ff5a $(package)_git_commit=06da3b9ac8f278e5d4ae13088cf0a4c03d2c13f5 -$(package)_dependencies=rust $(rust_crates) +$(package)_dependencies=rust +ifeq ($(LIBRUSTZCASH_OVERRIDE),) +$(package)_dependencies+=$(rust_crates) $(package)_patches=cargo.config 0001-Start-using-cargo-clippy-for-CI.patch remove-dev-dependencies.diff +endif $(package)_rust_target=$(if $(rust_rust_target_$(canonical_host)),$(rust_rust_target_$(canonical_host)),$(canonical_host)) @@ -19,12 +22,37 @@ $(package)_library_file=target/release/librustzcash.a endif define $(package)_set_vars -$(package)_build_opts=--frozen --release +$(package)_build_opts=--release +ifeq ($(LIBRUSTZCASH_OVERRIDE),) +$(package)_build_opts+=--frozen +endif ifneq ($(canonical_host),$(build)) $(package)_build_opts+=--target=$($(package)_rust_target) endif endef +ifneq ($(LIBRUSTZCASH_OVERRIDE),) + +define $(package)_fetch_cmds +endef + +define $(package)_extract_cmds +endef + +define $(package)_build_cmds + cd $(LIBRUSTZCASH_OVERRIDE) && \ + $(host_prefix)/native/bin/cargo build --package librustzcash $($(package)_build_opts) +endef + +define $(package)_stage_cmds + mkdir $($(package)_staging_dir)$(host_prefix)/lib/ && \ + mkdir $($(package)_staging_dir)$(host_prefix)/include/ && \ + cp $(LIBRUSTZCASH_OVERRIDE)/$($(package)_library_file) $($(package)_staging_dir)$(host_prefix)/lib/ && \ + cp $(LIBRUSTZCASH_OVERRIDE)/librustzcash/include/librustzcash.h $($(package)_staging_dir)$(host_prefix)/include/ +endef + +else + define $(package)_preprocess_cmds patch -p1 -d pairing < $($(package)_patch_dir)/0001-Start-using-cargo-clippy-for-CI.patch && \ patch -p1 < $($(package)_patch_dir)/remove-dev-dependencies.diff && \ @@ -42,3 +70,5 @@ define $(package)_stage_cmds cp $($(package)_library_file) $($(package)_staging_dir)$(host_prefix)/lib/ && \ cp librustzcash/include/librustzcash.h $($(package)_staging_dir)$(host_prefix)/include/ endef + +endif From a1473b48fe975947b346720d57c0ad15fca68406 Mon Sep 17 00:00:00 2001 From: Bryant Eisenbach Date: Sat, 7 Sep 2019 10:41:12 -0400 Subject: [PATCH 287/395] doc: Change Debian package description --- contrib/debian/control | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/debian/control b/contrib/debian/control index c2c9d17d555..1f9892563f2 100644 --- a/contrib/debian/control +++ b/contrib/debian/control @@ -13,9 +13,9 @@ Vcs-Browser: https://github.com/zcash/zcash Package: zcash Architecture: amd64 Depends: ${shlibs:Depends} -Description: HTTPS for money. +Description: Zcash libraries and tools Based on Bitcoin's code, it intends to offer a far higher standard of privacy and anonymity through a sophisticiated zero-knowledge proving scheme which preserves confidentiality of transaction metadata. This package provides the daemon, zcashd, and the CLI tool, - zcash-cli, to interact with the daemon. + zcash-cli, to interact with the daemon. Think of it as HTTPS for money. From cecccce6fa8ead30b91cde797d9ee4992ba8d176 Mon Sep 17 00:00:00 2001 From: Gareth Davies Date: Thu, 12 Sep 2019 20:30:31 -0700 Subject: [PATCH 288/395] Updating IPFS link for chunking --- zcutil/fetch-params.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/zcutil/fetch-params.sh b/zcutil/fetch-params.sh index 300e12341a9..d53efde9221 100755 --- a/zcutil/fetch-params.sh +++ b/zcutil/fetch-params.sh @@ -13,8 +13,8 @@ SPROUT_VKEY_NAME='sprout-verifying.key' SAPLING_SPEND_NAME='sapling-spend.params' SAPLING_OUTPUT_NAME='sapling-output.params' SAPLING_SPROUT_GROTH16_NAME='sprout-groth16.params' -SPROUT_URL="https://download.z.cash/downloads" -SPROUT_IPFS="/ipfs/QmZKKx7Xup7LiAtFRhYsE1M7waXcv9ir9eCECyXAFGxhEo" +DOWNLOAD_URL="https://download.z.cash/downloads" +IPFS_HASH="/ipfs/QmXRHVGLQBiKwvNq7c2vPxAKz1zRVmMYbmt7G5TQss7tY7" SHA256CMD="$(command -v sha256sum || echo shasum)" SHA256ARGS="$(command -v sha256sum >/dev/null || echo '-a 256')" @@ -38,7 +38,7 @@ function fetch_wget { cat < Date: Mon, 16 Sep 2019 12:23:46 +0100 Subject: [PATCH 289/395] tests: Clean up use of repr() in mininode --- qa/rpc-tests/test_framework/mininode.py | 85 ++++++++++++------------- 1 file changed, 42 insertions(+), 43 deletions(-) diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 9b75eb514ca..ee323c58095 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -355,8 +355,8 @@ def serialize(self): return r def __repr__(self): - return "CBlockLocator(nVersion=%i vHave=%s)" \ - % (self.nVersion, repr(self.vHave)) + return "CBlockLocator(nVersion=%i vHave=%r)" \ + % (self.nVersion, self.vHave) class SpendDescription(object): @@ -476,11 +476,11 @@ def ser_g2(self, p): return r def __repr__(self): - return "ZCProof(g_A=%s g_A_prime=%s g_B=%s g_B_prime=%s g_C=%s g_C_prime=%s g_K=%s g_H=%s)" \ - % (repr(self.g_A), repr(self.g_A_prime), - repr(self.g_B), repr(self.g_B_prime), - repr(self.g_C), repr(self.g_C_prime), - repr(self.g_K), repr(self.g_H)) + return "ZCProof(g_A=%r g_A_prime=%r g_B=%r g_B_prime=%r g_C=%r g_C_prime=%r g_K=%r g_H=%r)" \ + % (self.g_A, self.g_A_prime, + self.g_B, self.g_B_prime, + self.g_C, self.g_C_prime, + self.g_K, self.g_H) ZC_NUM_JS_INPUTS = 2 @@ -566,9 +566,9 @@ def serialize(self): return r def __repr__(self): - return "JSDescription(vpub_old=%i.%08i vpub_new=%i.%08i anchor=%064x onetimePubKey=%064x randomSeed=%064x proof=%s)" \ + return "JSDescription(vpub_old=%i.%08i vpub_new=%i.%08i anchor=%064x onetimePubKey=%064x randomSeed=%064x proof=%r)" \ % (self.vpub_old, self.vpub_new, self.anchor, - self.onetimePubKey, self.randomSeed, repr(self.proof)) + self.onetimePubKey, self.randomSeed, self.proof) class COutPoint(object): @@ -613,8 +613,8 @@ def serialize(self): return r def __repr__(self): - return "CTxIn(prevout=%s scriptSig=%s nSequence=%i)" \ - % (repr(self.prevout), binascii.hexlify(self.scriptSig), + return "CTxIn(prevout=%r scriptSig=%s nSequence=%i)" \ + % (self.prevout, binascii.hexlify(self.scriptSig), self.nSequence) @@ -762,18 +762,18 @@ def is_valid(self): def __repr__(self): r = ("CTransaction(fOverwintered=%r nVersion=%i nVersionGroupId=0x%08x " - "vin=%s vout=%s nLockTime=%i nExpiryHeight=%i valueBalance=%i " - "shieldedSpends=%s shieldedOutputs=%s" + "vin=%r vout=%r nLockTime=%i nExpiryHeight=%i " + "valueBalance=%i shieldedSpends=%r shieldedOutputs=%r" % (self.fOverwintered, self.nVersion, self.nVersionGroupId, - repr(self.vin), repr(self.vout), self.nLockTime, self.nExpiryHeight, - self.valueBalance, repr(self.shieldedSpends), repr(self.shieldedOutputs))) + self.vin, self.vout, self.nLockTime, self.nExpiryHeight, + self.valueBalance, self.shieldedSpends, self.shieldedOutputs)) if self.nVersion >= 2: - r += " vJoinSplit=%s" % repr(self.vJoinSplit) + r += " vJoinSplit=%r" % (self.vJoinSplit,) if len(self.vJoinSplit) > 0: r += " joinSplitPubKey=%064x joinSplitSig=%064x" \ (self.joinSplitPubKey, self.joinSplitSig) if len(self.shieldedSpends) > 0 or len(self.shieldedOutputs) > 0: - r += " bindingSig=%064x" % self.bindingSig + r += " bindingSig=%064x" % (self.bindingSig,) r += ")" return r @@ -851,9 +851,9 @@ def rehash(self): return self.sha256 def __repr__(self): - return "CBlockHeader(nVersion=%i hashPrevBlock=%064x hashMerkleRoot=%064x hashFinalSaplingRoot=%064x nTime=%s nBits=%08x nNonce=%064x nSolution=%s)" \ + return "CBlockHeader(nVersion=%i hashPrevBlock=%064x hashMerkleRoot=%064x hashFinalSaplingRoot=%064x nTime=%s nBits=%08x nNonce=%064x nSolution=%r)" \ % (self.nVersion, self.hashPrevBlock, self.hashMerkleRoot, self.hashFinalSaplingRoot, - time.ctime(self.nTime), self.nBits, self.nNonce, repr(self.nSolution)) + time.ctime(self.nTime), self.nBits, self.nNonce, self.nSolution) class CBlock(CBlockHeader): @@ -923,10 +923,10 @@ def solve(self, n=48, k=5): self.nNonce += 1 def __repr__(self): - return "CBlock(nVersion=%i hashPrevBlock=%064x hashMerkleRoot=%064x hashFinalSaplingRoot=%064x nTime=%s nBits=%08x nNonce=%064x nSolution=%s vtx=%s)" \ + return "CBlock(nVersion=%i hashPrevBlock=%064x hashMerkleRoot=%064x hashFinalSaplingRoot=%064x nTime=%s nBits=%08x nNonce=%064x nSolution=%r vtx=%r)" \ % (self.nVersion, self.hashPrevBlock, self.hashMerkleRoot, self.hashFinalSaplingRoot, time.ctime(self.nTime), self.nBits, - self.nNonce, repr(self.nSolution), repr(self.vtx)) + self.nNonce, self.nSolution, self.vtx) class CUnsignedAlert(object): @@ -1054,9 +1054,9 @@ def serialize(self): return r def __repr__(self): - return 'msg_version(nVersion=%i nServices=%i nTime=%s addrTo=%s addrFrom=%s nNonce=0x%016X strSubVer=%s nStartingHeight=%i)' \ + return 'msg_version(nVersion=%i nServices=%i nTime=%s addrTo=%r addrFrom=%r nNonce=0x%016X strSubVer=%s nStartingHeight=%i)' \ % (self.nVersion, self.nServices, time.ctime(self.nTime), - repr(self.addrTo), repr(self.addrFrom), self.nNonce, + self.addrTo, self.addrFrom, self.nNonce, self.strSubVer, self.nStartingHeight) @@ -1089,7 +1089,7 @@ def serialize(self): return ser_vector(self.addrs) def __repr__(self): - return "msg_addr(addrs=%s)" % (repr(self.addrs)) + return "msg_addr(addrs=%r)" % (self.addrs,) class msg_alert(object): @@ -1108,7 +1108,7 @@ def serialize(self): return r def __repr__(self): - return "msg_alert(alert=%s)" % (repr(self.alert), ) + return "msg_alert(alert=%r)" % (self.alert,) class msg_inv(object): @@ -1127,7 +1127,7 @@ def serialize(self): return ser_vector(self.inv) def __repr__(self): - return "msg_inv(inv=%s)" % (repr(self.inv)) + return "msg_inv(inv=%r)" % (self.inv,) class msg_getdata(object): @@ -1143,7 +1143,7 @@ def serialize(self): return ser_vector(self.inv) def __repr__(self): - return "msg_getdata(inv=%s)" % (repr(self.inv)) + return "msg_getdata(inv=%r)" % (self.inv,) class msg_notfound(object): @@ -1159,7 +1159,7 @@ def serialize(self): return ser_vector(self.inv) def __repr__(self): - return "msg_notfound(inv=%s)" % (repr(self.inv)) + return "msg_notfound(inv=%r)" % (self.inv,) class msg_getblocks(object): @@ -1181,8 +1181,8 @@ def serialize(self): return r def __repr__(self): - return "msg_getblocks(locator=%s hashstop=%064x)" \ - % (repr(self.locator), self.hashstop) + return "msg_getblocks(locator=%r hashstop=%064x)" \ + % (self.locator, self.hashstop) class msg_tx(object): @@ -1198,7 +1198,7 @@ def serialize(self): return self.tx.serialize() def __repr__(self): - return "msg_tx(tx=%s)" % (repr(self.tx)) + return "msg_tx(tx=%r)" % (self.tx,) class msg_block(object): @@ -1217,7 +1217,7 @@ def serialize(self): return self.block.serialize() def __repr__(self): - return "msg_block(block=%s)" % (repr(self.block)) + return "msg_block(block=%r)" % (self.block,) class msg_getaddr(object): @@ -1327,8 +1327,8 @@ def serialize(self): return r def __repr__(self): - return "msg_getheaders(locator=%s, stop=%064x)" \ - % (repr(self.locator), self.hashstop) + return "msg_getheaders(locator=%r, stop=%064x)" \ + % (self.locator, self.hashstop) # headers message has @@ -1350,7 +1350,7 @@ def serialize(self): return ser_vector(blocks) def __repr__(self): - return "msg_headers(headers=%s)" % repr(self.headers) + return "msg_headers(headers=%r)" % (self.headers,) class msg_reject(object): @@ -1395,7 +1395,7 @@ def serialize(self): return ser_string(self.data) def __repr__(self): - return "msg_filteradd(data=%s)" % (repr(self.data)) + return "msg_filteradd(data=%r)" % (self.data,) class msg_filterclear(object): @@ -1448,7 +1448,7 @@ def deliver(self, conn, message): try: self.cbmap[message.command](conn, message) except: - print "ERROR delivering %s (%s)" % (repr(message), + print "ERROR delivering %r (%s)" % (message, sys.exc_info()[0]) def on_version(self, conn, message): @@ -1599,7 +1599,7 @@ def got_data(self): if len(self.recvbuf) < 4: return if self.recvbuf[:4] != self.MAGIC_BYTES[self.network]: - raise ValueError("got garbage %s" % repr(self.recvbuf)) + raise ValueError("got garbage %r" % (self.recvbuf,)) if self.ver_recv < 209: if len(self.recvbuf) < 4 + 12 + 4: return @@ -1622,7 +1622,7 @@ def got_data(self): th = sha256(msg) h = sha256(th) if checksum != h[:4]: - raise ValueError("got bad checksum " + repr(self.recvbuf)) + raise ValueError("got bad checksum %r" % (self.recvbuf,)) self.recvbuf = self.recvbuf[4+12+4+4+msglen:] if command in self.messagemap: f = cStringIO.StringIO(msg) @@ -1630,13 +1630,12 @@ def got_data(self): t.deserialize(f) self.got_message(t) else: - self.show_debug_msg("Unknown command: '" + command + "' " + - repr(msg)) + self.show_debug_msg("Unknown command: '%s' %r" % (command, msg)) def send_message(self, message, pushbuf=False): if self.state != "connected" and not pushbuf: return - self.show_debug_msg("Send %s" % repr(message)) + self.show_debug_msg("Send %r" % (message,)) command = message.command data = message.serialize() tmsg = self.MAGIC_BYTES[self.network] @@ -1658,7 +1657,7 @@ def got_message(self, message): self.messagemap['ping'] = msg_ping_prebip31 if self.last_sent + 30 * 60 < time.time(): self.send_message(self.messagemap['ping']()) - self.show_debug_msg("Recv %s" % repr(message)) + self.show_debug_msg("Recv %r" % (message,)) self.cb.deliver(self, message) def disconnect_node(self): From fe3cb8ec93ebf2bb0abfff01b18d7ea341849e78 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 16 Sep 2019 13:10:54 +0100 Subject: [PATCH 290/395] Remove makeGrothProof argument from JoinSplit::prove --- src/gtest/test_checktransaction.cpp | 1 - src/gtest/test_joinsplit.cpp | 3 +- src/gtest/test_transaction.cpp | 3 - src/primitives/transaction.cpp | 4 - src/primitives/transaction.h | 2 - src/test/transaction_tests.cpp | 8 +- src/transaction_builder.cpp | 2 +- src/utiltest.cpp | 4 +- .../asyncrpcoperation_mergetoaddress.cpp | 2 +- src/wallet/asyncrpcoperation_sendmany.cpp | 2 +- .../asyncrpcoperation_shieldcoinbase.cpp | 2 +- src/wallet/rpcwallet.cpp | 46 ++++++----- src/zcash/JoinSplit.cpp | 76 +++++++++---------- src/zcash/JoinSplit.hpp | 1 - src/zcbenchmarks.cpp | 3 +- 15 files changed, 76 insertions(+), 83 deletions(-) diff --git a/src/gtest/test_checktransaction.cpp b/src/gtest/test_checktransaction.cpp index 762686ef589..04d69ab1965 100644 --- a/src/gtest/test_checktransaction.cpp +++ b/src/gtest/test_checktransaction.cpp @@ -748,7 +748,6 @@ TEST(checktransaction_tests, SaplingSproutInputSumsTooLarge) { std::array outputMap; auto jsdesc = JSDescription::Randomized( - true, *params, joinSplitPubKey, rt, inputs, outputs, inputMap, outputMap, diff --git a/src/gtest/test_joinsplit.cpp b/src/gtest/test_joinsplit.cpp index b324d10d671..8032fc97210 100644 --- a/src/gtest/test_joinsplit.cpp +++ b/src/gtest/test_joinsplit.cpp @@ -33,7 +33,7 @@ JSDescription makeSproutProof( uint64_t vpub_new, const uint256& rt ){ - return JSDescription(true, js, joinSplitPubKey, rt, inputs, outputs, vpub_old, vpub_new); + return JSDescription(js, joinSplitPubKey, rt, inputs, outputs, vpub_old, vpub_new); } bool verifySproutProof( @@ -182,7 +182,6 @@ void invokeAPI( // Groth SproutProof proof = js->prove( - true, inputs, outputs, output_notes, diff --git a/src/gtest/test_transaction.cpp b/src/gtest/test_transaction.cpp index 099bb10314c..4ba48c3d2a7 100644 --- a/src/gtest/test_transaction.cpp +++ b/src/gtest/test_transaction.cpp @@ -45,7 +45,6 @@ TEST(Transaction, JSDescriptionRandomized) { { auto jsdesc = JSDescription::Randomized( - true, *params, joinSplitPubKey, rt, inputs, outputs, inputMap, outputMap, @@ -62,7 +61,6 @@ TEST(Transaction, JSDescriptionRandomized) { { auto jsdesc = JSDescription::Randomized( - true, *params, joinSplitPubKey, rt, inputs, outputs, inputMap, outputMap, @@ -76,7 +74,6 @@ TEST(Transaction, JSDescriptionRandomized) { { auto jsdesc = JSDescription::Randomized( - true, *params, joinSplitPubKey, rt, inputs, outputs, inputMap, outputMap, diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index 27cfd18f200..b4f72ed452a 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -12,7 +12,6 @@ #include "librustzcash.h" JSDescription::JSDescription( - bool makeGrothProof, ZCJoinSplit& params, const uint256& joinSplitPubKey, const uint256& anchor, @@ -27,7 +26,6 @@ JSDescription::JSDescription( std::array notes; proof = params.prove( - makeGrothProof, inputs, outputs, notes, @@ -47,7 +45,6 @@ JSDescription::JSDescription( } JSDescription JSDescription::Randomized( - bool makeGrothProof, ZCJoinSplit& params, const uint256& joinSplitPubKey, const uint256& anchor, @@ -72,7 +69,6 @@ JSDescription JSDescription::Randomized( MappedShuffle(outputs.begin(), outputMap.begin(), ZC_NUM_JS_OUTPUTS, gen); return JSDescription( - makeGrothProof, params, joinSplitPubKey, anchor, inputs, outputs, vpub_old, vpub_new, computeProof, esk // payment disclosure diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 20011e9b5fb..3e8e2e7fa84 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -227,7 +227,6 @@ class JSDescription JSDescription(): vpub_old(0), vpub_new(0) { } JSDescription( - bool makeGrothProof, ZCJoinSplit& params, const uint256& joinSplitPubKey, const uint256& rt, @@ -240,7 +239,6 @@ class JSDescription ); static JSDescription Randomized( - bool makeGrothProof, ZCJoinSplit& params, const uint256& joinSplitPubKey, const uint256& rt, diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 725d60cfeb3..085b3d03963 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -373,7 +373,7 @@ BOOST_AUTO_TEST_CASE(test_basic_joinsplit_verification) auto verifier = libzcash::ProofVerifier::Strict(); { - JSDescription jsdesc(true, *pzcashParams, joinSplitPubKey, rt, inputs, outputs, 0, 0); + JSDescription jsdesc(*pzcashParams, joinSplitPubKey, rt, inputs, outputs, 0, 0); BOOST_CHECK(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey)); CDataStream ss(SER_DISK, CLIENT_VERSION); @@ -389,13 +389,13 @@ BOOST_AUTO_TEST_CASE(test_basic_joinsplit_verification) { // Ensure that the balance equation is working. - BOOST_CHECK_THROW(JSDescription(true, *pzcashParams, joinSplitPubKey, rt, inputs, outputs, 10, 0), std::invalid_argument); - BOOST_CHECK_THROW(JSDescription(true, *pzcashParams, joinSplitPubKey, rt, inputs, outputs, 0, 10), std::invalid_argument); + BOOST_CHECK_THROW(JSDescription(*pzcashParams, joinSplitPubKey, rt, inputs, outputs, 10, 0), std::invalid_argument); + BOOST_CHECK_THROW(JSDescription(*pzcashParams, joinSplitPubKey, rt, inputs, outputs, 0, 10), std::invalid_argument); } { // Ensure that it won't verify if the root is changed. - auto test = JSDescription(true, *pzcashParams, joinSplitPubKey, rt, inputs, outputs, 0, 0); + auto test = JSDescription(*pzcashParams, joinSplitPubKey, rt, inputs, outputs, 0, 0); test.anchor = GetRandHash(); BOOST_CHECK(!test.Verify(*pzcashParams, verifier, joinSplitPubKey)); } diff --git a/src/transaction_builder.cpp b/src/transaction_builder.cpp index 3332780917c..ed1768c25be 100644 --- a/src/transaction_builder.cpp +++ b/src/transaction_builder.cpp @@ -695,8 +695,8 @@ void TransactionBuilder::CreateJSDescription( uint256 esk; // payment disclosure - secret // Generate the proof, this can take over a minute. + assert(mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION)); JSDescription jsdesc = JSDescription::Randomized( - mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION), *sproutParams, mtx.joinSplitPubKey, vjsin[0].witness.root(), diff --git a/src/utiltest.cpp b/src/utiltest.cpp index f3d6d1c98ec..a3576fd6d98 100644 --- a/src/utiltest.cpp +++ b/src/utiltest.cpp @@ -52,7 +52,7 @@ CMutableTransaction GetValidSproutReceiveTransaction(ZCJoinSplit& params, // Prepare JoinSplits uint256 rt; - JSDescription jsdesc {true, params, mtx.joinSplitPubKey, rt, + JSDescription jsdesc {params, mtx.joinSplitPubKey, rt, inputs, outputs, 2*value, 0, false}; mtx.vJoinSplit.push_back(jsdesc); @@ -178,7 +178,7 @@ CWalletTx GetValidSproutSpend(ZCJoinSplit& params, // Prepare JoinSplits uint256 rt = tree.root(); - JSDescription jsdesc {true, params, mtx.joinSplitPubKey, rt, + JSDescription jsdesc {params, mtx.joinSplitPubKey, rt, inputs, outputs, 0, value, false}; mtx.vJoinSplit.push_back(jsdesc); diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index c44e7d221e0..82e8736b5cd 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -802,8 +802,8 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit( uint256 esk; // payment disclosure - secret + assert(mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION)); JSDescription jsdesc = JSDescription::Randomized( - mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION), *pzcashParams, joinSplitPubKey_, anchor, diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index 657ff22c450..1562cf1eef9 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -1079,8 +1079,8 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit( uint256 esk; // payment disclosure - secret + assert(mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION)); JSDescription jsdesc = JSDescription::Randomized( - mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION), *pzcashParams, joinSplitPubKey_, anchor, diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp index 9bc1cbcc262..1d7d3ef0abf 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp @@ -318,8 +318,8 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf uint256 esk; // payment disclosure - secret + assert(mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION)); JSDescription jsdesc = JSDescription::Randomized( - mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION), *pzcashParams, joinSplitPubKey_, anchor, diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index aa610ff56ff..3852b8e0288 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2683,8 +2683,7 @@ UniValue zc_sample_joinsplit(const UniValue& params, bool fHelp) uint256 joinSplitPubKey; uint256 anchor = SproutMerkleTree().root(); - JSDescription samplejoinsplit(true, - *pzcashParams, + JSDescription samplejoinsplit(*pzcashParams, joinSplitPubKey, anchor, {JSInput(), JSInput()}, @@ -3050,8 +3049,7 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp) mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID; mtx.joinSplitPubKey = joinSplitPubKey; - JSDescription jsdesc(true, - *pzcashParams, + JSDescription jsdesc(*pzcashParams, joinSplitPubKey, anchor, {vjsin[0], vjsin[1]}, @@ -3883,6 +3881,15 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) o.push_back(Pair("fee", std::stod(FormatMoney(nFee)))); UniValue contextInfo = o; + if (!fromTaddr || !zaddrRecipients.empty()) { + // We have shielded inputs or outputs, and therefore cannot create + // transactions before Sapling activates. + if (!Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_SAPLING)) { + throw JSONRPCError( + RPC_INVALID_PARAMETER, "Cannot create shielded transactions before Sapling has activated"); + } + } + // Builder (used if Sapling addresses are involved) boost::optional builder; if (noSproutAddrs) { @@ -4120,21 +4127,17 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp) } int nextBlockHeight = chainActive.Height() + 1; + const bool saplingActive = Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_SAPLING); + + // We cannot create shielded transactions before Sapling activates. + if (!saplingActive) { + throw JSONRPCError( + RPC_INVALID_PARAMETER, "Cannot create shielded transactions before Sapling has activated"); + } + bool overwinterActive = Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_OVERWINTER); + assert(overwinterActive); unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING; - if (!Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_SAPLING)) { - max_tx_size = MAX_TX_SIZE_BEFORE_SAPLING; - auto res = DecodePaymentAddress(destaddress); - // If Sapling is not active, do not allow sending to a Sapling address. - if (IsValidPaymentAddress(res)) { - bool toSapling = boost::get(&res) != nullptr; - if (toSapling) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated"); - } - } else { - throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress ); - } - } // Prepare to get coinbase utxos std::vector inputs; @@ -4637,6 +4640,15 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) contextInfo.push_back(Pair("toaddress", params[1])); contextInfo.push_back(Pair("fee", ValueFromAmount(nFee))); + if (!sproutNoteInputs.empty() || !saplingNoteInputs.empty() || !IsValidDestination(taddr)) { + // We have shielded inputs or the recipient is a shielded address, and + // therefore we cannot create transactions before Sapling activates. + if (!saplingActive) { + throw JSONRPCError( + RPC_INVALID_PARAMETER, "Cannot create shielded transactions before Sapling has activated"); + } + } + // Contextual transaction we will build on CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction( Params().GetConsensus(), diff --git a/src/zcash/JoinSplit.cpp b/src/zcash/JoinSplit.cpp index 834ea76429b..0a052209ae5 100644 --- a/src/zcash/JoinSplit.cpp +++ b/src/zcash/JoinSplit.cpp @@ -29,7 +29,6 @@ class JoinSplitCircuit : public JoinSplit { ~JoinSplitCircuit() {} SproutProof prove( - bool makeGrothProof, const std::array& inputs, const std::array& outputs, std::array& out_notes, @@ -160,57 +159,52 @@ class JoinSplitCircuit : public JoinSplit { out_macs[i] = PRF_pk(inputs[i].key, i, h_sig); } - if (makeGrothProof) { - if (!computeProof) { - return GrothProof(); - } - - GrothProof proof; + if (!computeProof) { + return GrothProof(); + } - CDataStream ss1(SER_NETWORK, PROTOCOL_VERSION); - ss1 << inputs[0].witness.path(); - std::vector auth1(ss1.begin(), ss1.end()); + GrothProof proof; - CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); - ss2 << inputs[1].witness.path(); - std::vector auth2(ss2.begin(), ss2.end()); + CDataStream ss1(SER_NETWORK, PROTOCOL_VERSION); + ss1 << inputs[0].witness.path(); + std::vector auth1(ss1.begin(), ss1.end()); - librustzcash_sprout_prove( - proof.begin(), + CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); + ss2 << inputs[1].witness.path(); + std::vector auth2(ss2.begin(), ss2.end()); - phi.begin(), - rt.begin(), - h_sig.begin(), + librustzcash_sprout_prove( + proof.begin(), - inputs[0].key.begin(), - inputs[0].note.value(), - inputs[0].note.rho.begin(), - inputs[0].note.r.begin(), - auth1.data(), + phi.begin(), + rt.begin(), + h_sig.begin(), - inputs[1].key.begin(), - inputs[1].note.value(), - inputs[1].note.rho.begin(), - inputs[1].note.r.begin(), - auth2.data(), + inputs[0].key.begin(), + inputs[0].note.value(), + inputs[0].note.rho.begin(), + inputs[0].note.r.begin(), + auth1.data(), - out_notes[0].a_pk.begin(), - out_notes[0].value(), - out_notes[0].r.begin(), + inputs[1].key.begin(), + inputs[1].note.value(), + inputs[1].note.rho.begin(), + inputs[1].note.r.begin(), + auth2.data(), - out_notes[1].a_pk.begin(), - out_notes[1].value(), - out_notes[1].r.begin(), + out_notes[0].a_pk.begin(), + out_notes[0].value(), + out_notes[0].r.begin(), - vpub_old, - vpub_new - ); + out_notes[1].a_pk.begin(), + out_notes[1].value(), + out_notes[1].r.begin(), - return proof; - } + vpub_old, + vpub_new + ); - // We have removed the ability to create pre-Sapling Sprout proofs. - throw std::invalid_argument("Cannot create non-Groth16 Sprout proofs"); + return proof; } }; diff --git a/src/zcash/JoinSplit.hpp b/src/zcash/JoinSplit.hpp index 98c8e30ddd5..09e31570fd5 100644 --- a/src/zcash/JoinSplit.hpp +++ b/src/zcash/JoinSplit.hpp @@ -65,7 +65,6 @@ class JoinSplit { // Compute nullifiers, macs, note commitments & encryptions, and SNARK proof virtual SproutProof prove( - bool makeGrothProof, const std::array& inputs, const std::array& outputs, std::array& out_notes, diff --git a/src/zcbenchmarks.cpp b/src/zcbenchmarks.cpp index c6ff9da49da..552ba330d89 100644 --- a/src/zcbenchmarks.cpp +++ b/src/zcbenchmarks.cpp @@ -100,8 +100,7 @@ double benchmark_create_joinsplit() struct timeval tv_start; timer_start(tv_start); - JSDescription jsdesc(true, - *pzcashParams, + JSDescription jsdesc(*pzcashParams, joinSplitPubKey, anchor, {JSInput(), JSInput()}, From 2efcb9e592d13964560ff5ed2c11b229c22a88a5 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 17 Sep 2019 12:00:03 +0100 Subject: [PATCH 291/395] Stop fetching old Sprout parameters We aren't automatically deleting them yet. --- zcutil/fetch-params.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/zcutil/fetch-params.sh b/zcutil/fetch-params.sh index 300e12341a9..5f7f019360f 100755 --- a/zcutil/fetch-params.sh +++ b/zcutil/fetch-params.sh @@ -211,8 +211,10 @@ EOF cd "$PARAMS_DIR" # Sprout parameters: - fetch_params "$SPROUT_PKEY_NAME" "$PARAMS_DIR/$SPROUT_PKEY_NAME" "8bc20a7f013b2b58970cddd2e7ea028975c88ae7ceb9259a5344a16bc2c0eef7" - fetch_params "$SPROUT_VKEY_NAME" "$PARAMS_DIR/$SPROUT_VKEY_NAME" "4bd498dae0aacfd8e98dc306338d017d9c08dd0918ead18172bd0aec2fc5df82" + # Commented out because they are unneeded, but we will eventually update + # this to delete the parameters if possible. + #fetch_params "$SPROUT_PKEY_NAME" "$PARAMS_DIR/$SPROUT_PKEY_NAME" "8bc20a7f013b2b58970cddd2e7ea028975c88ae7ceb9259a5344a16bc2c0eef7" + #fetch_params "$SPROUT_VKEY_NAME" "$PARAMS_DIR/$SPROUT_VKEY_NAME" "4bd498dae0aacfd8e98dc306338d017d9c08dd0918ead18172bd0aec2fc5df82" # Sapling parameters: fetch_params "$SAPLING_SPEND_NAME" "$PARAMS_DIR/$SAPLING_SPEND_NAME" "8e48ffd23abb3a5fd9c5589204f32d9c31285a04b78096ba40a79b75677efc13" From 4cae370328c71e160eefab40941d2b89ea201217 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 17 Sep 2019 12:25:43 +0100 Subject: [PATCH 292/395] Add libsnark removal to notable changes --- doc/release-notes.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index a29094b5174..49ef03ace1a 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,3 +4,40 @@ release-notes at release time) Notable changes =============== +Disabling old Sprout proofs +--------------------------- + +As part of our ongoing work to clean up the codebase and minimise the security +surface of `zcashd`, we are removing `libsnark` from the codebase, and dropping +support for creating and verifying old Sprout proofs. Funds stored in Sprout +addresses are not affected, as they are spent using the hybrid Sprout circuit +(built using `bellman`) that was deployed during the Sapling network upgrade. + +This change has several implications: + +- `zcashd` no longer verifies old Sprout proofs, and will instead assume they + are valid. This has a minor implication for nodes: during initial block + download, an adversary could feed the node fake blocks containing invalid old + Sprout proofs, and the node would accept the fake chain as valid. However, + `zcashd` internally contains checkpoints after Sapling activation for both + block heights and cumulative chain work, and does not exit the initial block + download phase until the active chain contains at least as much work as the + checkpointed chain work. The node would therefore be non-functional (and would + not broadcast the fake chain to other peers) until the fake chain contained as + much work as the main chain, making this a 50% + 1 attack, which the current + consensus rules already does not protect against. + +- Shielded transactions can no longer be created before Sapling has activated. + This does not affect Zcash itself, but will affect downstream codebases that + have not yet activated Sapling (or that start a new chain after this point and + do not activate Sapling from launch). Note that the old Sprout circuit is + [vulnerable to counterfeiting](https://z.cash/support/security/announcements/security-announcement-2019-02-05-cve-2019-7167/) + and should not be used in current deployments. + +- Starting from this release, the circuit parameters from the original Sprout + MPC are no longer required to start `zcashd`, and will not be downloaded by + `fetch-params.sh`. They are not being automatically deleted at this time. + +We would like to take a moment to thank the `libsnark` authors and contributors. +It was vital to the success of Zcash, and the development of zero-knowledge +proofs in general, to have this code available and usable. From 94a4761b8503a3270aa812df2aacd90f5df75651 Mon Sep 17 00:00:00 2001 From: Bryant Eisenbach Date: Tue, 17 Sep 2019 20:09:11 -0400 Subject: [PATCH 293/395] doc: Move text prior to "This package provides..." --- contrib/debian/control | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contrib/debian/control b/contrib/debian/control index 1f9892563f2..ab54f517fd5 100644 --- a/contrib/debian/control +++ b/contrib/debian/control @@ -17,5 +17,6 @@ Description: Zcash libraries and tools Based on Bitcoin's code, it intends to offer a far higher standard of privacy and anonymity through a sophisticiated zero-knowledge proving scheme which preserves confidentiality of transaction metadata. + Think of it as HTTPS for money. This package provides the daemon, zcashd, and the CLI tool, - zcash-cli, to interact with the daemon. Think of it as HTTPS for money. + zcash-cli, to interact with the daemon. From 188f3254fc678dcd8feaab142831cf171db3e1e0 Mon Sep 17 00:00:00 2001 From: jeff-liang <46398134+jeff-liang@users.noreply.github.com> Date: Sat, 5 Jan 2019 08:19:20 -0500 Subject: [PATCH 294/395] Display which network the node is running on. Co-authored-by: Jeff Liang Signed-off-by: Daira Hopwood --- src/metrics.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/metrics.cpp b/src/metrics.cpp index 1fe7660b33f..19a9f0f1a18 100644 --- a/src/metrics.cpp +++ b/src/metrics.cpp @@ -109,6 +109,15 @@ double GetLocalSolPS() return miningTimer.rate(solutionTargetChecks); } +std::string WhichNetwork() +{ + if (GetBoolArg("-regtest", false)) + return "regtest "; + if (GetBoolArg("-testnet", false)) + return "testnet "; + return "mainnet "; +} + int EstimateNetHeight(const Consensus::Params& params, int currentHeadersHeight, int64_t currentHeadersTime) { int64_t now = GetAdjustedTime(); @@ -460,7 +469,7 @@ void ThreadShowMetricsScreen() std::cout << std::endl; // Thank you text - std::cout << _("Thank you for running a Zcash node!") << std::endl; + std::cout << _("Thank you for running a " + WhichNetwork() + "Zcash node!") << std::endl; std::cout << _("You're helping to strengthen the network and contributing to a social good :)") << std::endl; // Privacy notice text From c8715f7fb3659c58f83ec81d664c77ea182533e2 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 18 Sep 2019 12:16:11 -0600 Subject: [PATCH 295/395] Wrap metrics message in strprintf --- src/metrics.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/metrics.cpp b/src/metrics.cpp index 19a9f0f1a18..e6488e6c877 100644 --- a/src/metrics.cpp +++ b/src/metrics.cpp @@ -112,10 +112,10 @@ double GetLocalSolPS() std::string WhichNetwork() { if (GetBoolArg("-regtest", false)) - return "regtest "; + return "regtest"; if (GetBoolArg("-testnet", false)) - return "testnet "; - return "mainnet "; + return "testnet"; + return "mainnet"; } int EstimateNetHeight(const Consensus::Params& params, int currentHeadersHeight, int64_t currentHeadersTime) @@ -469,7 +469,7 @@ void ThreadShowMetricsScreen() std::cout << std::endl; // Thank you text - std::cout << _("Thank you for running a " + WhichNetwork() + "Zcash node!") << std::endl; + std::cout << strprintf(_("Thank you for running a %s Zcash node!"), WhichNetwork()) << std::endl; std::cout << _("You're helping to strengthen the network and contributing to a social good :)") << std::endl; // Privacy notice text From 10b9d6306b99ac4907d6bd172e35fe9fbad809cf Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 19 Sep 2019 14:52:55 +0100 Subject: [PATCH 296/395] Move AbortNode to the top of main.cpp It is in an anonymous namespace, so it needs to be above all code in the file that uses it. --- src/main.cpp | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 9318deaf74a..7a0ff25143d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -113,6 +113,24 @@ const string strMessageMagic = "Zcash Signed Message:\n"; // Internal stuff namespace { + /** Abort with a message */ + bool AbortNode(const std::string& strMessage, const std::string& userMessage="") + { + strMiscWarning = strMessage; + LogPrintf("*** %s\n", strMessage); + uiInterface.ThreadSafeMessageBox( + userMessage.empty() ? _("Error: A fatal internal error occurred, see debug.log for details") : userMessage, + "", CClientUIInterface::MSG_ERROR); + StartShutdown(); + return false; + } + + bool AbortNode(CValidationState& state, const std::string& strMessage, const std::string& userMessage="") + { + AbortNode(strMessage, userMessage); + return state.Error(strMessage); + } + struct CBlockIndexWorkComparator { bool operator()(CBlockIndex *pa, CBlockIndex *pb) const { @@ -2236,24 +2254,6 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uin return true; } -/** Abort with a message */ -bool AbortNode(const std::string& strMessage, const std::string& userMessage="") -{ - strMiscWarning = strMessage; - LogPrintf("*** %s\n", strMessage); - uiInterface.ThreadSafeMessageBox( - userMessage.empty() ? _("Error: A fatal internal error occurred, see debug.log for details") : userMessage, - "", CClientUIInterface::MSG_ERROR); - StartShutdown(); - return false; -} - -bool AbortNode(CValidationState& state, const std::string& strMessage, const std::string& userMessage="") -{ - AbortNode(strMessage, userMessage); - return state.Error(strMessage); -} - } // anon namespace /** From 150e3303109047118179f33b1cc5fc63095eb21d Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 19 Sep 2019 15:00:04 +0100 Subject: [PATCH 297/395] Abort node if NU activations have unexpected hashes --- src/consensus/params.h | 12 ++++++++++++ src/main.cpp | 23 +++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/consensus/params.h b/src/consensus/params.h index a206738ee17..09cbc766196 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -59,6 +59,18 @@ struct NetworkUpgrade { * should remain disabled on mainnet. */ static constexpr int NO_ACTIVATION_HEIGHT = -1; + + /** + * The hash of the block at height nActivationHeight, if known. This is set manually + * after a network upgrade activates. + * + * We use this in IsInitialBlockDownload to detect whether we are potentially being + * fed a fake alternate chain. We use NU activation blocks for this purpose instead of + * the checkpoint blocks, because network upgrades (should) have significantly more + * scrutiny than regular releases. nMinimumChainWork MUST be set to at least the chain + * work of this block, otherwise this detection will have false positives. + */ + boost::optional hashActivationBlock; }; /** ZIP208 block target interval in seconds. */ diff --git a/src/main.cpp b/src/main.cpp index 7a0ff25143d..54c11319c81 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1865,6 +1865,29 @@ bool IsInitialBlockDownload(const CChainParams& chainParams) return true; if (chainActive.Tip()->nChainWork < UintToArith256(chainParams.GetConsensus().nMinimumChainWork)) return true; + // Don't bother checking Sprout, it is always active. + for (int idx = Consensus::BASE_SPROUT + 1; idx < Consensus::MAX_NETWORK_UPGRADES; idx++) { + // If we expect a particular activation block hash, and either the upgrade is not + // active or it doesn't match the block at that height on the current chain, then + // we are not on the correct chain. As we have already checked that the current + // chain satisfies the minimum chain work, this is likely an adversarial situation + // where the node is being fed a fake alternate chain; shut down for safety. + auto upgrade = chainParams.GetConsensus().vUpgrades[idx]; + if (upgrade.hashActivationBlock && ( + !chainParams.GetConsensus().NetworkUpgradeActive(chainActive.Height(), Consensus::UpgradeIndex(idx)) + || chainActive[upgrade.nActivationHeight]->GetBlockHash() != upgrade.hashActivationBlock.get() + )) { + AbortNode( + strprintf( + "%s: Activation block hash mismatch for the %s network upgrade (expected %s, found %s). Likely adversarial condition; shutting down for safety.", + __func__, + NetworkUpgradeInfo[idx].strName, + upgrade.hashActivationBlock.get().GetHex(), + chainActive[upgrade.nActivationHeight]->GetBlockHash().GetHex()), + _("We are on a chain with sufficient work, but the network upgrade checkpoints do not match. Your node may be under attack! Shutting down for safety.")); + return true; + } + } if (chainActive.Tip()->GetBlockTime() < (GetTime() - nMaxTipAge)) return true; LogPrintf("Leaving InitialBlockDownload (latching to false)\n"); From c8c43c4210fae422cc03b5b14e8d22dd1753e68c Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 19 Sep 2019 16:08:48 +0100 Subject: [PATCH 298/395] Add block hashes for Overwinter, Sapling, and testnet Blossom Also updates nMinimumChainWork for testnet (using block 585000). --- src/chainparams.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index cf47610f602..dbe9f603a0e 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -110,8 +110,12 @@ class CMainParams : public CChainParams { Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion = 170005; consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = 347500; + consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].hashActivationBlock = + uint256S("0000000003761c0d0c3974b54bdb425613bbb1eaadd6e70b764de82f195ea243"); consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nProtocolVersion = 170007; consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = 419200; + consensus.vUpgrades[Consensus::UPGRADE_SAPLING].hashActivationBlock = + uint256S("00000000025a57200d898ac7f21e26bf29028bbe96ec46e05b2c17cc9db9e4f3"); consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].nProtocolVersion = 170009; consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight = Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; @@ -303,13 +307,19 @@ class CTestNetParams : public CChainParams { Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion = 170003; consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = 207500; + consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].hashActivationBlock = + uint256S("0000257c4331b098045023fcfbfa2474681f4564ab483f84e4e1ad078e4acf44"); consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nProtocolVersion = 170007; consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = 280000; + consensus.vUpgrades[Consensus::UPGRADE_SAPLING].hashActivationBlock = + uint256S("000420e7fcc3a49d729479fb0b560dd7b8617b178a08e9e389620a9d1dd6361a"); consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].nProtocolVersion = 170008; consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight = 584000; + consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].hashActivationBlock = + uint256S("00367515ef2e781b8c9358b443b6329572599edd02c59e8af67db9785122f298"); // The best chain should have at least this much work. - consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000000000001d0c4d9cd"); + consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000000000000000001dbb4c4224"); pchMessageStart[0] = 0xfa; pchMessageStart[1] = 0x1a; From 5ae7b70ae644ee52b6ebcd76ea2957225c8aa4b5 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 19 Sep 2019 18:05:56 +0100 Subject: [PATCH 299/395] Disable -shrinkdebugfile command --- src/init.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index bbc6f3782ef..083aabb5a3c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -483,7 +483,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-regtest", "Enter regression test mode, which uses a special chain in which blocks can be solved instantly. " "This is intended for regression testing tools and app development."); } - strUsage += HelpMessageOpt("-shrinkdebugfile", _("Shrink debug.log file on client startup (default: 1 when no -debug)")); + // strUsage += HelpMessageOpt("-shrinkdebugfile", _("Shrink debug.log file on client startup (default: 1 when no -debug)")); strUsage += HelpMessageOpt("-testnet", _("Use the test network")); strUsage += HelpMessageGroup(_("Node relay options:")); @@ -1191,8 +1191,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) #ifndef WIN32 CreatePidFile(GetPidFile(), getpid()); #endif - if (GetBoolArg("-shrinkdebugfile", !fDebug)) - ShrinkDebugFile(); + // if (GetBoolArg("-shrinkdebugfile", !fDebug)) + // ShrinkDebugFile(); if (fPrintToDebugLog) OpenDebugLog(); From d917c11572e44b80cec8d61b5f8e9503f7c6b6d8 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 19 Sep 2019 20:57:39 +0100 Subject: [PATCH 300/395] SetMerkleBranch: remove unused code, remove cs_main lock requirement Includes equivalent changes to bitcoin/bitcoin#9446 --- src/wallet/wallet.cpp | 14 +------------- src/wallet/wallet.h | 2 +- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 5163f6a06fe..dbf292b7e10 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4387,9 +4387,8 @@ CWalletKey::CWalletKey(int64_t nExpires) nTimeExpires = nExpires; } -int CMerkleTx::SetMerkleBranch(const CBlock& block) +void CMerkleTx::SetMerkleBranch(const CBlock& block) { - AssertLockHeld(cs_main); CBlock blockTmp; // Update the tx's hashBlock @@ -4404,21 +4403,10 @@ int CMerkleTx::SetMerkleBranch(const CBlock& block) vMerkleBranch.clear(); nIndex = -1; LogPrintf("ERROR: SetMerkleBranch(): couldn't find tx in block\n"); - return 0; } // Fill in merkle branch vMerkleBranch = block.GetMerkleBranch(nIndex); - - // Is the tx in a block that's in the main chain - BlockMap::iterator mi = mapBlockIndex.find(hashBlock); - if (mi == mapBlockIndex.end()) - return 0; - const CBlockIndex* pindex = (*mi).second; - if (!pindex || !chainActive.Contains(pindex)) - return 0; - - return chainActive.Height() - pindex->nHeight + 1; } int CMerkleTx::GetDepthInMainChainINTERNAL(const CBlockIndex* &pindexRet) const diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 2ee1074613c..74a1c3d6a38 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -374,7 +374,7 @@ class CMerkleTx : public CTransaction READWRITE(nIndex); } - int SetMerkleBranch(const CBlock& block); + void SetMerkleBranch(const CBlock& block); /** From 7c8111f30471aa028820a5da441df34844a20ac8 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 19 Sep 2019 20:59:05 +0100 Subject: [PATCH 301/395] Remove cs_main lock requirement from CWallet::SyncTransaction SetMerkleBranch was the only call underneath SyncTransaction that required the cs_main lock. --- src/wallet/wallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index dbf292b7e10..e83a1734e8b 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1703,7 +1703,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl void CWallet::SyncTransaction(const CTransaction& tx, const CBlock* pblock) { - LOCK2(cs_main, cs_wallet); + LOCK(cs_wallet); if (!AddToWalletIfInvolvingMe(tx, pblock, true)) return; // Not one of ours From c1fbf8ab5d73cff5e1f45236995857c75ba4128d Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 19 Sep 2019 18:25:09 +0100 Subject: [PATCH 302/395] Ignore exceptions when deserializing note plaintexts --- src/zcash/Note.cpp | 50 +++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/src/zcash/Note.cpp b/src/zcash/Note.cpp index ee8f7b641e3..23210c784ab 100644 --- a/src/zcash/Note.cpp +++ b/src/zcash/Note.cpp @@ -173,15 +173,21 @@ boost::optional SaplingOutgoingPlaintext::decrypt( } // Deserialize from the plaintext - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << pt.get(); + try { + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << pt.get(); - SaplingOutgoingPlaintext ret; - ss >> ret; + SaplingOutgoingPlaintext ret; + ss >> ret; - assert(ss.size() == 0); + assert(ss.size() == 0); - return ret; + return ret; + } catch (const boost::thread_interrupted&) { + throw; + } catch (...) { + return boost::none; + } } boost::optional SaplingNotePlaintext::decrypt( @@ -197,13 +203,17 @@ boost::optional SaplingNotePlaintext::decrypt( } // Deserialize from the plaintext - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << pt.get(); - SaplingNotePlaintext ret; - ss >> ret; - - assert(ss.size() == 0); + try { + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << pt.get(); + ss >> ret; + assert(ss.size() == 0); + } catch (const boost::thread_interrupted&) { + throw; + } catch (...) { + return boost::none; + } uint256 pk_d; if (!librustzcash_ivk_to_pkd(ivk.begin(), ret.d.data(), pk_d.begin())) { @@ -243,11 +253,17 @@ boost::optional SaplingNotePlaintext::decrypt( } // Deserialize from the plaintext - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << pt.get(); - SaplingNotePlaintext ret; - ss >> ret; + try { + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << pt.get(); + ss >> ret; + assert(ss.size() == 0); + } catch (const boost::thread_interrupted&) { + throw; + } catch (...) { + return boost::none; + } uint256 cmu_expected; if (!librustzcash_sapling_compute_cm( @@ -265,8 +281,6 @@ boost::optional SaplingNotePlaintext::decrypt( return boost::none; } - assert(ss.size() == 0); - return ret; } From f48cfeffe5ea278f045ad7b657f1e76b3ff047f4 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 20 Sep 2019 09:40:45 +0100 Subject: [PATCH 303/395] Update release notes with node abort behaviour --- doc/release-notes.md | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index 49ef03ace1a..412d514df31 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,6 +4,23 @@ release-notes at release time) Notable changes =============== +Fake chain detection during initial block download +-------------------------------------------------- + +One of the mechanisms that `zcashd` uses to detect whether it is in "initial +block download" (IBD) mode is to compare the active chain's cumulative work +against a hard-coded "minimum chain work" value. This mechanism (inherited from +Bitcoin Core) means that once a node exits IBD mode, it is either on the main +chain, or a fake alternate chain with similar amounts of work. In the latter +case, the node has most likely become the victim of a 50% + 1 adversary. + +Starting from this release, `zcashd` additionally hard-codes the block hashes +for the activation blocks of each past network upgrade (NU). During initial +chain synchronization, and after the active chain has reached "minimum chain +work", the node checks the blocks at each NU activation height against the +hard-coded hashes. If any of them do not match, the node will immediately alert +the user and **shut down for safety**. + Disabling old Sprout proofs --------------------------- @@ -19,13 +36,8 @@ This change has several implications: are valid. This has a minor implication for nodes: during initial block download, an adversary could feed the node fake blocks containing invalid old Sprout proofs, and the node would accept the fake chain as valid. However, - `zcashd` internally contains checkpoints after Sapling activation for both - block heights and cumulative chain work, and does not exit the initial block - download phase until the active chain contains at least as much work as the - checkpointed chain work. The node would therefore be non-functional (and would - not broadcast the fake chain to other peers) until the fake chain contained as - much work as the main chain, making this a 50% + 1 attack, which the current - consensus rules already does not protect against. + as soon as the active chain contains at least as much work as the hard-coded + "minimum chain work" value, the node will detect this situation and shut down. - Shielded transactions can no longer be created before Sapling has activated. This does not affect Zcash itself, but will affect downstream codebases that From 3ff68c50528dedcc0122f5922df8bfe4c9959bf6 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 19 Sep 2019 21:30:05 +0100 Subject: [PATCH 304/395] Move mempool SyncWithWallets call into its own thread --- src/init.cpp | 20 ++++++++++++++++++++ src/main.cpp | 2 -- src/txmempool.cpp | 31 +++++++++++++++++++++++++++++++ src/txmempool.h | 3 +++ src/wallet/wallet.cpp | 7 +++++++ 5 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index bbc6f3782ef..e428fdf3fa9 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -663,6 +663,22 @@ void ThreadImport(std::vector vImportFiles) } } +void ThreadNotifyRecentlyAdded() +{ + while (true) { + // Run the notifier on an integer second in the steady clock. + auto now = std::chrono::steady_clock::now().time_since_epoch(); + auto nextFire = std::chrono::duration_cast( + now + std::chrono::seconds(1)); + std::this_thread::sleep_until( + std::chrono::time_point(nextFire)); + + boost::this_thread::interruption_point(); + + mempool.NotifyRecentlyAdded(); + } +} + /** Sanity checks * Ensure that Bitcoin is running in a usable environment with all * necessary library support. @@ -1859,6 +1875,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) LogPrintf("mapAddressBook.size() = %u\n", pwalletMain ? pwalletMain->mapAddressBook.size() : 0); #endif + // Start the thread that notifies listeners of transactions that have been + // recently added to the mempool. + threadGroup.create_thread(boost::bind(&TraceThread, "txnotify", &ThreadNotifyRecentlyAdded)); + if (GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)) StartTorControl(threadGroup, scheduler); diff --git a/src/main.cpp b/src/main.cpp index 382435c2d51..d8dbb3ae73a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1612,8 +1612,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } } - SyncWithWallets(tx, NULL); - return true; } diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 9c03b023d6f..f484cdc9c5e 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -14,6 +14,7 @@ #include "timedata.h" #include "util.h" #include "utilmoneystr.h" +#include "validationinterface.h" #include "version.h" using namespace std; @@ -103,6 +104,7 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, LOCK(cs); mapTx.insert(entry); const CTransaction& tx = mapTx.find(hash)->GetTx(); + mapRecentlyAddedTx[tx.GetHash()] = &tx; for (unsigned int i = 0; i < tx.vin.size(); i++) mapNextTx[tx.vin[i].prevout] = CInPoint(&tx, i); BOOST_FOREACH(const JSDescription &joinsplit, tx.vJoinSplit) { @@ -262,6 +264,7 @@ void CTxMemPool::remove(const CTransaction &origTx, std::list& rem txToRemove.push_back(it->second.ptx->GetHash()); } } + mapRecentlyAddedTx.erase(hash); BOOST_FOREACH(const CTxIn& txin, tx.vin) mapNextTx.erase(txin.prevout); BOOST_FOREACH(const JSDescription& joinsplit, tx.vJoinSplit) { @@ -724,6 +727,34 @@ bool CTxMemPool::nullifierExists(const uint256& nullifier, ShieldedType type) co } } +void CTxMemPool::NotifyRecentlyAdded() +{ + std::vector txs; + { + LOCK(cs); + for (const auto& kv : mapRecentlyAddedTx) { + txs.push_back(*(kv.second)); + } + mapRecentlyAddedTx.clear(); + } + + // A race condition can occur here between these SyncWithWallets calls, and + // the ones triggered by block logic (in ConnectTip and DisconnectTip). It + // is harmless because calling SyncWithWallets(_, NULL) does not alter the + // wallet transaction's block information. + for (auto tx : txs) { + try { + SyncWithWallets(tx, NULL); + } catch (const boost::thread_interrupted&) { + throw; + } catch (const std::exception& e) { + PrintExceptionContinue(&e, "CTxMemPool::NotifyRecentlyAdded()"); + } catch (...) { + PrintExceptionContinue(NULL, "CTxMemPool::NotifyRecentlyAdded()"); + } + } +} + CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView *baseIn, CTxMemPool &mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { } bool CCoinsViewMemPool::GetNullifier(const uint256 &nf, ShieldedType type) const diff --git a/src/txmempool.h b/src/txmempool.h index 6cd87a79c40..caa1c9f1b0f 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -133,6 +133,7 @@ class CTxMemPool uint64_t totalTxSize = 0; //!< sum of all mempool tx' byte sizes uint64_t cachedInnerUsage; //!< sum of dynamic memory usage of all the map elements (NOT the maps themselves) + std::map mapRecentlyAddedTx; std::map mapSproutNullifiers; std::map mapSaplingNullifiers; @@ -217,6 +218,8 @@ class CTxMemPool bool nullifierExists(const uint256& nullifier, ShieldedType type) const; + void NotifyRecentlyAdded(); + unsigned long size() { LOCK(cs); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index e83a1734e8b..f79ce4b1d3a 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1659,6 +1659,13 @@ bool CWallet::UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx) * Add a transaction to the wallet, or update it. * pblock is optional, but should be provided if the transaction is known to be in a block. * If fUpdate is true, existing transactions will be updated. + * + * If pblock is null, this transaction has either recently entered the mempool from the + * network, is re-entering the mempool after a block was disconnected, or is exiting the + * mempool because it conflicts with another transaction. In all these cases, if there is + * an existing wallet transaction, the wallet transaction's Merkle branch data is _not_ + * updated; instead, the transaction being in the mempool or conflicted is determined on + * the fly in CMerkleTx::GetDepthInMainChain(). */ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate) { From 9d8322a3418ca0fbdc31cb684e392af86663927f Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 20 Sep 2019 21:41:49 +0100 Subject: [PATCH 305/395] Enable RPC tests to wait on mempool notifications --- qa/rpc-tests/test_framework/util.py | 10 +++++++++- src/rpc/blockchain.cpp | 4 ++++ src/txmempool.cpp | 16 ++++++++++++++++ src/txmempool.h | 4 ++++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index ef933f5460c..7c804b32ce7 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -57,7 +57,7 @@ def sync_blocks(rpc_connections, wait=1): def sync_mempools(rpc_connections, wait=1): """ Wait until everybody has the same transactions in their memory - pools + pools, and has notified all internal listeners of them """ while True: pool = set(rpc_connections[0].getrawmempool()) @@ -69,6 +69,14 @@ def sync_mempools(rpc_connections, wait=1): break time.sleep(wait) + # Now that the mempools are in sync, wait for the internal + # notifications to finish + while True: + notified = [ x.getmempoolinfo()['fullyNotified'] for x in rpc_connections ] + if notified == [ True ] * len(notified): + break + time.sleep(wait) + bitcoind_processes = {} def initialize_datadir(dirname, n): diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index a140d42a49e..7a581f80791 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1185,6 +1185,10 @@ UniValue mempoolInfoToJSON() ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize())); ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage())); + if (Params().NetworkIDString() == "regtest") { + ret.push_back(Pair("fullyNotified", mempool.IsFullyNotified())); + } + return ret; } diff --git a/src/txmempool.cpp b/src/txmempool.cpp index f484cdc9c5e..325109fe436 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -105,6 +105,7 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, mapTx.insert(entry); const CTransaction& tx = mapTx.find(hash)->GetTx(); mapRecentlyAddedTx[tx.GetHash()] = &tx; + nRecentlyAddedSequence += 1; for (unsigned int i = 0; i < tx.vin.size(); i++) mapNextTx[tx.vin[i].prevout] = CInPoint(&tx, i); BOOST_FOREACH(const JSDescription &joinsplit, tx.vJoinSplit) { @@ -729,9 +730,11 @@ bool CTxMemPool::nullifierExists(const uint256& nullifier, ShieldedType type) co void CTxMemPool::NotifyRecentlyAdded() { + uint64_t recentlyAddedSequence; std::vector txs; { LOCK(cs); + recentlyAddedSequence = nRecentlyAddedSequence; for (const auto& kv : mapRecentlyAddedTx) { txs.push_back(*(kv.second)); } @@ -753,6 +756,19 @@ void CTxMemPool::NotifyRecentlyAdded() PrintExceptionContinue(NULL, "CTxMemPool::NotifyRecentlyAdded()"); } } + + // Update the notified sequence number. We only need this in regtest mode, + // and should not lock on cs after calling SyncWithWallets otherwise. + if (Params().NetworkIDString() == "regtest") { + LOCK(cs); + nNotifiedSequence = recentlyAddedSequence; + } +} + +bool CTxMemPool::IsFullyNotified() { + assert(Params().NetworkIDString() == "regtest"); + LOCK(cs); + return nRecentlyAddedSequence == nNotifiedSequence; } CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView *baseIn, CTxMemPool &mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { } diff --git a/src/txmempool.h b/src/txmempool.h index caa1c9f1b0f..23f864adc8b 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -134,6 +134,9 @@ class CTxMemPool uint64_t cachedInnerUsage; //!< sum of dynamic memory usage of all the map elements (NOT the maps themselves) std::map mapRecentlyAddedTx; + uint64_t nRecentlyAddedSequence = 0; + uint64_t nNotifiedSequence = 0; + std::map mapSproutNullifiers; std::map mapSaplingNullifiers; @@ -219,6 +222,7 @@ class CTxMemPool bool nullifierExists(const uint256& nullifier, ShieldedType type) const; void NotifyRecentlyAdded(); + bool IsFullyNotified(); unsigned long size() { From 2f5d665f53f0611e2cf1846222209bb0d771d7d2 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Mon, 23 Sep 2019 22:18:40 +0100 Subject: [PATCH 306/395] Add hotfix release notes. Signed-off-by: Daira Hopwood --- doc/release-notes.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index a29094b5174..ae28b011aa5 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,3 +4,13 @@ release-notes at release time) Notable changes =============== +This release fixes a security issue described at +https://z.cash/support/security/announcements/security-announcement-2019-09-24/ . + + +Shrinking of debug.log files is temporarily disabled +---------------------------------------------------- + +In previous versions, `zcashd` would shrink the `debug.log` file to 200 KB on +startup if it was larger than 10 MB. This behaviour, and the `-shrinkdebugfile` +option that controlled it, has been disabled. From 1ef3f7b1d6350c4a79f76f33e20cfe3e123518e0 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Tue, 24 Sep 2019 20:55:14 +0100 Subject: [PATCH 307/395] Make a note of the shorter service period in the release notes. Signed-off-by: Daira Hopwood --- doc/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index ae28b011aa5..51ed19349ae 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -7,6 +7,10 @@ Notable changes This release fixes a security issue described at https://z.cash/support/security/announcements/security-announcement-2019-09-24/ . +The service period of this release is shorter than normal due to the upcoming +v2.1.0 Blossom release. The End-of-Service of v2.0.7-3 will occur at block height +653012, expected to be on 2019-12-10. + Shrinking of debug.log files is temporarily disabled ---------------------------------------------------- From 1e11ffb6bb9fd55d8fb480dff4b41aca63b94ab8 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Tue, 24 Sep 2019 20:58:26 +0100 Subject: [PATCH 308/395] make-release.py: Versioning changes for 2.0.7-3. --- README.md | 2 +- configure.ac | 2 +- contrib/gitian-descriptors/gitian-linux.yml | 2 +- src/clientversion.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4ab6f3513c6..6117b077280 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Zcash 2.0.7-2 +Zcash 2.0.7-3 =========== diff --git a/configure.ac b/configure.ac index 5c0ee02060f..42bb0a3f59e 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 2) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_REVISION, 7) -define(_CLIENT_VERSION_BUILD, 52) +define(_CLIENT_VERSION_BUILD, 53) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 57de597b67c..cb3990fc235 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "zcash-2.0.7-2" +name: "zcash-2.0.7-3" enable_cache: true distro: "debian" suites: diff --git a/src/clientversion.h b/src/clientversion.h index 0d5c394de32..82ac6faf21a 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -18,7 +18,7 @@ #define CLIENT_VERSION_MAJOR 2 #define CLIENT_VERSION_MINOR 0 #define CLIENT_VERSION_REVISION 7 -#define CLIENT_VERSION_BUILD 52 +#define CLIENT_VERSION_BUILD 53 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true From ef508aeb5bb6f5cd6b0c6561e8940e6d7d7c0645 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Tue, 24 Sep 2019 21:01:13 +0100 Subject: [PATCH 309/395] make-release.py: Updated manpages for 2.0.7-3. --- doc/man/zcash-cli.1 | 8 ++++---- doc/man/zcash-tx.1 | 8 ++++---- doc/man/zcashd.1 | 14 +++++--------- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/doc/man/zcash-cli.1 b/doc/man/zcash-cli.1 index 3f187e49cee..7238b8e173e 100644 --- a/doc/man/zcash-cli.1 +++ b/doc/man/zcash-cli.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-CLI "1" "August 2019" "zcash-cli v2.0.7-2" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.8. +.TH ZCASH-CLI "1" "September 2019" "zcash-cli v2.0.7-3" "User Commands" .SH NAME -zcash-cli \- manual page for zcash-cli v2.0.7-2 +zcash-cli \- manual page for zcash-cli v2.0.7-3 .SH DESCRIPTION -Zcash RPC client version v2.0.7\-2 +Zcash RPC client version v2.0.7\-3 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . diff --git a/doc/man/zcash-tx.1 b/doc/man/zcash-tx.1 index 89ac04d28f6..64a1aa22b68 100644 --- a/doc/man/zcash-tx.1 +++ b/doc/man/zcash-tx.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-TX "1" "August 2019" "zcash-tx v2.0.7-2" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.8. +.TH ZCASH-TX "1" "September 2019" "zcash-tx v2.0.7-3" "User Commands" .SH NAME -zcash-tx \- manual page for zcash-tx v2.0.7-2 +zcash-tx \- manual page for zcash-tx v2.0.7-3 .SH DESCRIPTION -Zcash zcash\-tx utility version v2.0.7\-2 +Zcash zcash\-tx utility version v2.0.7\-3 .SS "Usage:" .TP zcash\-tx [options] [commands] diff --git a/doc/man/zcashd.1 b/doc/man/zcashd.1 index 0c3aaf84eeb..414413f164a 100644 --- a/doc/man/zcashd.1 +++ b/doc/man/zcashd.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASHD "1" "August 2019" "zcashd v2.0.7-2" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.8. +.TH ZCASHD "1" "September 2019" "zcashd v2.0.7-3" "User Commands" .SH NAME -zcashd \- manual page for zcashd v2.0.7-2 +zcashd \- manual page for zcashd v2.0.7-3 .SH DESCRIPTION -Zcash Daemon version v2.0.7\-2 +Zcash Daemon version v2.0.7\-3 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . @@ -75,7 +75,7 @@ limit applied) .HP \fB\-par=\fR .IP -Set the number of script verification threads (\fB\-4\fR to 16, 0 = auto, <0 = +Set the number of script verification threads (\fB\-6\fR to 16, 0 = auto, <0 = leave that many cores free, default: 0) .HP \fB\-pid=\fR @@ -361,10 +361,6 @@ Fees (in ZEC/kB) smaller than this are considered zero fee for relaying .IP Send trace/debug info to console instead of debug.log file .HP -\fB\-shrinkdebugfile\fR -.IP -Shrink debug.log file on client startup (default: 1 when no \fB\-debug\fR) -.HP \fB\-testnet\fR .IP Use the test network From 5beb316b6b8f3be75c2724662471fbbc7ae41441 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Tue, 24 Sep 2019 21:01:13 +0100 Subject: [PATCH 310/395] make-release.py: Updated release notes and changelog for 2.0.7-3. --- contrib/debian/changelog | 6 ++++ doc/authors.md | 4 +-- doc/release-notes.md | 14 --------- doc/release-notes/release-notes-2.0.7-3.md | 35 ++++++++++++++++++++++ 4 files changed, 43 insertions(+), 16 deletions(-) create mode 100644 doc/release-notes/release-notes-2.0.7-3.md diff --git a/contrib/debian/changelog b/contrib/debian/changelog index ba3a2a2942c..40a3de65792 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,9 @@ +zcash (2.0.7+3) stable; urgency=medium + + * 2.0.7-3 release. + + -- Electric Coin Company Tue, 24 Sep 2019 21:01:13 +0100 + zcash (2.0.7+2) stable; urgency=medium * 2.0.7-2 release. diff --git a/doc/authors.md b/doc/authors.md index 1583fd014b1..c21e5ddd351 100644 --- a/doc/authors.md +++ b/doc/authors.md @@ -1,11 +1,11 @@ Zcash Contributors ================== -Jack Grigg (874) +Jack Grigg (880) Simon Liu (459) Sean Bowe (278) Eirik Ogilvie-Wigley (169) -Daira Hopwood (136) +Daira Hopwood (140) Jay Graber (89) Wladimir J. van der Laan (82) Taylor Hornby (73) diff --git a/doc/release-notes.md b/doc/release-notes.md index 51ed19349ae..a29094b5174 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,17 +4,3 @@ release-notes at release time) Notable changes =============== -This release fixes a security issue described at -https://z.cash/support/security/announcements/security-announcement-2019-09-24/ . - -The service period of this release is shorter than normal due to the upcoming -v2.1.0 Blossom release. The End-of-Service of v2.0.7-3 will occur at block height -653012, expected to be on 2019-12-10. - - -Shrinking of debug.log files is temporarily disabled ----------------------------------------------------- - -In previous versions, `zcashd` would shrink the `debug.log` file to 200 KB on -startup if it was larger than 10 MB. This behaviour, and the `-shrinkdebugfile` -option that controlled it, has been disabled. diff --git a/doc/release-notes/release-notes-2.0.7-3.md b/doc/release-notes/release-notes-2.0.7-3.md new file mode 100644 index 00000000000..baf7cac150e --- /dev/null +++ b/doc/release-notes/release-notes-2.0.7-3.md @@ -0,0 +1,35 @@ +Notable changes +=============== + +This release fixes a security issue described at +https://z.cash/support/security/announcements/security-announcement-2019-09-24/ . + +The service period of this release is shorter than normal due to the upcoming +v2.1.0 Blossom release. The End-of-Service of v2.0.7-3 will occur at block height +653012, expected to be on 2019-12-10. + + +Shrinking of debug.log files is temporarily disabled +---------------------------------------------------- + +In previous versions, `zcashd` would shrink the `debug.log` file to 200 KB on +startup if it was larger than 10 MB. This behaviour, and the `-shrinkdebugfile` +option that controlled it, has been disabled. + +Changelog +========= + +Daira Hopwood (4): + Add hotfix release notes. + Make a note of the shorter service period in the release notes. + make-release.py: Versioning changes for 2.0.7-3. + make-release.py: Updated manpages for 2.0.7-3. + +Jack Grigg (6): + Disable -shrinkdebugfile command + SetMerkleBranch: remove unused code, remove cs_main lock requirement + Remove cs_main lock requirement from CWallet::SyncTransaction + Ignore exceptions when deserializing note plaintexts + Move mempool SyncWithWallets call into its own thread + Enable RPC tests to wait on mempool notifications + From dffdbcf31d0bd5a4d8c3f53bfc62ab92e7d01742 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Tue, 24 Sep 2019 21:04:45 +0100 Subject: [PATCH 311/395] Set Debian changelog urgency to critical. Signed-off-by: Daira Hopwood --- contrib/debian/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/debian/changelog b/contrib/debian/changelog index 40a3de65792..431b80e75d9 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,4 +1,4 @@ -zcash (2.0.7+3) stable; urgency=medium +zcash (2.0.7+3) stable; urgency=critical * 2.0.7-3 release. From 7167dc9b2ce40a1d5b5bf2a0042c0b331a9fb164 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Mon, 16 Sep 2019 13:04:27 +0100 Subject: [PATCH 312/395] Test setting an expiry height of 0. Signed-off-by: Daira Hopwood --- qa/rpc-tests/signrawtransactions.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qa/rpc-tests/signrawtransactions.py b/qa/rpc-tests/signrawtransactions.py index e6eff05edbf..622b18bf5ca 100755 --- a/qa/rpc-tests/signrawtransactions.py +++ b/qa/rpc-tests/signrawtransactions.py @@ -38,7 +38,8 @@ def successful_signing_test(self): outputs = {'tmJXomn8fhYy3AFqDEteifjHRMUdKtBuTGM': 0.1} - rawTx = self.nodes[0].createrawtransaction(inputs, outputs) + # Also test setting an expiry height of 0. + rawTx = self.nodes[0].createrawtransaction(inputs, outputs, 0, 0) rawTxSigned = self.nodes[0].signrawtransaction(rawTx, inputs, privKeys) # 1) The transaction has a complete set of signatures From 3e37152bf5492664708ebfc32c14cb7dab04c928 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Mon, 16 Sep 2019 13:47:30 +0100 Subject: [PATCH 313/395] Fix setting an expiry height of 0. fixes #4132 Signed-off-by: Daira Hopwood --- src/rpc/rawtransaction.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 7d20f101749..4b6140f4cf4 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -543,7 +543,7 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, expiryheight must be nonnegative and less than %d.", TX_EXPIRY_HEIGHT_THRESHOLD)); } // DoS mitigation: reject transactions expiring soon - if (nextBlockHeight + TX_EXPIRING_SOON_THRESHOLD > nExpiryHeight) { + if (nExpiryHeight != 0 && nextBlockHeight + TX_EXPIRING_SOON_THRESHOLD > nExpiryHeight) { throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, expiryheight should be at least %d to avoid transaction expiring soon", nextBlockHeight + TX_EXPIRING_SOON_THRESHOLD)); From 3b9237b88384ca3f9c1360bf606e10d9dde64e08 Mon Sep 17 00:00:00 2001 From: zebambam Date: Mon, 7 Oct 2019 13:17:00 -0700 Subject: [PATCH 314/395] Removed stale seeder, fixing #4153 --- src/chainparams.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index cf47610f602..c5ee248f0ec 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -143,7 +143,6 @@ class CMainParams : public CChainParams { vSeeds.clear(); vSeeds.push_back(CDNSSeedData("z.cash", "dnsseed.z.cash")); // Zcash vSeeds.push_back(CDNSSeedData("str4d.xyz", "dnsseed.str4d.xyz")); // @str4d - vSeeds.push_back(CDNSSeedData("znodes.org", "dnsseed.znodes.org")); // @bitcartel // guarantees the first 2 characters, when base58 encoded, are "t1" base58Prefixes[PUBKEY_ADDRESS] = {0x1C,0xB8}; From ae9ecf09e8a6827476b3efd0a1a4e0f830527aaf Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Thu, 26 Sep 2019 09:22:25 -0600 Subject: [PATCH 315/395] DoS protection: Weighted random drop of txs if mempool full --- qa/pull-tester/rpc-tests.sh | 1 + qa/rpc-tests/mempool_limit.py | 90 ++++++++++++++++++++ src/Makefile.am | 2 + src/Makefile.gtest.include | 1 + src/gtest/test_mempoollimit.cpp | 140 ++++++++++++++++++++++++++++++++ src/init.cpp | 8 +- src/main.cpp | 37 +++++++-- src/mempoollimit.cpp | 116 ++++++++++++++++++++++++++ src/mempoollimit.h | 76 +++++++++++++++++ src/txmempool.cpp | 33 ++++++++ src/txmempool.h | 9 ++ 11 files changed, 503 insertions(+), 10 deletions(-) create mode 100755 qa/rpc-tests/mempool_limit.py create mode 100644 src/gtest/test_mempoollimit.cpp create mode 100644 src/mempoollimit.cpp create mode 100644 src/mempoollimit.h diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index ca26c82a8b4..b521b4b6d61 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -41,6 +41,7 @@ testScripts=( 'rawtransactions.py' 'getrawtransaction_insight.py' 'rest.py' + 'mempool_limit.py' 'mempool_spendcoinbase.py' 'mempool_reorg.py' 'mempool_nu_activation.py' diff --git a/qa/rpc-tests/mempool_limit.py b/qa/rpc-tests/mempool_limit.py new file mode 100755 index 00000000000..b58cf9f367a --- /dev/null +++ b/qa/rpc-tests/mempool_limit.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python +# Copyright (c) 2019 The Zcash developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . + +import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + assert_equal, + initialize_chain_clean, + start_nodes, +) + +from decimal import Decimal +from time import sleep + +# Test wallet behaviour with Sapling addresses +class MempoolLimit(BitcoinTestFramework): + def setup_chain(self): + print("Initializing test directory " + self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 4) + + def setup_nodes(self): + args = [ + '-nuparams=5ba81b19:1', # Overwinter + '-nuparams=76b809bb:1', # Sapling + "-debug=mempool", + ] + extra_args = [ + args + ['-mempooltotalcostlimit=8000'], # 2 transactions at min cost + args + ['-mempooltotalcostlimit=8000'], # 2 transactions at min cost + args + ['-mempooltotalcostlimit=8000'], # 2 transactions at min cost + # Let node 3 hold one more transaction + args + ['-mempooltotalcostlimit=12000'], # 3 transactions at min cost + ] + return start_nodes(4, self.options.tmpdir, extra_args) + + def run_test(self): + print("Mining blocks...") + self.sync_all() + self.nodes[1].generate(1) + self.sync_all() + self.nodes[2].generate(1) + self.sync_all() + self.nodes[3].generate(1) + self.sync_all() + self.nodes[0].generate(100) + self.sync_all() + assert_equal(Decimal("10.00"), Decimal(self.nodes[1].z_gettotalbalance()['transparent'])) + assert_equal(Decimal("10.00"), Decimal(self.nodes[2].z_gettotalbalance()['transparent'])) + assert_equal(Decimal("10.00"), Decimal(self.nodes[3].z_gettotalbalance()['transparent'])) + + taddr1 = self.nodes[0].getnewaddress() + taddr2 = self.nodes[0].getnewaddress() + taddr3 = self.nodes[0].getnewaddress() + + print("Filling mempool...") + self.nodes[1].sendtoaddress(taddr1, 9.999) + self.nodes[2].sendtoaddress(taddr2, 9.999) + self.sync_all() + + for i in range(0, 4): + mempool = self.nodes[i].getrawmempool() + print("Mempool for node {}: {}".format(i, mempool)) + assert_equal(2, len(mempool), "node {}".format(i)) + + print("Adding one more transaction...") + self.nodes[3].sendtoaddress(taddr3, 9.999) + # The mempools are no longer guarenteed to be in a consistent state, so we cannot sync + sleep(5) + mempool_node3 = self.nodes[i].getrawmempool() + print("Mempool for node 3: {}".format(mempool_node3)) + assert_equal(3, len(mempool_node3), "node {}".format(i)) + + print("Checking mempool size...") + # Due to the size limit, there should only be 2 transactions in the mempool + for i in range(0, 3): + mempool = self.nodes[i].getrawmempool() + print("Mempool for node {}: {}".format(i, mempool)) + assert_equal(2, len(mempool), "node {}".format(i)) + + # self.nodes[0].generate(1) + # self.sync_all() + + print("Success") + + +if __name__ == '__main__': + MempoolLimit().main() diff --git a/src/Makefile.am b/src/Makefile.am index f3f8de7061f..82beb74c149 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -192,6 +192,7 @@ BITCOIN_CORE_H = \ torcontrol.h \ transaction_builder.h \ txdb.h \ + mempoollimit.h \ txmempool.h \ ui_interface.h \ uint256.h \ @@ -266,6 +267,7 @@ libbitcoin_server_a_SOURCES = \ timedata.cpp \ torcontrol.cpp \ txdb.cpp \ + mempoollimit.cpp \ txmempool.cpp \ validationinterface.cpp \ $(BITCOIN_CORE_H) \ diff --git a/src/Makefile.gtest.include b/src/Makefile.gtest.include index 474dd31e508..769e7885bbd 100644 --- a/src/Makefile.gtest.include +++ b/src/Makefile.gtest.include @@ -27,6 +27,7 @@ zcash_gtest_SOURCES += \ gtest/test_keystore.cpp \ gtest/test_noteencryption.cpp \ gtest/test_mempool.cpp \ + gtest/test_mempoollimit.cpp \ gtest/test_merkletree.cpp \ gtest/test_metrics.cpp \ gtest/test_miner.cpp \ diff --git a/src/gtest/test_mempoollimit.cpp b/src/gtest/test_mempoollimit.cpp new file mode 100644 index 00000000000..84d0902a055 --- /dev/null +++ b/src/gtest/test_mempoollimit.cpp @@ -0,0 +1,140 @@ +// Copyright (c) 2019 The Zcash developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php + +#include +#include + +#include "arith_uint256.h" +#include "mempoollimit.h" +#include "utiltime.h" +#include "utiltest.h" +#include "transaction_builder.h" + + +const uint256 TX_ID1 = ArithToUint256(1); +const uint256 TX_ID2 = ArithToUint256(2); +const uint256 TX_ID3 = ArithToUint256(3); + +TEST(MempoolLimitTests, RecentlyEvictedList_AddWrapsAfterMaxSize) +{ + RecentlyEvictedList recentlyEvicted(2, 100); + SetMockTime(1); + recentlyEvicted.add(TX_ID1); + recentlyEvicted.add(TX_ID2); + recentlyEvicted.add(TX_ID3); + // tx 1 should be overwritten by tx 3 due maxSize 2 + EXPECT_FALSE(recentlyEvicted.contains(TX_ID1)); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID2)); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID3)); +} + +TEST(MempoolLimitTests, RecentlyEvictedList_DoesNotContainAfterExpiry) +{ + SetMockTime(1); + // maxSize=3, timeToKeep=1 + RecentlyEvictedList recentlyEvicted(3, 1); + recentlyEvicted.add(TX_ID1); + SetMockTime(2); + recentlyEvicted.add(TX_ID2); + recentlyEvicted.add(TX_ID3); + // After 1 second the txId will still be there + EXPECT_TRUE(recentlyEvicted.contains(TX_ID1)); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID2)); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID3)); + SetMockTime(3); + // After 2 second it is gone + EXPECT_FALSE(recentlyEvicted.contains(TX_ID1)); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID2)); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID3)); + SetMockTime(4); + EXPECT_FALSE(recentlyEvicted.contains(TX_ID2)); + EXPECT_FALSE(recentlyEvicted.contains(TX_ID3)); +} + +TEST(MempoolLimitTests, WeightedTransactionList_CheckSizeAfterDropping) +{ + std::set testedDropping; + // Run the test until we have tested dropping each of the elements + int trialNum = 0; + while (testedDropping.size() < 3) { + WeightedTransactionList list(MIN_TX_COST * 2); + EXPECT_EQ(0, list.getTotalCost()); + EXPECT_EQ(0, list.getTotalLowFeePenaltyCost()); + list.add(WeightedTxInfo(TX_ID1, MIN_TX_COST, MIN_TX_COST)); + EXPECT_EQ(4000, list.getTotalCost()); + EXPECT_EQ(4000, list.getTotalLowFeePenaltyCost()); + list.add(WeightedTxInfo(TX_ID2, MIN_TX_COST, MIN_TX_COST)); + EXPECT_EQ(8000, list.getTotalCost()); + EXPECT_EQ(8000, list.getTotalLowFeePenaltyCost()); + EXPECT_FALSE(list.maybeDropRandom().is_initialized()); + list.add(WeightedTxInfo(TX_ID3, MIN_TX_COST, MIN_TX_COST + LOW_FEE_PENALTY)); + EXPECT_EQ(12000, list.getTotalCost()); + EXPECT_EQ(12000 + LOW_FEE_PENALTY, list.getTotalLowFeePenaltyCost()); + boost::optional drop = list.maybeDropRandom(); + ASSERT_TRUE(drop.is_initialized()); + uint256 txid = drop.get().txId; + std::cerr << "Trial " << trialNum++ << ": dropped " << txid.ToString() << std::endl; + testedDropping.insert(txid); + // Do not continue to test if a particular trial fails + ASSERT_EQ(8000, list.getTotalCost()); + ASSERT_EQ(txid == TX_ID3 ? 8000 : 8000 + LOW_FEE_PENALTY, list.getTotalLowFeePenaltyCost()); + } + std::cerr << "All 3 scenarios tested in " << trialNum << " trials" << std::endl; +} + +TEST(MempoolLimitTests, WeightedTXInfo_FromTx) +{ + // The transaction creation is based on the test: + // test_transaction_builder.cpp/TEST(TransactionBuilder, SetFee) + auto consensusParams = RegtestActivateSapling(); + + auto sk = libzcash::SaplingSpendingKey::random(); + auto expsk = sk.expanded_spending_key(); + auto fvk = sk.full_viewing_key(); + auto pa = sk.default_address(); + + auto testNote = GetTestSaplingNote(pa, 50000); + + // Default fee + { + auto builder = TransactionBuilder(consensusParams, 1); + builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); + builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); + + WeightedTxInfo info = WeightedTxInfo::from(builder.Build().GetTxOrThrow()); + EXPECT_EQ(MIN_TX_COST, info.cost); + EXPECT_EQ(MIN_TX_COST, info.lowFeePenaltyCost); + } + + // Lower than standard fee + { + auto builder = TransactionBuilder(consensusParams, 1); + builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); + builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); + builder.SetFee(1); + + WeightedTxInfo info = WeightedTxInfo::from(builder.Build().GetTxOrThrow()); + EXPECT_EQ(MIN_TX_COST, info.cost); + EXPECT_EQ(MIN_TX_COST + LOW_FEE_PENALTY, info.lowFeePenaltyCost); + } + + // Larger Tx + { + auto testNote2 = GetTestSaplingNote(pa, 50000); + auto testNote3 = GetTestSaplingNote(pa, 50000); + auto testNote4 = GetTestSaplingNote(pa, 50000); + auto builder = TransactionBuilder(consensusParams, 1); + builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); + builder.AddSaplingSpend(expsk, testNote2.note, testNote2.tree.root(), testNote2.tree.witness()); + builder.AddSaplingSpend(expsk, testNote3.note, testNote3.tree.root(), testNote3.tree.witness()); + builder.AddSaplingSpend(expsk, testNote4.note, testNote4.tree.root(), testNote4.tree.witness()); + builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); + + WeightedTxInfo info = WeightedTxInfo::from(builder.Build().GetTxOrThrow()); + EXPECT_EQ(MIN_TX_COST, info.cost); + EXPECT_EQ(MIN_TX_COST, info.lowFeePenaltyCost); + } + + RegtestDeactivateSapling(); +} diff --git a/src/init.cpp b/src/init.cpp index aeb8c5a6c1d..054199bc26c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -399,6 +399,8 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-whitebind=", _("Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6")); strUsage += HelpMessageOpt("-whitelist=", _("Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times.") + " " + _("Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway")); + strUsage += HelpMessageOpt("-mempooltotalcostlimit=", _("An upper bound on the maximum size in bytes of all txs in the mempool. (default: 80000000)")); + strUsage += HelpMessageOpt("-mempoolevictionmemoryminutes=", _("The number of minutes before reallowing rejected transactions from reentering the mempool. (default: 60)")); #ifdef ENABLE_WALLET strUsage += HelpMessageGroup(_("Wallet options:")); @@ -974,6 +976,11 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (ratio != 0) { mempool.setSanityCheck(1.0 / ratio); } + + int64_t mempoolTotalCostLimit = GetArg("-mempooltotalcostlimit", 80000000); + int64_t mempoolEvictionMemorySeconds = GetArg("-mempoolevictionmemoryminutes", 60) * 1000; + mempool.setMempoolCostLimit(mempoolTotalCostLimit, mempoolEvictionMemorySeconds); + fCheckBlockIndex = GetBoolArg("-checkblockindex", chainparams.DefaultConsistencyChecks()); fCheckpointsEnabled = GetBoolArg("-checkpoints", true); @@ -1595,7 +1602,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) mempool.ReadFeeEstimates(est_filein); fFeeEstimatesInitialized = true; - // ********************************************************* Step 8: load wallet #ifdef ENABLE_WALLET if (fDisableWallet) { diff --git a/src/main.cpp b/src/main.cpp index b5372e52c1c..b7bcd598072 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1395,6 +1395,10 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } } + if (pool.isRecentlyEvicted(tx.GetHash())) { + return error("AcceptToMemoryPool: Transaction recently evicted"); + } + auto verifier = libzcash::ProofVerifier::Strict(); if (!CheckTransaction(tx, state, verifier)) return error("AcceptToMemoryPool: CheckTransaction failed"); @@ -1616,17 +1620,32 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa return error("AcceptToMemoryPool: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s", hash.ToString()); } - // Store transaction in memory - pool.addUnchecked(hash, entry, !IsInitialBlockDownload(Params())); + { + // We lock to prevent other threads from accessing the mempool between adding and evicting + LOCK(pool.cs); + + // Store transaction in memory + pool.addUnchecked(hash, entry, !IsInitialBlockDownload(Params())); + + // Add memory address index + if (fAddressIndex) { + pool.addAddressIndex(entry, view); + } - // Add memory address index - if (fAddressIndex) { - pool.addAddressIndex(entry, view); - } + // insightexplorer: Add memory spent index + if (fSpentIndex) { + pool.addSpentIndex(entry, view); + } + + // In normal circumstances the following should be empty + list removed; + std::vector evictedTxIds = pool.ensureSizeLimit(); + for (const uint256& txId : evictedTxIds) { + CTransaction toRemove = pool.mapTx.find(txId)->GetTx(); + pool.remove(toRemove, removed, true); + } - // insightexplorer: Add memory spent index - if (fSpentIndex) { - pool.addSpentIndex(entry, view); + // TODO rebuild list here and when a block is made } } diff --git a/src/mempoollimit.cpp b/src/mempoollimit.cpp new file mode 100644 index 00000000000..0bc16720ac1 --- /dev/null +++ b/src/mempoollimit.cpp @@ -0,0 +1,116 @@ +// Copyright (c) 2019 The Zcash developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php + +#include "core_memusage.h" +#include "mempoollimit.h" +#include "random.h" +#include "timedata.h" + +const int64_t DEFAULT_FEE = 10000; + +void RecentlyEvictedList::pruneList() +{ + if (txIdSet.empty()) { + return; + } + int64_t now = GetAdjustedTime(); + size_t startIndex = (txIdsAndTimesIndex + maxSize - txIdSet.size()) % maxSize; + boost::optional> txIdAndTime; + while ((txIdAndTime = txIdsAndTimes[startIndex]).is_initialized() && (now - txIdAndTime.get().second) > timeToKeep) { + txIdsAndTimes[startIndex] = boost::none; + txIdSet.erase(txIdAndTime.get().first); + startIndex = (startIndex + 1) % maxSize; + } +} +void RecentlyEvictedList::add(uint256 txId) +{ + pruneList(); + if (txIdsAndTimes[txIdsAndTimesIndex].is_initialized()) { + auto txIdAndTime = txIdsAndTimes[txIdsAndTimesIndex]; + txIdSet.erase(txIdAndTime.get().first); + } + txIdsAndTimes[txIdsAndTimesIndex] = std::make_pair(txId, GetAdjustedTime()); + txIdSet.insert(txId); + txIdsAndTimesIndex = (txIdsAndTimesIndex + 1) % maxSize; +} + +bool RecentlyEvictedList::contains(const uint256& txId) +{ + pruneList(); + return txIdSet.count(txId) > 0; +} + + +int64_t WeightedTransactionList::getTotalCost() +{ + return weightedTxInfos.empty() ? 0 : weightedTxInfos.back().cost; +} + +int64_t WeightedTransactionList::getTotalLowFeePenaltyCost() +{ + return weightedTxInfos.empty() ? 0 : weightedTxInfos.back().lowFeePenaltyCost; +} + +void WeightedTransactionList::add(WeightedTxInfo weightedTxInfo) +{ + if (weightedTxInfos.empty()) { + weightedTxInfos.push_back(weightedTxInfo); + return; + } + weightedTxInfo.plusEquals(weightedTxInfos.back()); + weightedTxInfos.push_back(weightedTxInfo); + for (int i =0; i < weightedTxInfos.size(); ++i) { + WeightedTxInfo info = weightedTxInfos[i]; + } +} + +boost::optional WeightedTransactionList::maybeDropRandom() +{ + int64_t totalCost = getTotalCost(); + if (totalCost <= maxTotalCost) { + return boost::none; + } + LogPrint("mempool", "Mempool cost limit exceeded (cost=%d, limit=%d)\n", totalCost, maxTotalCost); + int randomWeight = GetRand(getTotalLowFeePenaltyCost()); + int i = 0; + while (randomWeight > weightedTxInfos[i].lowFeePenaltyCost) { + ++i; + } + WeightedTxInfo drop = weightedTxInfos[i]; + if (i > 0) { + drop.minusEquals(weightedTxInfos[i - 1]); + } + while (++i < weightedTxInfos.size()) { + WeightedTxInfo nextTx = weightedTxInfos[i]; + nextTx.minusEquals(drop); + weightedTxInfos[i - 1] = nextTx; + } + weightedTxInfos.pop_back(); + LogPrint("mempool", "Evicting transaction (txid=%s, cost=%d, penaltyCost=%d)\n", drop.txId.ToString(), drop.cost, drop.lowFeePenaltyCost); + return drop; +} + +WeightedTxInfo WeightedTxInfo::from(const CTransaction& tx) +{ + size_t memUsage = RecursiveDynamicUsage(tx); + int64_t cost = std::max(memUsage, MIN_TX_COST); + int64_t lowFeePenaltyCost = cost; + int64_t fee = DEFAULT_FEE; + if (fee < DEFAULT_FEE) { + lowFeePenaltyCost += LOW_FEE_PENALTY; + } + return WeightedTxInfo(tx.GetHash(), cost, lowFeePenaltyCost); +} + +void WeightedTxInfo::plusEquals(const WeightedTxInfo& other) +{ + cost += other.cost; + lowFeePenaltyCost += other.lowFeePenaltyCost; +} + +void WeightedTxInfo::minusEquals(const WeightedTxInfo& other) +{ + cost -= other.cost; + lowFeePenaltyCost -= other.lowFeePenaltyCost; +} diff --git a/src/mempoollimit.h b/src/mempoollimit.h new file mode 100644 index 00000000000..96d528f7cf5 --- /dev/null +++ b/src/mempoollimit.h @@ -0,0 +1,76 @@ +// Copyright (c) 2019 The Zcash developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +#ifndef MEMPOOLLIMIT_H +#define MEMPOOLLIMIT_H + +#include +#include +#include "uint256.h" +#include "primitives/transaction.h" + +#include "boost/optional.hpp" + +const size_t RECENTLY_EVICTED_SIZE = 10000; +const uint64_t MIN_TX_COST = 4000; +const uint64_t LOW_FEE_PENALTY = 16000; + +struct WeightedTxInfo; + +class RecentlyEvictedList +{ + const size_t maxSize; + const int64_t timeToKeep; + // Pairs of txid and time (seconds since epoch) + boost::optional> txIdsAndTimes[RECENTLY_EVICTED_SIZE]; + size_t txIdsAndTimesIndex; + std::set txIdSet; + + void pruneList(); +public: + RecentlyEvictedList(size_t maxSize_, int64_t timeToKeep_) : + maxSize(maxSize_), + timeToKeep(timeToKeep_), + txIdsAndTimesIndex(0) + { + assert(maxSize <= RECENTLY_EVICTED_SIZE); + std::fill_n(txIdsAndTimes, maxSize, boost::none); + } + RecentlyEvictedList(int64_t timeToKeep_) : RecentlyEvictedList(RECENTLY_EVICTED_SIZE, timeToKeep_) {} + + void add(uint256 txId); + bool contains(const uint256& txId); +}; + + +class WeightedTransactionList +{ + const uint64_t maxTotalCost; + std::vector weightedTxInfos; +public: + WeightedTransactionList(int64_t maxTotalCost_) : maxTotalCost(maxTotalCost_) {} + + int64_t getTotalCost(); + int64_t getTotalLowFeePenaltyCost(); + + void add(WeightedTxInfo weightedTxInfo); + boost::optional maybeDropRandom(); +}; + + +struct WeightedTxInfo { + uint256 txId; + uint64_t cost; + uint64_t lowFeePenaltyCost; + + WeightedTxInfo(uint256 txId_, uint64_t cost_, uint64_t lowFeePenaltyCost_) + : txId(txId_), cost(cost_), lowFeePenaltyCost(lowFeePenaltyCost_) {} + + static WeightedTxInfo from(const CTransaction& tx); + + void plusEquals(const WeightedTxInfo& other); + void minusEquals(const WeightedTxInfo& other); +}; + +#endif // MEMPOOLLIMIT_H diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 325109fe436..ae4ebb707f5 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -102,6 +102,9 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, // Used by main.cpp AcceptToMemoryPool(), which DOES do // all the appropriate checks. LOCK(cs); + if (weightedTxList) { + weightedTxList->add(WeightedTxInfo::from(entry.GetTx())); + } mapTx.insert(entry); const CTransaction& tx = mapTx.find(hash)->GetTx(); mapRecentlyAddedTx[tx.GetHash()] = &tx; @@ -799,3 +802,33 @@ size_t CTxMemPool::DynamicMemoryUsage() const { // Estimate the overhead of mapTx to be 6 pointers + an allocation, as no exact formula for boost::multi_index_contained is implemented. return memusage::MallocUsage(sizeof(CTxMemPoolEntry) + 6 * sizeof(void*)) * mapTx.size() + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + cachedInnerUsage; } + +void CTxMemPool::setMempoolCostLimit(int64_t totalCostLimit, int64_t evictionMemorySeconds) { + LogPrint("mempool", "Setting mempool cost limit: (limit=%d, time=%d)\n", totalCostLimit, evictionMemorySeconds); + // This method should not be called more than once + assert(!recentlyEvicted); + assert(!weightedTxList); + recentlyEvicted = new RecentlyEvictedList(evictionMemorySeconds); + weightedTxList = new WeightedTransactionList(totalCostLimit); +} + +bool CTxMemPool::isRecentlyEvicted(const uint256& txId) { + if (!recentlyEvicted) { + return false; + } + return recentlyEvicted->contains(txId); +} + +std::vector CTxMemPool::ensureSizeLimit() { + std::vector evicted; + if (!weightedTxList || !recentlyEvicted) { + return evicted; + } + boost::optional txToDrop; + while ((txToDrop = weightedTxList->maybeDropRandom()).is_initialized()) { + uint256 txId = txToDrop->txId; + recentlyEvicted->add(txId); + evicted.push_back(txId); + } + return evicted; +} diff --git a/src/txmempool.h b/src/txmempool.h index 23f864adc8b..279b1d0a694 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -10,6 +10,7 @@ #include "amount.h" #include "coins.h" +#include "mempoollimit.h" #include "primitives/transaction.h" #include "sync.h" #include "addressindex.h" @@ -139,6 +140,8 @@ class CTxMemPool std::map mapSproutNullifiers; std::map mapSaplingNullifiers; + RecentlyEvictedList* recentlyEvicted = nullptr; + WeightedTransactionList* weightedTxList = nullptr; void checkNullifiers(ShieldedType type) const; @@ -260,6 +263,12 @@ class CTxMemPool uint32_t GetCheckFrequency() const { return nCheckFrequency; } + + void setMempoolCostLimit(int64_t totalCostLimit, int64_t evictionMemorySeconds); + // Returns true if a transaction has been recently evicted + bool isRecentlyEvicted(const uint256& txId); + // Returns a list of txids which have been evicted + std::vector ensureSizeLimit(); }; /** From a48b1ba7e2b1f3728ea0da63997199da11b664b9 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 27 Sep 2019 14:03:23 -0600 Subject: [PATCH 316/395] Rebuild weighted list on removal and fix size calculation --- qa/rpc-tests/mempool_limit.py | 19 ++++++++++--- src/gtest/test_mempoollimit.cpp | 47 +++++++++++++++------------------ src/main.cpp | 11 +++----- src/mempoollimit.cpp | 37 ++++++++++++++++++-------- src/mempoollimit.h | 10 ++++--- src/txmempool.cpp | 24 ++++++++--------- src/txmempool.h | 4 +-- 7 files changed, 88 insertions(+), 64 deletions(-) diff --git a/qa/rpc-tests/mempool_limit.py b/qa/rpc-tests/mempool_limit.py index b58cf9f367a..52dd4419d9e 100755 --- a/qa/rpc-tests/mempool_limit.py +++ b/qa/rpc-tests/mempool_limit.py @@ -80,10 +80,23 @@ def run_test(self): print("Mempool for node {}: {}".format(i, mempool)) assert_equal(2, len(mempool), "node {}".format(i)) - # self.nodes[0].generate(1) - # self.sync_all() + self.nodes[3].generate(1) + self.sync_all() + + # The mempool sizes should be reset + print("Checking mempool size reset after block mined...") + taddr4 = self.nodes[0].getnewaddress() + self.nodes[0].sendtoaddress(taddr4, 9.999) + self.nodes[0].sendtoaddress(taddr4, 9.999) + self.sync_all() - print("Success") + for i in range(0, 4): + mempool = self.nodes[i].getrawmempool() + print("Mempool for node {}: {}".format(i, mempool)) + assert_equal(2, len(mempool), "node {}".format(i)) + + self.nodes[3].generate(1) + self.sync_all() if __name__ == '__main__': diff --git a/src/gtest/test_mempoollimit.cpp b/src/gtest/test_mempoollimit.cpp index 84d0902a055..8c6f7040a54 100644 --- a/src/gtest/test_mempoollimit.cpp +++ b/src/gtest/test_mempoollimit.cpp @@ -67,11 +67,11 @@ TEST(MempoolLimitTests, WeightedTransactionList_CheckSizeAfterDropping) list.add(WeightedTxInfo(TX_ID2, MIN_TX_COST, MIN_TX_COST)); EXPECT_EQ(8000, list.getTotalCost()); EXPECT_EQ(8000, list.getTotalLowFeePenaltyCost()); - EXPECT_FALSE(list.maybeDropRandom().is_initialized()); + EXPECT_FALSE(list.maybeDropRandom(true).is_initialized()); list.add(WeightedTxInfo(TX_ID3, MIN_TX_COST, MIN_TX_COST + LOW_FEE_PENALTY)); EXPECT_EQ(12000, list.getTotalCost()); EXPECT_EQ(12000 + LOW_FEE_PENALTY, list.getTotalLowFeePenaltyCost()); - boost::optional drop = list.maybeDropRandom(); + boost::optional drop = list.maybeDropRandom(true); ASSERT_TRUE(drop.is_initialized()); uint256 txid = drop.get().txId; std::cerr << "Trial " << trialNum++ << ": dropped " << txid.ToString() << std::endl; @@ -90,19 +90,15 @@ TEST(MempoolLimitTests, WeightedTXInfo_FromTx) auto consensusParams = RegtestActivateSapling(); auto sk = libzcash::SaplingSpendingKey::random(); - auto expsk = sk.expanded_spending_key(); - auto fvk = sk.full_viewing_key(); - auto pa = sk.default_address(); - - auto testNote = GetTestSaplingNote(pa, 50000); + auto testNote = GetTestSaplingNote(sk.default_address(), 50000); // Default fee { auto builder = TransactionBuilder(consensusParams, 1); - builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); - builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); + builder.AddSaplingSpend(sk.expanded_spending_key(), testNote.note, testNote.tree.root(), testNote.tree.witness()); + builder.AddSaplingOutput(sk.full_viewing_key().ovk, sk.default_address(), 25000, {}); - WeightedTxInfo info = WeightedTxInfo::from(builder.Build().GetTxOrThrow()); + WeightedTxInfo info = WeightedTxInfo::from(builder.Build().GetTxOrThrow(), 10000); EXPECT_EQ(MIN_TX_COST, info.cost); EXPECT_EQ(MIN_TX_COST, info.lowFeePenaltyCost); } @@ -110,30 +106,31 @@ TEST(MempoolLimitTests, WeightedTXInfo_FromTx) // Lower than standard fee { auto builder = TransactionBuilder(consensusParams, 1); - builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); - builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); - builder.SetFee(1); + builder.AddSaplingSpend(sk.expanded_spending_key(), testNote.note, testNote.tree.root(), testNote.tree.witness()); + builder.AddSaplingOutput(sk.full_viewing_key().ovk, sk.default_address(), 25000, {}); + builder.SetFee(9999); - WeightedTxInfo info = WeightedTxInfo::from(builder.Build().GetTxOrThrow()); + WeightedTxInfo info = WeightedTxInfo::from(builder.Build().GetTxOrThrow(), 9999); EXPECT_EQ(MIN_TX_COST, info.cost); EXPECT_EQ(MIN_TX_COST + LOW_FEE_PENALTY, info.lowFeePenaltyCost); } // Larger Tx { - auto testNote2 = GetTestSaplingNote(pa, 50000); - auto testNote3 = GetTestSaplingNote(pa, 50000); - auto testNote4 = GetTestSaplingNote(pa, 50000); auto builder = TransactionBuilder(consensusParams, 1); - builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); - builder.AddSaplingSpend(expsk, testNote2.note, testNote2.tree.root(), testNote2.tree.witness()); - builder.AddSaplingSpend(expsk, testNote3.note, testNote3.tree.root(), testNote3.tree.witness()); - builder.AddSaplingSpend(expsk, testNote4.note, testNote4.tree.root(), testNote4.tree.witness()); - builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); + builder.AddSaplingSpend(sk.expanded_spending_key(), testNote.note, testNote.tree.root(), testNote.tree.witness()); + builder.AddSaplingOutput(sk.full_viewing_key().ovk, sk.default_address(), 5000, {}); + builder.AddSaplingOutput(sk.full_viewing_key().ovk, sk.default_address(), 5000, {}); + builder.AddSaplingOutput(sk.full_viewing_key().ovk, sk.default_address(), 5000, {}); + builder.AddSaplingOutput(sk.full_viewing_key().ovk, sk.default_address(), 5000, {}); - WeightedTxInfo info = WeightedTxInfo::from(builder.Build().GetTxOrThrow()); - EXPECT_EQ(MIN_TX_COST, info.cost); - EXPECT_EQ(MIN_TX_COST, info.lowFeePenaltyCost); + auto result = builder.Build(); + if (result.IsError()) { + std::cerr << result.GetError() << std::endl; + } + WeightedTxInfo info = WeightedTxInfo::from(result.GetTxOrThrow(), 10000); + EXPECT_EQ(5124, info.cost); + EXPECT_EQ(5124, info.lowFeePenaltyCost); } RegtestDeactivateSapling(); diff --git a/src/main.cpp b/src/main.cpp index b7bcd598072..4ec428bf42d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1637,15 +1637,12 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa pool.addSpentIndex(entry, view); } - // In normal circumstances the following should be empty + // In normal circumstances the following should be boost::none + boost::optional maybeDropTxId; list removed; - std::vector evictedTxIds = pool.ensureSizeLimit(); - for (const uint256& txId : evictedTxIds) { - CTransaction toRemove = pool.mapTx.find(txId)->GetTx(); - pool.remove(toRemove, removed, true); + while ((maybeDropTxId = pool.ensureSizeLimit()).is_initialized()) { + pool.remove(pool.mapTx.find(maybeDropTxId.get())->GetTx(), removed, true); } - - // TODO rebuild list here and when a block is made } } diff --git a/src/mempoollimit.cpp b/src/mempoollimit.cpp index 0bc16720ac1..2f89f4e9e52 100644 --- a/src/mempoollimit.cpp +++ b/src/mempoollimit.cpp @@ -5,9 +5,11 @@ #include "core_memusage.h" #include "mempoollimit.h" #include "random.h" +#include "serialize.h" #include "timedata.h" +#include "version.h" -const int64_t DEFAULT_FEE = 10000; +const CAmount DEFAULT_FEE = 10000; void RecentlyEvictedList::pruneList() { @@ -42,12 +44,16 @@ bool RecentlyEvictedList::contains(const uint256& txId) } -int64_t WeightedTransactionList::getTotalCost() +void WeightedTransactionList::clear() { + weightedTxInfos.clear(); +} + +int64_t WeightedTransactionList::getTotalCost() const { return weightedTxInfos.empty() ? 0 : weightedTxInfos.back().cost; } -int64_t WeightedTransactionList::getTotalLowFeePenaltyCost() +int64_t WeightedTransactionList::getTotalLowFeePenaltyCost() const { return weightedTxInfos.empty() ? 0 : weightedTxInfos.back().lowFeePenaltyCost; } @@ -65,7 +71,7 @@ void WeightedTransactionList::add(WeightedTxInfo weightedTxInfo) } } -boost::optional WeightedTransactionList::maybeDropRandom() +boost::optional WeightedTransactionList::maybeDropRandom(bool rebuildList) { int64_t totalCost = getTotalCost(); if (totalCost <= maxTotalCost) { @@ -81,22 +87,31 @@ boost::optional WeightedTransactionList::maybeDropRandom() if (i > 0) { drop.minusEquals(weightedTxInfos[i - 1]); } - while (++i < weightedTxInfos.size()) { - WeightedTxInfo nextTx = weightedTxInfos[i]; - nextTx.minusEquals(drop); - weightedTxInfos[i - 1] = nextTx; + if (rebuildList) { + while (++i < weightedTxInfos.size()) { + WeightedTxInfo nextTx = weightedTxInfos[i]; + nextTx.minusEquals(drop); + weightedTxInfos[i - 1] = nextTx; + } + weightedTxInfos.pop_back(); } - weightedTxInfos.pop_back(); LogPrint("mempool", "Evicting transaction (txid=%s, cost=%d, penaltyCost=%d)\n", drop.txId.ToString(), drop.cost, drop.lowFeePenaltyCost); return drop; } -WeightedTxInfo WeightedTxInfo::from(const CTransaction& tx) +// These are also defined in rpcwallet.cpp +#define JOINSPLIT_SIZE GetSerializeSize(JSDescription(), SER_NETWORK, PROTOCOL_VERSION) +#define OUTPUTDESCRIPTION_SIZE GetSerializeSize(OutputDescription(), SER_NETWORK, PROTOCOL_VERSION) +#define SPENDDESCRIPTION_SIZE GetSerializeSize(SpendDescription(), SER_NETWORK, PROTOCOL_VERSION) + +WeightedTxInfo WeightedTxInfo::from(const CTransaction& tx, const CAmount& fee) { size_t memUsage = RecursiveDynamicUsage(tx); + memUsage += tx.vJoinSplit.size() * JOINSPLIT_SIZE; + memUsage += tx.vShieldedOutput.size() * OUTPUTDESCRIPTION_SIZE; + memUsage += tx.vShieldedSpend.size() * SPENDDESCRIPTION_SIZE; int64_t cost = std::max(memUsage, MIN_TX_COST); int64_t lowFeePenaltyCost = cost; - int64_t fee = DEFAULT_FEE; if (fee < DEFAULT_FEE) { lowFeePenaltyCost += LOW_FEE_PENALTY; } diff --git a/src/mempoollimit.h b/src/mempoollimit.h index 96d528f7cf5..bc36b3aa9e9 100644 --- a/src/mempoollimit.h +++ b/src/mempoollimit.h @@ -51,11 +51,13 @@ class WeightedTransactionList public: WeightedTransactionList(int64_t maxTotalCost_) : maxTotalCost(maxTotalCost_) {} - int64_t getTotalCost(); - int64_t getTotalLowFeePenaltyCost(); + void clear(); + + int64_t getTotalCost() const; + int64_t getTotalLowFeePenaltyCost() const; void add(WeightedTxInfo weightedTxInfo); - boost::optional maybeDropRandom(); + boost::optional maybeDropRandom(bool rebuildList); }; @@ -67,7 +69,7 @@ struct WeightedTxInfo { WeightedTxInfo(uint256 txId_, uint64_t cost_, uint64_t lowFeePenaltyCost_) : txId(txId_), cost(cost_), lowFeePenaltyCost(lowFeePenaltyCost_) {} - static WeightedTxInfo from(const CTransaction& tx); + static WeightedTxInfo from(const CTransaction& tx, const CAmount& fee); void plusEquals(const WeightedTxInfo& other); void minusEquals(const WeightedTxInfo& other); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index ae4ebb707f5..29fddc042a9 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -103,7 +103,7 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, // all the appropriate checks. LOCK(cs); if (weightedTxList) { - weightedTxList->add(WeightedTxInfo::from(entry.GetTx())); + weightedTxList->add(WeightedTxInfo::from(entry.GetTx(), entry.GetFee())); } mapTx.insert(entry); const CTransaction& tx = mapTx.find(hash)->GetTx(); @@ -291,6 +291,12 @@ void CTxMemPool::remove(const CTransaction &origTx, std::list& rem removeAddressIndex(hash); if (fSpentIndex) removeSpentIndex(hash); + } + if (weightedTxList) { + weightedTxList->clear(); + for (const CTxMemPoolEntry& e : mapTx) { + weightedTxList->add(WeightedTxInfo::from(e.GetTx(), e.GetFee())); + } } } } @@ -819,16 +825,10 @@ bool CTxMemPool::isRecentlyEvicted(const uint256& txId) { return recentlyEvicted->contains(txId); } -std::vector CTxMemPool::ensureSizeLimit() { - std::vector evicted; - if (!weightedTxList || !recentlyEvicted) { - return evicted; - } - boost::optional txToDrop; - while ((txToDrop = weightedTxList->maybeDropRandom()).is_initialized()) { - uint256 txId = txToDrop->txId; - recentlyEvicted->add(txId); - evicted.push_back(txId); +boost::optional CTxMemPool::ensureSizeLimit() { + auto maybeDrop = weightedTxList->maybeDropRandom(false); + if (maybeDrop) { + return maybeDrop.get().txId; } - return evicted; + return boost::none; } diff --git a/src/txmempool.h b/src/txmempool.h index 279b1d0a694..ac9eeacd5ac 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -267,8 +267,8 @@ class CTxMemPool void setMempoolCostLimit(int64_t totalCostLimit, int64_t evictionMemorySeconds); // Returns true if a transaction has been recently evicted bool isRecentlyEvicted(const uint256& txId); - // Returns a list of txids which have been evicted - std::vector ensureSizeLimit(); + // Returns a txid if a transaction is evicted from the mempool + boost::optional ensureSizeLimit(); }; /** From 0b2c5cfcc2e36989b41822540663a7f072156fe2 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 27 Sep 2019 14:05:28 -0600 Subject: [PATCH 317/395] Grammatical fixes Co-Authored-By: Daira Hopwood --- qa/rpc-tests/mempool_limit.py | 2 +- src/gtest/test_mempoollimit.cpp | 2 +- src/init.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/qa/rpc-tests/mempool_limit.py b/qa/rpc-tests/mempool_limit.py index 52dd4419d9e..98e0a6c014a 100755 --- a/qa/rpc-tests/mempool_limit.py +++ b/qa/rpc-tests/mempool_limit.py @@ -67,7 +67,7 @@ def run_test(self): print("Adding one more transaction...") self.nodes[3].sendtoaddress(taddr3, 9.999) - # The mempools are no longer guarenteed to be in a consistent state, so we cannot sync + # The mempools are no longer guaranteed to be in a consistent state, so we cannot sync sleep(5) mempool_node3 = self.nodes[i].getrawmempool() print("Mempool for node 3: {}".format(mempool_node3)) diff --git a/src/gtest/test_mempoollimit.cpp b/src/gtest/test_mempoollimit.cpp index 8c6f7040a54..e331bf05be1 100644 --- a/src/gtest/test_mempoollimit.cpp +++ b/src/gtest/test_mempoollimit.cpp @@ -23,7 +23,7 @@ TEST(MempoolLimitTests, RecentlyEvictedList_AddWrapsAfterMaxSize) recentlyEvicted.add(TX_ID1); recentlyEvicted.add(TX_ID2); recentlyEvicted.add(TX_ID3); - // tx 1 should be overwritten by tx 3 due maxSize 2 + // tx 1 should be overwritten by tx 3 due to maxSize 2 EXPECT_FALSE(recentlyEvicted.contains(TX_ID1)); EXPECT_TRUE(recentlyEvicted.contains(TX_ID2)); EXPECT_TRUE(recentlyEvicted.contains(TX_ID3)); diff --git a/src/init.cpp b/src/init.cpp index 054199bc26c..416f87876e5 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -400,7 +400,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-whitelist=", _("Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times.") + " " + _("Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway")); strUsage += HelpMessageOpt("-mempooltotalcostlimit=", _("An upper bound on the maximum size in bytes of all txs in the mempool. (default: 80000000)")); - strUsage += HelpMessageOpt("-mempoolevictionmemoryminutes=", _("The number of minutes before reallowing rejected transactions from reentering the mempool. (default: 60)")); + strUsage += HelpMessageOpt("-mempoolevictionmemoryminutes=", _("The number of minutes before reallowing rejected transactions to reenter the mempool. (default: 60)")); #ifdef ENABLE_WALLET strUsage += HelpMessageGroup(_("Wallet options:")); From 1407fd10a13600fe3e4cefe837348b6b720f945b Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 30 Sep 2019 10:46:15 -0600 Subject: [PATCH 318/395] Remove transactions when ensuring size limit --- src/main.cpp | 7 +------ src/txmempool.cpp | 22 ++++++++++++++-------- src/txmempool.h | 2 +- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 4ec428bf42d..94f15c27e05 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1637,12 +1637,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa pool.addSpentIndex(entry, view); } - // In normal circumstances the following should be boost::none - boost::optional maybeDropTxId; - list removed; - while ((maybeDropTxId = pool.ensureSizeLimit()).is_initialized()) { - pool.remove(pool.mapTx.find(maybeDropTxId.get())->GetTx(), removed, true); - } + pool.ensureSizeLimit(); } } diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 29fddc042a9..d2e60e3b3a4 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -68,6 +68,8 @@ CTxMemPool::CTxMemPool(const CFeeRate& _minRelayFee) : CTxMemPool::~CTxMemPool() { delete minerPolicyEstimator; + delete recentlyEvicted; + delete weightedTxList; } void CTxMemPool::pruneSpent(const uint256 &hashTx, CCoins &coins) @@ -819,16 +821,20 @@ void CTxMemPool::setMempoolCostLimit(int64_t totalCostLimit, int64_t evictionMem } bool CTxMemPool::isRecentlyEvicted(const uint256& txId) { - if (!recentlyEvicted) { - return false; - } + LOCK(cs); + assert(recentlyEvicted); return recentlyEvicted->contains(txId); } -boost::optional CTxMemPool::ensureSizeLimit() { - auto maybeDrop = weightedTxList->maybeDropRandom(false); - if (maybeDrop) { - return maybeDrop.get().txId; +void CTxMemPool::ensureSizeLimit() { + AssertLockHeld(cs); + assert(recentlyEvicted); + assert(weightedTxList); + boost::optional maybeDrop; + std::list removed; + while ((maybeDrop = weightedTxList->maybeDropRandom(false)).is_initialized()) { + uint256 txId = maybeDrop.get().txId; + recentlyEvicted->add(txId); + remove(mapTx.find(txId)->GetTx(), removed, true); } - return boost::none; } diff --git a/src/txmempool.h b/src/txmempool.h index ac9eeacd5ac..14cff878ec5 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -268,7 +268,7 @@ class CTxMemPool // Returns true if a transaction has been recently evicted bool isRecentlyEvicted(const uint256& txId); // Returns a txid if a transaction is evicted from the mempool - boost::optional ensureSizeLimit(); + void ensureSizeLimit(); }; /** From 6fdd8f529896a805280bb63c342d85b06ec07e2a Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 30 Sep 2019 10:54:57 -0600 Subject: [PATCH 319/395] Help message cleanup and add lock --- src/init.cpp | 10 ++++++---- src/mempoollimit.h | 3 +++ src/txmempool.cpp | 1 + 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 416f87876e5..2b6c5f7e9da 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -22,6 +22,7 @@ #include "key_io.h" #endif #include "main.h" +#include "mempoollimit.h" #include "metrics.h" #include "miner.h" #include "net.h" @@ -383,6 +384,8 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-maxconnections=", strprintf(_("Maintain at most connections to peers (default: %u)"), DEFAULT_MAX_PEER_CONNECTIONS)); strUsage += HelpMessageOpt("-maxreceivebuffer=", strprintf(_("Maximum per-connection receive buffer, *1000 bytes (default: %u)"), 5000)); strUsage += HelpMessageOpt("-maxsendbuffer=", strprintf(_("Maximum per-connection send buffer, *1000 bytes (default: %u)"), 1000)); + strUsage += HelpMessageOpt("-mempoolevictionmemoryminutes=", strprintf(_("The number of minutes before allowing rejected transactions to re-enter the mempool. (default: %u)"), DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES)); + strUsage += HelpMessageOpt("-mempooltotalcostlimit=",strprintf(_("An upper bound on the maximum size in bytes of all transactions in the mempool. (default: %s)"), DEFAULT_MEMPOOL_TOTAL_COST_LIMIT)); strUsage += HelpMessageOpt("-onion=", strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy")); strUsage += HelpMessageOpt("-onlynet=", _("Only connect to nodes in network (ipv4, ipv6 or onion)")); strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), 1)); @@ -399,8 +402,6 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-whitebind=", _("Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6")); strUsage += HelpMessageOpt("-whitelist=", _("Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times.") + " " + _("Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway")); - strUsage += HelpMessageOpt("-mempooltotalcostlimit=", _("An upper bound on the maximum size in bytes of all txs in the mempool. (default: 80000000)")); - strUsage += HelpMessageOpt("-mempoolevictionmemoryminutes=", _("The number of minutes before reallowing rejected transactions to reenter the mempool. (default: 60)")); #ifdef ENABLE_WALLET strUsage += HelpMessageGroup(_("Wallet options:")); @@ -977,8 +978,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) mempool.setSanityCheck(1.0 / ratio); } - int64_t mempoolTotalCostLimit = GetArg("-mempooltotalcostlimit", 80000000); - int64_t mempoolEvictionMemorySeconds = GetArg("-mempoolevictionmemoryminutes", 60) * 1000; + int64_t mempoolTotalCostLimit = GetArg("-mempooltotalcostlimit", DEFAULT_MEMPOOL_TOTAL_COST_LIMIT); + int64_t mempoolEvictionMemorySeconds = GetArg("-mempoolevictionmemoryminutes", DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES) * 60; mempool.setMempoolCostLimit(mempoolTotalCostLimit, mempoolEvictionMemorySeconds); fCheckBlockIndex = GetBoolArg("-checkblockindex", chainparams.DefaultConsistencyChecks()); @@ -1602,6 +1603,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) mempool.ReadFeeEstimates(est_filein); fFeeEstimatesInitialized = true; + // ********************************************************* Step 8: load wallet #ifdef ENABLE_WALLET if (fDisableWallet) { diff --git a/src/mempoollimit.h b/src/mempoollimit.h index bc36b3aa9e9..a3bbb8ea2d2 100644 --- a/src/mempoollimit.h +++ b/src/mempoollimit.h @@ -12,6 +12,9 @@ #include "boost/optional.hpp" +const size_t DEFAULT_MEMPOOL_TOTAL_COST_LIMIT = 80000000; +const int64_t DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES = 60; + const size_t RECENTLY_EVICTED_SIZE = 10000; const uint64_t MIN_TX_COST = 4000; const uint64_t LOW_FEE_PENALTY = 16000; diff --git a/src/txmempool.cpp b/src/txmempool.cpp index d2e60e3b3a4..bd9d4b2d22d 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -812,6 +812,7 @@ size_t CTxMemPool::DynamicMemoryUsage() const { } void CTxMemPool::setMempoolCostLimit(int64_t totalCostLimit, int64_t evictionMemorySeconds) { + LOCK(cs); LogPrint("mempool", "Setting mempool cost limit: (limit=%d, time=%d)\n", totalCostLimit, evictionMemorySeconds); // This method should not be called more than once assert(!recentlyEvicted); From 1a06727c0c15dd7ca7450985ce3d2af757c45362 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 7 Oct 2019 14:13:10 -0600 Subject: [PATCH 320/395] Performance: Store weighted transactions in a tree --- qa/rpc-tests/mempool_limit.py | 29 ++++--- src/gtest/test_mempoollimit.cpp | 48 +++++------ src/init.cpp | 4 +- src/mempoollimit.cpp | 140 +++++++++++++++++++------------- src/mempoollimit.h | 82 +++++++++++-------- src/txmempool.cpp | 31 ++++--- src/txmempool.h | 2 +- 7 files changed, 191 insertions(+), 145 deletions(-) diff --git a/qa/rpc-tests/mempool_limit.py b/qa/rpc-tests/mempool_limit.py index 98e0a6c014a..4e8e14ba975 100755 --- a/qa/rpc-tests/mempool_limit.py +++ b/qa/rpc-tests/mempool_limit.py @@ -8,8 +8,10 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, + get_coinbase_address, initialize_chain_clean, start_nodes, + wait_and_assert_operationid_status, ) from decimal import Decimal @@ -51,13 +53,15 @@ def run_test(self): assert_equal(Decimal("10.00"), Decimal(self.nodes[2].z_gettotalbalance()['transparent'])) assert_equal(Decimal("10.00"), Decimal(self.nodes[3].z_gettotalbalance()['transparent'])) - taddr1 = self.nodes[0].getnewaddress() - taddr2 = self.nodes[0].getnewaddress() - taddr3 = self.nodes[0].getnewaddress() + zaddr1 = self.nodes[0].z_getnewaddress('sapling') + zaddr2 = self.nodes[0].z_getnewaddress('sapling') + zaddr3 = self.nodes[0].z_getnewaddress('sapling') print("Filling mempool...") - self.nodes[1].sendtoaddress(taddr1, 9.999) - self.nodes[2].sendtoaddress(taddr2, 9.999) + opid1 = self.nodes[1].z_sendmany(get_coinbase_address(self.nodes[1]), [{"address": zaddr1, "amount": Decimal('9.999')}]) + wait_and_assert_operationid_status(self.nodes[1], opid1) + opid2 = self.nodes[2].z_sendmany(get_coinbase_address(self.nodes[2]), [{"address": zaddr2, "amount": Decimal('9.999')}]) + wait_and_assert_operationid_status(self.nodes[2], opid2) self.sync_all() for i in range(0, 4): @@ -66,12 +70,13 @@ def run_test(self): assert_equal(2, len(mempool), "node {}".format(i)) print("Adding one more transaction...") - self.nodes[3].sendtoaddress(taddr3, 9.999) + opid3 = self.nodes[3].z_sendmany(get_coinbase_address(self.nodes[3]), [{"address": zaddr3, "amount": Decimal('9.999')}]) + wait_and_assert_operationid_status(self.nodes[3], opid3) # The mempools are no longer guaranteed to be in a consistent state, so we cannot sync sleep(5) - mempool_node3 = self.nodes[i].getrawmempool() + mempool_node3 = self.nodes[3].getrawmempool() print("Mempool for node 3: {}".format(mempool_node3)) - assert_equal(3, len(mempool_node3), "node {}".format(i)) + assert_equal(3, len(mempool_node3), "node {}".format(3)) print("Checking mempool size...") # Due to the size limit, there should only be 2 transactions in the mempool @@ -85,9 +90,11 @@ def run_test(self): # The mempool sizes should be reset print("Checking mempool size reset after block mined...") - taddr4 = self.nodes[0].getnewaddress() - self.nodes[0].sendtoaddress(taddr4, 9.999) - self.nodes[0].sendtoaddress(taddr4, 9.999) + zaddr4 = self.nodes[0].z_getnewaddress('sapling') + opid4 = self.nodes[0].z_sendmany(zaddr1, [{"address": zaddr4, "amount": Decimal('9.998')}]) + wait_and_assert_operationid_status(self.nodes[0], opid4) + opid5 = self.nodes[0].z_sendmany(zaddr2, [{"address": zaddr4, "amount": Decimal('9.998')}]) + wait_and_assert_operationid_status(self.nodes[0], opid5) self.sync_all() for i in range(0, 4): diff --git a/src/gtest/test_mempoollimit.cpp b/src/gtest/test_mempoollimit.cpp index e331bf05be1..af12d1b2fa4 100644 --- a/src/gtest/test_mempoollimit.cpp +++ b/src/gtest/test_mempoollimit.cpp @@ -52,33 +52,33 @@ TEST(MempoolLimitTests, RecentlyEvictedList_DoesNotContainAfterExpiry) EXPECT_FALSE(recentlyEvicted.contains(TX_ID3)); } -TEST(MempoolLimitTests, WeightedTransactionList_CheckSizeAfterDropping) +TEST(MempoolLimitTests, WeightedTxTree_CheckSizeAfterDropping) { std::set testedDropping; // Run the test until we have tested dropping each of the elements int trialNum = 0; while (testedDropping.size() < 3) { - WeightedTransactionList list(MIN_TX_COST * 2); - EXPECT_EQ(0, list.getTotalCost()); - EXPECT_EQ(0, list.getTotalLowFeePenaltyCost()); - list.add(WeightedTxInfo(TX_ID1, MIN_TX_COST, MIN_TX_COST)); - EXPECT_EQ(4000, list.getTotalCost()); - EXPECT_EQ(4000, list.getTotalLowFeePenaltyCost()); - list.add(WeightedTxInfo(TX_ID2, MIN_TX_COST, MIN_TX_COST)); - EXPECT_EQ(8000, list.getTotalCost()); - EXPECT_EQ(8000, list.getTotalLowFeePenaltyCost()); - EXPECT_FALSE(list.maybeDropRandom(true).is_initialized()); - list.add(WeightedTxInfo(TX_ID3, MIN_TX_COST, MIN_TX_COST + LOW_FEE_PENALTY)); - EXPECT_EQ(12000, list.getTotalCost()); - EXPECT_EQ(12000 + LOW_FEE_PENALTY, list.getTotalLowFeePenaltyCost()); - boost::optional drop = list.maybeDropRandom(true); + WeightedTxTree tree(MIN_TX_WEIGHT * 2); + EXPECT_EQ(0, tree.getTotalWeight().weight); + EXPECT_EQ(0, tree.getTotalWeight().lowFeePenaltyWeight); + tree.add(WeightedTxInfo(TX_ID1, TxWeight(MIN_TX_WEIGHT, MIN_TX_WEIGHT))); + EXPECT_EQ(4000, tree.getTotalWeight().weight); + EXPECT_EQ(4000, tree.getTotalWeight().lowFeePenaltyWeight); + tree.add(WeightedTxInfo(TX_ID2, TxWeight(MIN_TX_WEIGHT, MIN_TX_WEIGHT))); + EXPECT_EQ(8000, tree.getTotalWeight().weight); + EXPECT_EQ(8000, tree.getTotalWeight().lowFeePenaltyWeight); + EXPECT_FALSE(tree.maybeDropRandom().is_initialized()); + tree.add(WeightedTxInfo(TX_ID3, TxWeight(MIN_TX_WEIGHT, MIN_TX_WEIGHT + LOW_FEE_PENALTY))); + EXPECT_EQ(12000, tree.getTotalWeight().weight); + EXPECT_EQ(12000 + LOW_FEE_PENALTY, tree.getTotalWeight().lowFeePenaltyWeight); + boost::optional drop = tree.maybeDropRandom(); ASSERT_TRUE(drop.is_initialized()); - uint256 txid = drop.get().txId; + uint256 txid = drop.get(); std::cerr << "Trial " << trialNum++ << ": dropped " << txid.ToString() << std::endl; testedDropping.insert(txid); // Do not continue to test if a particular trial fails - ASSERT_EQ(8000, list.getTotalCost()); - ASSERT_EQ(txid == TX_ID3 ? 8000 : 8000 + LOW_FEE_PENALTY, list.getTotalLowFeePenaltyCost()); + ASSERT_EQ(8000, tree.getTotalWeight().weight); + ASSERT_EQ(txid == TX_ID3 ? 8000 : 8000 + LOW_FEE_PENALTY, tree.getTotalWeight().lowFeePenaltyWeight); } std::cerr << "All 3 scenarios tested in " << trialNum << " trials" << std::endl; } @@ -99,8 +99,8 @@ TEST(MempoolLimitTests, WeightedTXInfo_FromTx) builder.AddSaplingOutput(sk.full_viewing_key().ovk, sk.default_address(), 25000, {}); WeightedTxInfo info = WeightedTxInfo::from(builder.Build().GetTxOrThrow(), 10000); - EXPECT_EQ(MIN_TX_COST, info.cost); - EXPECT_EQ(MIN_TX_COST, info.lowFeePenaltyCost); + EXPECT_EQ(MIN_TX_WEIGHT, info.txWeight.weight); + EXPECT_EQ(MIN_TX_WEIGHT, info.txWeight.lowFeePenaltyWeight); } // Lower than standard fee @@ -111,8 +111,8 @@ TEST(MempoolLimitTests, WeightedTXInfo_FromTx) builder.SetFee(9999); WeightedTxInfo info = WeightedTxInfo::from(builder.Build().GetTxOrThrow(), 9999); - EXPECT_EQ(MIN_TX_COST, info.cost); - EXPECT_EQ(MIN_TX_COST + LOW_FEE_PENALTY, info.lowFeePenaltyCost); + EXPECT_EQ(MIN_TX_WEIGHT, info.txWeight.weight); + EXPECT_EQ(MIN_TX_WEIGHT + LOW_FEE_PENALTY, info.txWeight.lowFeePenaltyWeight); } // Larger Tx @@ -129,8 +129,8 @@ TEST(MempoolLimitTests, WeightedTXInfo_FromTx) std::cerr << result.GetError() << std::endl; } WeightedTxInfo info = WeightedTxInfo::from(result.GetTxOrThrow(), 10000); - EXPECT_EQ(5124, info.cost); - EXPECT_EQ(5124, info.lowFeePenaltyCost); + EXPECT_EQ(5124, info.txWeight.weight); + EXPECT_EQ(5124, info.txWeight.lowFeePenaltyWeight); } RegtestDeactivateSapling(); diff --git a/src/init.cpp b/src/init.cpp index 2b6c5f7e9da..888626f8f79 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -385,7 +385,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-maxreceivebuffer=", strprintf(_("Maximum per-connection receive buffer, *1000 bytes (default: %u)"), 5000)); strUsage += HelpMessageOpt("-maxsendbuffer=", strprintf(_("Maximum per-connection send buffer, *1000 bytes (default: %u)"), 1000)); strUsage += HelpMessageOpt("-mempoolevictionmemoryminutes=", strprintf(_("The number of minutes before allowing rejected transactions to re-enter the mempool. (default: %u)"), DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES)); - strUsage += HelpMessageOpt("-mempooltotalcostlimit=",strprintf(_("An upper bound on the maximum size in bytes of all transactions in the mempool. (default: %s)"), DEFAULT_MEMPOOL_TOTAL_COST_LIMIT)); + strUsage += HelpMessageOpt("-mempooltotalcostlimit=",strprintf(_("An upper bound on the maximum size in bytes of all transactions in the mempool. (default: %s)"), DEFAULT_MEMPOOL_TOTAL_WEIGHT_LIMIT)); strUsage += HelpMessageOpt("-onion=", strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy")); strUsage += HelpMessageOpt("-onlynet=", _("Only connect to nodes in network (ipv4, ipv6 or onion)")); strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), 1)); @@ -978,7 +978,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) mempool.setSanityCheck(1.0 / ratio); } - int64_t mempoolTotalCostLimit = GetArg("-mempooltotalcostlimit", DEFAULT_MEMPOOL_TOTAL_COST_LIMIT); + int64_t mempoolTotalCostLimit = GetArg("-mempooltotalcostlimit", DEFAULT_MEMPOOL_TOTAL_WEIGHT_LIMIT); int64_t mempoolEvictionMemorySeconds = GetArg("-mempoolevictionmemoryminutes", DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES) * 60; mempool.setMempoolCostLimit(mempoolTotalCostLimit, mempoolEvictionMemorySeconds); diff --git a/src/mempoollimit.cpp b/src/mempoollimit.cpp index 2f89f4e9e52..4e02f8987b7 100644 --- a/src/mempoollimit.cpp +++ b/src/mempoollimit.cpp @@ -10,6 +10,7 @@ #include "version.h" const CAmount DEFAULT_FEE = 10000; +const TxWeight ZERO_WEIGHT = TxWeight(0, 0); void RecentlyEvictedList::pruneList() { @@ -17,15 +18,16 @@ void RecentlyEvictedList::pruneList() return; } int64_t now = GetAdjustedTime(); - size_t startIndex = (txIdsAndTimesIndex + maxSize - txIdSet.size()) % maxSize; + size_t startIndex = (txIdsAndTimesIndex + capacity - txIdSet.size()) % capacity; boost::optional> txIdAndTime; while ((txIdAndTime = txIdsAndTimes[startIndex]).is_initialized() && (now - txIdAndTime.get().second) > timeToKeep) { txIdsAndTimes[startIndex] = boost::none; txIdSet.erase(txIdAndTime.get().first); - startIndex = (startIndex + 1) % maxSize; + startIndex = (startIndex + 1) % capacity; } } -void RecentlyEvictedList::add(uint256 txId) + +void RecentlyEvictedList::add(const uint256& txId) { pruneList(); if (txIdsAndTimes[txIdsAndTimesIndex].is_initialized()) { @@ -34,7 +36,7 @@ void RecentlyEvictedList::add(uint256 txId) } txIdsAndTimes[txIdsAndTimesIndex] = std::make_pair(txId, GetAdjustedTime()); txIdSet.insert(txId); - txIdsAndTimesIndex = (txIdsAndTimesIndex + 1) % maxSize; + txIdsAndTimesIndex = (txIdsAndTimesIndex + 1) % capacity; } bool RecentlyEvictedList::contains(const uint256& txId) @@ -44,61 +46,99 @@ bool RecentlyEvictedList::contains(const uint256& txId) } -void WeightedTransactionList::clear() { - weightedTxInfos.clear(); +TxWeight WeightedTxTree::getWeightAt(size_t index) const +{ + return index < size ? txIdAndWeights[index].txWeight.add(childWeights[index]) : ZERO_WEIGHT; } -int64_t WeightedTransactionList::getTotalCost() const +void WeightedTxTree::backPropagate(size_t fromIndex, const TxWeight& weightDelta) { - return weightedTxInfos.empty() ? 0 : weightedTxInfos.back().cost; + while (fromIndex > 0) { + fromIndex = (fromIndex - 1) / 2; + childWeights[fromIndex] = childWeights[fromIndex].add(weightDelta); + } } -int64_t WeightedTransactionList::getTotalLowFeePenaltyCost() const +size_t WeightedTxTree::findByWeight(size_t fromIndex, uint64_t weightToFind) const { - return weightedTxInfos.empty() ? 0 : weightedTxInfos.back().lowFeePenaltyCost; + int leftWeight = getWeightAt(fromIndex * 2 + 1).lowFeePenaltyWeight; + int rightWeight = getWeightAt(fromIndex).lowFeePenaltyWeight - getWeightAt(fromIndex * 2 + 2).lowFeePenaltyWeight; + // On Left + if (weightToFind < leftWeight) { + return findByWeight(fromIndex * 2 + 1, weightToFind); + } + // Found + if (weightToFind < rightWeight) { + return fromIndex; + } + // On Right + return findByWeight(fromIndex * 2 + 2, weightToFind - rightWeight); } -void WeightedTransactionList::add(WeightedTxInfo weightedTxInfo) +TxWeight WeightedTxTree::getTotalWeight() const +{ + return getWeightAt(0); +} + + +void WeightedTxTree::add(const WeightedTxInfo& weightedTxInfo) { - if (weightedTxInfos.empty()) { - weightedTxInfos.push_back(weightedTxInfo); + txIdAndWeights.push_back(weightedTxInfo); + childWeights.push_back(ZERO_WEIGHT); + txIdToIndexMap[weightedTxInfo.txId] = size; + backPropagate(size++, weightedTxInfo.txWeight); +} + +void WeightedTxTree::remove(const uint256& txId) +{ + if (txIdToIndexMap.find(txId) == txIdToIndexMap.end()) { return; } - weightedTxInfo.plusEquals(weightedTxInfos.back()); - weightedTxInfos.push_back(weightedTxInfo); - for (int i =0; i < weightedTxInfos.size(); ++i) { - WeightedTxInfo info = weightedTxInfos[i]; + + size_t removeIndex = txIdToIndexMap[txId]; + + TxWeight lastChildWeight = txIdAndWeights[--size].txWeight; + backPropagate(size, lastChildWeight.negate()); + + if (removeIndex < size) { + TxWeight weightDelta = lastChildWeight.add(txIdAndWeights[removeIndex].txWeight.negate()); + txIdAndWeights[removeIndex] = txIdAndWeights[size]; + txIdToIndexMap[txIdAndWeights[removeIndex].txId] = removeIndex; + backPropagate(removeIndex, weightDelta); } + + txIdToIndexMap.erase(txId); + txIdAndWeights.pop_back(); + childWeights.pop_back(); } - -boost::optional WeightedTransactionList::maybeDropRandom(bool rebuildList) + +boost::optional WeightedTxTree::maybeDropRandom() { - int64_t totalCost = getTotalCost(); - if (totalCost <= maxTotalCost) { + uint64_t totalPenaltyWeight = getTotalWeight().lowFeePenaltyWeight; + if (totalPenaltyWeight <= capacity) { return boost::none; } - LogPrint("mempool", "Mempool cost limit exceeded (cost=%d, limit=%d)\n", totalCost, maxTotalCost); - int randomWeight = GetRand(getTotalLowFeePenaltyCost()); - int i = 0; - while (randomWeight > weightedTxInfos[i].lowFeePenaltyCost) { - ++i; - } - WeightedTxInfo drop = weightedTxInfos[i]; - if (i > 0) { - drop.minusEquals(weightedTxInfos[i - 1]); - } - if (rebuildList) { - while (++i < weightedTxInfos.size()) { - WeightedTxInfo nextTx = weightedTxInfos[i]; - nextTx.minusEquals(drop); - weightedTxInfos[i - 1] = nextTx; - } - weightedTxInfos.pop_back(); - } - LogPrint("mempool", "Evicting transaction (txid=%s, cost=%d, penaltyCost=%d)\n", drop.txId.ToString(), drop.cost, drop.lowFeePenaltyCost); - return drop; + LogPrint("mempool", "Mempool cost limit exceeded (cost=%d, limit=%d)\n", totalPenaltyWeight, capacity); + int randomWeight = GetRand(totalPenaltyWeight); + WeightedTxInfo drop = txIdAndWeights[findByWeight(0, randomWeight)]; + LogPrint("mempool", "Evicting transaction (txid=%s, cost=%d, penaltyCost=%d)\n", + drop.txId.ToString(), drop.txWeight.weight, drop.txWeight.lowFeePenaltyWeight); + remove(drop.txId); + return drop.txId; } + +TxWeight TxWeight::add(const TxWeight& other) const +{ + return TxWeight(weight + other.weight, lowFeePenaltyWeight + other.lowFeePenaltyWeight); +} + +TxWeight TxWeight::negate() const +{ + return TxWeight(-weight, -lowFeePenaltyWeight); +} + + // These are also defined in rpcwallet.cpp #define JOINSPLIT_SIZE GetSerializeSize(JSDescription(), SER_NETWORK, PROTOCOL_VERSION) #define OUTPUTDESCRIPTION_SIZE GetSerializeSize(OutputDescription(), SER_NETWORK, PROTOCOL_VERSION) @@ -110,22 +150,10 @@ WeightedTxInfo WeightedTxInfo::from(const CTransaction& tx, const CAmount& fee) memUsage += tx.vJoinSplit.size() * JOINSPLIT_SIZE; memUsage += tx.vShieldedOutput.size() * OUTPUTDESCRIPTION_SIZE; memUsage += tx.vShieldedSpend.size() * SPENDDESCRIPTION_SIZE; - int64_t cost = std::max(memUsage, MIN_TX_COST); - int64_t lowFeePenaltyCost = cost; + uint64_t cost = std::max(memUsage, MIN_TX_WEIGHT); + uint64_t lowFeePenaltyCost = cost; if (fee < DEFAULT_FEE) { lowFeePenaltyCost += LOW_FEE_PENALTY; } - return WeightedTxInfo(tx.GetHash(), cost, lowFeePenaltyCost); -} - -void WeightedTxInfo::plusEquals(const WeightedTxInfo& other) -{ - cost += other.cost; - lowFeePenaltyCost += other.lowFeePenaltyCost; -} - -void WeightedTxInfo::minusEquals(const WeightedTxInfo& other) -{ - cost -= other.cost; - lowFeePenaltyCost -= other.lowFeePenaltyCost; + return WeightedTxInfo(tx.GetHash(), TxWeight(cost, lowFeePenaltyCost)); } diff --git a/src/mempoollimit.h b/src/mempoollimit.h index a3bbb8ea2d2..b02caf70734 100644 --- a/src/mempoollimit.h +++ b/src/mempoollimit.h @@ -5,77 +5,91 @@ #ifndef MEMPOOLLIMIT_H #define MEMPOOLLIMIT_H -#include +#include #include -#include "uint256.h" -#include "primitives/transaction.h" +#include #include "boost/optional.hpp" +#include "primitives/transaction.h" +#include "uint256.h" -const size_t DEFAULT_MEMPOOL_TOTAL_COST_LIMIT = 80000000; +const size_t DEFAULT_MEMPOOL_TOTAL_WEIGHT_LIMIT = 80000000; const int64_t DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES = 60; const size_t RECENTLY_EVICTED_SIZE = 10000; -const uint64_t MIN_TX_COST = 4000; +const uint64_t MIN_TX_WEIGHT = 4000; const uint64_t LOW_FEE_PENALTY = 16000; -struct WeightedTxInfo; - class RecentlyEvictedList { - const size_t maxSize; + const size_t capacity; + size_t txIdsAndTimesIndex = 0; + const int64_t timeToKeep; // Pairs of txid and time (seconds since epoch) boost::optional> txIdsAndTimes[RECENTLY_EVICTED_SIZE]; - size_t txIdsAndTimesIndex; std::set txIdSet; void pruneList(); + public: - RecentlyEvictedList(size_t maxSize_, int64_t timeToKeep_) : - maxSize(maxSize_), - timeToKeep(timeToKeep_), - txIdsAndTimesIndex(0) + RecentlyEvictedList(size_t capacity_, int64_t timeToKeep_) : capacity(capacity_), timeToKeep(timeToKeep_) { - assert(maxSize <= RECENTLY_EVICTED_SIZE); - std::fill_n(txIdsAndTimes, maxSize, boost::none); + assert(capacity <= RECENTLY_EVICTED_SIZE); + std::fill_n(txIdsAndTimes, capacity, boost::none); } RecentlyEvictedList(int64_t timeToKeep_) : RecentlyEvictedList(RECENTLY_EVICTED_SIZE, timeToKeep_) {} - void add(uint256 txId); + void add(const uint256& txId); bool contains(const uint256& txId); }; -class WeightedTransactionList -{ - const uint64_t maxTotalCost; - std::vector weightedTxInfos; -public: - WeightedTransactionList(int64_t maxTotalCost_) : maxTotalCost(maxTotalCost_) {} - - void clear(); +struct TxWeight { + uint64_t weight; + uint64_t lowFeePenaltyWeight; - int64_t getTotalCost() const; - int64_t getTotalLowFeePenaltyCost() const; + TxWeight(uint64_t weight_, uint64_t lowFeePenaltyWeight_) + : weight(weight_), lowFeePenaltyWeight(lowFeePenaltyWeight_) {} - void add(WeightedTxInfo weightedTxInfo); - boost::optional maybeDropRandom(bool rebuildList); + TxWeight add(const TxWeight& other) const; + TxWeight negate() const; }; struct WeightedTxInfo { uint256 txId; - uint64_t cost; - uint64_t lowFeePenaltyCost; + TxWeight txWeight; - WeightedTxInfo(uint256 txId_, uint64_t cost_, uint64_t lowFeePenaltyCost_) - : txId(txId_), cost(cost_), lowFeePenaltyCost(lowFeePenaltyCost_) {} + WeightedTxInfo(uint256 txId_, TxWeight txWeight_) : txId(txId_), txWeight(txWeight_) {} static WeightedTxInfo from(const CTransaction& tx, const CAmount& fee); +}; + + +class WeightedTxTree +{ + const uint64_t capacity; + size_t size = 0; - void plusEquals(const WeightedTxInfo& other); - void minusEquals(const WeightedTxInfo& other); + std::vector txIdAndWeights; + std::vector childWeights; + std::map txIdToIndexMap; + + TxWeight getWeightAt(size_t index) const; + void backPropagate(size_t fromIndex, const TxWeight& weightDelta); + size_t findByWeight(size_t fromIndex, uint64_t weightToFind) const; + +public: + WeightedTxTree(uint64_t capacity_) : capacity(capacity_) {} + + TxWeight getTotalWeight() const; + + void add(const WeightedTxInfo& weightedTxInfo); + void remove(const uint256& txId); + + boost::optional maybeDropRandom(); }; + #endif // MEMPOOLLIMIT_H diff --git a/src/txmempool.cpp b/src/txmempool.cpp index bd9d4b2d22d..be81c952ed9 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -69,7 +69,7 @@ CTxMemPool::~CTxMemPool() { delete minerPolicyEstimator; delete recentlyEvicted; - delete weightedTxList; + delete weightedTxTree; } void CTxMemPool::pruneSpent(const uint256 &hashTx, CCoins &coins) @@ -104,9 +104,8 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, // Used by main.cpp AcceptToMemoryPool(), which DOES do // all the appropriate checks. LOCK(cs); - if (weightedTxList) { - weightedTxList->add(WeightedTxInfo::from(entry.GetTx(), entry.GetFee())); - } + assert(weightedTxTree); + weightedTxTree->add(WeightedTxInfo::from(entry.GetTx(), entry.GetFee())); mapTx.insert(entry); const CTransaction& tx = mapTx.find(hash)->GetTx(); mapRecentlyAddedTx[tx.GetHash()] = &tx; @@ -293,12 +292,10 @@ void CTxMemPool::remove(const CTransaction &origTx, std::list& rem removeAddressIndex(hash); if (fSpentIndex) removeSpentIndex(hash); - } - if (weightedTxList) { - weightedTxList->clear(); - for (const CTxMemPoolEntry& e : mapTx) { - weightedTxList->add(WeightedTxInfo::from(e.GetTx(), e.GetFee())); - } + } + assert(weightedTxTree); + for (CTransaction tx : removed) { + weightedTxTree->remove(tx.GetHash()); } } } @@ -816,9 +813,9 @@ void CTxMemPool::setMempoolCostLimit(int64_t totalCostLimit, int64_t evictionMem LogPrint("mempool", "Setting mempool cost limit: (limit=%d, time=%d)\n", totalCostLimit, evictionMemorySeconds); // This method should not be called more than once assert(!recentlyEvicted); - assert(!weightedTxList); + assert(!weightedTxTree); recentlyEvicted = new RecentlyEvictedList(evictionMemorySeconds); - weightedTxList = new WeightedTransactionList(totalCostLimit); + weightedTxTree = new WeightedTxTree(totalCostLimit); } bool CTxMemPool::isRecentlyEvicted(const uint256& txId) { @@ -830,12 +827,12 @@ bool CTxMemPool::isRecentlyEvicted(const uint256& txId) { void CTxMemPool::ensureSizeLimit() { AssertLockHeld(cs); assert(recentlyEvicted); - assert(weightedTxList); - boost::optional maybeDrop; - std::list removed; - while ((maybeDrop = weightedTxList->maybeDropRandom(false)).is_initialized()) { - uint256 txId = maybeDrop.get().txId; + assert(weightedTxTree); + boost::optional maybeDropTxId; + while ((maybeDropTxId = weightedTxTree->maybeDropRandom()).is_initialized()) { + uint256 txId = maybeDropTxId.get(); recentlyEvicted->add(txId); + std::list removed; remove(mapTx.find(txId)->GetTx(), removed, true); } } diff --git a/src/txmempool.h b/src/txmempool.h index 14cff878ec5..c9d139859b7 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -141,7 +141,7 @@ class CTxMemPool std::map mapSproutNullifiers; std::map mapSaplingNullifiers; RecentlyEvictedList* recentlyEvicted = nullptr; - WeightedTransactionList* weightedTxList = nullptr; + WeightedTxTree* weightedTxTree = nullptr; void checkNullifiers(ShieldedType type) const; From 9e97833952af46029987b91a5cd69e2a159fd378 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 7 Oct 2019 14:23:06 -0600 Subject: [PATCH 321/395] Fix naming conventions --- src/gtest/test_mempoollimit.cpp | 8 ++++---- src/init.cpp | 2 +- src/main.cpp | 4 ++-- src/txmempool.cpp | 6 +++--- src/txmempool.h | 6 +++--- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/gtest/test_mempoollimit.cpp b/src/gtest/test_mempoollimit.cpp index af12d1b2fa4..844563f9b27 100644 --- a/src/gtest/test_mempoollimit.cpp +++ b/src/gtest/test_mempoollimit.cpp @@ -16,7 +16,7 @@ const uint256 TX_ID1 = ArithToUint256(1); const uint256 TX_ID2 = ArithToUint256(2); const uint256 TX_ID3 = ArithToUint256(3); -TEST(MempoolLimitTests, RecentlyEvictedList_AddWrapsAfterMaxSize) +TEST(MempoolLimitTests, RecentlyEvictedListAddWrapsAfterMaxSize) { RecentlyEvictedList recentlyEvicted(2, 100); SetMockTime(1); @@ -29,7 +29,7 @@ TEST(MempoolLimitTests, RecentlyEvictedList_AddWrapsAfterMaxSize) EXPECT_TRUE(recentlyEvicted.contains(TX_ID3)); } -TEST(MempoolLimitTests, RecentlyEvictedList_DoesNotContainAfterExpiry) +TEST(MempoolLimitTests, RecentlyEvictedListDoesNotContainAfterExpiry) { SetMockTime(1); // maxSize=3, timeToKeep=1 @@ -52,7 +52,7 @@ TEST(MempoolLimitTests, RecentlyEvictedList_DoesNotContainAfterExpiry) EXPECT_FALSE(recentlyEvicted.contains(TX_ID3)); } -TEST(MempoolLimitTests, WeightedTxTree_CheckSizeAfterDropping) +TEST(MempoolLimitTests, WeightedTxTreeCheckSizeAfterDropping) { std::set testedDropping; // Run the test until we have tested dropping each of the elements @@ -83,7 +83,7 @@ TEST(MempoolLimitTests, WeightedTxTree_CheckSizeAfterDropping) std::cerr << "All 3 scenarios tested in " << trialNum << " trials" << std::endl; } -TEST(MempoolLimitTests, WeightedTXInfo_FromTx) +TEST(MempoolLimitTests, WeightedTxInfoFromTx) { // The transaction creation is based on the test: // test_transaction_builder.cpp/TEST(TransactionBuilder, SetFee) diff --git a/src/init.cpp b/src/init.cpp index 888626f8f79..1447ac139ca 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -980,7 +980,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) int64_t mempoolTotalCostLimit = GetArg("-mempooltotalcostlimit", DEFAULT_MEMPOOL_TOTAL_WEIGHT_LIMIT); int64_t mempoolEvictionMemorySeconds = GetArg("-mempoolevictionmemoryminutes", DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES) * 60; - mempool.setMempoolCostLimit(mempoolTotalCostLimit, mempoolEvictionMemorySeconds); + mempool.SetMempoolCostLimit(mempoolTotalCostLimit, mempoolEvictionMemorySeconds); fCheckBlockIndex = GetBoolArg("-checkblockindex", chainparams.DefaultConsistencyChecks()); fCheckpointsEnabled = GetBoolArg("-checkpoints", true); diff --git a/src/main.cpp b/src/main.cpp index 94f15c27e05..8438fc14d58 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1395,7 +1395,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } } - if (pool.isRecentlyEvicted(tx.GetHash())) { + if (pool.IsRecentlyEvicted(tx.GetHash())) { return error("AcceptToMemoryPool: Transaction recently evicted"); } @@ -1637,7 +1637,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa pool.addSpentIndex(entry, view); } - pool.ensureSizeLimit(); + pool.EnsureSizeLimit(); } } diff --git a/src/txmempool.cpp b/src/txmempool.cpp index be81c952ed9..2ddf19ef295 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -808,7 +808,7 @@ size_t CTxMemPool::DynamicMemoryUsage() const { return memusage::MallocUsage(sizeof(CTxMemPoolEntry) + 6 * sizeof(void*)) * mapTx.size() + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + cachedInnerUsage; } -void CTxMemPool::setMempoolCostLimit(int64_t totalCostLimit, int64_t evictionMemorySeconds) { +void CTxMemPool::SetMempoolCostLimit(int64_t totalCostLimit, int64_t evictionMemorySeconds) { LOCK(cs); LogPrint("mempool", "Setting mempool cost limit: (limit=%d, time=%d)\n", totalCostLimit, evictionMemorySeconds); // This method should not be called more than once @@ -818,13 +818,13 @@ void CTxMemPool::setMempoolCostLimit(int64_t totalCostLimit, int64_t evictionMem weightedTxTree = new WeightedTxTree(totalCostLimit); } -bool CTxMemPool::isRecentlyEvicted(const uint256& txId) { +bool CTxMemPool::IsRecentlyEvicted(const uint256& txId) { LOCK(cs); assert(recentlyEvicted); return recentlyEvicted->contains(txId); } -void CTxMemPool::ensureSizeLimit() { +void CTxMemPool::EnsureSizeLimit() { AssertLockHeld(cs); assert(recentlyEvicted); assert(weightedTxTree); diff --git a/src/txmempool.h b/src/txmempool.h index c9d139859b7..76aecaf9440 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -264,11 +264,11 @@ class CTxMemPool return nCheckFrequency; } - void setMempoolCostLimit(int64_t totalCostLimit, int64_t evictionMemorySeconds); + void SetMempoolCostLimit(int64_t totalCostLimit, int64_t evictionMemorySeconds); // Returns true if a transaction has been recently evicted - bool isRecentlyEvicted(const uint256& txId); + bool IsRecentlyEvicted(const uint256& txId); // Returns a txid if a transaction is evicted from the mempool - void ensureSizeLimit(); + void EnsureSizeLimit(); }; /** From a515b0057a360f0d161d75289be45b744c90fecc Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 7 Oct 2019 14:43:44 -0600 Subject: [PATCH 322/395] No need to activate Overwinter/Sapling in rpc test --- qa/rpc-tests/mempool_limit.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/qa/rpc-tests/mempool_limit.py b/qa/rpc-tests/mempool_limit.py index 4e8e14ba975..6fe8838eab4 100755 --- a/qa/rpc-tests/mempool_limit.py +++ b/qa/rpc-tests/mempool_limit.py @@ -24,17 +24,12 @@ def setup_chain(self): initialize_chain_clean(self.options.tmpdir, 4) def setup_nodes(self): - args = [ - '-nuparams=5ba81b19:1', # Overwinter - '-nuparams=76b809bb:1', # Sapling - "-debug=mempool", - ] extra_args = [ - args + ['-mempooltotalcostlimit=8000'], # 2 transactions at min cost - args + ['-mempooltotalcostlimit=8000'], # 2 transactions at min cost - args + ['-mempooltotalcostlimit=8000'], # 2 transactions at min cost + ["-debug=mempool", '-mempooltotalcostlimit=8000'], # 2 transactions at min cost + ["-debug=mempool", '-mempooltotalcostlimit=8000'], # 2 transactions at min cost + ["-debug=mempool", '-mempooltotalcostlimit=8000'], # 2 transactions at min cost # Let node 3 hold one more transaction - args + ['-mempooltotalcostlimit=12000'], # 3 transactions at min cost + ["-debug=mempool", '-mempooltotalcostlimit=12000'], # 3 transactions at min cost ] return start_nodes(4, self.options.tmpdir, extra_args) From 30be75064485951d1d44b934fd04b66764cecf83 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 9 Oct 2019 11:59:14 -0600 Subject: [PATCH 323/395] Fix recently evicted list size --- src/mempoollimit.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mempoollimit.h b/src/mempoollimit.h index b02caf70734..af7b93f1f72 100644 --- a/src/mempoollimit.h +++ b/src/mempoollimit.h @@ -16,7 +16,7 @@ const size_t DEFAULT_MEMPOOL_TOTAL_WEIGHT_LIMIT = 80000000; const int64_t DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES = 60; -const size_t RECENTLY_EVICTED_SIZE = 10000; +const size_t RECENTLY_EVICTED_SIZE = 40000; const uint64_t MIN_TX_WEIGHT = 4000; const uint64_t LOW_FEE_PENALTY = 16000; From 2365ba7b97a00d4c14fb0d1df1298b50ad4c9466 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 9 Oct 2019 12:06:03 -0600 Subject: [PATCH 324/395] Put size increment and decrement on their own lines --- src/mempoollimit.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/mempoollimit.cpp b/src/mempoollimit.cpp index 4e02f8987b7..08430f1b56d 100644 --- a/src/mempoollimit.cpp +++ b/src/mempoollimit.cpp @@ -86,7 +86,8 @@ void WeightedTxTree::add(const WeightedTxInfo& weightedTxInfo) txIdAndWeights.push_back(weightedTxInfo); childWeights.push_back(ZERO_WEIGHT); txIdToIndexMap[weightedTxInfo.txId] = size; - backPropagate(size++, weightedTxInfo.txWeight); + backPropagate(size, weightedTxInfo.txWeight); + size += 1; } void WeightedTxTree::remove(const uint256& txId) @@ -97,7 +98,11 @@ void WeightedTxTree::remove(const uint256& txId) size_t removeIndex = txIdToIndexMap[txId]; - TxWeight lastChildWeight = txIdAndWeights[--size].txWeight; + // We reduce the size at the start of this method to avoid saying size - 1 + // when refering to the last element of the array below + size -= 1; + + TxWeight lastChildWeight = txIdAndWeights[size].txWeight; backPropagate(size, lastChildWeight.negate()); if (removeIndex < size) { From 69a5ffe5d4ff52c0d268e31e464859d341eec34d Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 9 Oct 2019 12:13:01 -0600 Subject: [PATCH 325/395] Prevent adding duplicate transactions --- src/mempoollimit.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/mempoollimit.cpp b/src/mempoollimit.cpp index 08430f1b56d..bf3373ff7a3 100644 --- a/src/mempoollimit.cpp +++ b/src/mempoollimit.cpp @@ -83,6 +83,10 @@ TxWeight WeightedTxTree::getTotalWeight() const void WeightedTxTree::add(const WeightedTxInfo& weightedTxInfo) { + if (txIdToIndexMap.count(weightedTxInfo.txId) > 0) { + // This should not happen, but should be prevented nonetheless + return; + } txIdAndWeights.push_back(weightedTxInfo); childWeights.push_back(ZERO_WEIGHT); txIdToIndexMap[weightedTxInfo.txId] = size; @@ -93,6 +97,7 @@ void WeightedTxTree::add(const WeightedTxInfo& weightedTxInfo) void WeightedTxTree::remove(const uint256& txId) { if (txIdToIndexMap.find(txId) == txIdToIndexMap.end()) { + // Remove may be called multiple times for a given tx, so this is necessary return; } From 61b7dfb6f0ace0c436f5ad4bad2fd490c5f0fca1 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 9 Oct 2019 12:25:56 -0600 Subject: [PATCH 326/395] Move duplicate macro to reusable location --- src/mempoollimit.cpp | 5 ----- src/primitives/transaction.h | 4 ++++ src/wallet/rpcwallet.cpp | 4 ---- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/mempoollimit.cpp b/src/mempoollimit.cpp index bf3373ff7a3..4c42d604401 100644 --- a/src/mempoollimit.cpp +++ b/src/mempoollimit.cpp @@ -149,11 +149,6 @@ TxWeight TxWeight::negate() const } -// These are also defined in rpcwallet.cpp -#define JOINSPLIT_SIZE GetSerializeSize(JSDescription(), SER_NETWORK, PROTOCOL_VERSION) -#define OUTPUTDESCRIPTION_SIZE GetSerializeSize(OutputDescription(), SER_NETWORK, PROTOCOL_VERSION) -#define SPENDDESCRIPTION_SIZE GetSerializeSize(SpendDescription(), SER_NETWORK, PROTOCOL_VERSION) - WeightedTxInfo WeightedTxInfo::from(const CTransaction& tx, const CAmount& fee) { size_t memUsage = RecursiveDynamicUsage(tx); diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 3e8e2e7fa84..5e5abcb802e 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -23,6 +23,10 @@ #include "zcash/JoinSplit.hpp" #include "zcash/Proof.hpp" +#define JOINSPLIT_SIZE GetSerializeSize(JSDescription(), SER_NETWORK, PROTOCOL_VERSION) +#define OUTPUTDESCRIPTION_SIZE GetSerializeSize(OutputDescription(), SER_NETWORK, PROTOCOL_VERSION) +#define SPENDDESCRIPTION_SIZE GetSerializeSize(SpendDescription(), SER_NETWORK, PROTOCOL_VERSION) + // Overwinter transaction version static const int32_t OVERWINTER_TX_VERSION = 3; static_assert(OVERWINTER_TX_VERSION >= OVERWINTER_MIN_TX_VERSION, diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 3852b8e0288..01efa16407c 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4257,10 +4257,6 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp) #define MERGE_TO_ADDRESS_DEFAULT_SPROUT_LIMIT 20 #define MERGE_TO_ADDRESS_DEFAULT_SAPLING_LIMIT 200 -#define JOINSPLIT_SIZE GetSerializeSize(JSDescription(), SER_NETWORK, PROTOCOL_VERSION) -#define OUTPUTDESCRIPTION_SIZE GetSerializeSize(OutputDescription(), SER_NETWORK, PROTOCOL_VERSION) -#define SPENDDESCRIPTION_SIZE GetSerializeSize(SpendDescription(), SER_NETWORK, PROTOCOL_VERSION) - UniValue z_mergetoaddress(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) From b680185f48cae4d6e96973fbfe782945db465428 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 9 Oct 2019 12:50:00 -0600 Subject: [PATCH 327/395] mempool_limit rpc test cleanup --- qa/rpc-tests/mempool_limit.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/qa/rpc-tests/mempool_limit.py b/qa/rpc-tests/mempool_limit.py index 6fe8838eab4..9ce8487f53b 100755 --- a/qa/rpc-tests/mempool_limit.py +++ b/qa/rpc-tests/mempool_limit.py @@ -9,6 +9,7 @@ from test_framework.util import ( assert_equal, get_coinbase_address, + fail, initialize_chain_clean, start_nodes, wait_and_assert_operationid_status, @@ -33,6 +34,15 @@ def setup_nodes(self): ] return start_nodes(4, self.options.tmpdir, extra_args) + def check_mempool_sizes(self, expected_size, check_node3=True): + for i in range(4 if check_node3 else 3): + mempool = self.nodes[i].getrawmempool() + if len(mempool) != expected_size: + # print all nodes mempools before failing + for i in range(4): + print("Mempool for node {}: {}".format(i, mempool)) + fail("Fail: Mempool for node {}: size={}, expected={}".format(i, len(mempool), expected_size)) + def run_test(self): print("Mining blocks...") self.sync_all() @@ -59,10 +69,7 @@ def run_test(self): wait_and_assert_operationid_status(self.nodes[2], opid2) self.sync_all() - for i in range(0, 4): - mempool = self.nodes[i].getrawmempool() - print("Mempool for node {}: {}".format(i, mempool)) - assert_equal(2, len(mempool), "node {}".format(i)) + self.check_mempool_sizes(2) print("Adding one more transaction...") opid3 = self.nodes[3].z_sendmany(get_coinbase_address(self.nodes[3]), [{"address": zaddr3, "amount": Decimal('9.999')}]) @@ -70,20 +77,17 @@ def run_test(self): # The mempools are no longer guaranteed to be in a consistent state, so we cannot sync sleep(5) mempool_node3 = self.nodes[3].getrawmempool() - print("Mempool for node 3: {}".format(mempool_node3)) assert_equal(3, len(mempool_node3), "node {}".format(3)) print("Checking mempool size...") # Due to the size limit, there should only be 2 transactions in the mempool - for i in range(0, 3): - mempool = self.nodes[i].getrawmempool() - print("Mempool for node {}: {}".format(i, mempool)) - assert_equal(2, len(mempool), "node {}".format(i)) + self.check_mempool_sizes(2, False) self.nodes[3].generate(1) self.sync_all() # The mempool sizes should be reset + self.check_mempool_sizes(0) print("Checking mempool size reset after block mined...") zaddr4 = self.nodes[0].z_getnewaddress('sapling') opid4 = self.nodes[0].z_sendmany(zaddr1, [{"address": zaddr4, "amount": Decimal('9.998')}]) @@ -92,11 +96,9 @@ def run_test(self): wait_and_assert_operationid_status(self.nodes[0], opid5) self.sync_all() - for i in range(0, 4): - mempool = self.nodes[i].getrawmempool() - print("Mempool for node {}: {}".format(i, mempool)) - assert_equal(2, len(mempool), "node {}".format(i)) + self.check_mempool_sizes(2) + # Make sure the transactions are mined without error self.nodes[3].generate(1) self.sync_all() From bf044cc0c3befd07d2f8a627c52be914e952c642 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 9 Oct 2019 13:14:35 -0600 Subject: [PATCH 328/395] Represent tx costs as signed integers --- src/mempoollimit.cpp | 8 ++++---- src/mempoollimit.h | 14 ++++++++------ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/mempoollimit.cpp b/src/mempoollimit.cpp index 4c42d604401..594154d3146 100644 --- a/src/mempoollimit.cpp +++ b/src/mempoollimit.cpp @@ -59,7 +59,7 @@ void WeightedTxTree::backPropagate(size_t fromIndex, const TxWeight& weightDelta } } -size_t WeightedTxTree::findByWeight(size_t fromIndex, uint64_t weightToFind) const +size_t WeightedTxTree::findByWeight(size_t fromIndex, int64_t weightToFind) const { int leftWeight = getWeightAt(fromIndex * 2 + 1).lowFeePenaltyWeight; int rightWeight = getWeightAt(fromIndex).lowFeePenaltyWeight - getWeightAt(fromIndex * 2 + 2).lowFeePenaltyWeight; @@ -124,7 +124,7 @@ void WeightedTxTree::remove(const uint256& txId) boost::optional WeightedTxTree::maybeDropRandom() { - uint64_t totalPenaltyWeight = getTotalWeight().lowFeePenaltyWeight; + int64_t totalPenaltyWeight = getTotalWeight().lowFeePenaltyWeight; if (totalPenaltyWeight <= capacity) { return boost::none; } @@ -155,8 +155,8 @@ WeightedTxInfo WeightedTxInfo::from(const CTransaction& tx, const CAmount& fee) memUsage += tx.vJoinSplit.size() * JOINSPLIT_SIZE; memUsage += tx.vShieldedOutput.size() * OUTPUTDESCRIPTION_SIZE; memUsage += tx.vShieldedSpend.size() * SPENDDESCRIPTION_SIZE; - uint64_t cost = std::max(memUsage, MIN_TX_WEIGHT); - uint64_t lowFeePenaltyCost = cost; + int64_t cost = std::max(memUsage, MIN_TX_WEIGHT); + int64_t lowFeePenaltyCost = cost; if (fee < DEFAULT_FEE) { lowFeePenaltyCost += LOW_FEE_PENALTY; } diff --git a/src/mempoollimit.h b/src/mempoollimit.h index af7b93f1f72..985d1db55a7 100644 --- a/src/mempoollimit.h +++ b/src/mempoollimit.h @@ -46,10 +46,10 @@ class RecentlyEvictedList struct TxWeight { - uint64_t weight; - uint64_t lowFeePenaltyWeight; + int64_t weight; + int64_t lowFeePenaltyWeight; - TxWeight(uint64_t weight_, uint64_t lowFeePenaltyWeight_) + TxWeight(int64_t weight_, int64_t lowFeePenaltyWeight_) : weight(weight_), lowFeePenaltyWeight(lowFeePenaltyWeight_) {} TxWeight add(const TxWeight& other) const; @@ -69,7 +69,7 @@ struct WeightedTxInfo { class WeightedTxTree { - const uint64_t capacity; + const int64_t capacity; size_t size = 0; std::vector txIdAndWeights; @@ -78,10 +78,12 @@ class WeightedTxTree TxWeight getWeightAt(size_t index) const; void backPropagate(size_t fromIndex, const TxWeight& weightDelta); - size_t findByWeight(size_t fromIndex, uint64_t weightToFind) const; + size_t findByWeight(size_t fromIndex, int64_t weightToFind) const; public: - WeightedTxTree(uint64_t capacity_) : capacity(capacity_) {} + WeightedTxTree(int64_t capacity_) : capacity(capacity_) { + assert(capacity >= 0); + } TxWeight getTotalWeight() const; From 1556ec672255895e2d736ab5efa0f8da469182bf Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 9 Oct 2019 13:19:09 -0600 Subject: [PATCH 329/395] Fix comments --- src/gtest/test_mempoollimit.cpp | 2 +- src/txmempool.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gtest/test_mempoollimit.cpp b/src/gtest/test_mempoollimit.cpp index 844563f9b27..b211e69922c 100644 --- a/src/gtest/test_mempoollimit.cpp +++ b/src/gtest/test_mempoollimit.cpp @@ -43,7 +43,7 @@ TEST(MempoolLimitTests, RecentlyEvictedListDoesNotContainAfterExpiry) EXPECT_TRUE(recentlyEvicted.contains(TX_ID2)); EXPECT_TRUE(recentlyEvicted.contains(TX_ID3)); SetMockTime(3); - // After 2 second it is gone + // After 2 seconds it is gone EXPECT_FALSE(recentlyEvicted.contains(TX_ID1)); EXPECT_TRUE(recentlyEvicted.contains(TX_ID2)); EXPECT_TRUE(recentlyEvicted.contains(TX_ID3)); diff --git a/src/txmempool.h b/src/txmempool.h index 76aecaf9440..5672a82cfeb 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -267,7 +267,7 @@ class CTxMemPool void SetMempoolCostLimit(int64_t totalCostLimit, int64_t evictionMemorySeconds); // Returns true if a transaction has been recently evicted bool IsRecentlyEvicted(const uint256& txId); - // Returns a txid if a transaction is evicted from the mempool + // If the mempool size limit is exceeded, this evicts transactions from the mempool until it is below capacity void EnsureSizeLimit(); }; From 2d9becbeb891c18f31f6089709691ac458184da7 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 9 Oct 2019 13:36:20 -0600 Subject: [PATCH 330/395] Rename variables for consistency --- src/gtest/test_mempoollimit.cpp | 32 ++++++++++++++++---------------- src/init.cpp | 4 ++-- src/mempoollimit.cpp | 28 ++++++++++++++-------------- src/mempoollimit.h | 12 ++++++------ 4 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/gtest/test_mempoollimit.cpp b/src/gtest/test_mempoollimit.cpp index b211e69922c..856834a4538 100644 --- a/src/gtest/test_mempoollimit.cpp +++ b/src/gtest/test_mempoollimit.cpp @@ -59,26 +59,26 @@ TEST(MempoolLimitTests, WeightedTxTreeCheckSizeAfterDropping) int trialNum = 0; while (testedDropping.size() < 3) { WeightedTxTree tree(MIN_TX_WEIGHT * 2); - EXPECT_EQ(0, tree.getTotalWeight().weight); - EXPECT_EQ(0, tree.getTotalWeight().lowFeePenaltyWeight); + EXPECT_EQ(0, tree.getTotalWeight().cost); + EXPECT_EQ(0, tree.getTotalWeight().evictionWeight); tree.add(WeightedTxInfo(TX_ID1, TxWeight(MIN_TX_WEIGHT, MIN_TX_WEIGHT))); - EXPECT_EQ(4000, tree.getTotalWeight().weight); - EXPECT_EQ(4000, tree.getTotalWeight().lowFeePenaltyWeight); + EXPECT_EQ(4000, tree.getTotalWeight().cost); + EXPECT_EQ(4000, tree.getTotalWeight().evictionWeight); tree.add(WeightedTxInfo(TX_ID2, TxWeight(MIN_TX_WEIGHT, MIN_TX_WEIGHT))); - EXPECT_EQ(8000, tree.getTotalWeight().weight); - EXPECT_EQ(8000, tree.getTotalWeight().lowFeePenaltyWeight); + EXPECT_EQ(8000, tree.getTotalWeight().cost); + EXPECT_EQ(8000, tree.getTotalWeight().evictionWeight); EXPECT_FALSE(tree.maybeDropRandom().is_initialized()); tree.add(WeightedTxInfo(TX_ID3, TxWeight(MIN_TX_WEIGHT, MIN_TX_WEIGHT + LOW_FEE_PENALTY))); - EXPECT_EQ(12000, tree.getTotalWeight().weight); - EXPECT_EQ(12000 + LOW_FEE_PENALTY, tree.getTotalWeight().lowFeePenaltyWeight); + EXPECT_EQ(12000, tree.getTotalWeight().cost); + EXPECT_EQ(12000 + LOW_FEE_PENALTY, tree.getTotalWeight().evictionWeight); boost::optional drop = tree.maybeDropRandom(); ASSERT_TRUE(drop.is_initialized()); uint256 txid = drop.get(); std::cerr << "Trial " << trialNum++ << ": dropped " << txid.ToString() << std::endl; testedDropping.insert(txid); // Do not continue to test if a particular trial fails - ASSERT_EQ(8000, tree.getTotalWeight().weight); - ASSERT_EQ(txid == TX_ID3 ? 8000 : 8000 + LOW_FEE_PENALTY, tree.getTotalWeight().lowFeePenaltyWeight); + ASSERT_EQ(8000, tree.getTotalWeight().cost); + ASSERT_EQ(txid == TX_ID3 ? 8000 : 8000 + LOW_FEE_PENALTY, tree.getTotalWeight().evictionWeight); } std::cerr << "All 3 scenarios tested in " << trialNum << " trials" << std::endl; } @@ -99,8 +99,8 @@ TEST(MempoolLimitTests, WeightedTxInfoFromTx) builder.AddSaplingOutput(sk.full_viewing_key().ovk, sk.default_address(), 25000, {}); WeightedTxInfo info = WeightedTxInfo::from(builder.Build().GetTxOrThrow(), 10000); - EXPECT_EQ(MIN_TX_WEIGHT, info.txWeight.weight); - EXPECT_EQ(MIN_TX_WEIGHT, info.txWeight.lowFeePenaltyWeight); + EXPECT_EQ(MIN_TX_WEIGHT, info.txWeight.cost); + EXPECT_EQ(MIN_TX_WEIGHT, info.txWeight.evictionWeight); } // Lower than standard fee @@ -111,8 +111,8 @@ TEST(MempoolLimitTests, WeightedTxInfoFromTx) builder.SetFee(9999); WeightedTxInfo info = WeightedTxInfo::from(builder.Build().GetTxOrThrow(), 9999); - EXPECT_EQ(MIN_TX_WEIGHT, info.txWeight.weight); - EXPECT_EQ(MIN_TX_WEIGHT + LOW_FEE_PENALTY, info.txWeight.lowFeePenaltyWeight); + EXPECT_EQ(MIN_TX_WEIGHT, info.txWeight.cost); + EXPECT_EQ(MIN_TX_WEIGHT + LOW_FEE_PENALTY, info.txWeight.evictionWeight); } // Larger Tx @@ -129,8 +129,8 @@ TEST(MempoolLimitTests, WeightedTxInfoFromTx) std::cerr << result.GetError() << std::endl; } WeightedTxInfo info = WeightedTxInfo::from(result.GetTxOrThrow(), 10000); - EXPECT_EQ(5124, info.txWeight.weight); - EXPECT_EQ(5124, info.txWeight.lowFeePenaltyWeight); + EXPECT_EQ(5124, info.txWeight.cost); + EXPECT_EQ(5124, info.txWeight.evictionWeight); } RegtestDeactivateSapling(); diff --git a/src/init.cpp b/src/init.cpp index 1447ac139ca..f8e9ed8712d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -385,7 +385,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-maxreceivebuffer=", strprintf(_("Maximum per-connection receive buffer, *1000 bytes (default: %u)"), 5000)); strUsage += HelpMessageOpt("-maxsendbuffer=", strprintf(_("Maximum per-connection send buffer, *1000 bytes (default: %u)"), 1000)); strUsage += HelpMessageOpt("-mempoolevictionmemoryminutes=", strprintf(_("The number of minutes before allowing rejected transactions to re-enter the mempool. (default: %u)"), DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES)); - strUsage += HelpMessageOpt("-mempooltotalcostlimit=",strprintf(_("An upper bound on the maximum size in bytes of all transactions in the mempool. (default: %s)"), DEFAULT_MEMPOOL_TOTAL_WEIGHT_LIMIT)); + strUsage += HelpMessageOpt("-mempooltotalcostlimit=",strprintf(_("An upper bound on the maximum size in bytes of all transactions in the mempool. (default: %s)"), DEFAULT_MEMPOOL_TOTAL_COST_LIMIT)); strUsage += HelpMessageOpt("-onion=", strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy")); strUsage += HelpMessageOpt("-onlynet=", _("Only connect to nodes in network (ipv4, ipv6 or onion)")); strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), 1)); @@ -978,7 +978,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) mempool.setSanityCheck(1.0 / ratio); } - int64_t mempoolTotalCostLimit = GetArg("-mempooltotalcostlimit", DEFAULT_MEMPOOL_TOTAL_WEIGHT_LIMIT); + int64_t mempoolTotalCostLimit = GetArg("-mempooltotalcostlimit", DEFAULT_MEMPOOL_TOTAL_COST_LIMIT); int64_t mempoolEvictionMemorySeconds = GetArg("-mempoolevictionmemoryminutes", DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES) * 60; mempool.SetMempoolCostLimit(mempoolTotalCostLimit, mempoolEvictionMemorySeconds); diff --git a/src/mempoollimit.cpp b/src/mempoollimit.cpp index 594154d3146..d20e805a6e3 100644 --- a/src/mempoollimit.cpp +++ b/src/mempoollimit.cpp @@ -59,20 +59,20 @@ void WeightedTxTree::backPropagate(size_t fromIndex, const TxWeight& weightDelta } } -size_t WeightedTxTree::findByWeight(size_t fromIndex, int64_t weightToFind) const +size_t WeightedTxTree::findByEvictionWeight(size_t fromIndex, int64_t weightToFind) const { - int leftWeight = getWeightAt(fromIndex * 2 + 1).lowFeePenaltyWeight; - int rightWeight = getWeightAt(fromIndex).lowFeePenaltyWeight - getWeightAt(fromIndex * 2 + 2).lowFeePenaltyWeight; + int leftWeight = getWeightAt(fromIndex * 2 + 1).evictionWeight; + int rightWeight = getWeightAt(fromIndex).evictionWeight - getWeightAt(fromIndex * 2 + 2).evictionWeight; // On Left if (weightToFind < leftWeight) { - return findByWeight(fromIndex * 2 + 1, weightToFind); + return findByEvictionWeight(fromIndex * 2 + 1, weightToFind); } // Found if (weightToFind < rightWeight) { return fromIndex; } // On Right - return findByWeight(fromIndex * 2 + 2, weightToFind - rightWeight); + return findByEvictionWeight(fromIndex * 2 + 2, weightToFind - rightWeight); } TxWeight WeightedTxTree::getTotalWeight() const @@ -124,15 +124,15 @@ void WeightedTxTree::remove(const uint256& txId) boost::optional WeightedTxTree::maybeDropRandom() { - int64_t totalPenaltyWeight = getTotalWeight().lowFeePenaltyWeight; + int64_t totalPenaltyWeight = getTotalWeight().evictionWeight; if (totalPenaltyWeight <= capacity) { return boost::none; } LogPrint("mempool", "Mempool cost limit exceeded (cost=%d, limit=%d)\n", totalPenaltyWeight, capacity); int randomWeight = GetRand(totalPenaltyWeight); - WeightedTxInfo drop = txIdAndWeights[findByWeight(0, randomWeight)]; - LogPrint("mempool", "Evicting transaction (txid=%s, cost=%d, penaltyCost=%d)\n", - drop.txId.ToString(), drop.txWeight.weight, drop.txWeight.lowFeePenaltyWeight); + WeightedTxInfo drop = txIdAndWeights[findByEvictionWeight(0, randomWeight)]; + LogPrint("mempool", "Evicting transaction (txid=%s, cost=%d, evictionWeight=%d)\n", + drop.txId.ToString(), drop.txWeight.cost, drop.txWeight.evictionWeight); remove(drop.txId); return drop.txId; } @@ -140,12 +140,12 @@ boost::optional WeightedTxTree::maybeDropRandom() TxWeight TxWeight::add(const TxWeight& other) const { - return TxWeight(weight + other.weight, lowFeePenaltyWeight + other.lowFeePenaltyWeight); + return TxWeight(cost + other.cost, evictionWeight + other.evictionWeight); } TxWeight TxWeight::negate() const { - return TxWeight(-weight, -lowFeePenaltyWeight); + return TxWeight(-cost, -evictionWeight); } @@ -156,9 +156,9 @@ WeightedTxInfo WeightedTxInfo::from(const CTransaction& tx, const CAmount& fee) memUsage += tx.vShieldedOutput.size() * OUTPUTDESCRIPTION_SIZE; memUsage += tx.vShieldedSpend.size() * SPENDDESCRIPTION_SIZE; int64_t cost = std::max(memUsage, MIN_TX_WEIGHT); - int64_t lowFeePenaltyCost = cost; + int64_t evictionWeight = cost; if (fee < DEFAULT_FEE) { - lowFeePenaltyCost += LOW_FEE_PENALTY; + evictionWeight += LOW_FEE_PENALTY; } - return WeightedTxInfo(tx.GetHash(), TxWeight(cost, lowFeePenaltyCost)); + return WeightedTxInfo(tx.GetHash(), TxWeight(cost, evictionWeight)); } diff --git a/src/mempoollimit.h b/src/mempoollimit.h index 985d1db55a7..7000b90b1fa 100644 --- a/src/mempoollimit.h +++ b/src/mempoollimit.h @@ -13,7 +13,7 @@ #include "primitives/transaction.h" #include "uint256.h" -const size_t DEFAULT_MEMPOOL_TOTAL_WEIGHT_LIMIT = 80000000; +const size_t DEFAULT_MEMPOOL_TOTAL_COST_LIMIT = 80000000; const int64_t DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES = 60; const size_t RECENTLY_EVICTED_SIZE = 40000; @@ -46,11 +46,11 @@ class RecentlyEvictedList struct TxWeight { - int64_t weight; - int64_t lowFeePenaltyWeight; + int64_t cost; + int64_t evictionWeight; - TxWeight(int64_t weight_, int64_t lowFeePenaltyWeight_) - : weight(weight_), lowFeePenaltyWeight(lowFeePenaltyWeight_) {} + TxWeight(int64_t cost_, int64_t evictionWeight_) + : cost(cost_), evictionWeight(evictionWeight_) {} TxWeight add(const TxWeight& other) const; TxWeight negate() const; @@ -78,7 +78,7 @@ class WeightedTxTree TxWeight getWeightAt(size_t index) const; void backPropagate(size_t fromIndex, const TxWeight& weightDelta); - size_t findByWeight(size_t fromIndex, int64_t weightToFind) const; + size_t findByEvictionWeight(size_t fromIndex, int64_t weightToFind) const; public: WeightedTxTree(int64_t capacity_) : capacity(capacity_) { From 9b2a04bd957a24bb64e7e8430520b6da7761bb20 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 9 Oct 2019 13:42:46 -0600 Subject: [PATCH 331/395] Use tx cost rather than evictionWeight when checking mempool capacity --- src/mempoollimit.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mempoollimit.cpp b/src/mempoollimit.cpp index d20e805a6e3..c04a90e41d0 100644 --- a/src/mempoollimit.cpp +++ b/src/mempoollimit.cpp @@ -124,12 +124,12 @@ void WeightedTxTree::remove(const uint256& txId) boost::optional WeightedTxTree::maybeDropRandom() { - int64_t totalPenaltyWeight = getTotalWeight().evictionWeight; - if (totalPenaltyWeight <= capacity) { + TxWeight totalTxWeight = getTotalWeight(); + if (totalTxWeight.cost <= capacity) { return boost::none; } - LogPrint("mempool", "Mempool cost limit exceeded (cost=%d, limit=%d)\n", totalPenaltyWeight, capacity); - int randomWeight = GetRand(totalPenaltyWeight); + LogPrint("mempool", "Mempool cost limit exceeded (cost=%d, limit=%d)\n", totalTxWeight.cost, capacity); + int randomWeight = GetRand(totalTxWeight.evictionWeight); WeightedTxInfo drop = txIdAndWeights[findByEvictionWeight(0, randomWeight)]; LogPrint("mempool", "Evicting transaction (txid=%s, cost=%d, evictionWeight=%d)\n", drop.txId.ToString(), drop.txWeight.cost, drop.txWeight.evictionWeight); From ca883c851762e6796f415c4b81d20a4625a317c1 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 9 Oct 2019 14:43:35 -0600 Subject: [PATCH 332/395] Log rather than return error if a transaction is recently evicted --- src/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 8438fc14d58..3ae1c0e5906 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1396,7 +1396,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } if (pool.IsRecentlyEvicted(tx.GetHash())) { - return error("AcceptToMemoryPool: Transaction recently evicted"); + LogPrint("mempool", "Dropping txid %s : recently evicted", tx.GetHash().ToString()); + return false; } auto verifier = libzcash::ProofVerifier::Strict(); From b4c4134956fd45653c4d0b17f36b4e4937aa1225 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 9 Oct 2019 15:12:32 -0600 Subject: [PATCH 333/395] Represent recently evicted list as a deque --- src/mempoollimit.cpp | 18 +++++++----------- src/mempoollimit.h | 4 +--- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/mempoollimit.cpp b/src/mempoollimit.cpp index c04a90e41d0..f14c60bf5d7 100644 --- a/src/mempoollimit.cpp +++ b/src/mempoollimit.cpp @@ -18,25 +18,21 @@ void RecentlyEvictedList::pruneList() return; } int64_t now = GetAdjustedTime(); - size_t startIndex = (txIdsAndTimesIndex + capacity - txIdSet.size()) % capacity; - boost::optional> txIdAndTime; - while ((txIdAndTime = txIdsAndTimes[startIndex]).is_initialized() && (now - txIdAndTime.get().second) > timeToKeep) { - txIdsAndTimes[startIndex] = boost::none; - txIdSet.erase(txIdAndTime.get().first); - startIndex = (startIndex + 1) % capacity; + while (txIdsAndTimes.size() > 0 && now - txIdsAndTimes.front().second > timeToKeep) { + txIdSet.erase(txIdsAndTimes.front().first); + txIdsAndTimes.pop_front(); } } void RecentlyEvictedList::add(const uint256& txId) { pruneList(); - if (txIdsAndTimes[txIdsAndTimesIndex].is_initialized()) { - auto txIdAndTime = txIdsAndTimes[txIdsAndTimesIndex]; - txIdSet.erase(txIdAndTime.get().first); + if (txIdsAndTimes.size() == capacity) { + txIdSet.erase(txIdsAndTimes.front().first); + txIdsAndTimes.pop_front(); } - txIdsAndTimes[txIdsAndTimesIndex] = std::make_pair(txId, GetAdjustedTime()); + txIdsAndTimes.push_back(std::make_pair(txId, GetAdjustedTime())); txIdSet.insert(txId); - txIdsAndTimesIndex = (txIdsAndTimesIndex + 1) % capacity; } bool RecentlyEvictedList::contains(const uint256& txId) diff --git a/src/mempoollimit.h b/src/mempoollimit.h index 7000b90b1fa..63b24eaa15a 100644 --- a/src/mempoollimit.h +++ b/src/mempoollimit.h @@ -23,11 +23,10 @@ const uint64_t LOW_FEE_PENALTY = 16000; class RecentlyEvictedList { const size_t capacity; - size_t txIdsAndTimesIndex = 0; const int64_t timeToKeep; // Pairs of txid and time (seconds since epoch) - boost::optional> txIdsAndTimes[RECENTLY_EVICTED_SIZE]; + std::deque> txIdsAndTimes; std::set txIdSet; void pruneList(); @@ -36,7 +35,6 @@ class RecentlyEvictedList RecentlyEvictedList(size_t capacity_, int64_t timeToKeep_) : capacity(capacity_), timeToKeep(timeToKeep_) { assert(capacity <= RECENTLY_EVICTED_SIZE); - std::fill_n(txIdsAndTimes, capacity, boost::none); } RecentlyEvictedList(int64_t timeToKeep_) : RecentlyEvictedList(RECENTLY_EVICTED_SIZE, timeToKeep_) {} From c4931a9a44f75fd122a263fbab6fffd8f9a8ec69 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Wed, 9 Oct 2019 15:22:49 -0600 Subject: [PATCH 334/395] Rename files --- src/Makefile.am | 4 ++-- src/gtest/test_mempoollimit.cpp | 2 +- src/init.cpp | 2 +- src/{mempoollimit.cpp => mempool_limit.cpp} | 2 +- src/{mempoollimit.h => mempool_limit.h} | 0 src/txmempool.h | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) rename src/{mempoollimit.cpp => mempool_limit.cpp} (99%) rename src/{mempoollimit.h => mempool_limit.h} (100%) diff --git a/src/Makefile.am b/src/Makefile.am index 82beb74c149..baa9e680d94 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -192,7 +192,7 @@ BITCOIN_CORE_H = \ torcontrol.h \ transaction_builder.h \ txdb.h \ - mempoollimit.h \ + mempool_limit.h \ txmempool.h \ ui_interface.h \ uint256.h \ @@ -267,7 +267,7 @@ libbitcoin_server_a_SOURCES = \ timedata.cpp \ torcontrol.cpp \ txdb.cpp \ - mempoollimit.cpp \ + mempool_limit.cpp \ txmempool.cpp \ validationinterface.cpp \ $(BITCOIN_CORE_H) \ diff --git a/src/gtest/test_mempoollimit.cpp b/src/gtest/test_mempoollimit.cpp index 856834a4538..0b269aa2d2a 100644 --- a/src/gtest/test_mempoollimit.cpp +++ b/src/gtest/test_mempoollimit.cpp @@ -6,7 +6,7 @@ #include #include "arith_uint256.h" -#include "mempoollimit.h" +#include "mempool_limit.h" #include "utiltime.h" #include "utiltest.h" #include "transaction_builder.h" diff --git a/src/init.cpp b/src/init.cpp index f8e9ed8712d..78da4ab9f73 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -22,7 +22,7 @@ #include "key_io.h" #endif #include "main.h" -#include "mempoollimit.h" +#include "mempool_limit.h" #include "metrics.h" #include "miner.h" #include "net.h" diff --git a/src/mempoollimit.cpp b/src/mempool_limit.cpp similarity index 99% rename from src/mempoollimit.cpp rename to src/mempool_limit.cpp index f14c60bf5d7..3d3a8907bbb 100644 --- a/src/mempoollimit.cpp +++ b/src/mempool_limit.cpp @@ -3,7 +3,7 @@ // file COPYING or https://www.opensource.org/licenses/mit-license.php #include "core_memusage.h" -#include "mempoollimit.h" +#include "mempool_limit.h" #include "random.h" #include "serialize.h" #include "timedata.h" diff --git a/src/mempoollimit.h b/src/mempool_limit.h similarity index 100% rename from src/mempoollimit.h rename to src/mempool_limit.h diff --git a/src/txmempool.h b/src/txmempool.h index 5672a82cfeb..b74d464d0a7 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -10,7 +10,7 @@ #include "amount.h" #include "coins.h" -#include "mempoollimit.h" +#include "mempool_limit.h" #include "primitives/transaction.h" #include "sync.h" #include "addressindex.h" From 7ec8c5d30925eb6ddaf24ceac00ccf10e865b589 Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Fri, 13 Sep 2019 00:42:32 -0600 Subject: [PATCH 335/395] precompute empty merkle roots --- src/zcash/IncrementalMerkleTree.cpp | 790 ++++++++++++++++++++++++++++ src/zcash/IncrementalMerkleTree.hpp | 13 +- 2 files changed, 795 insertions(+), 8 deletions(-) diff --git a/src/zcash/IncrementalMerkleTree.cpp b/src/zcash/IncrementalMerkleTree.cpp index f8d5fad6190..5a7d71537f2 100644 --- a/src/zcash/IncrementalMerkleTree.cpp +++ b/src/zcash/IncrementalMerkleTree.cpp @@ -35,6 +35,392 @@ PedersenHash PedersenHash::uncommitted() { return res; } +static const std::array pedersen_empty_roots = { + uint256(std::vector{ + 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, + }), + uint256(std::vector{ + 0x81, 0x7d, 0xe3, 0x6a, 0xb2, 0xd5, 0x7f, 0xeb, + 0x07, 0x76, 0x34, 0xbc, 0xa7, 0x78, 0x19, 0xc8, + 0xe0, 0xbd, 0x29, 0x8c, 0x04, 0xf6, 0xfe, 0xd0, + 0xe6, 0xa8, 0x3c, 0xc1, 0x35, 0x6c, 0xa1, 0x55, + }), + uint256(std::vector{ + 0xff, 0xe9, 0xfc, 0x03, 0xf1, 0x8b, 0x17, 0x6c, + 0x99, 0x88, 0x06, 0x43, 0x9f, 0xf0, 0xbb, 0x8a, + 0xd1, 0x93, 0xaf, 0xdb, 0x27, 0xb2, 0xcc, 0xbc, + 0x88, 0x85, 0x69, 0x16, 0xdd, 0x80, 0x4e, 0x34, + }), + uint256(std::vector{ + 0xd8, 0x28, 0x33, 0x86, 0xef, 0x2e, 0xf0, 0x7e, + 0xbd, 0xbb, 0x43, 0x83, 0xc1, 0x2a, 0x73, 0x9a, + 0x95, 0x3a, 0x4d, 0x6e, 0x0d, 0x6f, 0xb1, 0x13, + 0x9a, 0x40, 0x36, 0xd6, 0x93, 0xbf, 0xbb, 0x6c, + }), + uint256(std::vector{ + 0xe1, 0x10, 0xde, 0x65, 0xc9, 0x07, 0xb9, 0xde, + 0xa4, 0xae, 0x0b, 0xd8, 0x3a, 0x4b, 0x0a, 0x51, + 0xbe, 0xa1, 0x75, 0x64, 0x6a, 0x64, 0xc1, 0x2b, + 0x4c, 0x9f, 0x93, 0x1b, 0x2c, 0xb3, 0x1b, 0x49, + }), + uint256(std::vector{ + 0x91, 0x2d, 0x82, 0xb2, 0xc2, 0xbc, 0xa2, 0x31, + 0xf7, 0x1e, 0xfc, 0xf6, 0x17, 0x37, 0xfb, 0xf0, + 0xa0, 0x8b, 0xef, 0xa0, 0x41, 0x62, 0x15, 0xae, + 0xef, 0x53, 0xe8, 0xbb, 0x6d, 0x23, 0x39, 0x0a, + }), + uint256(std::vector{ + 0x8a, 0xc9, 0xcf, 0x9c, 0x39, 0x1e, 0x3f, 0xd4, + 0x28, 0x91, 0xd2, 0x72, 0x38, 0xa8, 0x1a, 0x8a, + 0x5c, 0x1d, 0x3a, 0x72, 0xb1, 0xbc, 0xbe, 0xa8, + 0xcf, 0x44, 0xa5, 0x8c, 0xe7, 0x38, 0x96, 0x13, + }), + uint256(std::vector{ + 0xd6, 0xc6, 0x39, 0xac, 0x24, 0xb4, 0x6b, 0xd1, + 0x93, 0x41, 0xc9, 0x1b, 0x13, 0xfd, 0xca, 0xb3, + 0x15, 0x81, 0xdd, 0xaf, 0x7f, 0x14, 0x11, 0x33, + 0x6a, 0x27, 0x1f, 0x3d, 0x0a, 0xa5, 0x28, 0x13, + }), + uint256(std::vector{ + 0x7b, 0x99, 0xab, 0xdc, 0x37, 0x30, 0x99, 0x1c, + 0xc9, 0x27, 0x47, 0x27, 0xd7, 0xd8, 0x2d, 0x28, + 0xcb, 0x79, 0x4e, 0xdb, 0xc7, 0x03, 0x4b, 0x4f, + 0x00, 0x53, 0xff, 0x7c, 0x4b, 0x68, 0x04, 0x44, + }), + uint256(std::vector{ + 0x43, 0xff, 0x54, 0x57, 0xf1, 0x3b, 0x92, 0x6b, + 0x61, 0xdf, 0x55, 0x2d, 0x4e, 0x40, 0x2e, 0xe6, + 0xdc, 0x14, 0x63, 0xf9, 0x9a, 0x53, 0x5f, 0x9a, + 0x71, 0x34, 0x39, 0x26, 0x4d, 0x5b, 0x61, 0x6b, + }), + uint256(std::vector{ + 0xba, 0x49, 0xb6, 0x59, 0xfb, 0xd0, 0xb7, 0x33, + 0x42, 0x11, 0xea, 0x6a, 0x9d, 0x9d, 0xf1, 0x85, + 0xc7, 0x57, 0xe7, 0x0a, 0xa8, 0x1d, 0xa5, 0x62, + 0xfb, 0x91, 0x2b, 0x84, 0xf4, 0x9b, 0xce, 0x72, + }), + uint256(std::vector{ + 0x47, 0x77, 0xc8, 0x77, 0x6a, 0x3b, 0x1e, 0x69, + 0xb7, 0x3a, 0x62, 0xfa, 0x70, 0x1f, 0xa4, 0xf7, + 0xa6, 0x28, 0x2d, 0x9a, 0xee, 0x2c, 0x7a, 0x6b, + 0x82, 0xe7, 0x93, 0x7d, 0x70, 0x81, 0xc2, 0x3c, + }), + uint256(std::vector{ + 0xec, 0x67, 0x71, 0x14, 0xc2, 0x72, 0x06, 0xf5, + 0xde, 0xbc, 0x1c, 0x1e, 0xd6, 0x6f, 0x95, 0xe2, + 0xb1, 0x88, 0x5d, 0xa5, 0xb7, 0xbe, 0x3d, 0x73, + 0x6b, 0x1d, 0xe9, 0x85, 0x79, 0x47, 0x30, 0x48, + }), + uint256(std::vector{ + 0x1b, 0x77, 0xda, 0xc4, 0xd2, 0x4f, 0xb7, 0x25, + 0x8c, 0x3c, 0x52, 0x87, 0x04, 0xc5, 0x94, 0x30, + 0xb6, 0x30, 0x71, 0x8b, 0xec, 0x48, 0x64, 0x21, + 0x83, 0x70, 0x21, 0xcf, 0x75, 0xda, 0xb6, 0x51, + }), + uint256(std::vector{ + 0xbd, 0x74, 0xb2, 0x5a, 0xac, 0xb9, 0x23, 0x78, + 0xa8, 0x71, 0xbf, 0x27, 0xd2, 0x25, 0xcf, 0xc2, + 0x6b, 0xac, 0xa3, 0x44, 0xa1, 0xea, 0x35, 0xfd, + 0xd9, 0x45, 0x10, 0xf3, 0xd1, 0x57, 0x08, 0x2c, + }), + uint256(std::vector{ + 0xd6, 0xac, 0xde, 0xdf, 0x95, 0xf6, 0x08, 0xe0, + 0x9f, 0xa5, 0x3f, 0xb4, 0x3d, 0xcd, 0x09, 0x90, + 0x47, 0x57, 0x26, 0xc5, 0x13, 0x12, 0x10, 0xc9, + 0xe5, 0xca, 0xea, 0xb9, 0x7f, 0x0e, 0x64, 0x2f, + }), + uint256(std::vector{ + 0x1e, 0xa6, 0x67, 0x5f, 0x95, 0x51, 0xee, 0xb9, + 0xdf, 0xaa, 0xa9, 0x24, 0x7b, 0xc9, 0x85, 0x82, + 0x70, 0xd3, 0xd3, 0xa4, 0xc5, 0xaf, 0xa7, 0x17, + 0x7a, 0x98, 0x4d, 0x5e, 0xd1, 0xbe, 0x24, 0x51, + }), + uint256(std::vector{ + 0x6e, 0xdb, 0x16, 0xd0, 0x19, 0x07, 0xb7, 0x59, + 0x97, 0x7d, 0x76, 0x50, 0xda, 0xd7, 0xe3, 0xec, + 0x04, 0x9a, 0xf1, 0xa3, 0xd8, 0x75, 0x38, 0x0b, + 0x69, 0x7c, 0x86, 0x2c, 0x9e, 0xc5, 0xd5, 0x1c, + }), + uint256(std::vector{ + 0xcd, 0x1c, 0x8d, 0xbf, 0x6e, 0x3a, 0xcc, 0x7a, + 0x80, 0x43, 0x9b, 0xc4, 0x96, 0x2c, 0xf2, 0x5b, + 0x9d, 0xce, 0x7c, 0x89, 0x6f, 0x3a, 0x5b, 0xd7, + 0x08, 0x03, 0xfc, 0x5a, 0x0e, 0x33, 0xcf, 0x00, + }), + uint256(std::vector{ + 0x6a, 0xca, 0x84, 0x48, 0xd8, 0x26, 0x3e, 0x54, + 0x7d, 0x5f, 0xf2, 0x95, 0x0e, 0x2e, 0xd3, 0x83, + 0x9e, 0x99, 0x8d, 0x31, 0xcb, 0xc6, 0xac, 0x9f, + 0xd5, 0x7b, 0xc6, 0x00, 0x2b, 0x15, 0x92, 0x16, + }), + uint256(std::vector{ + 0x8d, 0x5f, 0xa4, 0x3e, 0x5a, 0x10, 0xd1, 0x16, + 0x05, 0xac, 0x74, 0x30, 0xba, 0x1f, 0x5d, 0x81, + 0xfb, 0x1b, 0x68, 0xd2, 0x9a, 0x64, 0x04, 0x05, + 0x76, 0x77, 0x49, 0xe8, 0x41, 0x52, 0x76, 0x73, + }), + uint256(std::vector{ + 0x08, 0xee, 0xab, 0x0c, 0x13, 0xab, 0xd6, 0x06, + 0x9e, 0x63, 0x10, 0x19, 0x7b, 0xf8, 0x0f, 0x9c, + 0x1e, 0xa6, 0xde, 0x78, 0xfd, 0x19, 0xcb, 0xae, + 0x24, 0xd4, 0xa5, 0x20, 0xe6, 0xcf, 0x30, 0x23, + }), + uint256(std::vector{ + 0x07, 0x69, 0x55, 0x7b, 0xc6, 0x82, 0xb1, 0xbf, + 0x30, 0x86, 0x46, 0xfd, 0x0b, 0x22, 0xe6, 0x48, + 0xe8, 0xb9, 0xe9, 0x8f, 0x57, 0xe2, 0x9f, 0x5a, + 0xf4, 0x0f, 0x6e, 0xdb, 0x83, 0x3e, 0x2c, 0x49, + }), + uint256(std::vector{ + 0x4c, 0x69, 0x37, 0xd7, 0x8f, 0x42, 0x68, 0x5f, + 0x84, 0xb4, 0x3a, 0xd3, 0xb7, 0xb0, 0x0f, 0x81, + 0x28, 0x56, 0x62, 0xf8, 0x5c, 0x6a, 0x68, 0xef, + 0x11, 0xd6, 0x2a, 0xd1, 0xa3, 0xee, 0x08, 0x50, + }), + uint256(std::vector{ + 0xfe, 0xe0, 0xe5, 0x28, 0x02, 0xcb, 0x0c, 0x46, + 0xb1, 0xeb, 0x4d, 0x37, 0x6c, 0x62, 0x69, 0x7f, + 0x47, 0x59, 0xf6, 0xc8, 0x91, 0x7f, 0xa3, 0x52, + 0x57, 0x12, 0x02, 0xfd, 0x77, 0x8f, 0xd7, 0x12, + }), + uint256(std::vector{ + 0x16, 0xd6, 0x25, 0x29, 0x68, 0x97, 0x1a, 0x83, + 0xda, 0x85, 0x21, 0xd6, 0x53, 0x82, 0xe6, 0x1f, + 0x01, 0x76, 0x64, 0x6d, 0x77, 0x1c, 0x91, 0x52, + 0x8e, 0x32, 0x76, 0xee, 0x45, 0x38, 0x3e, 0x4a, + }), + uint256(std::vector{ + 0xd2, 0xe1, 0x64, 0x2c, 0x9a, 0x46, 0x22, 0x29, + 0x28, 0x9e, 0x5b, 0x0e, 0x3b, 0x7f, 0x90, 0x08, + 0xe0, 0x30, 0x1c, 0xbb, 0x93, 0x38, 0x5e, 0xe0, + 0xe2, 0x1d, 0xa2, 0x54, 0x50, 0x73, 0xcb, 0x58, + }), + uint256(std::vector{ + 0xa5, 0x12, 0x2c, 0x08, 0xff, 0x9c, 0x16, 0x1d, + 0x9c, 0xa6, 0xfc, 0x46, 0x20, 0x73, 0x39, 0x6c, + 0x7d, 0x7d, 0x38, 0xe8, 0xee, 0x48, 0xcd, 0xb3, + 0xbe, 0xa7, 0xe2, 0x23, 0x01, 0x34, 0xed, 0x6a, + }), + uint256(std::vector{ + 0x28, 0xe7, 0xb8, 0x41, 0xdc, 0xbc, 0x47, 0xcc, + 0xeb, 0x69, 0xd7, 0xcb, 0x8d, 0x94, 0x24, 0x5f, + 0xb7, 0xcb, 0x2b, 0xa3, 0xa7, 0xa6, 0xbc, 0x18, + 0xf1, 0x3f, 0x94, 0x5f, 0x7d, 0xbd, 0x6e, 0x2a, + }), + uint256(std::vector{ + 0xe1, 0xf3, 0x4b, 0x03, 0x4d, 0x4a, 0x3c, 0xd2, + 0x85, 0x57, 0xe2, 0x90, 0x7e, 0xbf, 0x99, 0x0c, + 0x91, 0x8f, 0x64, 0xec, 0xb5, 0x0a, 0x94, 0xf0, + 0x1d, 0x6f, 0xda, 0x5c, 0xa5, 0xc7, 0xef, 0x72, + }), + uint256(std::vector{ + 0x12, 0x93, 0x5f, 0x14, 0xb6, 0x76, 0x50, 0x9b, + 0x81, 0xeb, 0x49, 0xef, 0x25, 0xf3, 0x92, 0x69, + 0xed, 0x72, 0x30, 0x92, 0x38, 0xb4, 0xc1, 0x45, + 0x80, 0x35, 0x44, 0xb6, 0x46, 0xdc, 0xa6, 0x2d, + }), + uint256(std::vector{ + 0xb2, 0xee, 0xd0, 0x31, 0xd4, 0xd6, 0xa4, 0xf0, + 0x2a, 0x09, 0x7f, 0x80, 0xb5, 0x4c, 0xc1, 0x54, + 0x1d, 0x41, 0x63, 0xc6, 0xb6, 0xf5, 0x97, 0x1f, + 0x88, 0xb6, 0xe4, 0x1d, 0x35, 0xc5, 0x38, 0x14, + }), + uint256(std::vector{ + 0xfb, 0xc2, 0xf4, 0x30, 0x0c, 0x01, 0xf0, 0xb7, + 0x82, 0x0d, 0x00, 0xe3, 0x34, 0x7c, 0x8d, 0xa4, + 0xee, 0x61, 0x46, 0x74, 0x37, 0x6c, 0xbc, 0x45, + 0x35, 0x9d, 0xaa, 0x54, 0xf9, 0xb5, 0x49, 0x3e, + }), + uint256(std::vector{ + 0x25, 0x2e, 0x67, 0x98, 0x64, 0x5f, 0x5b, 0xf1, + 0x14, 0xe4, 0xb4, 0xe9, 0x0e, 0x96, 0x18, 0x28, + 0x61, 0x48, 0x98, 0x40, 0xd9, 0xb4, 0xcc, 0xc4, + 0xc1, 0xfb, 0x5a, 0x46, 0x99, 0x7c, 0xee, 0x14, + }), + uint256(std::vector{ + 0x98, 0xb1, 0x90, 0x42, 0xf1, 0xf7, 0xc7, 0xdd, + 0x11, 0xec, 0x25, 0xea, 0x66, 0xb6, 0xff, 0x74, + 0xe0, 0x8c, 0xe1, 0x1d, 0x44, 0x7e, 0xd6, 0xf1, + 0xbf, 0xe8, 0x7e, 0x11, 0x0e, 0x33, 0x1e, 0x11, + }), + uint256(std::vector{ + 0xd4, 0x51, 0x30, 0x47, 0x99, 0x57, 0x2b, 0xa9, + 0xf4, 0x2c, 0x4d, 0xab, 0x6b, 0x07, 0xc7, 0x03, + 0xbd, 0x2c, 0x12, 0x3a, 0xb9, 0xd6, 0x0f, 0x2a, + 0x60, 0xf9, 0x95, 0x58, 0x54, 0x91, 0x0b, 0x6a, + }), + uint256(std::vector{ + 0x3e, 0xcd, 0x5f, 0x27, 0xac, 0xf0, 0x1b, 0xd3, + 0x7a, 0x33, 0xe4, 0x51, 0x78, 0x67, 0xef, 0x76, + 0x47, 0x4c, 0xd8, 0x3f, 0xb3, 0x1c, 0x92, 0x08, + 0xdc, 0xef, 0x2e, 0xed, 0xce, 0xf3, 0x6c, 0x72, + }), + uint256(std::vector{ + 0x26, 0xc3, 0x7d, 0xa6, 0x78, 0x94, 0xa1, 0x3d, + 0xf8, 0xaa, 0x48, 0x78, 0xd2, 0x51, 0x4a, 0x42, + 0x12, 0x57, 0x3b, 0x73, 0xec, 0xca, 0xab, 0x16, + 0xfe, 0x4f, 0xa6, 0x60, 0xe8, 0xfe, 0x27, 0x07, + }), + uint256(std::vector{ + 0xb5, 0x45, 0xef, 0x34, 0x48, 0x5e, 0xed, 0x30, + 0xd4, 0x2b, 0x2c, 0x29, 0x5a, 0x4a, 0x5b, 0x68, + 0x0d, 0xe8, 0xa9, 0xd5, 0xe3, 0x83, 0x45, 0x78, + 0x24, 0x62, 0xc0, 0x4f, 0x09, 0xdc, 0x68, 0x51, + }), + uint256(std::vector{ + 0x77, 0xfd, 0x20, 0xb3, 0x00, 0x94, 0x67, 0x65, + 0xa8, 0x7f, 0x24, 0xbd, 0x04, 0x50, 0x73, 0x72, + 0x9c, 0xbd, 0x7b, 0x66, 0xeb, 0x8f, 0xa1, 0x40, + 0xb5, 0x83, 0xfa, 0xa9, 0xd1, 0x42, 0x58, 0x01, + }), + uint256(std::vector{ + 0xcb, 0xaa, 0x57, 0x6b, 0x17, 0x99, 0xb5, 0x8f, + 0xf3, 0xa6, 0xde, 0xcb, 0xba, 0x91, 0x9b, 0x0b, + 0x68, 0xd7, 0xc8, 0x93, 0xe4, 0x6f, 0xde, 0x99, + 0x87, 0x68, 0xe8, 0x7e, 0x35, 0x0a, 0x07, 0x25, + }), + uint256(std::vector{ + 0x45, 0xfe, 0x81, 0xb1, 0x8c, 0xa3, 0x00, 0x74, + 0xd0, 0x12, 0x0d, 0x2b, 0x1a, 0x0d, 0x10, 0xb3, + 0xa0, 0x50, 0x93, 0x35, 0x12, 0xdb, 0x8e, 0xe3, + 0x4e, 0x52, 0x47, 0x3d, 0x4f, 0x08, 0xa2, 0x67, + }), + uint256(std::vector{ + 0x0e, 0x60, 0xa1, 0xf0, 0x12, 0x1f, 0x59, 0x1e, + 0x55, 0x1d, 0x3e, 0xd1, 0x86, 0x5b, 0x50, 0xa7, + 0x5d, 0x7c, 0xcf, 0xf1, 0x28, 0x9d, 0xf7, 0xc4, + 0x4d, 0xd4, 0x65, 0xa5, 0x43, 0x17, 0xf5, 0x6a, + }), + uint256(std::vector{ + 0xce, 0xdf, 0xb1, 0x84, 0xdd, 0x92, 0xa0, 0xcb, + 0xfc, 0x11, 0xe8, 0xbe, 0x69, 0x7b, 0x47, 0x69, + 0x88, 0xed, 0x5f, 0x39, 0x36, 0x9a, 0xbd, 0xd9, + 0x0c, 0x61, 0x54, 0x49, 0x88, 0x60, 0x1c, 0x0d, + }), + uint256(std::vector{ + 0xf3, 0x62, 0x68, 0x66, 0x12, 0x64, 0x9a, 0x31, + 0x3b, 0xa4, 0x64, 0x43, 0x7a, 0x0c, 0xad, 0x0e, + 0x7e, 0x3d, 0x7e, 0x1b, 0x4b, 0x37, 0x43, 0xf9, + 0x0e, 0x05, 0xa2, 0x10, 0x0a, 0x49, 0x5f, 0x42, + }), + uint256(std::vector{ + 0x7d, 0xea, 0xe5, 0xf3, 0xbb, 0xde, 0xff, 0xd3, + 0xf8, 0x52, 0x71, 0xa0, 0x8b, 0x5e, 0xc3, 0x1f, + 0x16, 0xf9, 0x37, 0x96, 0x4a, 0xe7, 0x08, 0xfd, + 0xff, 0x7c, 0x13, 0xe5, 0xa4, 0xf3, 0xdf, 0x6b, + }), + uint256(std::vector{ + 0x40, 0xcc, 0xf0, 0xfc, 0x1e, 0xab, 0x6d, 0x85, + 0x02, 0xbd, 0x93, 0xdc, 0x31, 0x34, 0x2d, 0xfd, + 0x57, 0xdf, 0x5b, 0xbb, 0x5d, 0x70, 0xa1, 0xbf, + 0x6b, 0x92, 0xef, 0xc6, 0x1e, 0xc9, 0xa2, 0x58, + }), + uint256(std::vector{ + 0xd7, 0x80, 0x25, 0x49, 0x1f, 0x1b, 0xca, 0x85, + 0x07, 0xf6, 0x4f, 0x25, 0x87, 0x2d, 0xd0, 0x23, + 0x88, 0x47, 0x9a, 0x1a, 0x22, 0x51, 0x26, 0xe4, + 0x0d, 0x2f, 0xe4, 0x18, 0xb9, 0x8e, 0x0e, 0x2c, + }), + uint256(std::vector{ + 0x0d, 0xb7, 0x29, 0x46, 0x85, 0xc8, 0xa0, 0x72, + 0x5f, 0x15, 0x84, 0x6e, 0xa5, 0x89, 0x9e, 0xa0, + 0xe9, 0x86, 0xc2, 0x70, 0x7b, 0xd7, 0xb4, 0x12, + 0x95, 0x44, 0x12, 0xf2, 0x6a, 0xbf, 0x55, 0x0a, + }), + uint256(std::vector{ + 0xb7, 0xe2, 0x90, 0xbe, 0x95, 0x55, 0xcf, 0x75, + 0x54, 0x86, 0x50, 0xda, 0x6d, 0x47, 0xc8, 0x93, + 0xae, 0xf7, 0xf8, 0xc6, 0xdd, 0x27, 0x35, 0x49, + 0x94, 0x95, 0xf6, 0x36, 0x59, 0x0d, 0xae, 0x0a, + }), + uint256(std::vector{ + 0x2d, 0xd2, 0x53, 0x2a, 0x85, 0x8c, 0x30, 0x01, + 0x45, 0xa6, 0x5e, 0x35, 0x1f, 0x91, 0xbe, 0x6a, + 0xfe, 0xab, 0x59, 0x7c, 0x41, 0xef, 0x07, 0x3f, + 0x50, 0xb6, 0x22, 0xd5, 0x86, 0xff, 0x59, 0x27, + }), + uint256(std::vector{ + 0x97, 0x2f, 0x0c, 0x5c, 0x6f, 0x9a, 0xeb, 0x0e, + 0x38, 0xbf, 0x83, 0x19, 0xf3, 0xa5, 0xfc, 0xdc, + 0x8f, 0xd8, 0x78, 0x2e, 0x41, 0x88, 0x73, 0x0c, + 0xd0, 0x82, 0xd9, 0xba, 0xbc, 0x58, 0x98, 0x51, + }), + uint256(std::vector{ + 0x00, 0x1e, 0x57, 0x7b, 0x0f, 0x43, 0x90, 0x18, + 0x2b, 0x4a, 0xe4, 0x3d, 0x32, 0x9b, 0x3a, 0xa8, + 0x83, 0x5d, 0xae, 0x1b, 0xb7, 0x9e, 0x60, 0x4b, + 0x7d, 0x2d, 0xa0, 0xe9, 0x0d, 0x06, 0x09, 0x29, + }), + uint256(std::vector{ + 0xaa, 0x6e, 0x70, 0xa9, 0x1e, 0xbc, 0x54, 0xee, + 0xfc, 0xe5, 0xff, 0xd5, 0xb6, 0x75, 0xda, 0xf3, + 0xf1, 0xd9, 0x40, 0xa8, 0x45, 0x1f, 0xcb, 0x01, + 0x08, 0x1f, 0xa9, 0xd4, 0xf2, 0x62, 0x43, 0x6f, + }), + uint256(std::vector{ + 0xd7, 0x70, 0x38, 0xbf, 0x67, 0xe6, 0x31, 0x75, + 0x29, 0x40, 0x23, 0x12, 0x51, 0xd7, 0xfe, 0x85, + 0xaf, 0x52, 0xdb, 0xdd, 0x6a, 0xab, 0x37, 0xc7, + 0xa5, 0xec, 0x32, 0xb6, 0x5f, 0xe6, 0xde, 0x03, + }), + uint256(std::vector{ + 0xd2, 0x27, 0xa1, 0x7a, 0x7e, 0x0c, 0xf9, 0x6d, + 0xce, 0xdd, 0x9f, 0xc7, 0xbc, 0xe4, 0x3c, 0x6c, + 0x1d, 0x66, 0xba, 0xdd, 0x75, 0x43, 0xa8, 0x87, + 0xc8, 0x65, 0x6c, 0x54, 0x7e, 0xcf, 0xb2, 0x4f, + }), + uint256(std::vector{ + 0x70, 0xe8, 0xa5, 0x21, 0x95, 0x15, 0x83, 0xe5, + 0x3f, 0xc0, 0x58, 0x5c, 0x70, 0x7e, 0xce, 0xda, + 0x89, 0xb7, 0xa7, 0xd1, 0xaf, 0x41, 0xd1, 0xa0, + 0x15, 0xd7, 0x97, 0xfa, 0x76, 0xc0, 0xf5, 0x69, + }), + uint256(std::vector{ + 0xe4, 0x85, 0xa9, 0x68, 0x55, 0xe8, 0x72, 0xfc, + 0x50, 0x90, 0x15, 0x0e, 0x2c, 0xd2, 0x4e, 0x10, + 0x59, 0x1d, 0x35, 0x16, 0x6e, 0xb0, 0xeb, 0x30, + 0xfc, 0xdf, 0xac, 0x93, 0xb0, 0x1d, 0x28, 0x1c, + }), + uint256(std::vector{ + 0xe4, 0xa1, 0x9f, 0xeb, 0xdf, 0x2a, 0x86, 0x89, + 0x6e, 0x41, 0xf2, 0xce, 0xdc, 0xf2, 0xae, 0x58, + 0x46, 0x71, 0x80, 0x2e, 0x6a, 0x46, 0x7e, 0x84, + 0x39, 0xca, 0xb5, 0xd6, 0x18, 0x43, 0x41, 0x6b, + }), + uint256(std::vector{ + 0xe9, 0x27, 0x83, 0x88, 0x47, 0x80, 0x6a, 0x43, + 0xbd, 0x6c, 0x60, 0x88, 0xe3, 0x9f, 0x65, 0xb8, + 0xb3, 0xe5, 0x8b, 0x2d, 0xb5, 0xf7, 0xad, 0x56, + 0x43, 0xd9, 0x1e, 0x06, 0x59, 0xa2, 0x8a, 0x2a, + }), + uint256(std::vector{ + 0x0b, 0xd3, 0xa8, 0x18, 0xe8, 0x3f, 0x9c, 0xd2, + 0xff, 0x4f, 0x62, 0x01, 0x1a, 0x51, 0x01, 0x76, + 0xac, 0x32, 0xf5, 0x44, 0x8e, 0x6e, 0x15, 0x45, + 0x15, 0x04, 0x3c, 0x59, 0x26, 0xd5, 0x1c, 0x6f, + }), + uint256(std::vector{ + 0xce, 0x41, 0x34, 0x45, 0xe0, 0x37, 0x90, 0x49, + 0x8f, 0xe7, 0x2d, 0x8e, 0x01, 0x91, 0x5e, 0x7f, + 0xf1, 0x20, 0xae, 0x35, 0xb3, 0xb5, 0x90, 0xd2, + 0x1b, 0x7f, 0x74, 0xde, 0xe1, 0x83, 0x0f, 0x0d, + }), + uint256(std::vector{ + 0x60, 0x0e, 0x6f, 0x93, 0xe7, 0x3d, 0x7a, 0xbd, + 0x4e, 0xe0, 0xa6, 0x5c, 0xb1, 0xb1, 0x9a, 0xa3, + 0xec, 0xc5, 0x25, 0x68, 0x9d, 0xbf, 0x17, 0x77, + 0x96, 0x58, 0x74, 0x1b, 0x95, 0xc1, 0x5a, 0x55, + }), +}; + +PedersenHash PedersenHash::EmptyRoot(size_t depth) { + assert(depth <= sizeof(pedersen_empty_roots)/sizeof(pedersen_empty_roots[0])); + return pedersen_empty_roots[depth]; +} + SHA256Compress SHA256Compress::combine( const SHA256Compress& a, const SHA256Compress& b, @@ -51,6 +437,410 @@ SHA256Compress SHA256Compress::combine( return res; } +static const std::array sha256_empty_roots = { + uint256(std::vector{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }), + uint256(std::vector{ + 0xda, 0x56, 0x98, 0xbe, 0x17, 0xb9, 0xb4, 0x69, + 0x62, 0x33, 0x57, 0x99, 0x77, 0x9f, 0xbe, 0xca, + 0x8c, 0xe5, 0xd4, 0x91, 0xc0, 0xd2, 0x62, 0x43, + 0xba, 0xfe, 0xf9, 0xea, 0x18, 0x37, 0xa9, 0xd8, + }), + uint256(std::vector{ + 0xdc, 0x76, 0x6f, 0xab, 0x49, 0x2c, 0xcf, 0x3d, + 0x1e, 0x49, 0xd4, 0xf3, 0x74, 0xb5, 0x23, 0x5f, + 0xa5, 0x65, 0x06, 0xaa, 0xc2, 0x22, 0x4d, 0x39, + 0xf9, 0x43, 0xfc, 0xd4, 0x92, 0x02, 0x97, 0x4c, + }), + uint256(std::vector{ + 0x3f, 0x0a, 0x40, 0x61, 0x81, 0x10, 0x59, 0x68, + 0xfd, 0xae, 0xe3, 0x06, 0x79, 0xe3, 0x27, 0x3c, + 0x66, 0xb7, 0x2b, 0xf9, 0xa7, 0xf5, 0xde, 0xbb, + 0xf3, 0xb5, 0xa0, 0xa2, 0x6e, 0x35, 0x9f, 0x92, + }), + uint256(std::vector{ + 0x26, 0xb0, 0x05, 0x26, 0x94, 0xfc, 0x42, 0xfd, + 0xff, 0x93, 0xe6, 0xfb, 0x5a, 0x71, 0xd3, 0x8c, + 0x3d, 0xd7, 0xdc, 0x5b, 0x6a, 0xd7, 0x10, 0xeb, + 0x04, 0x8c, 0x66, 0x02, 0x33, 0x13, 0x7f, 0xab, + }), + uint256(std::vector{ + 0x01, 0x09, 0xec, 0xc0, 0x72, 0x26, 0x59, 0xff, + 0x83, 0x45, 0x0b, 0x8f, 0x7b, 0x88, 0x46, 0xe6, + 0x7b, 0x28, 0x59, 0xf3, 0x3c, 0x30, 0xd9, 0xb7, + 0xac, 0xd5, 0xbf, 0x39, 0xca, 0xe5, 0x4e, 0x31, + }), + uint256(std::vector{ + 0x3f, 0x90, 0x9b, 0x8c, 0xe3, 0xd7, 0xff, 0xd8, + 0xa5, 0xb3, 0x09, 0x08, 0xf6, 0x05, 0xa0, 0x3b, + 0x0d, 0xb8, 0x51, 0x69, 0x55, 0x8d, 0xdc, 0x1d, + 0xa7, 0xbb, 0xbc, 0xc9, 0xb0, 0x9f, 0xd3, 0x25, + }), + uint256(std::vector{ + 0x40, 0x46, 0x0f, 0xa6, 0xbc, 0x69, 0x2a, 0x06, + 0xf4, 0x75, 0x21, 0xa6, 0x72, 0x5a, 0x54, 0x7c, + 0x02, 0x8a, 0x6a, 0x24, 0x0d, 0x84, 0x09, 0xf1, + 0x65, 0xe6, 0x3c, 0xb5, 0x4d, 0xa2, 0xd2, 0x3f, + }), + uint256(std::vector{ + 0x8c, 0x08, 0x56, 0x74, 0x24, 0x9b, 0x43, 0xda, + 0x1b, 0x9a, 0x31, 0xa0, 0xe8, 0x20, 0xe8, 0x1e, + 0x75, 0xf3, 0x42, 0x80, 0x7b, 0x03, 0xb6, 0xb9, + 0xe6, 0x49, 0x83, 0x21, 0x7b, 0xc2, 0xb3, 0x8e, + }), + uint256(std::vector{ + 0xa0, 0x83, 0x45, 0x0c, 0x1b, 0xa2, 0xa3, 0xa7, + 0xbe, 0x76, 0xfa, 0xd9, 0xd1, 0x3b, 0xc3, 0x7b, + 0xe4, 0xbf, 0x83, 0xbd, 0x3e, 0x59, 0xfc, 0x37, + 0x5a, 0x36, 0xba, 0x62, 0xdc, 0x62, 0x02, 0x98, + }), + uint256(std::vector{ + 0x1d, 0xdd, 0xda, 0xbc, 0x2c, 0xaa, 0x2d, 0xe9, + 0xef, 0xf9, 0xe1, 0x8c, 0x8c, 0x5a, 0x39, 0x40, + 0x6d, 0x79, 0x36, 0xe8, 0x89, 0xbc, 0x16, 0xcf, + 0xab, 0xb1, 0x44, 0xf5, 0xc0, 0x02, 0x26, 0x82, + }), + uint256(std::vector{ + 0xc2, 0x2d, 0x8f, 0x0b, 0x5e, 0x40, 0x56, 0xe5, + 0xf3, 0x18, 0xba, 0x22, 0x09, 0x1c, 0xc0, 0x7d, + 0xb5, 0x69, 0x4f, 0xbe, 0xb5, 0xe8, 0x7e, 0xf0, + 0xd7, 0xe2, 0xc5, 0x7c, 0xa3, 0x52, 0x35, 0x9e, + }), + uint256(std::vector{ + 0x89, 0xa4, 0x34, 0xae, 0x1f, 0xeb, 0xd7, 0x68, + 0x7e, 0xce, 0xea, 0x21, 0xd0, 0x7f, 0x20, 0xa2, + 0x51, 0x24, 0x49, 0xd0, 0x8c, 0xe2, 0xee, 0xe5, + 0x58, 0x71, 0xcd, 0xb9, 0xd4, 0x6c, 0x12, 0x33, + }), + uint256(std::vector{ + 0x73, 0x33, 0xdb, 0xff, 0xbd, 0x11, 0xf0, 0x92, + 0x47, 0xa2, 0xb3, 0x3a, 0x01, 0x3e, 0xc4, 0xc4, + 0x34, 0x20, 0x29, 0xd8, 0x51, 0xe2, 0x2b, 0xa4, + 0x85, 0xd4, 0x46, 0x18, 0x51, 0x37, 0x0c, 0x15, + }), + uint256(std::vector{ + 0x5d, 0xad, 0x84, 0x4a, 0xb9, 0x46, 0x6b, 0x70, + 0xf7, 0x45, 0x13, 0x71, 0x95, 0xca, 0x22, 0x1b, + 0x48, 0xf3, 0x46, 0xab, 0xd1, 0x45, 0xfb, 0x5e, + 0xfc, 0x23, 0xa8, 0xb4, 0xba, 0x50, 0x80, 0x22, + }), + uint256(std::vector{ + 0x50, 0x7e, 0x0d, 0xae, 0x81, 0xcb, 0xfb, 0xe4, + 0x57, 0xfd, 0x37, 0x0e, 0xf1, 0xca, 0x42, 0x01, + 0xc2, 0xb6, 0x40, 0x10, 0x83, 0xdd, 0xab, 0x44, + 0x0e, 0x4a, 0x03, 0x8d, 0xc1, 0xe3, 0x58, 0xc4, + }), + uint256(std::vector{ + 0xbd, 0xcd, 0xb3, 0x29, 0x31, 0x88, 0xc9, 0x80, + 0x7d, 0x80, 0x82, 0x67, 0x01, 0x86, 0x84, 0xcf, + 0xec, 0xe0, 0x7a, 0xc3, 0x5a, 0x42, 0xc0, 0x0f, + 0x2c, 0x79, 0xb4, 0x00, 0x38, 0x25, 0x30, 0x5d, + }), + uint256(std::vector{ + 0xba, 0xb5, 0x80, 0x09, 0x72, 0xa1, 0x6c, 0x2c, + 0x22, 0x53, 0x0c, 0x66, 0x06, 0x6d, 0x0a, 0x58, + 0x67, 0xe9, 0x87, 0xbe, 0xd2, 0x1a, 0x6d, 0x5a, + 0x45, 0x0b, 0x68, 0x3c, 0xf1, 0xcf, 0xd7, 0x09, + }), + uint256(std::vector{ + 0x11, 0xaa, 0x0b, 0x4a, 0xd2, 0x9b, 0x13, 0xb0, + 0x57, 0xa3, 0x16, 0x19, 0xd6, 0x50, 0x0d, 0x63, + 0x6c, 0xd7, 0x35, 0xcd, 0xd0, 0x7d, 0x81, 0x1e, + 0xa2, 0x65, 0xec, 0x4b, 0xcb, 0xbb, 0xd0, 0x58, + }), + uint256(std::vector{ + 0x51, 0x45, 0xb1, 0xb0, 0x55, 0xc2, 0xdf, 0x02, + 0xb9, 0x56, 0x75, 0xe3, 0x79, 0x7b, 0x91, 0xde, + 0x1b, 0x84, 0x6d, 0x25, 0x00, 0x3c, 0x0a, 0x80, + 0x3d, 0x08, 0x90, 0x07, 0x28, 0xf2, 0xcd, 0x6a, + }), + uint256(std::vector{ + 0x03, 0x23, 0xf2, 0x85, 0x0b, 0xf3, 0x44, 0x4f, + 0x4b, 0x4c, 0x5c, 0x09, 0xa6, 0x05, 0x7e, 0xc7, + 0x16, 0x91, 0x90, 0xf4, 0x5a, 0xcb, 0x9e, 0x46, + 0x98, 0x4a, 0xb3, 0xdf, 0xce, 0xc4, 0xf0, 0x6a, + }), + uint256(std::vector{ + 0x67, 0x15, 0x46, 0xe2, 0x6b, 0x1d, 0xa1, 0xaf, + 0x75, 0x45, 0x31, 0xe2, 0x6d, 0x8a, 0x6a, 0x51, + 0x07, 0x3a, 0x57, 0xdd, 0xd7, 0x2d, 0xc4, 0x72, + 0xef, 0xb4, 0x3f, 0xcb, 0x25, 0x7c, 0xff, 0xff, + }), + uint256(std::vector{ + 0xbb, 0x23, 0xa9, 0xbb, 0xa5, 0x6d, 0xe5, 0x7c, + 0xb2, 0x84, 0xb0, 0xd2, 0xb0, 0x1c, 0x64, 0x2c, + 0xf7, 0x9c, 0x9a, 0x55, 0x63, 0xf0, 0x06, 0x7a, + 0x21, 0x29, 0x24, 0x12, 0x14, 0x5b, 0xd7, 0x8a, + }), + uint256(std::vector{ + 0xf3, 0x0c, 0xc8, 0x36, 0xb9, 0xf7, 0x1b, 0x4e, + 0x7e, 0xe3, 0xc7, 0x2b, 0x1f, 0xd2, 0x53, 0x26, + 0x8a, 0xf9, 0xa2, 0x7e, 0x9d, 0x72, 0x91, 0xa2, + 0x3d, 0x02, 0x82, 0x1b, 0x21, 0xdd, 0xfd, 0x16, + }), + uint256(std::vector{ + 0x58, 0xa2, 0x75, 0x3d, 0xad, 0xe1, 0x03, 0xce, + 0xcb, 0xcd, 0xa5, 0x0b, 0x5e, 0xbf, 0xce, 0x31, + 0xe1, 0x2d, 0x41, 0xd5, 0x84, 0x1d, 0xcc, 0x95, + 0x62, 0x0f, 0x7b, 0x3d, 0x50, 0xa1, 0xb9, 0xa1, + }), + uint256(std::vector{ + 0x92, 0x5e, 0x6d, 0x47, 0x4a, 0x5d, 0x8d, 0x30, + 0x04, 0xf2, 0x9d, 0xa0, 0xdd, 0x78, 0xd3, 0x0a, + 0xe3, 0x82, 0x4c, 0xe7, 0x9d, 0xfe, 0x49, 0x34, + 0xbb, 0x29, 0xec, 0x3a, 0xfa, 0xf3, 0xd5, 0x21, + }), + uint256(std::vector{ + 0x08, 0xf2, 0x79, 0x61, 0x86, 0x16, 0xbc, 0xdd, + 0x4e, 0xad, 0xc9, 0xc7, 0xa9, 0x06, 0x26, 0x91, + 0xa5, 0x9b, 0x43, 0xb0, 0x7e, 0x2c, 0x1e, 0x23, + 0x7f, 0x17, 0xbd, 0x18, 0x9c, 0xd6, 0xa8, 0xfe, + }), + uint256(std::vector{ + 0xc9, 0x2b, 0x32, 0xdb, 0x42, 0xf4, 0x2e, 0x2b, + 0xf0, 0xa5, 0x9d, 0xf9, 0x05, 0x5b, 0xe5, 0xc6, + 0x69, 0xd3, 0x24, 0x2d, 0xf4, 0x53, 0x57, 0x65, + 0x9b, 0x75, 0xae, 0x2c, 0x27, 0xa7, 0x6f, 0x50, + }), + uint256(std::vector{ + 0xc0, 0xdb, 0x2a, 0x74, 0x99, 0x8c, 0x50, 0xeb, + 0x7b, 0xa6, 0x53, 0x4f, 0x6d, 0x41, 0x0e, 0xfc, + 0x27, 0xc4, 0xbb, 0x88, 0xac, 0xb0, 0x22, 0x2c, + 0x79, 0x06, 0xea, 0x28, 0xa3, 0x27, 0xb5, 0x11, + }), + uint256(std::vector{ + 0xd7, 0xc6, 0x12, 0xc8, 0x17, 0x79, 0x31, 0x91, + 0xa1, 0xe6, 0x86, 0x52, 0x12, 0x18, 0x76, 0xd6, + 0xb3, 0xbd, 0xe4, 0x0f, 0x4f, 0xa5, 0x2b, 0xc3, + 0x14, 0x14, 0x5c, 0xe6, 0xe5, 0xcd, 0xd2, 0x59, + }), + uint256(std::vector{ + 0xb2, 0x23, 0x70, 0x10, 0x6c, 0x67, 0xa1, 0x72, + 0x09, 0xf6, 0x13, 0x0b, 0xc0, 0x9f, 0x73, 0x5d, + 0x83, 0xaa, 0x2c, 0x04, 0xfc, 0x4f, 0xe7, 0x2e, + 0xa5, 0xd8, 0x0b, 0x21, 0x67, 0x23, 0xe7, 0xce, + }), + uint256(std::vector{ + 0x9f, 0x67, 0xd5, 0xf6, 0x64, 0x66, 0x4c, 0x90, + 0x19, 0x40, 0xee, 0xe3, 0xd0, 0x2d, 0xd5, 0xb3, + 0xe4, 0xb9, 0x2e, 0x7b, 0x42, 0x82, 0x0c, 0x42, + 0xfc, 0x51, 0x59, 0xe9, 0x1b, 0x41, 0x17, 0x2a, + }), + uint256(std::vector{ + 0xac, 0x58, 0xcd, 0x13, 0x88, 0xfe, 0xc2, 0x90, + 0xd3, 0x98, 0xf1, 0x94, 0x4b, 0x56, 0x44, 0x49, + 0xa6, 0x3c, 0x81, 0x58, 0x80, 0x56, 0x6b, 0xd1, + 0xd1, 0x89, 0xf7, 0x83, 0x9e, 0x3b, 0x0c, 0x8c, + }), + uint256(std::vector{ + 0x56, 0x98, 0xea, 0xe7, 0xc8, 0x51, 0x5e, 0xd0, + 0x5a, 0x70, 0x33, 0x9b, 0xdf, 0x7c, 0x10, 0x28, + 0xe7, 0xac, 0xca, 0x13, 0xa4, 0xfa, 0x97, 0xd9, + 0x53, 0x8f, 0x01, 0xac, 0x8d, 0x88, 0x9a, 0xe3, + }), + uint256(std::vector{ + 0x2d, 0x49, 0x95, 0x77, 0x0a, 0x76, 0xfb, 0x93, + 0x31, 0x4c, 0xa7, 0x4b, 0x35, 0x24, 0xea, 0x1d, + 0xb5, 0x68, 0x8a, 0xd0, 0xa7, 0x61, 0x83, 0xea, + 0x17, 0x20, 0x4a, 0x8f, 0x02, 0x4a, 0x9f, 0x3b, + }), + uint256(std::vector{ + 0x5e, 0x89, 0x92, 0xc1, 0xb0, 0x72, 0xc1, 0x6e, + 0x9e, 0x28, 0xa8, 0x53, 0x58, 0xfb, 0x5f, 0xb6, + 0x90, 0x1a, 0x81, 0x58, 0x77, 0x66, 0xda, 0xdb, + 0x7a, 0xa0, 0xb9, 0x73, 0xde, 0xd2, 0xf2, 0x64, + }), + uint256(std::vector{ + 0xe9, 0x5d, 0xb7, 0x1e, 0x1f, 0x72, 0x91, 0xba, + 0x54, 0x99, 0x46, 0x1b, 0xc7, 0x15, 0x20, 0x3e, + 0x29, 0xb8, 0x4b, 0xfa, 0x42, 0x83, 0xe3, 0xbb, + 0x7f, 0x47, 0x0a, 0x15, 0xd0, 0xe1, 0x58, 0x4e, + }), + uint256(std::vector{ + 0x41, 0xf0, 0x78, 0xbd, 0x18, 0x24, 0xc8, 0xa4, + 0xb7, 0x19, 0x64, 0xf3, 0x94, 0xaa, 0x59, 0x50, + 0x84, 0xd8, 0xeb, 0x17, 0xb9, 0x7a, 0x36, 0x30, + 0x43, 0x3a, 0xf7, 0x0d, 0x10, 0xe0, 0xef, 0xf6, + }), + uint256(std::vector{ + 0xa1, 0x91, 0x3f, 0xe6, 0xb2, 0x01, 0x32, 0x31, + 0x2f, 0x8c, 0x1f, 0x00, 0xdd, 0xd6, 0x3c, 0xec, + 0x7a, 0x03, 0xf5, 0xf1, 0xd7, 0xd8, 0x34, 0x92, + 0xfa, 0x28, 0x4c, 0x0b, 0x5d, 0x63, 0x20, 0xb0, + }), + uint256(std::vector{ + 0xba, 0x94, 0x40, 0xc4, 0xdb, 0xfc, 0xf5, 0x5c, + 0xeb, 0x60, 0x5a, 0x5b, 0x89, 0x90, 0xfc, 0x11, + 0xf8, 0xef, 0x22, 0x87, 0x0d, 0x8d, 0x12, 0xe1, + 0x30, 0xf9, 0x86, 0x49, 0x1e, 0xae, 0x84, 0xb3, + }), + uint256(std::vector{ + 0x49, 0xdb, 0x2d, 0x5e, 0x22, 0xb8, 0x01, 0x5c, + 0xae, 0x48, 0x10, 0xd7, 0x5e, 0x54, 0x01, 0x4c, + 0x54, 0x69, 0x86, 0x27, 0x38, 0xe1, 0x61, 0xec, + 0x96, 0xec, 0x20, 0x21, 0x87, 0x18, 0x82, 0x8a, + }), + uint256(std::vector{ + 0xd4, 0x85, 0x1f, 0xb8, 0x43, 0x1e, 0xdf, 0xbb, + 0x8b, 0x1e, 0x85, 0xad, 0xa6, 0x89, 0x59, 0x67, + 0xc2, 0xda, 0xc8, 0x7d, 0xf3, 0x44, 0x99, 0x2a, + 0x05, 0xfa, 0xf1, 0xec, 0xf8, 0x36, 0xee, 0xc9, + }), + uint256(std::vector{ + 0xe4, 0xab, 0x9f, 0x44, 0x70, 0xf0, 0x0c, 0xd1, + 0x96, 0xd4, 0x7c, 0x75, 0xc8, 0x2e, 0x7a, 0xda, + 0xf0, 0x6f, 0xe1, 0x7e, 0x04, 0x2e, 0x39, 0x53, + 0xd9, 0x3b, 0xb5, 0xd5, 0x6d, 0x8c, 0xd8, 0xfb, + }), + uint256(std::vector{ + 0x7e, 0x43, 0x20, 0x43, 0x48, 0x49, 0xec, 0xb3, + 0x57, 0xf1, 0xaf, 0xaa, 0xba, 0x21, 0xa5, 0x44, + 0x00, 0xef, 0x2d, 0x11, 0xcf, 0xf8, 0x3b, 0x93, + 0x7d, 0x87, 0xfd, 0xaf, 0xa4, 0x9f, 0x81, 0x99, + }), + uint256(std::vector{ + 0x02, 0x0a, 0xdc, 0x98, 0xd9, 0x6c, 0xfb, 0xbc, + 0xca, 0x15, 0xfc, 0x3a, 0xa0, 0x37, 0x60, 0xed, + 0x28, 0x66, 0x86, 0xc3, 0x5b, 0x5d, 0x92, 0xc7, + 0xcb, 0x64, 0xa9, 0x99, 0xb3, 0x94, 0xa8, 0x54, + }), + uint256(std::vector{ + 0x3a, 0x26, 0xb2, 0x9f, 0xe1, 0xac, 0xfd, 0xd6, + 0xc6, 0xa1, 0x51, 0xbc, 0xc3, 0xdb, 0xcb, 0x95, + 0xa1, 0x0e, 0xbe, 0x2f, 0x05, 0x53, 0xf8, 0x07, + 0x79, 0x56, 0x9b, 0x67, 0xb7, 0x24, 0x4e, 0x77, + }), + uint256(std::vector{ + 0xec, 0x2d, 0x09, 0x86, 0xe6, 0xa0, 0xdd, 0xf4, + 0x38, 0x97, 0xb2, 0xd4, 0xf2, 0x3b, 0xb0, 0x34, + 0xf5, 0x38, 0xff, 0xe0, 0x08, 0x27, 0xf3, 0x10, + 0xdc, 0x49, 0x63, 0xf3, 0x26, 0x7f, 0x0b, 0xfb, + }), + uint256(std::vector{ + 0xd4, 0x80, 0x73, 0xf8, 0x81, 0x9f, 0x81, 0xf0, + 0x35, 0x8e, 0x3f, 0xc3, 0x5a, 0x04, 0x7c, 0xc7, + 0x40, 0x82, 0xae, 0x1c, 0xb7, 0xee, 0x22, 0xfb, + 0x60, 0x9c, 0x01, 0x64, 0x93, 0x42, 0xd0, 0xe6, + }), + uint256(std::vector{ + 0xad, 0x80, 0x37, 0x60, 0x17, 0x93, 0xf1, 0x72, + 0x44, 0x1e, 0xcb, 0x00, 0xdc, 0x13, 0x8d, 0x9f, + 0xc5, 0x95, 0x71, 0x25, 0xec, 0xc3, 0x82, 0xec, + 0x65, 0xe3, 0x6f, 0x81, 0x7d, 0xc7, 0x99, 0xfb, + }), + uint256(std::vector{ + 0xca, 0x50, 0x0a, 0x54, 0x41, 0xf3, 0x6f, 0x4d, + 0xf6, 0x73, 0xd6, 0xb8, 0xed, 0x07, 0x5d, 0x36, + 0xda, 0xe2, 0xc7, 0xe6, 0x48, 0x14, 0x28, 0xc7, + 0x0a, 0x5a, 0x76, 0xb7, 0xa9, 0xbe, 0xbc, 0xe8, + }), + uint256(std::vector{ + 0x42, 0x2b, 0x6d, 0xdd, 0x47, 0x32, 0x31, 0xdc, + 0x4d, 0x56, 0xfe, 0x91, 0x34, 0x44, 0xcc, 0xd5, + 0x6f, 0x7c, 0x61, 0xf7, 0x47, 0xba, 0x57, 0xca, + 0x94, 0x6d, 0x5f, 0xef, 0x72, 0xd8, 0x40, 0xa0, + }), + uint256(std::vector{ + 0xab, 0x41, 0xf4, 0xec, 0xb7, 0xd7, 0x08, 0x96, + 0x15, 0x80, 0x0e, 0x19, 0xfc, 0xc5, 0x3b, 0x83, + 0x79, 0xed, 0x05, 0xee, 0x35, 0xc8, 0x25, 0x67, + 0x09, 0x55, 0x83, 0xfd, 0x90, 0xff, 0x30, 0x35, + }), + uint256(std::vector{ + 0xbb, 0xf7, 0x61, 0x82, 0x48, 0x35, 0x4c, 0xeb, + 0x1b, 0xc1, 0xfc, 0x9d, 0xbc, 0x42, 0xc4, 0x26, + 0xa4, 0xe2, 0xc1, 0xe0, 0xd4, 0x43, 0xc5, 0x68, + 0x3a, 0x92, 0x56, 0xc6, 0x2e, 0xcd, 0xc2, 0x6f, + }), + uint256(std::vector{ + 0xe5, 0x0a, 0xe7, 0x14, 0x79, 0xfc, 0x8e, 0xc5, + 0x69, 0x19, 0x2a, 0x13, 0x07, 0x2e, 0x01, 0x1a, + 0xfc, 0x24, 0x9f, 0x47, 0x1a, 0xf0, 0x95, 0x00, + 0xea, 0x39, 0xf7, 0x5d, 0x0a, 0xf8, 0x56, 0xbf, + }), + uint256(std::vector{ + 0xe7, 0x4c, 0x0b, 0x92, 0x20, 0x14, 0x7d, 0xb2, + 0xd5, 0x0a, 0x3b, 0x58, 0xd4, 0x13, 0x77, 0x5d, + 0x16, 0xc9, 0x84, 0x69, 0x0b, 0xe7, 0xd9, 0x0f, + 0x0b, 0xc4, 0x3d, 0x99, 0xdb, 0xa1, 0xb6, 0x89, + }), + uint256(std::vector{ + 0x29, 0x32, 0x4a, 0x0a, 0x48, 0xd1, 0x16, 0x57, + 0xa5, 0x1b, 0xa0, 0x8b, 0x00, 0x48, 0x79, 0xbf, + 0xcf, 0xc6, 0x6a, 0x1a, 0xcb, 0x7c, 0xe3, 0x6d, + 0xfe, 0x47, 0x8d, 0x26, 0x55, 0x48, 0x4b, 0x48, + }), + uint256(std::vector{ + 0x88, 0x95, 0x2e, 0x3d, 0x0a, 0xc0, 0x6c, 0xb1, + 0x6b, 0x66, 0x52, 0x01, 0x12, 0x22, 0x49, 0x65, + 0x9a, 0x22, 0x32, 0x5e, 0x01, 0xc8, 0x70, 0xf4, + 0x9e, 0x29, 0xda, 0x6b, 0x17, 0x57, 0xe0, 0x82, + }), + uint256(std::vector{ + 0xcd, 0xf8, 0x79, 0xf2, 0x43, 0x5b, 0x95, 0xaf, + 0x04, 0x2a, 0x3b, 0xf7, 0xb8, 0x50, 0xf7, 0x81, + 0x92, 0x46, 0xc8, 0x05, 0x28, 0x58, 0x03, 0xd6, + 0x7f, 0xfb, 0xf4, 0xf2, 0x95, 0xbe, 0xd0, 0x04, + }), + uint256(std::vector{ + 0xe0, 0x05, 0xe3, 0x24, 0x20, 0x0b, 0x4f, 0x42, + 0x8c, 0x62, 0xbc, 0x33, 0x31, 0xe6, 0x95, 0xc3, + 0x73, 0x60, 0x7c, 0xd0, 0xfa, 0xa9, 0x79, 0x03, + 0x41, 0xfa, 0x3b, 0xa1, 0xed, 0x22, 0x8b, 0xc5, + }), + uint256(std::vector{ + 0x35, 0x44, 0x47, 0x72, 0x7a, 0xa9, 0xa5, 0x3d, + 0xd8, 0x34, 0x5b, 0x6b, 0x6c, 0x69, 0x34, 0x43, + 0xe5, 0x6e, 0xf4, 0xae, 0xba, 0x13, 0xc4, 0x10, + 0x17, 0x9f, 0xc8, 0x58, 0x9e, 0x77, 0x33, 0xd5, + }), + uint256(std::vector{ + 0xda, 0x52, 0xdd, 0xa9, 0x1f, 0x28, 0x29, 0xc1, + 0x5c, 0x0e, 0x58, 0xd2, 0x9a, 0x95, 0x36, 0x0b, + 0x86, 0xab, 0x30, 0xcf, 0x0c, 0xac, 0x81, 0x01, + 0x83, 0x2a, 0x29, 0xf3, 0x8c, 0x31, 0x85, 0xf1, + }), + uint256(std::vector{ + 0xc7, 0xda, 0x78, 0x14, 0xe2, 0x28, 0xe1, 0x14, + 0x44, 0x11, 0xd7, 0x8b, 0x53, 0x60, 0x92, 0xfe, + 0x92, 0x0b, 0xcd, 0xfc, 0xc3, 0x6c, 0xf1, 0x9d, + 0x12, 0x59, 0x04, 0x7b, 0x26, 0x7d, 0x58, 0xb5, + }), + uint256(std::vector{ + 0xab, 0xa1, 0xf6, 0x8b, 0x6c, 0x2b, 0x4d, 0xb6, + 0xcc, 0x06, 0xa7, 0x34, 0x0e, 0x12, 0x31, 0x3c, + 0x4b, 0x4a, 0x4e, 0xa6, 0xde, 0xb1, 0x7d, 0xeb, + 0x3e, 0x1e, 0x66, 0xcd, 0x8e, 0xac, 0xf3, 0x2b, + }), + uint256(std::vector{ + 0xc1, 0x60, 0xae, 0x4f, 0x64, 0xab, 0x76, 0x4d, + 0x86, 0x4a, 0x52, 0xad, 0x5e, 0x33, 0x12, 0x6c, + 0x4b, 0x5c, 0xe1, 0x05, 0xa4, 0x7d, 0xee, 0xdd, + 0x75, 0xbc, 0x70, 0x19, 0x9a, 0x52, 0x47, 0xef, + }), + uint256(std::vector{ + 0xea, 0xdf, 0x23, 0xfc, 0x99, 0xd5, 0x14, 0xdd, + 0x8e, 0xa2, 0x04, 0xd2, 0x23, 0xe9, 0x8d, 0xa9, + 0x88, 0x83, 0x1f, 0x9b, 0x5d, 0x19, 0x40, 0x27, + 0x4c, 0xa5, 0x20, 0xb7, 0xfb, 0x17, 0x3d, 0x8a, + }), + uint256(std::vector{ + 0x5b, 0x8e, 0x14, 0xfa, 0xca, 0xc8, 0xa7, 0xc7, + 0xa3, 0xbf, 0xee, 0x8b, 0xae, 0x71, 0xf2, 0xf7, + 0x79, 0x3d, 0x3a, 0xd5, 0xfe, 0x33, 0x83, 0xf9, + 0x3a, 0xb6, 0x06, 0x1f, 0x2a, 0x11, 0xbb, 0x02 + }), +}; + +SHA256Compress SHA256Compress::EmptyRoot(size_t depth) { + assert(depth <= sizeof(sha256_empty_roots)/sizeof(sha256_empty_roots[0])); + return sha256_empty_roots[depth]; +} + template class PathFiller { private: diff --git a/src/zcash/IncrementalMerkleTree.hpp b/src/zcash/IncrementalMerkleTree.hpp index 79a90bc5bb5..1ebb2b499d6 100644 --- a/src/zcash/IncrementalMerkleTree.hpp +++ b/src/zcash/IncrementalMerkleTree.hpp @@ -57,14 +57,9 @@ class MerklePath { template class EmptyMerkleRoots { public: - EmptyMerkleRoots() { - empty_roots.at(0) = Hash::uncommitted(); - for (size_t d = 1; d <= Depth; d++) { - empty_roots.at(d) = Hash::combine(empty_roots.at(d-1), empty_roots.at(d-1), d-1); - } - } - Hash empty_root(size_t depth) { - return empty_roots.at(depth); + EmptyMerkleRoots() { } + Hash empty_root(size_t depth) const { + return Hash::EmptyRoot(depth); } template friend bool operator==(const EmptyMerkleRoots& a, @@ -227,6 +222,7 @@ class SHA256Compress : public uint256 { static SHA256Compress uncommitted() { return SHA256Compress(); } + static SHA256Compress EmptyRoot(size_t); }; class PedersenHash : public uint256 { @@ -241,6 +237,7 @@ class PedersenHash : public uint256 { ); static PedersenHash uncommitted(); + static PedersenHash EmptyRoot(size_t); }; template From a3eb2b8708a8ebe376cad8b2bce117769f2fe654 Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Fri, 13 Sep 2019 09:12:05 -0600 Subject: [PATCH 336/395] update unit tests to compute empty roots --- src/Makefile.test.include | 2 - src/gtest/test_merkletree.cpp | 22 +++--- src/test/data/merkle_roots_empty.json | 68 ------------------- src/test/data/merkle_roots_empty_sapling.json | 65 ------------------ 4 files changed, 12 insertions(+), 145 deletions(-) delete mode 100644 src/test/data/merkle_roots_empty.json delete mode 100644 src/test/data/merkle_roots_empty_sapling.json diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 42ca0d13875..a73e0ed71cf 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -33,13 +33,11 @@ JSON_TEST_FILES = \ test/data/tx_valid.json \ test/data/sighash.json \ test/data/merkle_roots.json \ - test/data/merkle_roots_empty.json \ test/data/merkle_serialization.json \ test/data/merkle_witness_serialization.json \ test/data/merkle_path.json \ test/data/merkle_commitments.json \ test/data/merkle_roots_sapling.json \ - test/data/merkle_roots_empty_sapling.json \ test/data/merkle_serialization_sapling.json \ test/data/merkle_witness_serialization_sapling.json \ test/data/merkle_path_sapling.json \ diff --git a/src/gtest/test_merkletree.cpp b/src/gtest/test_merkletree.cpp index dd9fbf85067..ad3c2ad0676 100644 --- a/src/gtest/test_merkletree.cpp +++ b/src/gtest/test_merkletree.cpp @@ -1,14 +1,12 @@ #include #include "test/data/merkle_roots.json.h" -#include "test/data/merkle_roots_empty.json.h" #include "test/data/merkle_serialization.json.h" #include "test/data/merkle_witness_serialization.json.h" #include "test/data/merkle_path.json.h" #include "test/data/merkle_commitments.json.h" #include "test/data/merkle_roots_sapling.json.h" -#include "test/data/merkle_roots_empty_sapling.json.h" #include "test/data/merkle_serialization_sapling.json.h" #include "test/data/merkle_witness_serialization_sapling.json.h" #include "test/data/merkle_path_sapling.json.h" @@ -165,12 +163,14 @@ TEST(merkletree, SaplingVectors) { } TEST(merkletree, emptyroots) { - UniValue empty_roots = read_json(MAKE_STRING(json_tests::merkle_roots_empty)); - libzcash::EmptyMerkleRoots<64, libzcash::SHA256Compress> emptyroots; + std::array computed; - for (size_t depth = 0; depth <= 64; depth++) { - expect_test_vector(empty_roots[depth], emptyroots.empty_root(depth)); + computed.at(0) = libzcash::SHA256Compress::uncommitted(); + ASSERT_TRUE(emptyroots.empty_root(0) == computed.at(0)); + for (size_t d = 1; d <= 64; d++) { + computed.at(d) = libzcash::SHA256Compress::combine(computed.at(d-1), computed.at(d-1), d-1); + ASSERT_TRUE(emptyroots.empty_root(d) == computed.at(d)); } // Double check that we're testing (at least) all the empty roots we'll use. @@ -178,12 +178,14 @@ TEST(merkletree, emptyroots) { } TEST(merkletree, EmptyrootsSapling) { - UniValue empty_roots = read_json(MAKE_STRING(json_tests::merkle_roots_empty_sapling)); - libzcash::EmptyMerkleRoots<62, libzcash::PedersenHash> emptyroots; + std::array computed; - for (size_t depth = 0; depth <= 62; depth++) { - expect_test_vector(empty_roots[depth], emptyroots.empty_root(depth)); + computed.at(0) = libzcash::PedersenHash::uncommitted(); + ASSERT_TRUE(emptyroots.empty_root(0) == computed.at(0)); + for (size_t d = 1; d <= 62; d++) { + computed.at(d) = libzcash::PedersenHash::combine(computed.at(d-1), computed.at(d-1), d-1); + ASSERT_TRUE(emptyroots.empty_root(d) == computed.at(d)); } // Double check that we're testing (at least) all the empty roots we'll use. diff --git a/src/test/data/merkle_roots_empty.json b/src/test/data/merkle_roots_empty.json deleted file mode 100644 index df2674190ab..00000000000 --- a/src/test/data/merkle_roots_empty.json +++ /dev/null @@ -1,68 +0,0 @@ -[ - "0000000000000000000000000000000000000000000000000000000000000000", - "da5698be17b9b46962335799779fbeca8ce5d491c0d26243bafef9ea1837a9d8", - "dc766fab492ccf3d1e49d4f374b5235fa56506aac2224d39f943fcd49202974c", - "3f0a406181105968fdaee30679e3273c66b72bf9a7f5debbf3b5a0a26e359f92", - "26b0052694fc42fdff93e6fb5a71d38c3dd7dc5b6ad710eb048c660233137fab", - "0109ecc0722659ff83450b8f7b8846e67b2859f33c30d9b7acd5bf39cae54e31", - "3f909b8ce3d7ffd8a5b30908f605a03b0db85169558ddc1da7bbbcc9b09fd325", - "40460fa6bc692a06f47521a6725a547c028a6a240d8409f165e63cb54da2d23f", - "8c085674249b43da1b9a31a0e820e81e75f342807b03b6b9e64983217bc2b38e", - "a083450c1ba2a3a7be76fad9d13bc37be4bf83bd3e59fc375a36ba62dc620298", - "1ddddabc2caa2de9eff9e18c8c5a39406d7936e889bc16cfabb144f5c0022682", - "c22d8f0b5e4056e5f318ba22091cc07db5694fbeb5e87ef0d7e2c57ca352359e", - "89a434ae1febd7687eceea21d07f20a2512449d08ce2eee55871cdb9d46c1233", - "7333dbffbd11f09247a2b33a013ec4c4342029d851e22ba485d4461851370c15", - "5dad844ab9466b70f745137195ca221b48f346abd145fb5efc23a8b4ba508022", - "507e0dae81cbfbe457fd370ef1ca4201c2b6401083ddab440e4a038dc1e358c4", - "bdcdb3293188c9807d808267018684cfece07ac35a42c00f2c79b4003825305d", - "bab5800972a16c2c22530c66066d0a5867e987bed21a6d5a450b683cf1cfd709", - "11aa0b4ad29b13b057a31619d6500d636cd735cdd07d811ea265ec4bcbbbd058", - "5145b1b055c2df02b95675e3797b91de1b846d25003c0a803d08900728f2cd6a", - "0323f2850bf3444f4b4c5c09a6057ec7169190f45acb9e46984ab3dfcec4f06a", - "671546e26b1da1af754531e26d8a6a51073a57ddd72dc472efb43fcb257cffff", - "bb23a9bba56de57cb284b0d2b01c642cf79c9a5563f0067a21292412145bd78a", - "f30cc836b9f71b4e7ee3c72b1fd253268af9a27e9d7291a23d02821b21ddfd16", - "58a2753dade103cecbcda50b5ebfce31e12d41d5841dcc95620f7b3d50a1b9a1", - "925e6d474a5d8d3004f29da0dd78d30ae3824ce79dfe4934bb29ec3afaf3d521", - "08f279618616bcdd4eadc9c7a9062691a59b43b07e2c1e237f17bd189cd6a8fe", - "c92b32db42f42e2bf0a59df9055be5c669d3242df45357659b75ae2c27a76f50", - "c0db2a74998c50eb7ba6534f6d410efc27c4bb88acb0222c7906ea28a327b511", - "d7c612c817793191a1e68652121876d6b3bde40f4fa52bc314145ce6e5cdd259", - "b22370106c67a17209f6130bc09f735d83aa2c04fc4fe72ea5d80b216723e7ce", - "9f67d5f664664c901940eee3d02dd5b3e4b92e7b42820c42fc5159e91b41172a", - "ac58cd1388fec290d398f1944b564449a63c815880566bd1d189f7839e3b0c8c", - "5698eae7c8515ed05a70339bdf7c1028e7acca13a4fa97d9538f01ac8d889ae3", - "2d4995770a76fb93314ca74b3524ea1db5688ad0a76183ea17204a8f024a9f3b", - "5e8992c1b072c16e9e28a85358fb5fb6901a81587766dadb7aa0b973ded2f264", - "e95db71e1f7291ba5499461bc715203e29b84bfa4283e3bb7f470a15d0e1584e", - "41f078bd1824c8a4b71964f394aa595084d8eb17b97a3630433af70d10e0eff6", - "a1913fe6b20132312f8c1f00ddd63cec7a03f5f1d7d83492fa284c0b5d6320b0", - "ba9440c4dbfcf55ceb605a5b8990fc11f8ef22870d8d12e130f986491eae84b3", - "49db2d5e22b8015cae4810d75e54014c5469862738e161ec96ec20218718828a", - "d4851fb8431edfbb8b1e85ada6895967c2dac87df344992a05faf1ecf836eec9", - "e4ab9f4470f00cd196d47c75c82e7adaf06fe17e042e3953d93bb5d56d8cd8fb", - "7e4320434849ecb357f1afaaba21a54400ef2d11cff83b937d87fdafa49f8199", - "020adc98d96cfbbcca15fc3aa03760ed286686c35b5d92c7cb64a999b394a854", - "3a26b29fe1acfdd6c6a151bcc3dbcb95a10ebe2f0553f80779569b67b7244e77", - "ec2d0986e6a0ddf43897b2d4f23bb034f538ffe00827f310dc4963f3267f0bfb", - "d48073f8819f81f0358e3fc35a047cc74082ae1cb7ee22fb609c01649342d0e6", - "ad8037601793f172441ecb00dc138d9fc5957125ecc382ec65e36f817dc799fb", - "ca500a5441f36f4df673d6b8ed075d36dae2c7e6481428c70a5a76b7a9bebce8", - "422b6ddd473231dc4d56fe913444ccd56f7c61f747ba57ca946d5fef72d840a0", - "ab41f4ecb7d7089615800e19fcc53b8379ed05ee35c82567095583fd90ff3035", - "bbf7618248354ceb1bc1fc9dbc42c426a4e2c1e0d443c5683a9256c62ecdc26f", - "e50ae71479fc8ec569192a13072e011afc249f471af09500ea39f75d0af856bf", - "e74c0b9220147db2d50a3b58d413775d16c984690be7d90f0bc43d99dba1b689", - "29324a0a48d11657a51ba08b004879bfcfc66a1acb7ce36dfe478d2655484b48", - "88952e3d0ac06cb16b665201122249659a22325e01c870f49e29da6b1757e082", - "cdf879f2435b95af042a3bf7b850f7819246c805285803d67ffbf4f295bed004", - "e005e324200b4f428c62bc3331e695c373607cd0faa9790341fa3ba1ed228bc5", - "354447727aa9a53dd8345b6b6c693443e56ef4aeba13c410179fc8589e7733d5", - "da52dda91f2829c15c0e58d29a95360b86ab30cf0cac8101832a29f38c3185f1", - "c7da7814e228e1144411d78b536092fe920bcdfcc36cf19d1259047b267d58b5", - "aba1f68b6c2b4db6cc06a7340e12313c4b4a4ea6deb17deb3e1e66cd8eacf32b", - "c160ae4f64ab764d864a52ad5e33126c4b5ce105a47deedd75bc70199a5247ef", - "eadf23fc99d514dd8ea204d223e98da988831f9b5d1940274ca520b7fb173d8a", - "5b8e14facac8a7c7a3bfee8bae71f2f7793d3ad5fe3383f93ab6061f2a11bb02" -] diff --git a/src/test/data/merkle_roots_empty_sapling.json b/src/test/data/merkle_roots_empty_sapling.json deleted file mode 100644 index e9646d5c714..00000000000 --- a/src/test/data/merkle_roots_empty_sapling.json +++ /dev/null @@ -1,65 +0,0 @@ -[ - "0100000000000000000000000000000000000000000000000000000000000000", - "817de36ab2d57feb077634bca77819c8e0bd298c04f6fed0e6a83cc1356ca155", - "ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e34", - "d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c", - "e110de65c907b9dea4ae0bd83a4b0a51bea175646a64c12b4c9f931b2cb31b49", - "912d82b2c2bca231f71efcf61737fbf0a08befa0416215aeef53e8bb6d23390a", - "8ac9cf9c391e3fd42891d27238a81a8a5c1d3a72b1bcbea8cf44a58ce7389613", - "d6c639ac24b46bd19341c91b13fdcab31581ddaf7f1411336a271f3d0aa52813", - "7b99abdc3730991cc9274727d7d82d28cb794edbc7034b4f0053ff7c4b680444", - "43ff5457f13b926b61df552d4e402ee6dc1463f99a535f9a713439264d5b616b", - "ba49b659fbd0b7334211ea6a9d9df185c757e70aa81da562fb912b84f49bce72", - "4777c8776a3b1e69b73a62fa701fa4f7a6282d9aee2c7a6b82e7937d7081c23c", - "ec677114c27206f5debc1c1ed66f95e2b1885da5b7be3d736b1de98579473048", - "1b77dac4d24fb7258c3c528704c59430b630718bec486421837021cf75dab651", - "bd74b25aacb92378a871bf27d225cfc26baca344a1ea35fdd94510f3d157082c", - "d6acdedf95f608e09fa53fb43dcd0990475726c5131210c9e5caeab97f0e642f", - "1ea6675f9551eeb9dfaaa9247bc9858270d3d3a4c5afa7177a984d5ed1be2451", - "6edb16d01907b759977d7650dad7e3ec049af1a3d875380b697c862c9ec5d51c", - "cd1c8dbf6e3acc7a80439bc4962cf25b9dce7c896f3a5bd70803fc5a0e33cf00", - "6aca8448d8263e547d5ff2950e2ed3839e998d31cbc6ac9fd57bc6002b159216", - "8d5fa43e5a10d11605ac7430ba1f5d81fb1b68d29a640405767749e841527673", - "08eeab0c13abd6069e6310197bf80f9c1ea6de78fd19cbae24d4a520e6cf3023", - "0769557bc682b1bf308646fd0b22e648e8b9e98f57e29f5af40f6edb833e2c49", - "4c6937d78f42685f84b43ad3b7b00f81285662f85c6a68ef11d62ad1a3ee0850", - "fee0e52802cb0c46b1eb4d376c62697f4759f6c8917fa352571202fd778fd712", - "16d6252968971a83da8521d65382e61f0176646d771c91528e3276ee45383e4a", - "d2e1642c9a462229289e5b0e3b7f9008e0301cbb93385ee0e21da2545073cb58", - "a5122c08ff9c161d9ca6fc462073396c7d7d38e8ee48cdb3bea7e2230134ed6a", - "28e7b841dcbc47cceb69d7cb8d94245fb7cb2ba3a7a6bc18f13f945f7dbd6e2a", - "e1f34b034d4a3cd28557e2907ebf990c918f64ecb50a94f01d6fda5ca5c7ef72", - "12935f14b676509b81eb49ef25f39269ed72309238b4c145803544b646dca62d", - "b2eed031d4d6a4f02a097f80b54cc1541d4163c6b6f5971f88b6e41d35c53814", - "fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e", - "252e6798645f5bf114e4b4e90e96182861489840d9b4ccc4c1fb5a46997cee14", - "98b19042f1f7c7dd11ec25ea66b6ff74e08ce11d447ed6f1bfe87e110e331e11", - "d451304799572ba9f42c4dab6b07c703bd2c123ab9d60f2a60f9955854910b6a", - "3ecd5f27acf01bd37a33e4517867ef76474cd83fb31c9208dcef2eedcef36c72", - "26c37da67894a13df8aa4878d2514a4212573b73eccaab16fe4fa660e8fe2707", - "b545ef34485eed30d42b2c295a4a5b680de8a9d5e38345782462c04f09dc6851", - "77fd20b300946765a87f24bd045073729cbd7b66eb8fa140b583faa9d1425801", - "cbaa576b1799b58ff3a6decbba919b0b68d7c893e46fde998768e87e350a0725", - "45fe81b18ca30074d0120d2b1a0d10b3a050933512db8ee34e52473d4f08a267", - "0e60a1f0121f591e551d3ed1865b50a75d7ccff1289df7c44dd465a54317f56a", - "cedfb184dd92a0cbfc11e8be697b476988ed5f39369abdd90c61544988601c0d", - "f362686612649a313ba464437a0cad0e7e3d7e1b4b3743f90e05a2100a495f42", - "7deae5f3bbdeffd3f85271a08b5ec31f16f937964ae708fdff7c13e5a4f3df6b", - "40ccf0fc1eab6d8502bd93dc31342dfd57df5bbb5d70a1bf6b92efc61ec9a258", - "d78025491f1bca8507f64f25872dd02388479a1a225126e40d2fe418b98e0e2c", - "0db7294685c8a0725f15846ea5899ea0e986c2707bd7b412954412f26abf550a", - "b7e290be9555cf75548650da6d47c893aef7f8c6dd2735499495f636590dae0a", - "2dd2532a858c300145a65e351f91be6afeab597c41ef073f50b622d586ff5927", - "972f0c5c6f9aeb0e38bf8319f3a5fcdc8fd8782e4188730cd082d9babc589851", - "001e577b0f4390182b4ae43d329b3aa8835dae1bb79e604b7d2da0e90d060929", - "aa6e70a91ebc54eefce5ffd5b675daf3f1d940a8451fcb01081fa9d4f262436f", - "d77038bf67e631752940231251d7fe85af52dbdd6aab37c7a5ec32b65fe6de03", - "d227a17a7e0cf96dcedd9fc7bce43c6c1d66badd7543a887c8656c547ecfb24f", - "70e8a521951583e53fc0585c707eceda89b7a7d1af41d1a015d797fa76c0f569", - "e485a96855e872fc5090150e2cd24e10591d35166eb0eb30fcdfac93b01d281c", - "e4a19febdf2a86896e41f2cedcf2ae584671802e6a467e8439cab5d61843416b", - "e927838847806a43bd6c6088e39f65b8b3e58b2db5f7ad5643d91e0659a28a2a", - "0bd3a818e83f9cd2ff4f62011a510176ac32f5448e6e154515043c5926d51c6f", - "ce413445e03790498fe72d8e01915e7ff120ae35b3b590d21b7f74dee1830f0d", - "600e6f93e73d7abd4ee0a65cb1b19aa3ecc525689dbf17779658741b95c15a55" -] From ffb8e6747bd4c89e40109987be9246a751ad6f9d Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Sat, 12 Oct 2019 19:06:51 -0600 Subject: [PATCH 337/395] access array element using at() --- src/zcash/IncrementalMerkleTree.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/zcash/IncrementalMerkleTree.cpp b/src/zcash/IncrementalMerkleTree.cpp index 5a7d71537f2..b8b3cd18378 100644 --- a/src/zcash/IncrementalMerkleTree.cpp +++ b/src/zcash/IncrementalMerkleTree.cpp @@ -417,8 +417,7 @@ static const std::array pedersen_empty_roots = { }; PedersenHash PedersenHash::EmptyRoot(size_t depth) { - assert(depth <= sizeof(pedersen_empty_roots)/sizeof(pedersen_empty_roots[0])); - return pedersen_empty_roots[depth]; + return pedersen_empty_roots.at(depth); } SHA256Compress SHA256Compress::combine( @@ -837,8 +836,7 @@ static const std::array sha256_empty_roots = { }; SHA256Compress SHA256Compress::EmptyRoot(size_t depth) { - assert(depth <= sizeof(sha256_empty_roots)/sizeof(sha256_empty_roots[0])); - return sha256_empty_roots[depth]; + return sha256_empty_roots.at(depth); } template From a80942f558a7d0a6e6c7d6fcbd15180a4d4503d9 Mon Sep 17 00:00:00 2001 From: Dimitris Apostolou Date: Wed, 16 Oct 2019 15:13:57 +0300 Subject: [PATCH 338/395] depends macOS: point --sysroot to SDK --- depends/builders/darwin.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/depends/builders/darwin.mk b/depends/builders/darwin.mk index 27f550ab036..7990b872fd8 100644 --- a/depends/builders/darwin.mk +++ b/depends/builders/darwin.mk @@ -10,8 +10,8 @@ build_darwin_SHA256SUM = shasum -a 256 build_darwin_DOWNLOAD = curl --location --fail --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -o #darwin host on darwin builder. overrides darwin host preferences. -darwin_CC=$(shell xcrun -f clang) -mmacosx-version-min=$(OSX_MIN_VERSION) -darwin_CXX:=$(shell xcrun -f clang++) -mmacosx-version-min=$(OSX_MIN_VERSION) -stdlib=libc++ +darwin_CC=$(shell xcrun -f clang) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(shell xcrun --show-sdk-path) +darwin_CXX:=$(shell xcrun -f clang++) -mmacosx-version-min=$(OSX_MIN_VERSION) -stdlib=libc++ --sysroot $(shell xcrun --show-sdk-path) darwin_AR:=$(shell xcrun -f ar) darwin_RANLIB:=$(shell xcrun -f ranlib) darwin_STRIP:=$(shell xcrun -f strip) From bbb6ce1007422b0469ca9cffe616c08acfc36741 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Thu, 17 Oct 2019 12:32:27 -0600 Subject: [PATCH 339/395] Update release notes --- doc/release-notes.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index 412d514df31..3cc2cb8488f 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,6 +4,20 @@ release-notes at release time) Notable changes =============== +DoS Mitigation: Mempool Size Limit and Random Drop +-------------------------------------------------- +This release adds a mechanism for preventing nodes from running out of memory +in the situation where an attacker is trying to overwhelm the network with +transactions. This is achieved by keeping track of and limiting the total +`cost`, a function of a transaction's size in bytes and its fee, of the +mempool. The maximum total cost is configurable via the parameter +`mempooltotalcostlimit` which defaults to 80,000,000 (up to 20,000 txs). If a +node's total mempool `cost` exceeds this limit the node will evict a random +transaction, weighted by its cost. To prevent a node from re-accepting evicted +transactions, it keeps track of ones that it has evicted recently. By default, +a transaction will be considered recently evicted for 60 minutes, but this can +be configured with the parameter `mempoolevictionmemoryminutes`. + Fake chain detection during initial block download -------------------------------------------------- From 1edeba61ac0eb5eda273d18448e9298251b10670 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Thu, 17 Oct 2019 12:32:33 -0600 Subject: [PATCH 340/395] Add test --- src/gtest/test_mempoollimit.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/gtest/test_mempoollimit.cpp b/src/gtest/test_mempoollimit.cpp index 0b269aa2d2a..7cfbab0006c 100644 --- a/src/gtest/test_mempoollimit.cpp +++ b/src/gtest/test_mempoollimit.cpp @@ -48,6 +48,33 @@ TEST(MempoolLimitTests, RecentlyEvictedListDoesNotContainAfterExpiry) EXPECT_TRUE(recentlyEvicted.contains(TX_ID2)); EXPECT_TRUE(recentlyEvicted.contains(TX_ID3)); SetMockTime(4); + EXPECT_FALSE(recentlyEvicted.contains(TX_ID1)); + EXPECT_FALSE(recentlyEvicted.contains(TX_ID2)); + EXPECT_FALSE(recentlyEvicted.contains(TX_ID3)); +} + +TEST(MempoolLimitTests, RecentlyEvictedDropOneAtATime) +{ + SetMockTime(1); + RecentlyEvictedList recentlyEvicted(3, 2); + recentlyEvicted.add(TX_ID1); + SetMockTime(2); + recentlyEvicted.add(TX_ID2); + SetMockTime(3); + recentlyEvicted.add(TX_ID3); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID1)); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID2)); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID3)); + SetMockTime(4); + EXPECT_FALSE(recentlyEvicted.contains(TX_ID1)); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID2)); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID3)); + SetMockTime(5); + EXPECT_FALSE(recentlyEvicted.contains(TX_ID1)); + EXPECT_FALSE(recentlyEvicted.contains(TX_ID2)); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID3)); + SetMockTime(6); + EXPECT_FALSE(recentlyEvicted.contains(TX_ID1)); EXPECT_FALSE(recentlyEvicted.contains(TX_ID2)); EXPECT_FALSE(recentlyEvicted.contains(TX_ID3)); } From 2033395e51c2f94f1c31631e2540afd327b2ef65 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Thu, 17 Oct 2019 12:37:05 -0600 Subject: [PATCH 341/395] minor rpc test clean up --- qa/rpc-tests/mempool_limit.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/mempool_limit.py b/qa/rpc-tests/mempool_limit.py index 9ce8487f53b..59802b19127 100755 --- a/qa/rpc-tests/mempool_limit.py +++ b/qa/rpc-tests/mempool_limit.py @@ -38,7 +38,7 @@ def check_mempool_sizes(self, expected_size, check_node3=True): for i in range(4 if check_node3 else 3): mempool = self.nodes[i].getrawmempool() if len(mempool) != expected_size: - # print all nodes mempools before failing + # print all nodes' mempools before failing for i in range(4): print("Mempool for node {}: {}".format(i, mempool)) fail("Fail: Mempool for node {}: size={}, expected={}".format(i, len(mempool), expected_size)) @@ -87,8 +87,8 @@ def run_test(self): self.sync_all() # The mempool sizes should be reset - self.check_mempool_sizes(0) print("Checking mempool size reset after block mined...") + self.check_mempool_sizes(0) zaddr4 = self.nodes[0].z_getnewaddress('sapling') opid4 = self.nodes[0].z_sendmany(zaddr1, [{"address": zaddr4, "amount": Decimal('9.998')}]) wait_and_assert_operationid_status(self.nodes[0], opid4) From 78592da52a89924b5d909cc511ed577ebd4781d1 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Thu, 17 Oct 2019 14:18:20 -0600 Subject: [PATCH 342/395] Add explanatory comments --- src/mempool_limit.h | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/mempool_limit.h b/src/mempool_limit.h index 63b24eaa15a..1a3cde7c62f 100644 --- a/src/mempool_limit.h +++ b/src/mempool_limit.h @@ -18,15 +18,20 @@ const int64_t DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES = 60; const size_t RECENTLY_EVICTED_SIZE = 40000; const uint64_t MIN_TX_WEIGHT = 4000; -const uint64_t LOW_FEE_PENALTY = 16000; +const uint64_t LOW_FEE_PENALTY = 16000; + +// This class keeps track of transactions which have been recently evicted from the mempool +// in order to prevent them from being re-accepted for a given amount of time. class RecentlyEvictedList { const size_t capacity; const int64_t timeToKeep; + // Pairs of txid and time (seconds since epoch) std::deque> txIdsAndTimes; + std::set txIdSet; void pruneList(); @@ -43,9 +48,15 @@ class RecentlyEvictedList }; +// The mempool of a node holds a set of transactions. Each transaction has a *cost*, +// which is an integer defined as: +// max(serialized transaction size in bytes, 4000) +// Each transaction also has an *eviction weight*, which is *cost* + *fee_penalty*, +// where *fee_penalty* is 16000 if the transaction pays a fee less than 10000 zatoshi, +// otherwise 0. struct TxWeight { int64_t cost; - int64_t evictionWeight; + int64_t evictionWeight; // *cost* + *fee_penalty* TxWeight(int64_t cost_, int64_t evictionWeight_) : cost(cost_), evictionWeight(evictionWeight_) {} @@ -55,27 +66,48 @@ struct TxWeight { }; +// This struct is a pair of txid, cost. struct WeightedTxInfo { uint256 txId; TxWeight txWeight; WeightedTxInfo(uint256 txId_, TxWeight txWeight_) : txId(txId_), txWeight(txWeight_) {} + // Factory method which calculates cost based on size in bytes and fee. static WeightedTxInfo from(const CTransaction& tx, const CAmount& fee); }; +// The following class is a collection of transaction ids and their costs. +// In order to be able to remove transactions randomly weighted by their cost, +// we keep track of the total cost of all transactions in this collection. +// For performance reasons, the collection is represented as a complete binary +// tree where each node knows the sum of the weights of the children. This +// allows for addition, removal, and random selection/dropping in logarithmic time. class WeightedTxTree { const int64_t capacity; size_t size = 0; + // The following two vectors are the tree representation of this collection. + // We keep track of 3 data points for each node: A transaction's txid, its cost, + // and the sum of the weights of all children and descendant of that node. std::vector txIdAndWeights; std::vector childWeights; + + // The following map is to simplify removal. When removing a tx, we do so by txid. + // This map allows look up the transactions index in the tree. std::map txIdToIndexMap; + // Returns the sum of a node and all of its childrens' TxWeights for a given index. TxWeight getWeightAt(size_t index) const; + + // When adding and removing a node we need to update its parent and all of its + // ancestors to reflect its cost. void backPropagate(size_t fromIndex, const TxWeight& weightDelta); + + // For a given random cost + fee penalty, this method recursively finds the + // correct transaction. This is used by WeightedTxTree::maybeDropRandom(). size_t findByEvictionWeight(size_t fromIndex, int64_t weightToFind) const; public: @@ -88,6 +120,8 @@ class WeightedTxTree void add(const WeightedTxInfo& weightedTxInfo); void remove(const uint256& txId); + // If the total cost limit is exceeded, pick a random number based on the total cost + // of the collection and remove the associated transaction. boost::optional maybeDropRandom(); }; From e7aed48e7a65b34a11ca2c93c13e0773c7b1a87e Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Thu, 17 Oct 2019 15:16:51 -0600 Subject: [PATCH 343/395] Wording and grammatical fixes --- doc/release-notes.md | 10 ++++++---- src/mempool_limit.h | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index 3cc2cb8488f..c5422000c75 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -6,6 +6,7 @@ Notable changes DoS Mitigation: Mempool Size Limit and Random Drop -------------------------------------------------- + This release adds a mechanism for preventing nodes from running out of memory in the situation where an attacker is trying to overwhelm the network with transactions. This is achieved by keeping track of and limiting the total @@ -13,10 +14,11 @@ transactions. This is achieved by keeping track of and limiting the total mempool. The maximum total cost is configurable via the parameter `mempooltotalcostlimit` which defaults to 80,000,000 (up to 20,000 txs). If a node's total mempool `cost` exceeds this limit the node will evict a random -transaction, weighted by its cost. To prevent a node from re-accepting evicted -transactions, it keeps track of ones that it has evicted recently. By default, -a transaction will be considered recently evicted for 60 minutes, but this can -be configured with the parameter `mempoolevictionmemoryminutes`. +transaction, preferentially picking larger transactions and ones with below +the standard fee. To prevent a node from re-accepting evicted transactions, it +keeps track of ones that it has evicted recently. By default, a transaction +will be considered recently evicted for 60 minutes, but this can be configured +with the parameter `mempoolevictionmemoryminutes`. Fake chain detection during initial block download -------------------------------------------------- diff --git a/src/mempool_limit.h b/src/mempool_limit.h index 1a3cde7c62f..b94e34ab85c 100644 --- a/src/mempool_limit.h +++ b/src/mempool_limit.h @@ -96,10 +96,10 @@ class WeightedTxTree std::vector childWeights; // The following map is to simplify removal. When removing a tx, we do so by txid. - // This map allows look up the transactions index in the tree. + // This map allows looking up the transaction's index in the tree. std::map txIdToIndexMap; - // Returns the sum of a node and all of its childrens' TxWeights for a given index. + // Returns the sum of a node and all of its children's TxWeights for a given index. TxWeight getWeightAt(size_t index) const; // When adding and removing a node we need to update its parent and all of its From 64fc25ed6eafa269b12ece456de7d60a8f2eb5b9 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Thu, 17 Oct 2019 16:39:32 -0600 Subject: [PATCH 344/395] Update parameter names to match ZIP --- doc/release-notes.md | 4 ++-- qa/rpc-tests/mempool_limit.py | 8 ++++---- src/gtest/test_mempoollimit.cpp | 16 ++++++++-------- src/init.cpp | 8 ++++---- src/mempool_limit.cpp | 2 +- src/mempool_limit.h | 8 ++++---- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index c5422000c75..4238e9f6b05 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -12,13 +12,13 @@ in the situation where an attacker is trying to overwhelm the network with transactions. This is achieved by keeping track of and limiting the total `cost`, a function of a transaction's size in bytes and its fee, of the mempool. The maximum total cost is configurable via the parameter -`mempooltotalcostlimit` which defaults to 80,000,000 (up to 20,000 txs). If a +`mempool.tx_cost_limit` which defaults to 80,000,000 (up to 20,000 txs). If a node's total mempool `cost` exceeds this limit the node will evict a random transaction, preferentially picking larger transactions and ones with below the standard fee. To prevent a node from re-accepting evicted transactions, it keeps track of ones that it has evicted recently. By default, a transaction will be considered recently evicted for 60 minutes, but this can be configured -with the parameter `mempoolevictionmemoryminutes`. +with the parameter `mempool.eviction_memory_minutes`. Fake chain detection during initial block download -------------------------------------------------- diff --git a/qa/rpc-tests/mempool_limit.py b/qa/rpc-tests/mempool_limit.py index 59802b19127..1c424a47aa0 100755 --- a/qa/rpc-tests/mempool_limit.py +++ b/qa/rpc-tests/mempool_limit.py @@ -26,11 +26,11 @@ def setup_chain(self): def setup_nodes(self): extra_args = [ - ["-debug=mempool", '-mempooltotalcostlimit=8000'], # 2 transactions at min cost - ["-debug=mempool", '-mempooltotalcostlimit=8000'], # 2 transactions at min cost - ["-debug=mempool", '-mempooltotalcostlimit=8000'], # 2 transactions at min cost + ["-debug=mempool", '-mempool.tx_cost_limit=8000'], # 2 transactions at min cost + ["-debug=mempool", '-mempool.tx_cost_limit=8000'], # 2 transactions at min cost + ["-debug=mempool", '-mempool.tx_cost_limit=8000'], # 2 transactions at min cost # Let node 3 hold one more transaction - ["-debug=mempool", '-mempooltotalcostlimit=12000'], # 3 transactions at min cost + ["-debug=mempool", '-mempool.tx_cost_limit=12000'], # 3 transactions at min cost ] return start_nodes(4, self.options.tmpdir, extra_args) diff --git a/src/gtest/test_mempoollimit.cpp b/src/gtest/test_mempoollimit.cpp index 7cfbab0006c..cdd16977f4d 100644 --- a/src/gtest/test_mempoollimit.cpp +++ b/src/gtest/test_mempoollimit.cpp @@ -85,17 +85,17 @@ TEST(MempoolLimitTests, WeightedTxTreeCheckSizeAfterDropping) // Run the test until we have tested dropping each of the elements int trialNum = 0; while (testedDropping.size() < 3) { - WeightedTxTree tree(MIN_TX_WEIGHT * 2); + WeightedTxTree tree(MIN_TX_COST * 2); EXPECT_EQ(0, tree.getTotalWeight().cost); EXPECT_EQ(0, tree.getTotalWeight().evictionWeight); - tree.add(WeightedTxInfo(TX_ID1, TxWeight(MIN_TX_WEIGHT, MIN_TX_WEIGHT))); + tree.add(WeightedTxInfo(TX_ID1, TxWeight(MIN_TX_COST, MIN_TX_COST))); EXPECT_EQ(4000, tree.getTotalWeight().cost); EXPECT_EQ(4000, tree.getTotalWeight().evictionWeight); - tree.add(WeightedTxInfo(TX_ID2, TxWeight(MIN_TX_WEIGHT, MIN_TX_WEIGHT))); + tree.add(WeightedTxInfo(TX_ID2, TxWeight(MIN_TX_COST, MIN_TX_COST))); EXPECT_EQ(8000, tree.getTotalWeight().cost); EXPECT_EQ(8000, tree.getTotalWeight().evictionWeight); EXPECT_FALSE(tree.maybeDropRandom().is_initialized()); - tree.add(WeightedTxInfo(TX_ID3, TxWeight(MIN_TX_WEIGHT, MIN_TX_WEIGHT + LOW_FEE_PENALTY))); + tree.add(WeightedTxInfo(TX_ID3, TxWeight(MIN_TX_COST, MIN_TX_COST + LOW_FEE_PENALTY))); EXPECT_EQ(12000, tree.getTotalWeight().cost); EXPECT_EQ(12000 + LOW_FEE_PENALTY, tree.getTotalWeight().evictionWeight); boost::optional drop = tree.maybeDropRandom(); @@ -126,8 +126,8 @@ TEST(MempoolLimitTests, WeightedTxInfoFromTx) builder.AddSaplingOutput(sk.full_viewing_key().ovk, sk.default_address(), 25000, {}); WeightedTxInfo info = WeightedTxInfo::from(builder.Build().GetTxOrThrow(), 10000); - EXPECT_EQ(MIN_TX_WEIGHT, info.txWeight.cost); - EXPECT_EQ(MIN_TX_WEIGHT, info.txWeight.evictionWeight); + EXPECT_EQ(MIN_TX_COST, info.txWeight.cost); + EXPECT_EQ(MIN_TX_COST, info.txWeight.evictionWeight); } // Lower than standard fee @@ -138,8 +138,8 @@ TEST(MempoolLimitTests, WeightedTxInfoFromTx) builder.SetFee(9999); WeightedTxInfo info = WeightedTxInfo::from(builder.Build().GetTxOrThrow(), 9999); - EXPECT_EQ(MIN_TX_WEIGHT, info.txWeight.cost); - EXPECT_EQ(MIN_TX_WEIGHT + LOW_FEE_PENALTY, info.txWeight.evictionWeight); + EXPECT_EQ(MIN_TX_COST, info.txWeight.cost); + EXPECT_EQ(MIN_TX_COST + LOW_FEE_PENALTY, info.txWeight.evictionWeight); } // Larger Tx diff --git a/src/init.cpp b/src/init.cpp index 78da4ab9f73..11d956551d5 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -384,8 +384,8 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-maxconnections=", strprintf(_("Maintain at most connections to peers (default: %u)"), DEFAULT_MAX_PEER_CONNECTIONS)); strUsage += HelpMessageOpt("-maxreceivebuffer=", strprintf(_("Maximum per-connection receive buffer, *1000 bytes (default: %u)"), 5000)); strUsage += HelpMessageOpt("-maxsendbuffer=", strprintf(_("Maximum per-connection send buffer, *1000 bytes (default: %u)"), 1000)); - strUsage += HelpMessageOpt("-mempoolevictionmemoryminutes=", strprintf(_("The number of minutes before allowing rejected transactions to re-enter the mempool. (default: %u)"), DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES)); - strUsage += HelpMessageOpt("-mempooltotalcostlimit=",strprintf(_("An upper bound on the maximum size in bytes of all transactions in the mempool. (default: %s)"), DEFAULT_MEMPOOL_TOTAL_COST_LIMIT)); + strUsage += HelpMessageOpt("-mempool.eviction_memory_minutes=", strprintf(_("The number of minutes before allowing rejected transactions to re-enter the mempool. (default: %u)"), DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES)); + strUsage += HelpMessageOpt("-mempool.tx_cost_limit=",strprintf(_("An upper bound on the maximum size in bytes of all transactions in the mempool. (default: %s)"), DEFAULT_MEMPOOL_TOTAL_COST_LIMIT)); strUsage += HelpMessageOpt("-onion=", strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy")); strUsage += HelpMessageOpt("-onlynet=", _("Only connect to nodes in network (ipv4, ipv6 or onion)")); strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), 1)); @@ -978,8 +978,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) mempool.setSanityCheck(1.0 / ratio); } - int64_t mempoolTotalCostLimit = GetArg("-mempooltotalcostlimit", DEFAULT_MEMPOOL_TOTAL_COST_LIMIT); - int64_t mempoolEvictionMemorySeconds = GetArg("-mempoolevictionmemoryminutes", DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES) * 60; + int64_t mempoolTotalCostLimit = GetArg("-mempool.tx_cost_limit", DEFAULT_MEMPOOL_TOTAL_COST_LIMIT); + int64_t mempoolEvictionMemorySeconds = GetArg("-mempool.eviction_memory_minutes", DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES) * 60; mempool.SetMempoolCostLimit(mempoolTotalCostLimit, mempoolEvictionMemorySeconds); fCheckBlockIndex = GetBoolArg("-checkblockindex", chainparams.DefaultConsistencyChecks()); diff --git a/src/mempool_limit.cpp b/src/mempool_limit.cpp index 3d3a8907bbb..762d2c7d1fa 100644 --- a/src/mempool_limit.cpp +++ b/src/mempool_limit.cpp @@ -151,7 +151,7 @@ WeightedTxInfo WeightedTxInfo::from(const CTransaction& tx, const CAmount& fee) memUsage += tx.vJoinSplit.size() * JOINSPLIT_SIZE; memUsage += tx.vShieldedOutput.size() * OUTPUTDESCRIPTION_SIZE; memUsage += tx.vShieldedSpend.size() * SPENDDESCRIPTION_SIZE; - int64_t cost = std::max(memUsage, MIN_TX_WEIGHT); + int64_t cost = std::max(memUsage, MIN_TX_COST); int64_t evictionWeight = cost; if (fee < DEFAULT_FEE) { evictionWeight += LOW_FEE_PENALTY; diff --git a/src/mempool_limit.h b/src/mempool_limit.h index b94e34ab85c..836144993ce 100644 --- a/src/mempool_limit.h +++ b/src/mempool_limit.h @@ -16,8 +16,8 @@ const size_t DEFAULT_MEMPOOL_TOTAL_COST_LIMIT = 80000000; const int64_t DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES = 60; -const size_t RECENTLY_EVICTED_SIZE = 40000; -const uint64_t MIN_TX_WEIGHT = 4000; +const size_t EVICTION_MEMORY_ENTRIES = 40000; +const uint64_t MIN_TX_COST = 4000; const uint64_t LOW_FEE_PENALTY = 16000; @@ -39,9 +39,9 @@ class RecentlyEvictedList public: RecentlyEvictedList(size_t capacity_, int64_t timeToKeep_) : capacity(capacity_), timeToKeep(timeToKeep_) { - assert(capacity <= RECENTLY_EVICTED_SIZE); + assert(capacity <= EVICTION_MEMORY_ENTRIES); } - RecentlyEvictedList(int64_t timeToKeep_) : RecentlyEvictedList(RECENTLY_EVICTED_SIZE, timeToKeep_) {} + RecentlyEvictedList(int64_t timeToKeep_) : RecentlyEvictedList(EVICTION_MEMORY_ENTRIES, timeToKeep_) {} void add(const uint256& txId); bool contains(const uint256& txId); From 898810213ca652e9e348b7d05a352334d612838e Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Thu, 17 Oct 2019 16:50:44 -0600 Subject: [PATCH 345/395] Clarify the difference between cost and evictionWeight --- doc/release-notes.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index 4238e9f6b05..5ce2a9d6670 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -10,15 +10,19 @@ DoS Mitigation: Mempool Size Limit and Random Drop This release adds a mechanism for preventing nodes from running out of memory in the situation where an attacker is trying to overwhelm the network with transactions. This is achieved by keeping track of and limiting the total -`cost`, a function of a transaction's size in bytes and its fee, of the -mempool. The maximum total cost is configurable via the parameter -`mempool.tx_cost_limit` which defaults to 80,000,000 (up to 20,000 txs). If a -node's total mempool `cost` exceeds this limit the node will evict a random -transaction, preferentially picking larger transactions and ones with below -the standard fee. To prevent a node from re-accepting evicted transactions, it -keeps track of ones that it has evicted recently. By default, a transaction -will be considered recently evicted for 60 minutes, but this can be configured -with the parameter `mempool.eviction_memory_minutes`. +`cost` and `evictionWeight` of all transactions in the mempool. The `cost` of a +transaction is determined by its size in bytes, and its `evictionWeight` is a +function of the transaction's `cost` and its fee. The maximum total cost is +configurable via the parameter `mempool.tx_cost_limit` which defaults to +80,000,000 (up to 20,000 txs). If a node's total mempool `cost` exceeds this +limit the node will evict a random transaction, preferentially picking larger +transactions and ones with below the standard fee. To prevent a node from +re-accepting evicted transactions, it keeps track of ones that it has evicted +recently. By default, a transaction will be considered recently evicted for 60 +minutes, but this can be configured with the parameter +`mempool.eviction_memory_minutes`. + +For full details see ZIP 401. Fake chain detection during initial block download -------------------------------------------------- From e744cece52c798ff784dcedb4204dbff74995a25 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 18 Oct 2019 13:36:12 -0600 Subject: [PATCH 346/395] Fix test cases: default mempool limiters --- src/txmempool.cpp | 10 ++-------- src/txmempool.h | 4 ++-- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 2ddf19ef295..9b60ef911cb 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -104,7 +104,6 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, // Used by main.cpp AcceptToMemoryPool(), which DOES do // all the appropriate checks. LOCK(cs); - assert(weightedTxTree); weightedTxTree->add(WeightedTxInfo::from(entry.GetTx(), entry.GetFee())); mapTx.insert(entry); const CTransaction& tx = mapTx.find(hash)->GetTx(); @@ -293,7 +292,6 @@ void CTxMemPool::remove(const CTransaction &origTx, std::list& rem if (fSpentIndex) removeSpentIndex(hash); } - assert(weightedTxTree); for (CTransaction tx : removed) { weightedTxTree->remove(tx.GetHash()); } @@ -811,23 +809,19 @@ size_t CTxMemPool::DynamicMemoryUsage() const { void CTxMemPool::SetMempoolCostLimit(int64_t totalCostLimit, int64_t evictionMemorySeconds) { LOCK(cs); LogPrint("mempool", "Setting mempool cost limit: (limit=%d, time=%d)\n", totalCostLimit, evictionMemorySeconds); - // This method should not be called more than once - assert(!recentlyEvicted); - assert(!weightedTxTree); + delete recentlyEvicted; + delete weightedTxTree; recentlyEvicted = new RecentlyEvictedList(evictionMemorySeconds); weightedTxTree = new WeightedTxTree(totalCostLimit); } bool CTxMemPool::IsRecentlyEvicted(const uint256& txId) { LOCK(cs); - assert(recentlyEvicted); return recentlyEvicted->contains(txId); } void CTxMemPool::EnsureSizeLimit() { AssertLockHeld(cs); - assert(recentlyEvicted); - assert(weightedTxTree); boost::optional maybeDropTxId; while ((maybeDropTxId = weightedTxTree->maybeDropRandom()).is_initialized()) { uint256 txId = maybeDropTxId.get(); diff --git a/src/txmempool.h b/src/txmempool.h index b74d464d0a7..630b132a6f5 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -140,8 +140,8 @@ class CTxMemPool std::map mapSproutNullifiers; std::map mapSaplingNullifiers; - RecentlyEvictedList* recentlyEvicted = nullptr; - WeightedTxTree* weightedTxTree = nullptr; + RecentlyEvictedList* recentlyEvicted = new RecentlyEvictedList(DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES * 60); + WeightedTxTree* weightedTxTree = new WeightedTxTree(DEFAULT_MEMPOOL_TOTAL_COST_LIMIT); void checkNullifiers(ShieldedType type) const; From 40a715602638ad2bed0f0587d8b75bed2cb0357d Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Mon, 21 Oct 2019 09:20:17 -0600 Subject: [PATCH 347/395] Remove dots and underscores from parameter names --- doc/release-notes.md | 4 ++-- qa/rpc-tests/mempool_limit.py | 8 ++++---- src/init.cpp | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index 5ce2a9d6670..c4faf264666 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -13,14 +13,14 @@ transactions. This is achieved by keeping track of and limiting the total `cost` and `evictionWeight` of all transactions in the mempool. The `cost` of a transaction is determined by its size in bytes, and its `evictionWeight` is a function of the transaction's `cost` and its fee. The maximum total cost is -configurable via the parameter `mempool.tx_cost_limit` which defaults to +configurable via the parameter `mempooltxcostlimit` which defaults to 80,000,000 (up to 20,000 txs). If a node's total mempool `cost` exceeds this limit the node will evict a random transaction, preferentially picking larger transactions and ones with below the standard fee. To prevent a node from re-accepting evicted transactions, it keeps track of ones that it has evicted recently. By default, a transaction will be considered recently evicted for 60 minutes, but this can be configured with the parameter -`mempool.eviction_memory_minutes`. +`mempoolevictionmemoryminutes`. For full details see ZIP 401. diff --git a/qa/rpc-tests/mempool_limit.py b/qa/rpc-tests/mempool_limit.py index 1c424a47aa0..918c6141485 100755 --- a/qa/rpc-tests/mempool_limit.py +++ b/qa/rpc-tests/mempool_limit.py @@ -26,11 +26,11 @@ def setup_chain(self): def setup_nodes(self): extra_args = [ - ["-debug=mempool", '-mempool.tx_cost_limit=8000'], # 2 transactions at min cost - ["-debug=mempool", '-mempool.tx_cost_limit=8000'], # 2 transactions at min cost - ["-debug=mempool", '-mempool.tx_cost_limit=8000'], # 2 transactions at min cost + ["-debug=mempool", '-mempooltxcostlimit=8000'], # 2 transactions at min cost + ["-debug=mempool", '-mempooltxcostlimit=8000'], # 2 transactions at min cost + ["-debug=mempool", '-mempooltxcostlimit=8000'], # 2 transactions at min cost # Let node 3 hold one more transaction - ["-debug=mempool", '-mempool.tx_cost_limit=12000'], # 3 transactions at min cost + ["-debug=mempool", '-mempooltxcostlimit=12000'], # 3 transactions at min cost ] return start_nodes(4, self.options.tmpdir, extra_args) diff --git a/src/init.cpp b/src/init.cpp index 11d956551d5..2403965636c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -384,8 +384,8 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-maxconnections=", strprintf(_("Maintain at most connections to peers (default: %u)"), DEFAULT_MAX_PEER_CONNECTIONS)); strUsage += HelpMessageOpt("-maxreceivebuffer=", strprintf(_("Maximum per-connection receive buffer, *1000 bytes (default: %u)"), 5000)); strUsage += HelpMessageOpt("-maxsendbuffer=", strprintf(_("Maximum per-connection send buffer, *1000 bytes (default: %u)"), 1000)); - strUsage += HelpMessageOpt("-mempool.eviction_memory_minutes=", strprintf(_("The number of minutes before allowing rejected transactions to re-enter the mempool. (default: %u)"), DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES)); - strUsage += HelpMessageOpt("-mempool.tx_cost_limit=",strprintf(_("An upper bound on the maximum size in bytes of all transactions in the mempool. (default: %s)"), DEFAULT_MEMPOOL_TOTAL_COST_LIMIT)); + strUsage += HelpMessageOpt("-mempoolevictionmemoryminutes=", strprintf(_("The number of minutes before allowing rejected transactions to re-enter the mempool. (default: %u)"), DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES)); + strUsage += HelpMessageOpt("-mempooltxcostlimit=",strprintf(_("An upper bound on the maximum size in bytes of all transactions in the mempool. (default: %s)"), DEFAULT_MEMPOOL_TOTAL_COST_LIMIT)); strUsage += HelpMessageOpt("-onion=", strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy")); strUsage += HelpMessageOpt("-onlynet=", _("Only connect to nodes in network (ipv4, ipv6 or onion)")); strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), 1)); @@ -978,8 +978,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) mempool.setSanityCheck(1.0 / ratio); } - int64_t mempoolTotalCostLimit = GetArg("-mempool.tx_cost_limit", DEFAULT_MEMPOOL_TOTAL_COST_LIMIT); - int64_t mempoolEvictionMemorySeconds = GetArg("-mempool.eviction_memory_minutes", DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES) * 60; + int64_t mempoolTotalCostLimit = GetArg("-mempooltxcostlimit", DEFAULT_MEMPOOL_TOTAL_COST_LIMIT); + int64_t mempoolEvictionMemorySeconds = GetArg("-mempoolevictionmemoryminutes", DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES) * 60; mempool.SetMempoolCostLimit(mempoolTotalCostLimit, mempoolEvictionMemorySeconds); fCheckBlockIndex = GetBoolArg("-checkblockindex", chainparams.DefaultConsistencyChecks()); From 8307a5db5abed428172d6b634cc5f6158921a22f Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Tue, 22 Oct 2019 11:29:55 -0600 Subject: [PATCH 348/395] Use same type when calling max --- src/mempool_limit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mempool_limit.cpp b/src/mempool_limit.cpp index 762d2c7d1fa..f6eab7d37ec 100644 --- a/src/mempool_limit.cpp +++ b/src/mempool_limit.cpp @@ -151,7 +151,7 @@ WeightedTxInfo WeightedTxInfo::from(const CTransaction& tx, const CAmount& fee) memUsage += tx.vJoinSplit.size() * JOINSPLIT_SIZE; memUsage += tx.vShieldedOutput.size() * OUTPUTDESCRIPTION_SIZE; memUsage += tx.vShieldedSpend.size() * SPENDDESCRIPTION_SIZE; - int64_t cost = std::max(memUsage, MIN_TX_COST); + int64_t cost = std::max((int64_t) memUsage, (int64_t) MIN_TX_COST); int64_t evictionWeight = cost; if (fee < DEFAULT_FEE) { evictionWeight += LOW_FEE_PENALTY; From bdfed7e178a220c09f74387af58f955b243f765c Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Tue, 22 Oct 2019 14:35:07 -0600 Subject: [PATCH 349/395] make-release.py: Versioning changes for 2.1.0-rc1. --- README.md | 2 +- configure.ac | 6 +++--- contrib/gitian-descriptors/gitian-linux.yml | 2 +- src/clientversion.h | 6 +++--- src/deprecation.h | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 6117b077280..bfbfb302a42 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Zcash 2.0.7-3 +Zcash 2.1.0-rc1 =========== diff --git a/configure.ac b/configure.ac index 8ad7354d4ca..e04c151009b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,9 +1,9 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 2) -define(_CLIENT_VERSION_MINOR, 0) -define(_CLIENT_VERSION_REVISION, 7) -define(_CLIENT_VERSION_BUILD, 53) +define(_CLIENT_VERSION_MINOR, 1) +define(_CLIENT_VERSION_REVISION, 0) +define(_CLIENT_VERSION_BUILD, 25) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index cb3990fc235..2502e36bb76 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "zcash-2.0.7-3" +name: "zcash-2.1.0-rc1" enable_cache: true distro: "debian" suites: diff --git a/src/clientversion.h b/src/clientversion.h index 82ac6faf21a..f1923b362d3 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -16,9 +16,9 @@ //! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 2 -#define CLIENT_VERSION_MINOR 0 -#define CLIENT_VERSION_REVISION 7 -#define CLIENT_VERSION_BUILD 53 +#define CLIENT_VERSION_MINOR 1 +#define CLIENT_VERSION_REVISION 0 +#define CLIENT_VERSION_BUILD 25 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/deprecation.h b/src/deprecation.h index 10bb3195d80..aa3da991c58 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -8,7 +8,7 @@ // Deprecation policy: // * Shut down 16 weeks' worth of blocks after the estimated release block height. // * A warning is shown during the 2 weeks' worth of blocks prior to shut down. -static const int APPROX_RELEASE_HEIGHT = 588500; +static const int APPROX_RELEASE_HEIGHT = 625500; static const int WEEKS_UNTIL_DEPRECATION = 16; static const int DEPRECATION_HEIGHT = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 24); From 17a70bcd675cfa1405c7c09a690ba3cb2cf2b121 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Tue, 22 Oct 2019 14:52:01 -0600 Subject: [PATCH 350/395] make-release.py: Updated manpages for 2.1.0-rc1. --- doc/man/zcash-cli.1 | 8 ++++---- doc/man/zcash-tx.1 | 8 ++++---- doc/man/zcashd.1 | 20 +++++++++++++++----- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/doc/man/zcash-cli.1 b/doc/man/zcash-cli.1 index 7238b8e173e..dd40802f39f 100644 --- a/doc/man/zcash-cli.1 +++ b/doc/man/zcash-cli.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.8. -.TH ZCASH-CLI "1" "September 2019" "zcash-cli v2.0.7-3" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. +.TH ZCASH-CLI "1" "October 2019" "zcash-cli v2.1.0-rc1" "User Commands" .SH NAME -zcash-cli \- manual page for zcash-cli v2.0.7-3 +zcash-cli \- manual page for zcash-cli v2.1.0-rc1 .SH DESCRIPTION -Zcash RPC client version v2.0.7\-3 +Zcash RPC client version v2.1.0\-rc1 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . diff --git a/doc/man/zcash-tx.1 b/doc/man/zcash-tx.1 index 64a1aa22b68..5a1d9f73626 100644 --- a/doc/man/zcash-tx.1 +++ b/doc/man/zcash-tx.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.8. -.TH ZCASH-TX "1" "September 2019" "zcash-tx v2.0.7-3" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. +.TH ZCASH-TX "1" "October 2019" "zcash-tx v2.1.0-rc1" "User Commands" .SH NAME -zcash-tx \- manual page for zcash-tx v2.0.7-3 +zcash-tx \- manual page for zcash-tx v2.1.0-rc1 .SH DESCRIPTION -Zcash zcash\-tx utility version v2.0.7\-3 +Zcash zcash\-tx utility version v2.1.0\-rc1 .SS "Usage:" .TP zcash\-tx [options] [commands] diff --git a/doc/man/zcashd.1 b/doc/man/zcashd.1 index 414413f164a..b60d9e7ed7f 100644 --- a/doc/man/zcashd.1 +++ b/doc/man/zcashd.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.8. -.TH ZCASHD "1" "September 2019" "zcashd v2.0.7-3" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. +.TH ZCASHD "1" "October 2019" "zcashd v2.1.0-rc1" "User Commands" .SH NAME -zcashd \- manual page for zcashd v2.0.7-3 +zcashd \- manual page for zcashd v2.1.0-rc1 .SH DESCRIPTION -Zcash Daemon version v2.0.7\-3 +Zcash Daemon version v2.1.0\-rc1 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . @@ -75,7 +75,7 @@ limit applied) .HP \fB\-par=\fR .IP -Set the number of script verification threads (\fB\-6\fR to 16, 0 = auto, <0 = +Set the number of script verification threads (\fB\-4\fR to 16, 0 = auto, <0 = leave that many cores free, default: 0) .HP \fB\-pid=\fR @@ -170,6 +170,16 @@ Maximum per\-connection receive buffer, *1000 bytes (default: 5000) .IP Maximum per\-connection send buffer, *1000 bytes (default: 1000) .HP +\fB\-mempoolevictionmemoryminutes=\fR +.IP +The number of minutes before allowing rejected transactions to re\-enter +the mempool. (default: 60) +.HP +\fB\-mempooltxcostlimit=\fR +.IP +An upper bound on the maximum size in bytes of all transactions in the +mempool. (default: 80000000) +.HP \fB\-onion=\fR .IP Use separate SOCKS5 proxy to reach peers via Tor hidden services From fd8004d2bdcd85969ea7fafb2309c0ff92312091 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Tue, 22 Oct 2019 14:52:02 -0600 Subject: [PATCH 351/395] make-release.py: Updated release notes and changelog for 2.1.0-rc1. --- contrib/debian/changelog | 6 + doc/release-notes/release-notes-2.1.0-rc1.md | 177 +++++++++++++++++++ 2 files changed, 183 insertions(+) create mode 100644 doc/release-notes/release-notes-2.1.0-rc1.md diff --git a/contrib/debian/changelog b/contrib/debian/changelog index 431b80e75d9..6a3a97ef379 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,9 @@ +zcash (2.1.0~rc1) stable; urgency=medium + + * 2.1.0-rc1 release. + + -- Electric Coin Company Tue, 22 Oct 2019 14:52:02 -0600 + zcash (2.0.7+3) stable; urgency=critical * 2.0.7-3 release. diff --git a/doc/release-notes/release-notes-2.1.0-rc1.md b/doc/release-notes/release-notes-2.1.0-rc1.md new file mode 100644 index 00000000000..e11a6c09c7a --- /dev/null +++ b/doc/release-notes/release-notes-2.1.0-rc1.md @@ -0,0 +1,177 @@ +Notable changes +=============== + +DoS Mitigation: Mempool Size Limit and Random Drop +-------------------------------------------------- + +This release adds a mechanism for preventing nodes from running out of memory +in the situation where an attacker is trying to overwhelm the network with +transactions. This is achieved by keeping track of and limiting the total +`cost` and `evictionWeight` of all transactions in the mempool. The `cost` of a +transaction is determined by its size in bytes, and its `evictionWeight` is a +function of the transaction's `cost` and its fee. The maximum total cost is +configurable via the parameter `mempooltxcostlimit` which defaults to +80,000,000 (up to 20,000 txs). If a node's total mempool `cost` exceeds this +limit the node will evict a random transaction, preferentially picking larger +transactions and ones with below the standard fee. To prevent a node from +re-accepting evicted transactions, it keeps track of ones that it has evicted +recently. By default, a transaction will be considered recently evicted for 60 +minutes, but this can be configured with the parameter +`mempoolevictionmemoryminutes`. + +For full details see ZIP 401. + +Fake chain detection during initial block download +-------------------------------------------------- + +One of the mechanisms that `zcashd` uses to detect whether it is in "initial +block download" (IBD) mode is to compare the active chain's cumulative work +against a hard-coded "minimum chain work" value. This mechanism (inherited from +Bitcoin Core) means that once a node exits IBD mode, it is either on the main +chain, or a fake alternate chain with similar amounts of work. In the latter +case, the node has most likely become the victim of a 50% + 1 adversary. + +Starting from this release, `zcashd` additionally hard-codes the block hashes +for the activation blocks of each past network upgrade (NU). During initial +chain synchronization, and after the active chain has reached "minimum chain +work", the node checks the blocks at each NU activation height against the +hard-coded hashes. If any of them do not match, the node will immediately alert +the user and **shut down for safety**. + +Disabling old Sprout proofs +--------------------------- + +As part of our ongoing work to clean up the codebase and minimise the security +surface of `zcashd`, we are removing `libsnark` from the codebase, and dropping +support for creating and verifying old Sprout proofs. Funds stored in Sprout +addresses are not affected, as they are spent using the hybrid Sprout circuit +(built using `bellman`) that was deployed during the Sapling network upgrade. + +This change has several implications: + +- `zcashd` no longer verifies old Sprout proofs, and will instead assume they + are valid. This has a minor implication for nodes: during initial block + download, an adversary could feed the node fake blocks containing invalid old + Sprout proofs, and the node would accept the fake chain as valid. However, + as soon as the active chain contains at least as much work as the hard-coded + "minimum chain work" value, the node will detect this situation and shut down. + +- Shielded transactions can no longer be created before Sapling has activated. + This does not affect Zcash itself, but will affect downstream codebases that + have not yet activated Sapling (or that start a new chain after this point and + do not activate Sapling from launch). Note that the old Sprout circuit is + [vulnerable to counterfeiting](https://z.cash/support/security/announcements/security-announcement-2019-02-05-cve-2019-7167/) + and should not be used in current deployments. + +- Starting from this release, the circuit parameters from the original Sprout + MPC are no longer required to start `zcashd`, and will not be downloaded by + `fetch-params.sh`. They are not being automatically deleted at this time. + +We would like to take a moment to thank the `libsnark` authors and contributors. +It was vital to the success of Zcash, and the development of zero-knowledge +proofs in general, to have this code available and usable. + +Changelog +========= + +Bryant Eisenbach (2): + doc: Change Debian package description + doc: Move text prior to "This package provides..." + +Daira Hopwood (4): + Remove copyright entries for Autoconf macros that have been deleted. + Remove copyright entry for libsnark. + Test setting an expiry height of 0. + Fix setting an expiry height of 0. fixes #4132 + +Eirik Ogilvie-Wigley (33): + Wrap metrics message in strprintf + DoS protection: Weighted random drop of txs if mempool full + Rebuild weighted list on removal and fix size calculation + Grammatical fixes + Remove transactions when ensuring size limit + Help message cleanup and add lock + Performance: Store weighted transactions in a tree + Fix naming conventions + No need to activate Overwinter/Sapling in rpc test + Fix recently evicted list size + Put size increment and decrement on their own lines + Prevent adding duplicate transactions + Move duplicate macro to reusable location + mempool_limit rpc test cleanup + Represent tx costs as signed integers + Fix comments + Rename variables for consistency + Use tx cost rather than evictionWeight when checking mempool capacity + Log rather than return error if a transaction is recently evicted + Represent recently evicted list as a deque + Rename files + Update release notes + Add test + minor rpc test clean up + Add explanatory comments + Wording and grammatical fixes + Update parameter names to match ZIP + Clarify the difference between cost and evictionWeight + Fix test cases: default mempool limiters + Remove dots and underscores from parameter names + Use same type when calling max + make-release.py: Versioning changes for 2.1.0-rc1. + make-release.py: Updated manpages for 2.1.0-rc1. + +Gareth Davies (1): + Updating IPFS link for chunking + +Jack Grigg (39): + depends: Add FreeBSD to hosts and builders + depends: Explicitly set Boost toolchain during configuration + depends: Add FreeBSD support to OpenSSL + depends: Patch libevent to detect arch4random_addrandom + depends: Add FreeBSD Rust binaries + depends: Explicitly call Rust install script using bash + depends: Use project-config.jam to configure Boost instead of user-config.jam + depends: Set PIC flags for FreeBSD + Always skip verification for old Sprout proofs + Remove ability to create non-Groth16 Sprout JSDescriptions + Use Sapling JSDescriptions in Boost tests + Remove non-Groth16 Sprout proofs from joinsplit gtests + Migrate test utilities to generate Sapling-type Sprout proofs + Use Sapling JSDescriptions in gtests + Revert "Allow user to ask server to save the Sprout R1CS out during startup." + Remove libsnark code for pre-Sapling Sprout proofs + Remove pre-Sapling Sprout circuit + Revert "configure: Guess -march for libsnark OPTFLAGS instead of hard-coding" + Revert "Check if OpenMP is available before using it" + Remove libsnark from build system + Remove libsnark + Remove libgmp + Remove libsnark unit tests from full test suite + test: Require minimum of Sapling for all RPC tests + test: Add Sapling v4 transactions to mininode framework + test: Add hashFinalSaplingProxy to create_block + test: Update RPC tests to use a minimum of Sapling + rpc: Use Sapling transactions in zc_raw_joinsplit + depends: Fix crate vendoring path + depends: Helper for vendoring new crates + depends: Add flag for building with a local librustzcash repo + tests: Clean up use of repr() in mininode + Remove makeGrothProof argument from JoinSplit::prove + Stop fetching old Sprout parameters + Add libsnark removal to notable changes + Move AbortNode to the top of main.cpp + Abort node if NU activations have unexpected hashes + Add block hashes for Overwinter, Sapling, and testnet Blossom + Update release notes with node abort behaviour + +Larry Ruane (4): + insightexplorer: formatting, pyflakes cleanups + precompute empty merkle roots + update unit tests to compute empty roots + access array element using at() + +jeff-liang (1): + Display which network the node is running on. + +Benjamin Winston (1): + Removed stale seeder, fixing #4153 + From 07f2edc91c5c18a8116eeee7a64b8bb58e2f558e Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Thu, 24 Oct 2019 22:47:31 -0600 Subject: [PATCH 352/395] #4175 z_sendmany coinbase to zaddr with change: report error status --- src/wallet/asyncrpcoperation_common.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/wallet/asyncrpcoperation_common.cpp b/src/wallet/asyncrpcoperation_common.cpp index dec29f8a2c2..0fd0cfeedc8 100644 --- a/src/wallet/asyncrpcoperation_common.cpp +++ b/src/wallet/asyncrpcoperation_common.cpp @@ -11,7 +11,10 @@ UniValue SendTransaction(CTransaction& tx, boost::optional reserve // Send the transaction if (!testmode) { CWalletTx wtx(pwalletMain, tx); - pwalletMain->CommitTransaction(wtx, reservekey); + if (!pwalletMain->CommitTransaction(wtx, reservekey)) { + // More details in debug.log + throw JSONRPCError(RPC_WALLET_ERROR, "SendTransaction: CommitTransaction failed"); + } o.push_back(Pair("txid", tx.GetHash().ToString())); } else { // Test mode does not send the transaction to the network. From 1d3c5b04ac00fbb849534a67312bbe47c8d81785 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Thu, 31 Oct 2019 15:54:18 -0600 Subject: [PATCH 353/395] Release notes for bug fix --- doc/release-notes.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index c4faf264666..eae0514210a 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -24,6 +24,16 @@ minutes, but this can be configured with the parameter For full details see ZIP 401. +Async-Operations Incorrectly Reporting Success +---------------------------------------------- +We fixed an issue where async-operations were sometimes reporting sucess when +they had actually failed. One way this could occur when trying using +`z_sendmany` to create a transaction spending coinbase funds in a way where +change would be generated (not a valid use of `z_sendmany`). In this case the +async-operation would erroneously report success, and the only way to see that +the transaction had actually failed was to look in the `debug.log` file. Such +operations will now correctly report that they have failed. + Fake chain detection during initial block download -------------------------------------------------- From ee5569207bca9696cd554e06e583b033673d80fb Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Thu, 31 Oct 2019 21:22:47 -0600 Subject: [PATCH 354/395] Better wording in release notes --- doc/release-notes.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index eae0514210a..99a67555a77 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -24,14 +24,14 @@ minutes, but this can be configured with the parameter For full details see ZIP 401. -Async-Operations Incorrectly Reporting Success ----------------------------------------------- -We fixed an issue where async-operations were sometimes reporting sucess when -they had actually failed. One way this could occur when trying using +Asynchronous Operations Incorrectly Reporting Success +----------------------------------------------------- +We fixed an issue where asynchronous operations were sometimes reporting sucess +when they had actually failed. One way this could occur when trying using `z_sendmany` to create a transaction spending coinbase funds in a way where change would be generated (not a valid use of `z_sendmany`). In this case the -async-operation would erroneously report success, and the only way to see that -the transaction had actually failed was to look in the `debug.log` file. Such +operation would erroneously report success, and the only way to see that the +transaction had actually failed was to look in the `debug.log` file. Such operations will now correctly report that they have failed. Fake chain detection during initial block download From 4180589f02e31bf3727b3e782b1e7a511873987f Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Thu, 31 Oct 2019 14:55:14 -0600 Subject: [PATCH 355/395] Set mainnet activation of Blossom --- doc/release-notes.md | 13 +++++++++++++ src/chainparams.cpp | 3 +-- src/deprecation.h | 13 +++++++++++-- src/test/main_tests.cpp | 12 ++++-------- src/version.h | 2 +- 5 files changed, 30 insertions(+), 13 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index c4faf264666..710bee74fd4 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,6 +4,19 @@ release-notes at release time) Notable changes =============== +Blossom network upgrade +----------------------- + +The mainnet activation of the Blossom network upgrade is supported by this +release, with an activation height of 653600, which should occur in early +December — roughly one day following the targeted EOS halt of our 2.0.7-3 +release. Please upgrade to this release, or any subsequent release, in order to +follow the Blossom network upgrade. + +The Blossom network upgrade implements +[ZIP208](https://github.com/zcash/zips/blob/master/zip-0208.rst) which shortens +block times from 150s to 75s. + DoS Mitigation: Mempool Size Limit and Random Drop -------------------------------------------------- diff --git a/src/chainparams.cpp b/src/chainparams.cpp index f840afb93b9..cfa2955eb6a 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -117,8 +117,7 @@ class CMainParams : public CChainParams { consensus.vUpgrades[Consensus::UPGRADE_SAPLING].hashActivationBlock = uint256S("00000000025a57200d898ac7f21e26bf29028bbe96ec46e05b2c17cc9db9e4f3"); consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].nProtocolVersion = 170009; - consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight = - Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; + consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight = 653600; // The best chain should have at least this much work. consensus.nMinimumChainWork = uint256S("000000000000000000000000000000000000000000000000017e73a331fae01c"); diff --git a/src/deprecation.h b/src/deprecation.h index aa3da991c58..78246de8750 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -10,10 +10,19 @@ // * A warning is shown during the 2 weeks' worth of blocks prior to shut down. static const int APPROX_RELEASE_HEIGHT = 625500; static const int WEEKS_UNTIL_DEPRECATION = 16; -static const int DEPRECATION_HEIGHT = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 24); +// static const int DEPRECATION_HEIGHT = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 24); + +// TEMPORARY! +// This is hardcoded to a height that is roughly 10 weeks following the +// activation of Blossom on mainnet, which is itself almost 6 weeks following +// this release. This is done because the calculation of the deprecation height +// does not account for the change in block target spacing; after Blossom has +// activated, this should be removed and the previous line fixed to use +// APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 48) +static const int DEPRECATION_HEIGHT = 734240; // Number of blocks before deprecation to warn users -static const int DEPRECATION_WARN_LIMIT = 14 * 24 * 24; // 2 weeks +static const int DEPRECATION_WARN_LIMIT = 14 * 24 * 48; // 2 weeks /** * Checks whether the node is deprecated based on the current block height, and diff --git a/src/test/main_tests.cpp b/src/test/main_tests.cpp index 983e3bdecfe..c490ce0eb67 100644 --- a/src/test/main_tests.cpp +++ b/src/test/main_tests.cpp @@ -98,16 +98,12 @@ BOOST_AUTO_TEST_CASE(subsidy_limit_test) // Changing the block interval from 10 to 2.5 minutes causes truncation // effects to occur earlier (from the 9th halving interval instead of the - // 11th), decreasing the total monetary supply by 0.0693 ZEC. If the - // transaction output field is widened, this discrepancy will become smaller - // or disappear entirely. - //BOOST_CHECK_EQUAL(nSum, 2099999997690000ULL); + // 11th), decreasing the total monetary supply by 0.0693 ZEC. + // BOOST_CHECK_EQUAL(nSum, 2099999997690000ULL); // Reducing the interval further to 1.25 minutes has a similar effect, // decreasing the total monetary supply by another 0.09240 ZEC. - // TODO Change this assert when setting the blossom activation height - // Note that these numbers may or may not change depending on the activation height - BOOST_CHECK_EQUAL(nSum, 2099999990760000ULL); - // BOOST_CHECK_EQUAL(nSum, 2099999981520000LL); + // BOOST_CHECK_EQUAL(nSum, 2099999990760000ULL); + BOOST_CHECK_EQUAL(nSum, 2099999981520000LL); } bool ReturnFalse() { return false; } diff --git a/src/version.h b/src/version.h index 6a1a25f9bc9..a6c9b6b9a56 100644 --- a/src/version.h +++ b/src/version.h @@ -9,7 +9,7 @@ * network protocol versioning */ -static const int PROTOCOL_VERSION = 170008; +static const int PROTOCOL_VERSION = 170009; //! initial proto version, to be increased after version/verack negotiation static const int INIT_PROTO_VERSION = 209; From e7a84d7bd8a2d0b903fe89e427790b444fb45164 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 1 Nov 2019 09:52:15 -0600 Subject: [PATCH 356/395] Fix wording Co-Authored-By: Daira Hopwood --- doc/release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index 99a67555a77..3ac71e8d024 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -27,7 +27,7 @@ For full details see ZIP 401. Asynchronous Operations Incorrectly Reporting Success ----------------------------------------------------- We fixed an issue where asynchronous operations were sometimes reporting sucess -when they had actually failed. One way this could occur when trying using +when they had actually failed. One way this could occur was when trying to use `z_sendmany` to create a transaction spending coinbase funds in a way where change would be generated (not a valid use of `z_sendmany`). In this case the operation would erroneously report success, and the only way to see that the From 0950c94c13f72035388f82555255391799906d99 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 1 Nov 2019 12:10:15 -0600 Subject: [PATCH 357/395] Fix getblocksubsidy tests --- src/test/rpc_wallet_tests.cpp | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index abae7ce78db..506a7d6d397 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -270,19 +270,42 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) */ BOOST_CHECK_THROW(CallRPC("getblocksubsidy too many args"), runtime_error); BOOST_CHECK_THROW(CallRPC("getblocksubsidy -1"), runtime_error); + BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 50000")); UniValue obj = retValue.get_obj(); BOOST_CHECK_EQUAL(find_value(obj, "miner").get_real(), 10.0); BOOST_CHECK_EQUAL(find_value(obj, "founders").get_real(), 2.5); - BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 1000000")); + + BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 653599")); // Blossom activation - 1 + obj = retValue.get_obj(); + BOOST_CHECK_EQUAL(find_value(obj, "miner").get_real(), 10.0); + BOOST_CHECK_EQUAL(find_value(obj, "founders").get_real(), 2.5); + + BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 653600")); // Blossom activation + obj = retValue.get_obj(); + BOOST_CHECK_EQUAL(find_value(obj, "miner").get_real(), 5.0); + BOOST_CHECK_EQUAL(find_value(obj, "founders").get_real(), 1.25); + + BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 1046399")); + obj = retValue.get_obj(); + BOOST_CHECK_EQUAL(find_value(obj, "miner").get_real(), 5.0); + BOOST_CHECK_EQUAL(find_value(obj, "founders").get_real(), 1.25); + // slow start + pre blossom halving + (pre blossom halving - blossom activation) * 2 + BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 1046400")); obj = retValue.get_obj(); - BOOST_CHECK_EQUAL(find_value(obj, "miner").get_real(), 6.25); + BOOST_CHECK_EQUAL(find_value(obj, "miner").get_real(), 3.125); BOOST_CHECK_EQUAL(find_value(obj, "founders").get_real(), 0.0); - BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 2000000")); + + BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 2726399")); obj = retValue.get_obj(); BOOST_CHECK_EQUAL(find_value(obj, "miner").get_real(), 3.125); BOOST_CHECK_EQUAL(find_value(obj, "founders").get_real(), 0.0); + BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 2726400")); + obj = retValue.get_obj(); + BOOST_CHECK_EQUAL(find_value(obj, "miner").get_real(), 1.5625); + BOOST_CHECK_EQUAL(find_value(obj, "founders").get_real(), 0.0); + /* * getblock */ From 5371e0cffbb0df92a8298d52ffb12588c642b94b Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Fri, 1 Nov 2019 14:46:15 -0600 Subject: [PATCH 358/395] fix comment --- src/test/rpc_wallet_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index 506a7d6d397..1da844bdfed 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -290,7 +290,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) obj = retValue.get_obj(); BOOST_CHECK_EQUAL(find_value(obj, "miner").get_real(), 5.0); BOOST_CHECK_EQUAL(find_value(obj, "founders").get_real(), 1.25); - // slow start + pre blossom halving + (pre blossom halving - blossom activation) * 2 + // slow start + blossom activation + (pre blossom halving - blossom activation) * 2 BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 1046400")); obj = retValue.get_obj(); BOOST_CHECK_EQUAL(find_value(obj, "miner").get_real(), 3.125); From 5be8d1ecd179de56bbab236df8c2f6923864386a Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Sat, 2 Nov 2019 10:53:13 -0600 Subject: [PATCH 359/395] make-release.py: Versioning changes for 2.1.0. --- README.md | 2 +- configure.ac | 2 +- contrib/gitian-descriptors/gitian-linux.yml | 2 +- src/clientversion.h | 2 +- src/deprecation.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index bfbfb302a42..4accbb2309c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Zcash 2.1.0-rc1 +Zcash 2.1.0 =========== diff --git a/configure.ac b/configure.ac index e04c151009b..fa22e088bcb 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 2) define(_CLIENT_VERSION_MINOR, 1) define(_CLIENT_VERSION_REVISION, 0) -define(_CLIENT_VERSION_BUILD, 25) +define(_CLIENT_VERSION_BUILD, 50) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 2502e36bb76..79c7d25fc96 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "zcash-2.1.0-rc1" +name: "zcash-2.1.0" enable_cache: true distro: "debian" suites: diff --git a/src/clientversion.h b/src/clientversion.h index f1923b362d3..27c913b48a9 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -18,7 +18,7 @@ #define CLIENT_VERSION_MAJOR 2 #define CLIENT_VERSION_MINOR 1 #define CLIENT_VERSION_REVISION 0 -#define CLIENT_VERSION_BUILD 25 +#define CLIENT_VERSION_BUILD 50 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/deprecation.h b/src/deprecation.h index 78246de8750..3596e6aa59d 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -8,7 +8,7 @@ // Deprecation policy: // * Shut down 16 weeks' worth of blocks after the estimated release block height. // * A warning is shown during the 2 weeks' worth of blocks prior to shut down. -static const int APPROX_RELEASE_HEIGHT = 625500; +static const int APPROX_RELEASE_HEIGHT = 632000; static const int WEEKS_UNTIL_DEPRECATION = 16; // static const int DEPRECATION_HEIGHT = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 24); From 06f511f88ee99e3a94dad4b18f1103aa5d1f9b0b Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Sat, 2 Nov 2019 11:01:00 -0600 Subject: [PATCH 360/395] make-release.py: Updated manpages for 2.1.0. --- doc/man/zcash-cli.1 | 6 +++--- doc/man/zcash-tx.1 | 6 +++--- doc/man/zcashd.1 | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/man/zcash-cli.1 b/doc/man/zcash-cli.1 index dd40802f39f..fc47f7f8632 100644 --- a/doc/man/zcash-cli.1 +++ b/doc/man/zcash-cli.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-CLI "1" "October 2019" "zcash-cli v2.1.0-rc1" "User Commands" +.TH ZCASH-CLI "1" "November 2019" "zcash-cli v2.1.0" "User Commands" .SH NAME -zcash-cli \- manual page for zcash-cli v2.1.0-rc1 +zcash-cli \- manual page for zcash-cli v2.1.0 .SH DESCRIPTION -Zcash RPC client version v2.1.0\-rc1 +Zcash RPC client version v2.1.0 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . diff --git a/doc/man/zcash-tx.1 b/doc/man/zcash-tx.1 index 5a1d9f73626..22428b6285a 100644 --- a/doc/man/zcash-tx.1 +++ b/doc/man/zcash-tx.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-TX "1" "October 2019" "zcash-tx v2.1.0-rc1" "User Commands" +.TH ZCASH-TX "1" "November 2019" "zcash-tx v2.1.0" "User Commands" .SH NAME -zcash-tx \- manual page for zcash-tx v2.1.0-rc1 +zcash-tx \- manual page for zcash-tx v2.1.0 .SH DESCRIPTION -Zcash zcash\-tx utility version v2.1.0\-rc1 +Zcash zcash\-tx utility version v2.1.0 .SS "Usage:" .TP zcash\-tx [options] [commands] diff --git a/doc/man/zcashd.1 b/doc/man/zcashd.1 index b60d9e7ed7f..1fb5f24bbab 100644 --- a/doc/man/zcashd.1 +++ b/doc/man/zcashd.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASHD "1" "October 2019" "zcashd v2.1.0-rc1" "User Commands" +.TH ZCASHD "1" "November 2019" "zcashd v2.1.0" "User Commands" .SH NAME -zcashd \- manual page for zcashd v2.1.0-rc1 +zcashd \- manual page for zcashd v2.1.0 .SH DESCRIPTION -Zcash Daemon version v2.1.0\-rc1 +Zcash Daemon version v2.1.0 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . From 842e73781e11b5669852f934b5b36e89c940d7e0 Mon Sep 17 00:00:00 2001 From: Eirik Ogilvie-Wigley Date: Sat, 2 Nov 2019 11:01:01 -0600 Subject: [PATCH 361/395] make-release.py: Updated release notes and changelog for 2.1.0. --- contrib/debian/changelog | 6 + doc/authors.md | 18 +- doc/release-notes.md | 92 ---------- doc/release-notes/release-notes-2.1.0.md | 215 +++++++++++++++++++++++ 4 files changed, 231 insertions(+), 100 deletions(-) create mode 100644 doc/release-notes/release-notes-2.1.0.md diff --git a/contrib/debian/changelog b/contrib/debian/changelog index 6a3a97ef379..016d2381439 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,9 @@ +zcash (2.1.0) stable; urgency=medium + + * 2.1.0 release. + + -- Electric Coin Company Sat, 02 Nov 2019 11:01:00 -0600 + zcash (2.1.0~rc1) stable; urgency=medium * 2.1.0-rc1 release. diff --git a/doc/authors.md b/doc/authors.md index c21e5ddd351..9fbff8d0468 100644 --- a/doc/authors.md +++ b/doc/authors.md @@ -1,11 +1,11 @@ Zcash Contributors ================== -Jack Grigg (880) +Jack Grigg (919) Simon Liu (459) -Sean Bowe (278) -Eirik Ogilvie-Wigley (169) -Daira Hopwood (140) +Sean Bowe (279) +Eirik Ogilvie-Wigley (210) +Daira Hopwood (144) Jay Graber (89) Wladimir J. van der Laan (82) Taylor Hornby (73) @@ -13,8 +13,8 @@ Jonas Schnelli (62) Nathan Wilcox (56) Pieter Wuille (54) Kevin Gallagher (38) +Larry Ruane (36) Cory Fields (35) -Larry Ruane (31) Marshall Gaucher (22) Jonathan "Duke" Leto (17) syd (15) @@ -24,13 +24,13 @@ Marco Falke (11) Ariel Gabizon (11) Jorge Timón (10) nomnombtc (9) +Dimitris Apostolou (9) kozyilmaz (8) fanquake (8) Luke Dashjr (8) -Dimitris Apostolou (8) +Benjamin Winston (8) Jeff Garzik (7) Gregory Maxwell (7) -Benjamin Winston (7) Marius Kjærstad (6) David Mercer (6) Daniel Cousens (6) @@ -39,6 +39,7 @@ Suhas Daftuar (5) Peter Todd (5) Karl-Johan Alm (5) Johnathan Corgan (5) +Gareth Davies (5) Alex Morcos (5) WO (4) Philip Kaufmann (4) @@ -46,7 +47,6 @@ Pavel Janík (4) Patrick Strateman (4) João Barbosa (4) George Tankersley (4) -Gareth Davies (4) Daniel Kraft (4) lpescher (3) ca333 (3) @@ -73,6 +73,7 @@ Joe Turgeon (2) Jack Gavigan (2) ITH4Coinomia (2) Gavin Andresen (2) +Bryant Eisenbach (2) Brad Miller (2) Bjorn Hjortsberg (2) Amgad Abdelhafez (2) @@ -84,6 +85,7 @@ sandakersmann (1) practicalswift (1) mrbandrews (1) kazcw (1) +jeff-liang (1) jc (1) isle2983 (1) instagibbs (1) diff --git a/doc/release-notes.md b/doc/release-notes.md index 6d2f9bd8a2f..a29094b5174 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -4,95 +4,3 @@ release-notes at release time) Notable changes =============== -Blossom network upgrade ------------------------ - -The mainnet activation of the Blossom network upgrade is supported by this -release, with an activation height of 653600, which should occur in early -December — roughly one day following the targeted EOS halt of our 2.0.7-3 -release. Please upgrade to this release, or any subsequent release, in order to -follow the Blossom network upgrade. - -The Blossom network upgrade implements -[ZIP208](https://github.com/zcash/zips/blob/master/zip-0208.rst) which shortens -block times from 150s to 75s. - -DoS Mitigation: Mempool Size Limit and Random Drop --------------------------------------------------- - -This release adds a mechanism for preventing nodes from running out of memory -in the situation where an attacker is trying to overwhelm the network with -transactions. This is achieved by keeping track of and limiting the total -`cost` and `evictionWeight` of all transactions in the mempool. The `cost` of a -transaction is determined by its size in bytes, and its `evictionWeight` is a -function of the transaction's `cost` and its fee. The maximum total cost is -configurable via the parameter `mempooltxcostlimit` which defaults to -80,000,000 (up to 20,000 txs). If a node's total mempool `cost` exceeds this -limit the node will evict a random transaction, preferentially picking larger -transactions and ones with below the standard fee. To prevent a node from -re-accepting evicted transactions, it keeps track of ones that it has evicted -recently. By default, a transaction will be considered recently evicted for 60 -minutes, but this can be configured with the parameter -`mempoolevictionmemoryminutes`. - -For full details see ZIP 401. - -Asynchronous Operations Incorrectly Reporting Success ------------------------------------------------------ -We fixed an issue where asynchronous operations were sometimes reporting sucess -when they had actually failed. One way this could occur was when trying to use -`z_sendmany` to create a transaction spending coinbase funds in a way where -change would be generated (not a valid use of `z_sendmany`). In this case the -operation would erroneously report success, and the only way to see that the -transaction had actually failed was to look in the `debug.log` file. Such -operations will now correctly report that they have failed. - -Fake chain detection during initial block download --------------------------------------------------- - -One of the mechanisms that `zcashd` uses to detect whether it is in "initial -block download" (IBD) mode is to compare the active chain's cumulative work -against a hard-coded "minimum chain work" value. This mechanism (inherited from -Bitcoin Core) means that once a node exits IBD mode, it is either on the main -chain, or a fake alternate chain with similar amounts of work. In the latter -case, the node has most likely become the victim of a 50% + 1 adversary. - -Starting from this release, `zcashd` additionally hard-codes the block hashes -for the activation blocks of each past network upgrade (NU). During initial -chain synchronization, and after the active chain has reached "minimum chain -work", the node checks the blocks at each NU activation height against the -hard-coded hashes. If any of them do not match, the node will immediately alert -the user and **shut down for safety**. - -Disabling old Sprout proofs ---------------------------- - -As part of our ongoing work to clean up the codebase and minimise the security -surface of `zcashd`, we are removing `libsnark` from the codebase, and dropping -support for creating and verifying old Sprout proofs. Funds stored in Sprout -addresses are not affected, as they are spent using the hybrid Sprout circuit -(built using `bellman`) that was deployed during the Sapling network upgrade. - -This change has several implications: - -- `zcashd` no longer verifies old Sprout proofs, and will instead assume they - are valid. This has a minor implication for nodes: during initial block - download, an adversary could feed the node fake blocks containing invalid old - Sprout proofs, and the node would accept the fake chain as valid. However, - as soon as the active chain contains at least as much work as the hard-coded - "minimum chain work" value, the node will detect this situation and shut down. - -- Shielded transactions can no longer be created before Sapling has activated. - This does not affect Zcash itself, but will affect downstream codebases that - have not yet activated Sapling (or that start a new chain after this point and - do not activate Sapling from launch). Note that the old Sprout circuit is - [vulnerable to counterfeiting](https://z.cash/support/security/announcements/security-announcement-2019-02-05-cve-2019-7167/) - and should not be used in current deployments. - -- Starting from this release, the circuit parameters from the original Sprout - MPC are no longer required to start `zcashd`, and will not be downloaded by - `fetch-params.sh`. They are not being automatically deleted at this time. - -We would like to take a moment to thank the `libsnark` authors and contributors. -It was vital to the success of Zcash, and the development of zero-knowledge -proofs in general, to have this code available and usable. diff --git a/doc/release-notes/release-notes-2.1.0.md b/doc/release-notes/release-notes-2.1.0.md new file mode 100644 index 00000000000..a34305b176c --- /dev/null +++ b/doc/release-notes/release-notes-2.1.0.md @@ -0,0 +1,215 @@ +Notable changes +=============== + +Blossom network upgrade +----------------------- + +The mainnet activation of the Blossom network upgrade is supported by this +release, with an activation height of 653600, which should occur in early +December — roughly one day following the targeted EOS halt of our 2.0.7-3 +release. Please upgrade to this release, or any subsequent release, in order to +follow the Blossom network upgrade. + +The Blossom network upgrade implements +[ZIP208](https://github.com/zcash/zips/blob/master/zip-0208.rst) which shortens +block times from 150s to 75s. + +DoS Mitigation: Mempool Size Limit and Random Drop +-------------------------------------------------- + +This release adds a mechanism for preventing nodes from running out of memory +in the situation where an attacker is trying to overwhelm the network with +transactions. This is achieved by keeping track of and limiting the total +`cost` and `evictionWeight` of all transactions in the mempool. The `cost` of a +transaction is determined by its size in bytes, and its `evictionWeight` is a +function of the transaction's `cost` and its fee. The maximum total cost is +configurable via the parameter `mempooltxcostlimit` which defaults to +80,000,000 (up to 20,000 txs). If a node's total mempool `cost` exceeds this +limit the node will evict a random transaction, preferentially picking larger +transactions and ones with below the standard fee. To prevent a node from +re-accepting evicted transactions, it keeps track of ones that it has evicted +recently. By default, a transaction will be considered recently evicted for 60 +minutes, but this can be configured with the parameter +`mempoolevictionmemoryminutes`. + +For full details see ZIP 401. + +Asynchronous Operations Incorrectly Reporting Success +----------------------------------------------------- +We fixed an issue where asynchronous operations were sometimes reporting sucess +when they had actually failed. One way this could occur was when trying to use +`z_sendmany` to create a transaction spending coinbase funds in a way where +change would be generated (not a valid use of `z_sendmany`). In this case the +operation would erroneously report success, and the only way to see that the +transaction had actually failed was to look in the `debug.log` file. Such +operations will now correctly report that they have failed. + +Fake chain detection during initial block download +-------------------------------------------------- + +One of the mechanisms that `zcashd` uses to detect whether it is in "initial +block download" (IBD) mode is to compare the active chain's cumulative work +against a hard-coded "minimum chain work" value. This mechanism (inherited from +Bitcoin Core) means that once a node exits IBD mode, it is either on the main +chain, or a fake alternate chain with similar amounts of work. In the latter +case, the node has most likely become the victim of a 50% + 1 adversary. + +Starting from this release, `zcashd` additionally hard-codes the block hashes +for the activation blocks of each past network upgrade (NU). During initial +chain synchronization, and after the active chain has reached "minimum chain +work", the node checks the blocks at each NU activation height against the +hard-coded hashes. If any of them do not match, the node will immediately alert +the user and **shut down for safety**. + +Disabling old Sprout proofs +--------------------------- + +As part of our ongoing work to clean up the codebase and minimise the security +surface of `zcashd`, we are removing `libsnark` from the codebase, and dropping +support for creating and verifying old Sprout proofs. Funds stored in Sprout +addresses are not affected, as they are spent using the hybrid Sprout circuit +(built using `bellman`) that was deployed during the Sapling network upgrade. + +This change has several implications: + +- `zcashd` no longer verifies old Sprout proofs, and will instead assume they + are valid. This has a minor implication for nodes: during initial block + download, an adversary could feed the node fake blocks containing invalid old + Sprout proofs, and the node would accept the fake chain as valid. However, + as soon as the active chain contains at least as much work as the hard-coded + "minimum chain work" value, the node will detect this situation and shut down. + +- Shielded transactions can no longer be created before Sapling has activated. + This does not affect Zcash itself, but will affect downstream codebases that + have not yet activated Sapling (or that start a new chain after this point and + do not activate Sapling from launch). Note that the old Sprout circuit is + [vulnerable to counterfeiting](https://z.cash/support/security/announcements/security-announcement-2019-02-05-cve-2019-7167/) + and should not be used in current deployments. + +- Starting from this release, the circuit parameters from the original Sprout + MPC are no longer required to start `zcashd`, and will not be downloaded by + `fetch-params.sh`. They are not being automatically deleted at this time. + +We would like to take a moment to thank the `libsnark` authors and contributors. +It was vital to the success of Zcash, and the development of zero-knowledge +proofs in general, to have this code available and usable. + +Changelog +========= + +Bryant Eisenbach (2): + doc: Change Debian package description + doc: Move text prior to "This package provides..." + +Daira Hopwood (4): + Remove copyright entries for Autoconf macros that have been deleted. + Remove copyright entry for libsnark. + Test setting an expiry height of 0. + Fix setting an expiry height of 0. fixes #4132 + +Dimitris Apostolou (1): + depends macOS: point --sysroot to SDK + +Eirik Ogilvie-Wigley (41): + Wrap metrics message in strprintf + DoS protection: Weighted random drop of txs if mempool full + Rebuild weighted list on removal and fix size calculation + Grammatical fixes + Remove transactions when ensuring size limit + Help message cleanup and add lock + Performance: Store weighted transactions in a tree + Fix naming conventions + No need to activate Overwinter/Sapling in rpc test + Fix recently evicted list size + Put size increment and decrement on their own lines + Prevent adding duplicate transactions + Move duplicate macro to reusable location + mempool_limit rpc test cleanup + Represent tx costs as signed integers + Fix comments + Rename variables for consistency + Use tx cost rather than evictionWeight when checking mempool capacity + Log rather than return error if a transaction is recently evicted + Represent recently evicted list as a deque + Rename files + Update release notes + Add test + minor rpc test clean up + Add explanatory comments + Wording and grammatical fixes + Update parameter names to match ZIP + Clarify the difference between cost and evictionWeight + Fix test cases: default mempool limiters + Remove dots and underscores from parameter names + Use same type when calling max + make-release.py: Versioning changes for 2.1.0-rc1. + make-release.py: Updated manpages for 2.1.0-rc1. + make-release.py: Updated release notes and changelog for 2.1.0-rc1. + Release notes for bug fix + Better wording in release notes + Fix wording + Fix getblocksubsidy tests + fix comment + make-release.py: Versioning changes for 2.1.0. + make-release.py: Updated manpages for 2.1.0. + +Gareth Davies (1): + Updating IPFS link for chunking + +Jack Grigg (39): + depends: Add FreeBSD to hosts and builders + depends: Explicitly set Boost toolchain during configuration + depends: Add FreeBSD support to OpenSSL + depends: Patch libevent to detect arch4random_addrandom + depends: Add FreeBSD Rust binaries + depends: Explicitly call Rust install script using bash + depends: Use project-config.jam to configure Boost instead of user-config.jam + depends: Set PIC flags for FreeBSD + Always skip verification for old Sprout proofs + Remove ability to create non-Groth16 Sprout JSDescriptions + Use Sapling JSDescriptions in Boost tests + Remove non-Groth16 Sprout proofs from joinsplit gtests + Migrate test utilities to generate Sapling-type Sprout proofs + Use Sapling JSDescriptions in gtests + Revert "Allow user to ask server to save the Sprout R1CS out during startup." + Remove libsnark code for pre-Sapling Sprout proofs + Remove pre-Sapling Sprout circuit + Revert "configure: Guess -march for libsnark OPTFLAGS instead of hard-coding" + Revert "Check if OpenMP is available before using it" + Remove libsnark from build system + Remove libsnark + Remove libgmp + Remove libsnark unit tests from full test suite + test: Require minimum of Sapling for all RPC tests + test: Add Sapling v4 transactions to mininode framework + test: Add hashFinalSaplingProxy to create_block + test: Update RPC tests to use a minimum of Sapling + rpc: Use Sapling transactions in zc_raw_joinsplit + depends: Fix crate vendoring path + depends: Helper for vendoring new crates + depends: Add flag for building with a local librustzcash repo + tests: Clean up use of repr() in mininode + Remove makeGrothProof argument from JoinSplit::prove + Stop fetching old Sprout parameters + Add libsnark removal to notable changes + Move AbortNode to the top of main.cpp + Abort node if NU activations have unexpected hashes + Add block hashes for Overwinter, Sapling, and testnet Blossom + Update release notes with node abort behaviour + +Larry Ruane (5): + insightexplorer: formatting, pyflakes cleanups + precompute empty merkle roots + update unit tests to compute empty roots + access array element using at() + #4175 z_sendmany coinbase to zaddr with change: report error status + +Sean Bowe (1): + Set mainnet activation of Blossom + +jeff-liang (1): + Display which network the node is running on. + +Benjamin Winston (1): + Removed stale seeder, fixing #4153 + From 812d0ac44bf99df7f07f8322adcf3f87e281d802 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Fri, 8 Nov 2019 09:16:50 -0700 Subject: [PATCH 362/395] Fix of CVE-2017-18350 Adapted from bitcoin/bitcoin#11397 by Wladimir J. van der Laan. Co-Authored-By: Jack Grigg Co-Authored-By: Daira Hopwood --- src/netbase.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/netbase.cpp b/src/netbase.cpp index c2e779846b9..9f8a69c9246 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -246,7 +246,7 @@ struct timeval MillisToTimeval(int64_t nTimeout) * * @note This function requires that hSocket is in non-blocking mode. */ -bool static InterruptibleRecv(char* data, size_t len, int timeout, SOCKET& hSocket) +bool static InterruptibleRecv(uint8_t* data, size_t len, int timeout, SOCKET& hSocket) { int64_t curTime = GetTimeMillis(); int64_t endTime = curTime + timeout; @@ -314,7 +314,7 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials CloseSocket(hSocket); return error("Error sending to proxy"); } - char pchRet1[2]; + uint8_t pchRet1[2]; if (!InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) { CloseSocket(hSocket); return error("Error reading proxy response"); @@ -339,7 +339,7 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials return error("Error sending authentication to proxy"); } LogPrint("proxy", "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password); - char pchRetA[2]; + uint8_t pchRetA[2]; if (!InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, hSocket)) { CloseSocket(hSocket); return error("Error reading proxy authentication response"); @@ -368,7 +368,7 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials CloseSocket(hSocket); return error("Error sending to proxy"); } - char pchRet2[4]; + uint8_t pchRet2[4]; if (!InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) { CloseSocket(hSocket); return error("Error reading proxy response"); @@ -396,7 +396,7 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials CloseSocket(hSocket); return error("Error: malformed proxy response"); } - char pchRet3[256]; + uint8_t pchRet3[256]; switch (pchRet2[3]) { case 0x01: ret = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket); break; @@ -408,7 +408,7 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials CloseSocket(hSocket); return error("Error reading from proxy"); } - int nRecv = pchRet3[0]; + size_t nRecv = pchRet3[0]; ret = InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket); break; } From e07604a132b81d4cd4cffa71212a26c07f71af9b Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 8 Nov 2019 18:34:15 +0000 Subject: [PATCH 363/395] make-release.py: Versioning changes for 2.1.0-1. --- README.md | 2 +- configure.ac | 2 +- contrib/gitian-descriptors/gitian-linux.yml | 2 +- src/clientversion.h | 2 +- src/deprecation.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4accbb2309c..4433fc72887 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Zcash 2.1.0 +Zcash 2.1.0-1 =========== diff --git a/configure.ac b/configure.ac index fa22e088bcb..97be913eaa7 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 2) define(_CLIENT_VERSION_MINOR, 1) define(_CLIENT_VERSION_REVISION, 0) -define(_CLIENT_VERSION_BUILD, 50) +define(_CLIENT_VERSION_BUILD, 51) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 79c7d25fc96..e1219cf68a7 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "zcash-2.1.0" +name: "zcash-2.1.0-1" enable_cache: true distro: "debian" suites: diff --git a/src/clientversion.h b/src/clientversion.h index 27c913b48a9..452622904a1 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -18,7 +18,7 @@ #define CLIENT_VERSION_MAJOR 2 #define CLIENT_VERSION_MINOR 1 #define CLIENT_VERSION_REVISION 0 -#define CLIENT_VERSION_BUILD 50 +#define CLIENT_VERSION_BUILD 51 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/deprecation.h b/src/deprecation.h index 3596e6aa59d..0e62eda6fe5 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -8,7 +8,7 @@ // Deprecation policy: // * Shut down 16 weeks' worth of blocks after the estimated release block height. // * A warning is shown during the 2 weeks' worth of blocks prior to shut down. -static const int APPROX_RELEASE_HEIGHT = 632000; +static const int APPROX_RELEASE_HEIGHT = 634650; static const int WEEKS_UNTIL_DEPRECATION = 16; // static const int DEPRECATION_HEIGHT = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 24); From 66e06054072390c287c3fecb1f844e281fcddad1 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 8 Nov 2019 18:56:31 +0000 Subject: [PATCH 364/395] make-release.py: Updated manpages for 2.1.0-1. --- doc/man/zcash-cli.1 | 6 +++--- doc/man/zcash-tx.1 | 6 +++--- doc/man/zcashd.1 | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/man/zcash-cli.1 b/doc/man/zcash-cli.1 index fc47f7f8632..c5b7abc4373 100644 --- a/doc/man/zcash-cli.1 +++ b/doc/man/zcash-cli.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-CLI "1" "November 2019" "zcash-cli v2.1.0" "User Commands" +.TH ZCASH-CLI "1" "November 2019" "zcash-cli v2.1.0-1" "User Commands" .SH NAME -zcash-cli \- manual page for zcash-cli v2.1.0 +zcash-cli \- manual page for zcash-cli v2.1.0-1 .SH DESCRIPTION -Zcash RPC client version v2.1.0 +Zcash RPC client version v2.1.0\-1 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . diff --git a/doc/man/zcash-tx.1 b/doc/man/zcash-tx.1 index 22428b6285a..2097d67d514 100644 --- a/doc/man/zcash-tx.1 +++ b/doc/man/zcash-tx.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-TX "1" "November 2019" "zcash-tx v2.1.0" "User Commands" +.TH ZCASH-TX "1" "November 2019" "zcash-tx v2.1.0-1" "User Commands" .SH NAME -zcash-tx \- manual page for zcash-tx v2.1.0 +zcash-tx \- manual page for zcash-tx v2.1.0-1 .SH DESCRIPTION -Zcash zcash\-tx utility version v2.1.0 +Zcash zcash\-tx utility version v2.1.0\-1 .SS "Usage:" .TP zcash\-tx [options] [commands] diff --git a/doc/man/zcashd.1 b/doc/man/zcashd.1 index 1fb5f24bbab..4902ca89bea 100644 --- a/doc/man/zcashd.1 +++ b/doc/man/zcashd.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASHD "1" "November 2019" "zcashd v2.1.0" "User Commands" +.TH ZCASHD "1" "November 2019" "zcashd v2.1.0-1" "User Commands" .SH NAME -zcashd \- manual page for zcashd v2.1.0 +zcashd \- manual page for zcashd v2.1.0-1 .SH DESCRIPTION -Zcash Daemon version v2.1.0 +Zcash Daemon version v2.1.0\-1 .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . @@ -75,7 +75,7 @@ limit applied) .HP \fB\-par=\fR .IP -Set the number of script verification threads (\fB\-4\fR to 16, 0 = auto, <0 = +Set the number of script verification threads (\fB\-2\fR to 16, 0 = auto, <0 = leave that many cores free, default: 0) .HP \fB\-pid=\fR From 501ca0c2ec44263d15c883feaaa91367e38c9069 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 8 Nov 2019 18:56:32 +0000 Subject: [PATCH 365/395] make-release.py: Updated release notes and changelog for 2.1.0-1. --- contrib/debian/changelog | 6 ++++++ doc/authors.md | 4 ++-- doc/release-notes/release-notes-2.1.0-1.md | 10 ++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 doc/release-notes/release-notes-2.1.0-1.md diff --git a/contrib/debian/changelog b/contrib/debian/changelog index 016d2381439..58dd5dcd1c4 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,9 @@ +zcash (2.1.0+1) stable; urgency=medium + + * 2.1.0-1 release. + + -- Electric Coin Company Fri, 08 Nov 2019 18:56:32 +0000 + zcash (2.1.0) stable; urgency=medium * 2.1.0 release. diff --git a/doc/authors.md b/doc/authors.md index 9fbff8d0468..300f58bc23f 100644 --- a/doc/authors.md +++ b/doc/authors.md @@ -1,9 +1,9 @@ Zcash Contributors ================== -Jack Grigg (919) +Jack Grigg (921) Simon Liu (459) -Sean Bowe (279) +Sean Bowe (280) Eirik Ogilvie-Wigley (210) Daira Hopwood (144) Jay Graber (89) diff --git a/doc/release-notes/release-notes-2.1.0-1.md b/doc/release-notes/release-notes-2.1.0-1.md new file mode 100644 index 00000000000..21b08f16829 --- /dev/null +++ b/doc/release-notes/release-notes-2.1.0-1.md @@ -0,0 +1,10 @@ +Changelog +========= + +Jack Grigg (2): + make-release.py: Versioning changes for 2.1.0-1. + make-release.py: Updated manpages for 2.1.0-1. + +Sean Bowe (1): + Fix of CVE-2017-18350 + From f8c7d103a9e69a9d4c8a0bb3c23c34499e8cab7f Mon Sep 17 00:00:00 2001 From: cryptoforge Date: Fri, 6 Dec 2019 21:44:52 -0800 Subject: [PATCH 366/395] Pull up to Zcash 2.0.6 --- .github/ISSUE_TEMPLATE.md | 4 +- contrib/debian/changelog | 24 + contrib/gitian-descriptors/gitian-linux.yml | 3 +- doc/authors.md | 33 +- doc/developer-notes.md | 6 + doc/release-notes/release-notes-2.0.5-1.md | 68 +++ doc/release-notes/release-notes-2.0.5-2.md | 77 +++ doc/release-notes/release-notes-2.0.6-rc1.md | 62 +++ doc/release-notes/release-notes-2.0.6.md | 102 ++++ qa/pull-tester/rpc-tests.sh | 2 + qa/rpc-tests/getrawtransaction_insight.py | 104 ++++ qa/rpc-tests/mergetoaddress_helper.py | 8 +- qa/rpc-tests/mergetoaddress_mixednotes.py | 82 +++ qa/rpc-tests/sprout_sapling_migration.py | 23 +- responsible_disclosure.md | 5 +- src/amqp/amqppublishnotifier.cpp | 4 +- src/chain.h | 56 +- src/chainparams.cpp | 30 +- src/chainparams.h | 4 - src/clientversion.h | 2 +- src/consensus/params.h | 2 + src/gtest/test_checkblock.cpp | 16 +- src/gtest/test_checktransaction.cpp | 25 +- src/gtest/test_merkletree.cpp | 4 +- src/gtest/test_transaction_builder.cpp | 42 +- src/gtest/test_validation.cpp | 12 +- src/init.cpp | 17 +- src/main.cpp | 404 ++++++++------- src/main.h | 489 ++---------------- src/metrics.cpp | 4 +- src/miner.cpp | 27 +- src/miner.h | 4 +- src/policy/fees.h | 4 +- src/pow.cpp | 6 +- src/pow.h | 2 +- src/rest.cpp | 5 +- src/rpc/blockchain.cpp | 12 +- src/rpc/client.cpp | 4 +- src/rpc/mining.cpp | 16 +- src/rpc/rawtransaction.cpp | 23 +- src/script/interpreter.cpp | 12 +- src/script/script.cpp | 8 +- src/script/script.h | 9 +- src/script/standard.cpp | 13 + src/script/standard.h | 5 +- src/test/alert_tests.cpp | 2 +- src/test/checkblock_tests.cpp | 2 +- src/test/miner_tests.cpp | 33 +- src/test/rpc_wallet_tests.cpp | 2 +- src/test/script_P2SH_tests.cpp | 6 +- src/test/test_bitcoin.cpp | 3 +- src/test/transaction_tests.cpp | 38 +- src/transaction_builder.cpp | 9 +- src/transaction_builder.h | 1 + src/txdb.cpp | 16 +- src/txdb.h | 33 +- src/txmempool.h | 28 +- src/utiltest.cpp | 2 +- src/utiltime.cpp | 2 +- .../asyncrpcoperation_mergetoaddress.cpp | 2 +- .../asyncrpcoperation_saplingmigration.cpp | 59 ++- .../asyncrpcoperation_saplingmigration.h | 4 +- src/wallet/asyncrpcoperation_sendmany.cpp | 14 +- src/wallet/gtest/test_wallet.cpp | 26 +- src/wallet/rpcdisclosure.cpp | 4 +- src/wallet/rpcwallet.cpp | 67 ++- src/wallet/wallet.cpp | 36 +- src/wallet/wallet.h | 21 +- src/zcbenchmarks.cpp | 11 +- src/zeronode/budget.cpp | 4 +- src/zeronode/obfuscation.cpp | 2 +- src/zeronode/spork.cpp | 2 +- src/zeronode/swifttx.cpp | 2 +- src/zeronode/zeronode.cpp | 2 +- src/zmq/zmqpublishnotifier.cpp | 4 +- zcutil/release-notes.py | 15 +- 76 files changed, 1322 insertions(+), 994 deletions(-) create mode 100644 doc/release-notes/release-notes-2.0.5-1.md create mode 100644 doc/release-notes/release-notes-2.0.5-2.md create mode 100644 doc/release-notes/release-notes-2.0.6-rc1.md create mode 100644 doc/release-notes/release-notes-2.0.6.md create mode 100755 qa/rpc-tests/getrawtransaction_insight.py create mode 100755 qa/rpc-tests/mergetoaddress_mixednotes.py diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 93d6f0f575d..eef17794fac 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -31,7 +31,9 @@ Run `zerod --version` to find out - Disk size: - Disk Type (HD/SDD): - Linux kernel version (uname -a): -- Compiler version (gcc -version): +- Compiler version (gcc --version): +- Linker version (ld -v): +- Assembler version (as --version): ### Any extra information that might be useful in the debugging process. This includes the relevant contents of `~/.zero/debug.log`. You can paste raw text, attach the file directly in the issue or link to the text via a pastebin type site. diff --git a/contrib/debian/changelog b/contrib/debian/changelog index b9b8c076751..ed12564cf6c 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,27 @@ +zcash (2.0.6) stable; urgency=medium + + * 2.0.6 release. + + -- Electric Coin Company Wed, 19 Jun 2019 00:28:06 +0100 + +zcash (2.0.6~rc1) stable; urgency=medium + + * 2.0.6-rc1 release. + + -- Electric Coin Company Wed, 12 Jun 2019 16:36:57 +0100 + +zcash (2.0.5+2) stable; urgency=medium + + * 2.0.5-2 release. + + -- Electric Coin Company Wed, 15 May 2019 09:56:01 -0600 + +zcash (2.0.5+1) stable; urgency=medium + + * 2.0.5-1 release. + + -- Electric Coin Company Wed, 08 May 2019 06:57:28 -0600 + zcash (2.0.5) stable; urgency=medium * 2.0.5 release. diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index df50d864163..d770c29fc31 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,9 +1,10 @@ --- -name: "zcash-2.0.5" +name: "zcash-2.0.6" enable_cache: true distro: "debian" suites: - "jessie" +- "stretch" architectures: - "amd64" packages: diff --git a/doc/authors.md b/doc/authors.md index 95018c4b572..6afdb557cdf 100644 --- a/doc/authors.md +++ b/doc/authors.md @@ -1,28 +1,28 @@ Zcash Contributors ================== -Jack Grigg (863) -Simon Liu (448) +Jack Grigg (873) +Simon Liu (451) Sean Bowe (278) -Daira Hopwood (110) -Eirik Ogilvie-Wigley (102) +Eirik Ogilvie-Wigley (152) +Daira Hopwood (124) Jay Graber (89) -Wladimir J. van der Laan (81) +Wladimir J. van der Laan (82) Taylor Hornby (73) Jonas Schnelli (62) Nathan Wilcox (56) Pieter Wuille (54) Kevin Gallagher (38) Cory Fields (35) -Eirik0 (27) -mdr0id (22) -Larry Ruane (22) +Larry Ruane (23) +Marshall Gaucher (22) Jonathan "Duke" Leto (17) syd (15) Matt Corallo (13) Paige Peterson (11) +Marco Falke (11) Ariel Gabizon (11) -MarcoFalke (10) +Jorge Timón (10) nomnombtc (9) kozyilmaz (8) fanquake (8) @@ -32,21 +32,21 @@ Marius Kjærstad (6) Luke Dashjr (6) David Mercer (6) Daniel Cousens (6) +Charlie O'Keefe (6) Suhas Daftuar (5) -Pavel Janík (5) +Peter Todd (5) Karl-Johan Alm (5) Johnathan Corgan (5) -Charlie O'Keefe (5) Alex Morcos (5) WO (4) Philip Kaufmann (4) -Peter Todd (4) +Pavel Janík (4) Patrick Strateman (4) João Barbosa (4) -Jorge Timón (4) George Tankersley (4) Gareth Davies (4) -zebambam (3) +Daniel Kraft (4) +Benjamin Winston (4) lpescher (3) ca333 (3) Per Grön (3) @@ -54,12 +54,11 @@ Patick Strateman (3) Jason Davies (3) James O'Beirne (3) Dimitris Apostolou (3) -Daniel Kraft (3) Alfie John (3) rofl0r (2) -paveljanik (2) mruddy (2) kpcyrd (2) +face (2) aniemerg (2) UdjinM6 (2) Scott (2) @@ -68,6 +67,7 @@ Pejvan (2) Pavol Rusnak (2) Pavel Vasin (2) Matthew King (2) +Mary Moore-Simmons (2) Kaz Wesley (2) Joe Turgeon (2) Jack Gavigan (2) @@ -110,7 +110,6 @@ Nathaniel Mahieu (1) Murilo Santana (1) Maxwell Gubler (1) Matt Quinn (1) -Mary Moore-Simmons (1) Mark Friedenbach (1) Louis Nyffenegger (1) Leo Arias (1) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 4ff83e4fd68..188ee4f3678 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -71,6 +71,12 @@ To describe a member or variable use: int var; //!< Detailed description after the member ``` +or +```cpp +//! Description before the member +int var; +``` + Also OK: ```c++ /// diff --git a/doc/release-notes/release-notes-2.0.5-1.md b/doc/release-notes/release-notes-2.0.5-1.md new file mode 100644 index 00000000000..ef02d80b571 --- /dev/null +++ b/doc/release-notes/release-notes-2.0.5-1.md @@ -0,0 +1,68 @@ +Notable changes +=============== + +Sprout to Sapling Migration Tool +-------------------------------- +This release includes the addition of a tool that will enable users to migrate +shielded funds from the Sprout pool to the Sapling pool while minimizing +information leakage. + +The migration can be enabled using the RPC `z_setmigration` or by including +`-migration` in the `zcash.conf` file. Unless otherwise specified funds will be +migrated to the wallet's default Sapling address; it is also possible to set the +receiving Sapling address using the `-migrationdestaddress` option in `zcash.conf`. + +See [ZIP308](https://github.com/zcash/zips/blob/master/zip-0308.rst) for full details. + +Sprout to Sapling Migration Tool Fixes +-------------------------------------- +The 2.0.5-1 release includes fixes to the Sprout to Sapling Migration Tool +found in testing. We resolved an issue which would cause the zcash daemon to +crash if calling the RPC `z_getmigrationstatus` while a wallet's migration +transactions are in the mempool. + +New consensus rule: Reject blocks that violate turnstile +-------------------------------------------------------- +In the 2.0.4 release the consensus rules were changed on testnet to enforce a +consensus rule which marks blocks as invalid if they would lead to a turnstile +violation in the Sprout or Shielded value pools. +**This release enforces the consensus rule change on mainnet** + +The motivations and deployment details can be found in the accompanying +[ZIP draft](https://github.com/zcash/zips/pull/210) and +[PR 3968](https://github.com/zcash/zcash/pull/3968). + +Developers can use a new experimental feature `-developersetpoolsizezero` to test +Sprout and Sapling turnstile violations. See [PR 3964](https://github.com/zcash/zcash/pull/3964) for more details. + + +64-bit ARMv8 support +-------------------- +Added ARMv8 (AArch64) support. This enables users to build zcash on even more +devices. + +For information on how to build see the [User Guide](https://zcash.readthedocs.io/en/latest/rtd_pages/user_guide.html#build) + +Users on the Zcash forum have reported successes with both the Pine64 Rock64Pro +and Odroid C2 which contain 4GB and 2GB of RAM respectively. + +Just released, the Odroid N2 looks like a great solution with 4GB of RAM. The +newly released Jetson Nano Developer Kit from Nvidia (also 4GB of RAM) is also +worth a look. The NanoPC-T3 Plus is another option but for the simplest/best +experience choose a board with 4GB of RAM. Just make sure before purchase that +the CPU supports the 64-bit ARMv8 architecture. + +Changelog +========= + +Eirik0 (9): + Correctly account for migration transactions in the mempool + Store the migration operation id rather than the operation iteslf + Rename variable and add comment + Notable changes for v2.0.5-1 + Fix summing available funds + Add the amount migrated to the operation's result + coinsView is required when using TransactionBuilder if there may be Sprout change + make-release.py: Versioning changes for 2.0.5-1. + make-release.py: Updated manpages for 2.0.5-1. + diff --git a/doc/release-notes/release-notes-2.0.5-2.md b/doc/release-notes/release-notes-2.0.5-2.md new file mode 100644 index 00000000000..8d7dc947afd --- /dev/null +++ b/doc/release-notes/release-notes-2.0.5-2.md @@ -0,0 +1,77 @@ +Notable changes +=============== + +Sprout to Sapling Migration Tool +-------------------------------- +This release includes the addition of a tool that will enable users to migrate +shielded funds from the Sprout pool to the Sapling pool while minimizing +information leakage. + +The migration can be enabled using the RPC `z_setmigration` or by including +`migration=1` in the `zcash.conf` file. Unless otherwise specified funds will be +migrated to the wallet's default Sapling address; it is also possible to set the +receiving Sapling address using the `migrationdestaddress=` option in +`zcash.conf`. + +See [ZIP308](https://github.com/zcash/zips/blob/master/zip-0308.rst) for full details. + +Sprout to Sapling Migration Tool Fixes +-------------------------------------- +The 2.0.5-1 and 2.0.5-2 releases include fixes to the Sprout to Sapling +Migration Tool found in testing. + +For a complete list of changes in 2.0.5, 2.0.5-1 and 2.0.5-2, see the [2.0.5 milestone](https://github.com/zcash/zcash/milestone/79?closed=1). + +New consensus rule: Reject blocks that violate turnstile +-------------------------------------------------------- +In the 2.0.4 release the consensus rules were changed on testnet to enforce a +consensus rule which marks blocks as invalid if they would lead to a turnstile +violation in the Sprout or Shielded value pools. +**This release enforces the consensus rule change on mainnet.** + +The motivations and deployment details can be found in +[ZIP209](https://github.com/zcash/zips/blob/master/zip-0209.rst) and +[PR 3968](https://github.com/zcash/zcash/pull/3968). + +Developers can use a new experimental feature `-developersetpoolsizezero` to test +Sprout and Sapling turnstile violations. See [PR 3964](https://github.com/zcash/zcash/pull/3964) for more details. + +64-bit ARMv8 support +-------------------- +Added ARMv8 (AArch64) support. This enables users to build zcash on even more +devices. + +For information on how to build see the [User Guide](https://zcash.readthedocs.io/en/latest/rtd_pages/user_guide.html#build). + +Users on the Zcash forum have reported successes with both the Pine64 Rock64Pro +and Odroid C2 which contain 4GB and 2GB of RAM respectively. + +Just released, the Odroid N2 looks like a great solution with 4GB of RAM. The +newly released Jetson Nano Developer Kit from Nvidia (also 4GB of RAM) is also +worth a look. The NanoPC-T3 Plus is another option but for the simplest/best +experience choose a board with 4GB of RAM. Just make sure before purchase that +the CPU supports the 64-bit ARMv8 architecture. + +Changelog +========= + +Daira Hopwood (5): + Generalize TransactionBuilder and CreateNewContextualCMutableTransaction to allow choosing the expiry delta. + Repair calls to TransactionBuilder from tests. + Change expiry delta for migration transactions to 450 blocks. + Test the expiry height of migration transactions. + Fix cosmetic spacing issue in z_setmigration help. + +Eirik0 (7): + Do not automatically remove async migration operations and return txids + Add logging for Sprout to Sapling migration transaction generation + Fix LogPrint statements + Notable changes for v2.0.5-2 + Release notes wording and punctuation + make-release.py: Versioning changes for 2.0.5-2. + make-release.py: Updated manpages for 2.0.5-2. + +Simon Liu (2): + Remove unused specifier from format string. + Don't allow migration when node is syncing at launch or after waking up. + diff --git a/doc/release-notes/release-notes-2.0.6-rc1.md b/doc/release-notes/release-notes-2.0.6-rc1.md new file mode 100644 index 00000000000..ce40147200a --- /dev/null +++ b/doc/release-notes/release-notes-2.0.6-rc1.md @@ -0,0 +1,62 @@ +Changelog +========= + +Daira Hopwood (3): + Closes #3992. Remove obsolete warning message. + make-release.py: Versioning changes for 2.0.6-rc1. + make-release.py: Updated manpages for 2.0.6-rc1. + +Daniel Kraft (1): + Add some const declarations where they are appropriate. + +Eirik Ogilvie-Wigley (7): + Fix tree depth in comment + Update author aliases + Remove old mergetoaddress RPC test + Replace CSproutNotePlaintextEntry with SproutNoteEntry to match Sapling + z_getmigrationstatus help message wording change + Fix z_mergetoaddress sending from ANY_SPROUT/ANY_SAPLING when the wallet contains both note types + Clarify what combinations of from addresses can be used in z_mergetoaddress + +Jack Grigg (10): + Move Equihash parameters into consensus params + Globals: Remove Zcash-specific Params() calls from main.cpp + Globals: Explicitly pass const CChainParams& to IsStandardTx() + Globals: Explicit const CChainParams& arg for main: + Globals: Explicitly pass const CChainParams& to ContextualCheckTransaction() + Globals: Explicit const CChainParams& arg for main: + Globals: Explicitly pass const CChainParams& to DisconnectBlock() + Consistently use chainparams and consensusParams + Globals: Explicitly pass const CChainParams& to IsInitialBlockDownload() + Globals: Explicitly pass const CChainParams& to ReceivedBlockTransactions() + +Jorge Timón (6): + Globals: Explicit Consensus::Params arg for main: + Globals: Make AcceptBlockHeader static (Fix #6163) + Chainparams: Explicit CChainParams arg for main (pre miner): + Chainparams: Explicit CChainParams arg for miner: + Globals: Remove a bunch of Params() calls from main.cpp: + Globals: Explicitly pass const CChainParams& to UpdateTip() + +Larry Ruane (1): + add spentindex to getrawtransaction RPC results + +MarcoFalke (1): + [doc] Fix doxygen comments for members + +Peter Todd (1): + Improve block validity/ConnectBlock() comments + +Simon Liu (1): + Fix typo and clean up help message for RPC z_getmigrationstatus. + +Wladimir J. van der Laan (1): + Break circular dependency main ↔ txdb + +face (2): + Pass CChainParams to DisconnectTip() + Explicitly pass CChainParams to ConnectBlock + +Benjamin Winston (1): + Fixes #4013, added BitcoinABC as a disclosure partner + diff --git a/doc/release-notes/release-notes-2.0.6.md b/doc/release-notes/release-notes-2.0.6.md new file mode 100644 index 00000000000..f1beec5117e --- /dev/null +++ b/doc/release-notes/release-notes-2.0.6.md @@ -0,0 +1,102 @@ +Notable changes +=============== + +Debian Stretch is now a Supported Platform +------------------------------------------ + +We now provide reproducible builds for Stretch as well as for Jessie. + + +Fixed a bug in ``z_mergetoaddress`` +----------------------------------- + +We fixed a bug which prevented users sending from ``ANY_SPROUT`` or ``ANY_SAPLING`` +with ``z_mergetoaddress`` when a wallet contained both Sprout and Sapling notes. + + +Insight Explorer +---------------- + +We have been incorporating changes to support the Insight explorer directly from +``zcashd``. v2.0.6 includes the first change to an RPC method. If ``zcashd`` is +run with the flag ``--insightexplorer``` (this requires an index rebuild), the +RPC method ``getrawtransaction`` will now return additional information about +spend indices. + +Changelog +========= + +Charlie O'Keefe (1): + Add stretch to list of suites in gitian linux descriptors + +Daira Hopwood (9): + Closes #3992. Remove obsolete warning message. + make-release.py: Versioning changes for 2.0.6-rc1. + make-release.py: Updated manpages for 2.0.6-rc1. + make-release.py: Updated release notes and changelog for 2.0.6-rc1. + ld --version doesn't work on macOS. + Tweak author aliases. + Add coding declaration to zcutil/release-notes.py + make-release.py: Versioning changes for 2.0.6. + make-release.py: Updated manpages for 2.0.6. + +Daniel Kraft (1): + Add some const declarations where they are appropriate. + +Eirik Ogilvie-Wigley (1): + Notable changes for 2.0.6 + +Eirik Ogilvie-Wigley (7): + Fix tree depth in comment + Update author aliases + Remove old mergetoaddress RPC test + Replace CSproutNotePlaintextEntry with SproutNoteEntry to match Sapling + z_getmigrationstatus help message wording change + Fix z_mergetoaddress sending from ANY_SPROUT/ANY_SAPLING when the wallet contains both note types + Clarify what combinations of from addresses can be used in z_mergetoaddress + +Jack Grigg (10): + Move Equihash parameters into consensus params + Globals: Remove Zcash-specific Params() calls from main.cpp + Globals: Explicitly pass const CChainParams& to IsStandardTx() + Globals: Explicit const CChainParams& arg for main: + Globals: Explicitly pass const CChainParams& to ContextualCheckTransaction() + Globals: Explicit const CChainParams& arg for main: + Globals: Explicitly pass const CChainParams& to DisconnectBlock() + Consistently use chainparams and consensusParams + Globals: Explicitly pass const CChainParams& to IsInitialBlockDownload() + Globals: Explicitly pass const CChainParams& to ReceivedBlockTransactions() + +Jorge Timón (6): + Globals: Explicit Consensus::Params arg for main: + Globals: Make AcceptBlockHeader static (Fix #6163) + Chainparams: Explicit CChainParams arg for main (pre miner): + Chainparams: Explicit CChainParams arg for miner: + Globals: Remove a bunch of Params() calls from main.cpp: + Globals: Explicitly pass const CChainParams& to UpdateTip() + +Larry Ruane (1): + add spentindex to getrawtransaction RPC results + +Marco Falke (1): + [doc] Fix doxygen comments for members + +Mary Moore-Simmons (1): + Fixes issue #3504: Changes to --version and adds a couple other useful commands. + +Peter Todd (1): + Improve block validity/ConnectBlock() comments + +Simon Liu (1): + Fix typo and clean up help message for RPC z_getmigrationstatus. + +Wladimir J. van der Laan (1): + Break circular dependency main ↔ txdb + +face (2): + Pass CChainParams to DisconnectTip() + Explicitly pass CChainParams to ConnectBlock + +Benjamin Winston (1): + Fixes #4013, added BitcoinABC as a disclosure partner + diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index bafdf95aa62..d8480046c47 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -31,12 +31,14 @@ testScripts=( 'wallet_listnotes.py' 'mergetoaddress_sprout.py' 'mergetoaddress_sapling.py' + 'mergetoaddress_mixednotes.py' 'listtransactions.py' 'mempool_resurrect_test.py' 'txn_doublespend.py' 'txn_doublespend.py --mineblock' 'getchaintips.py' 'rawtransactions.py' + 'getrawtransaction_insight.py' 'rest.py' 'mempool_spendcoinbase.py' 'mempool_reorg.py' diff --git a/qa/rpc-tests/getrawtransaction_insight.py b/qa/rpc-tests/getrawtransaction_insight.py new file mode 100755 index 00000000000..f18eed5d465 --- /dev/null +++ b/qa/rpc-tests/getrawtransaction_insight.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python2 +# Copyright (c) 2019 The Zcash developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Test the new fields added to the output of getrawtransaction +# RPC for the Insight Explorer by the new spentindex +# + +from test_framework.test_framework import BitcoinTestFramework + +from test_framework.util import assert_equal +from test_framework.util import initialize_chain_clean +from test_framework.util import start_nodes, stop_nodes, connect_nodes +from test_framework.util import wait_bitcoinds + +from test_framework.mininode import COIN + + +class GetrawtransactionTest(BitcoinTestFramework): + + def setup_chain(self): + print("Initializing test directory "+self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 4) + + def setup_network(self): + # -insightexplorer causes spentindex to be enabled (fSpentIndex = true) + + self.nodes = start_nodes(3, self.options.tmpdir, + [['-debug', '-txindex', '-experimentalfeatures', '-insightexplorer']]*3) + connect_nodes(self.nodes[0], 1) + connect_nodes(self.nodes[0], 2) + + self.is_network_split = False + self.sync_all() + + def run_test(self): + self.nodes[0].generate(105) + self.sync_all() + + chain_height = self.nodes[1].getblockcount() + assert_equal(chain_height, 105) + + # Test getrawtransaction changes and the getspentinfo RPC + + # send coinbase to address a + a = self.nodes[1].getnewaddress() + txid_a = self.nodes[0].sendtoaddress(a, 2) + self.sync_all() + self.nodes[0].generate(1) + self.sync_all() + + # send from a to b + # (the only utxo on node 1 is from address a) + b = self.nodes[2].getnewaddress() + txid_b = self.nodes[1].sendtoaddress(b, 1) + self.sync_all() + + # a to b transaction is not confirmed, so it has no height + tx_b = self.nodes[2].getrawtransaction(txid_b, 1) + assert('height' not in tx_b) + + self.sync_all() + tx_a = self.nodes[2].getrawtransaction(txid_a, 1) + + # txid_b is not yet confirmed, so these should not be set + assert('spentTxId' not in tx_a['vout'][0]) + assert('spentIndex' not in tx_a['vout'][0]) + assert('spentHeight' not in tx_a['vout'][0]) + + # confirm txid_b (a to b transaction) + self.nodes[0].generate(1) + self.sync_all() + + # Restart all nodes to ensure index files are saved to disk and recovered + stop_nodes(self.nodes) + wait_bitcoinds() + self.setup_network() + + # Check new fields added to getrawtransaction + tx_a = self.nodes[2].getrawtransaction(txid_a, 1) + assert_equal(tx_a['vin'][0]['value'], 10) # coinbase + assert_equal(tx_a['vin'][0]['valueSat'], 10*COIN) + # we want the non-change (payment) output + vout = filter(lambda o: o['value'] == 2, tx_a['vout']) + assert_equal(vout[0]['spentTxId'], txid_b) + assert_equal(vout[0]['spentIndex'], 0) + assert_equal(vout[0]['spentHeight'], 107) + assert_equal(tx_a['height'], 106) + + tx_b = self.nodes[2].getrawtransaction(txid_b, 1) + assert_equal(tx_b['vin'][0]['address'], a) + assert_equal(tx_b['vin'][0]['value'], 2) + assert_equal(tx_b['vin'][0]['valueSat'], 2*COIN) + # since this transaction's outputs haven't yet been + # spent, these fields should not be present + assert('spentTxId' not in tx_b['vout'][0]) + assert('spentIndex' not in tx_b['vout'][0]) + assert('spentHeight' not in tx_b['vout'][0]) + assert_equal(tx_b['height'], 107) + +if __name__ == '__main__': + GetrawtransactionTest().main() diff --git a/qa/rpc-tests/mergetoaddress_helper.py b/qa/rpc-tests/mergetoaddress_helper.py index cc829f8b8aa..962c2b7ff49 100755 --- a/qa/rpc-tests/mergetoaddress_helper.py +++ b/qa/rpc-tests/mergetoaddress_helper.py @@ -17,11 +17,12 @@ def assert_mergetoaddress_exception(expected_error_msg, merge_to_address_lambda): try: merge_to_address_lambda() - fail("Expected exception: %s" % expected_error_msg) except JSONRPCException as e: assert_equal(expected_error_msg, e.error['message']) except Exception as e: fail("Expected JSONRPCException. Found %s" % repr(e)) + else: + fail("Expected exception: %s" % expected_error_msg) class MergeToAddressHelper: @@ -152,6 +153,11 @@ def run_test(self, test): "Destination address is also the only source address, and all its funds are already merged.", lambda: test.nodes[0].z_mergetoaddress([mytaddr], mytaddr)) + # Merging will fail for this specific case where it would spend a fee and do nothing + assert_mergetoaddress_exception( + "Cannot send from both Sprout and Sapling addresses using z_mergetoaddress", + lambda: test.nodes[0].z_mergetoaddress(["ANY_SPROUT", "ANY_SAPLING"], mytaddr)) + # Merge UTXOs from node 0 of value 30, standard fee of 0.00010000 result = test.nodes[0].z_mergetoaddress([mytaddr, mytaddr2, mytaddr3], myzaddr) wait_and_assert_operationid_status(test.nodes[0], result['opid']) diff --git a/qa/rpc-tests/mergetoaddress_mixednotes.py b/qa/rpc-tests/mergetoaddress_mixednotes.py new file mode 100755 index 00000000000..b787429aa99 --- /dev/null +++ b/qa/rpc-tests/mergetoaddress_mixednotes.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python +# Copyright (c) 2019 The Zcash developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." + +from decimal import Decimal +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import assert_equal, get_coinbase_address, \ + initialize_chain_clean, start_nodes, wait_and_assert_operationid_status +from mergetoaddress_helper import assert_mergetoaddress_exception + + +class MergeToAddressMixedNotes(BitcoinTestFramework): + def setup_nodes(self): + return start_nodes(4, self.options.tmpdir, [[ + '-nuparams=5ba81b19:100', # Overwinter + '-nuparams=76b809bb:100', # Sapling + '-experimentalfeatures', '-zmergetoaddress' + ]] * 4) + + def setup_chain(self): + print("Initializing test directory " + self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 4) + + def run_test(self): + print "Mining blocks..." + self.nodes[0].generate(102) + self.sync_all() + + # Send some ZEC to Sprout/Sapling addresses + coinbase_addr = get_coinbase_address(self.nodes[0]) + sproutAddr = self.nodes[0].z_getnewaddress('sprout') + saplingAddr = self.nodes[0].z_getnewaddress('sapling') + t_addr = self.nodes[1].getnewaddress() + + opid = self.nodes[0].z_sendmany(coinbase_addr, [{"address": sproutAddr, "amount": Decimal('10')}], 1, 0) + wait_and_assert_operationid_status(self.nodes[0], opid) + self.nodes[0].generate(1) + self.sync_all() + assert_equal(self.nodes[0].z_getbalance(sproutAddr), Decimal('10')) + assert_equal(self.nodes[0].z_getbalance(saplingAddr), Decimal('0')) + assert_equal(Decimal(self.nodes[1].z_gettotalbalance()["transparent"]), Decimal('0')) + # Make sure we cannot use "ANY_SPROUT" and "ANY_SAPLING" even if we only have Sprout Notes + assert_mergetoaddress_exception( + "Cannot send from both Sprout and Sapling addresses using z_mergetoaddress", + lambda: self.nodes[0].z_mergetoaddress(["ANY_SPROUT", "ANY_SAPLING"], t_addr)) + opid = self.nodes[0].z_sendmany(coinbase_addr, [{"address": saplingAddr, "amount": Decimal('10')}], 1, 0) + wait_and_assert_operationid_status(self.nodes[0], opid) + self.nodes[0].generate(1) + self.sync_all() + + assert_equal(Decimal(self.nodes[1].z_gettotalbalance()["transparent"]), Decimal('0')) + + # Merge Sprout -> taddr + result = self.nodes[0].z_mergetoaddress(["ANY_SPROUT"], t_addr, 0) + wait_and_assert_operationid_status(self.nodes[0], result['opid']) + self.nodes[0].generate(1) + self.sync_all() + + assert_equal(self.nodes[0].z_getbalance(sproutAddr), Decimal('0')) + assert_equal(self.nodes[0].z_getbalance(saplingAddr), Decimal('10')) + assert_equal(Decimal(self.nodes[1].z_gettotalbalance()["transparent"]), Decimal('10')) + + # Make sure we cannot use "ANY_SPROUT" and "ANY_SAPLING" even if we only have Sapling Notes + assert_mergetoaddress_exception( + "Cannot send from both Sprout and Sapling addresses using z_mergetoaddress", + lambda: self.nodes[0].z_mergetoaddress(["ANY_SPROUT", "ANY_SAPLING"], t_addr)) + # Merge Sapling -> taddr + result = self.nodes[0].z_mergetoaddress(["ANY_SAPLING"], t_addr, 0) + wait_and_assert_operationid_status(self.nodes[0], result['opid']) + self.nodes[0].generate(1) + self.sync_all() + + assert_equal(self.nodes[0].z_getbalance(sproutAddr), Decimal('0')) + assert_equal(self.nodes[0].z_getbalance(saplingAddr), Decimal('0')) + assert_equal(Decimal(self.nodes[1].z_gettotalbalance()["transparent"]), Decimal('20')) + + +if __name__ == '__main__': + MergeToAddressMixedNotes().main() diff --git a/qa/rpc-tests/sprout_sapling_migration.py b/qa/rpc-tests/sprout_sapling_migration.py index 5f47d779616..03e1ccde77c 100755 --- a/qa/rpc-tests/sprout_sapling_migration.py +++ b/qa/rpc-tests/sprout_sapling_migration.py @@ -45,9 +45,10 @@ def setup_nodes(self): # Add migration parameters to nodes[0] extra_args[0] = extra_args[0] + [ '-migration', - '-migrationdestaddress=' + SAPLING_ADDR + '-migrationdestaddress=' + SAPLING_ADDR, + '-debug=zrpcunsafe' ] - assert_equal(4, len(extra_args[0])) + assert_equal(5, len(extra_args[0])) assert_equal(2, len(extra_args[1])) return start_nodes(4, self.options.tmpdir, extra_args) @@ -87,6 +88,8 @@ def run_migration_test(self, node, sproutAddr, saplingAddr, target_height): assert_equal('saplingmigration', result['method']) assert_equal(target_height, result['target_height']) assert_equal(1, result['result']['num_tx_created']) + assert_equal(1, len(result['result']['migration_txids'])) + assert_true(result['result']['amount_migrated'] > Decimal('0')) assert_equal(0, len(node.getrawmempool()), "mempool size at 495 % 500") @@ -102,10 +105,24 @@ def run_migration_test(self, node, sproutAddr, saplingAddr, target_height): self.sync_all() # At 499 % 500 there will be a transaction in the mempool and the note will be locked - assert_equal(1, len(node.getrawmempool()), "mempool size at 499 % 500") + mempool = node.getrawmempool() + print("mempool: {}".format(mempool)) + assert_equal(1, len(mempool), "mempool size at 499 % 500") assert_equal(node.z_getbalance(sproutAddr), Decimal('0')) assert_equal(node.z_getbalance(saplingAddr), Decimal('0')) assert_true(node.z_getbalance(saplingAddr, 0) > Decimal('0'), "Unconfirmed sapling balance at 499 % 500") + # Check that unmigrated amount + unfinalized = starting balance - fee + status = node.z_getmigrationstatus() + print("status: {}".format(status)) + assert_equal(Decimal('9.9999'), Decimal(status['unmigrated_amount']) + Decimal(status['unfinalized_migrated_amount'])) + + # The transaction in the mempool should be the one listed in migration_txids, + # and it should expire at the next 450 % 500. + assert_equal(1, len(status['migration_txids'])) + txid = status['migration_txids'][0] + assert_equal(txid, mempool[0]) + tx = node.getrawtransaction(txid, 1) + assert_equal(target_height + 450, tx['expiryheight']) node.generate(1) self.sync_all() diff --git a/responsible_disclosure.md b/responsible_disclosure.md index 1f3c9401bba..718cf42d9c0 100644 --- a/responsible_disclosure.md +++ b/responsible_disclosure.md @@ -51,8 +51,9 @@ We have set up agreements with the following neighboring projects to share vulne Specifically, we have agreed to engage in responsible disclosures for security issues affecting Zcash technology with the following contacts: -- security@horizen.com via PGP -- ca333@komodoplatform.com via PGP +- Horizen security@horizen.com via PGP +- Komodo ca333@komodoplatform.com via PGP +- BitcoinABC https://github.com/Bitcoin-ABC/bitcoin-abc/blob/master/DISCLOSURE_POLICY.md ## Deviations from the Standard diff --git a/src/amqp/amqppublishnotifier.cpp b/src/amqp/amqppublishnotifier.cpp index 589eb151fb6..2704d94c2c5 100644 --- a/src/amqp/amqppublishnotifier.cpp +++ b/src/amqp/amqppublishnotifier.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "amqppublishnotifier.h" +#include "chainparams.h" #include "main.h" #include "util.h" @@ -152,11 +153,12 @@ bool AMQPPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex) { LogPrint("amqp", "amqp: Publish rawblock %s\n", pindex->GetBlockHash().GetHex()); + const Consensus::Params& consensusParams = Params().GetConsensus(); CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); { LOCK(cs_main); CBlock block; - if(!ReadBlockFromDisk(block, pindex)) { + if(!ReadBlockFromDisk(block, pindex, consensusParams)) { LogPrint("amqp", "amqp: Can't read block from disk"); return false; } diff --git a/src/chain.h b/src/chain.h index a532c85642f..5a7b3ad9cf4 100644 --- a/src/chain.h +++ b/src/chain.h @@ -14,11 +14,63 @@ #include -#include - static const int SPROUT_VALUE_VERSION = 1001400; static const int SAPLING_VALUE_VERSION = 1010100; +class CBlockFileInfo +{ +public: + unsigned int nBlocks; //!< number of blocks stored in file + unsigned int nSize; //!< number of used bytes of block file + unsigned int nUndoSize; //!< number of used bytes in the undo file + unsigned int nHeightFirst; //!< lowest height of block in file + unsigned int nHeightLast; //!< highest height of block in file + uint64_t nTimeFirst; //!< earliest time of block in file + uint64_t nTimeLast; //!< latest time of block in file + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(VARINT(nBlocks)); + READWRITE(VARINT(nSize)); + READWRITE(VARINT(nUndoSize)); + READWRITE(VARINT(nHeightFirst)); + READWRITE(VARINT(nHeightLast)); + READWRITE(VARINT(nTimeFirst)); + READWRITE(VARINT(nTimeLast)); + } + + void SetNull() { + nBlocks = 0; + nSize = 0; + nUndoSize = 0; + nHeightFirst = 0; + nHeightLast = 0; + nTimeFirst = 0; + nTimeLast = 0; + } + + CBlockFileInfo() { + SetNull(); + } + + std::string ToString() const; + + /** update statistics (does not update nSize) */ + void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) { + if (nBlocks==0 || nHeightFirst > nHeightIn) + nHeightFirst = nHeightIn; + if (nBlocks==0 || nTimeFirst > nTimeIn) + nTimeFirst = nTimeIn; + nBlocks++; + if (nHeightIn > nHeightLast) + nHeightLast = nHeightIn; + if (nTimeIn > nTimeLast) + nTimeLast = nTimeIn; + } +}; + struct CDiskBlockPos { int nFile; diff --git a/src/chainparams.cpp b/src/chainparams.cpp index aec2d6b8eff..cf0cb0d76a8 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -89,6 +89,11 @@ class CMainParams : public CChainParams { consensus.nMajorityEnforceBlockUpgrade = 750; consensus.nMajorityRejectBlockOutdated = 950; consensus.nMajorityWindow = 4000; + + const size_t N = 192, K = 7; + BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K)); + consensus.nEquihashN = N; + consensus.nEquihashK = K; consensus.powLimit = uint256S("0AB1Efffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.nPowAveragingWindow = 17; assert(maxUint/UintToArith256(consensus.powLimit) >= consensus.nPowAveragingWindow); @@ -126,10 +131,6 @@ class CMainParams : public CChainParams { nDefaultPort = 23801; //nMaxTipAge = 24 * 60 * 60; nPruneAfterHeight = 100000; - const size_t N = 192, K = 7; - BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K)); - nEquihashN = N; - nEquihashK = K; //Start Zeronode nZeronodeCountDrift = 0; @@ -249,6 +250,11 @@ class CTestNetParams : public CChainParams { consensus.nMajorityEnforceBlockUpgrade = 51; consensus.nMajorityRejectBlockOutdated = 75; consensus.nMajorityWindow = 400; + + const size_t N = 192, K = 7; + BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K)); + consensus.nEquihashN = N; + consensus.nEquihashK = K; consensus.powLimit = uint256S("0effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.nPowAveragingWindow = 17; assert(maxUint/UintToArith256(consensus.powLimit) >= consensus.nPowAveragingWindow); @@ -284,10 +290,6 @@ class CTestNetParams : public CChainParams { nDefaultPort = 23802; //nMaxTipAge = 1000000000; nPruneAfterHeight = 1000; - const size_t N = 192, K = 7; - BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K)); - nEquihashN = N; - nEquihashK = K; //Start Zeronode nZeronodeCountDrift = 0; @@ -397,6 +399,10 @@ class CRegTestParams : public CChainParams { consensus.nMajorityEnforceBlockUpgrade = 750; consensus.nMajorityRejectBlockOutdated = 950; consensus.nMajorityWindow = 1000; + const size_t N = 48, K = 5; + BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K)); + consensus.nEquihashN = N; + consensus.nEquihashK = K; consensus.powLimit = uint256S("0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"); consensus.nPowAveragingWindow = 17; assert(maxUint/UintToArith256(consensus.powLimit) >= consensus.nPowAveragingWindow); @@ -435,10 +441,6 @@ class CRegTestParams : public CChainParams { nDefaultPort = 23803; //nMaxTipAge = 24 * 60 * 60; nPruneAfterHeight = 1000; - const size_t N = 48, K = 5; - BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K)); - nEquihashN = N; - nEquihashK = K; //Start Zeronode nZeronodeCountDrift = 0; @@ -462,8 +464,8 @@ class CRegTestParams : public CChainParams { assert(consensus.hashGenesisBlock == uint256S("0275863eebea76f824674494b7f6a3770ac46c732aaa62b07328feaa9d79798b")); //assert(genesis.hashMerkleRoot == uint256S("")); - vFixedSeeds.clear(); //! Regtest mode doesn't have any fixed seeds. - vSeeds.clear(); //! Regtest mode doesn't have any DNS seeds. + vFixedSeeds.clear(); //!< Regtest mode doesn't have any fixed seeds. + vSeeds.clear(); //!< Regtest mode doesn't have any DNS seeds. // guarantees the first 2 characters, when base58 encoded, are "tm" base58Prefixes[PUBKEY_ADDRESS] = {0x1D,0x25}; diff --git a/src/chainparams.h b/src/chainparams.h index 25adae3aea1..cd0f811b525 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -83,8 +83,6 @@ class CChainParams /** Policy: Filter transactions that do not match well-defined patterns */ bool RequireStandard() const { return fRequireStandard; } int64_t PruneAfterHeight() const { return nPruneAfterHeight; } - unsigned int EquihashN() const { return nEquihashN; } - unsigned int EquihashK() const { return nEquihashK; } std::string CurrencyUnits() const { return strCurrencyUnits; } uint32_t BIP44CoinType() const { return bip44CoinType; } /** Make miner stop after a block is found. In RPC, don't return until nGenProcLimit blocks are generated */ @@ -124,8 +122,6 @@ class CChainParams std::vector vAlertPubKey; int nDefaultPort = 0; uint64_t nPruneAfterHeight = 0; - unsigned int nEquihashN = 0; - unsigned int nEquihashK = 0; std::vector vSeeds; std::vector base58Prefixes[MAX_BASE58_TYPES]; std::string bech32HRPs[MAX_BECH32_TYPES]; diff --git a/src/clientversion.h b/src/clientversion.h index 0e21ca63e5e..259d6d4b3e5 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -17,7 +17,7 @@ //! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 2 #define CLIENT_VERSION_MINOR 0 -#define CLIENT_VERSION_REVISION 5 +#define CLIENT_VERSION_REVISION 6 #define CLIENT_VERSION_BUILD 50 //! Set to true for release, false for prerelease or test build diff --git a/src/consensus/params.h b/src/consensus/params.h index b362e741520..b83a1cc97c1 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -83,6 +83,8 @@ struct Params { int nMajorityWindow; NetworkUpgrade vUpgrades[MAX_NETWORK_UPGRADES]; /** Proof of work parameters */ + unsigned int nEquihashN = 0; + unsigned int nEquihashK = 0; uint256 powLimit; boost::optional nPowAllowMinDifficultyBlocksAfterHeight; int64_t nPowAveragingWindow; diff --git a/src/gtest/test_checkblock.cpp b/src/gtest/test_checkblock.cpp index 2919e1314d7..4195647e815 100644 --- a/src/gtest/test_checkblock.cpp +++ b/src/gtest/test_checkblock.cpp @@ -31,7 +31,7 @@ TEST(CheckBlock, VersionTooLow) { MockCValidationState state; EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "version-too-low", false)).Times(1); - EXPECT_FALSE(CheckBlock(block, state, verifier, false, false)); + EXPECT_FALSE(CheckBlock(block, state, Params(), verifier, false, false)); } @@ -64,7 +64,7 @@ TEST(CheckBlock, BlockSproutRejectsBadVersion) { auto verifier = libzcash::ProofVerifier::Strict(); EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-version-too-low", false)).Times(1); - EXPECT_FALSE(CheckBlock(block, state, verifier, false, false)); + EXPECT_FALSE(CheckBlock(block, state, Params(), verifier, false, false)); } @@ -117,7 +117,7 @@ class ContextualCheckBlockTest : public ::testing::Test { // We now expect this to be a valid block. MockCValidationState state; - EXPECT_TRUE(ContextualCheckBlock(block, state, &indexPrev)); + EXPECT_TRUE(ContextualCheckBlock(block, state, Params(), &indexPrev)); } // Expects a height-1 block containing a given transaction to fail @@ -135,7 +135,7 @@ class ContextualCheckBlockTest : public ::testing::Test { // We now expect this to be an invalid block, for the given reason. MockCValidationState state; EXPECT_CALL(state, DoS(level, false, REJECT_INVALID, reason, false)).Times(1); - EXPECT_FALSE(ContextualCheckBlock(block, state, &indexPrev)); + EXPECT_FALSE(ContextualCheckBlock(block, state, Params(), &indexPrev)); } }; @@ -152,7 +152,7 @@ TEST_F(ContextualCheckBlockTest, BadCoinbaseHeight) { // Treating block as genesis should pass MockCValidationState state; - EXPECT_TRUE(ContextualCheckBlock(block, state, NULL)); + EXPECT_TRUE(ContextualCheckBlock(block, state, Params(), NULL)); // Give the transaction a Founder's Reward vout mtx.vout.push_back(CTxOut( @@ -166,20 +166,20 @@ TEST_F(ContextualCheckBlockTest, BadCoinbaseHeight) { CBlockIndex indexPrev {prev}; indexPrev.nHeight = 0; EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-height", false)).Times(1); - EXPECT_FALSE(ContextualCheckBlock(block, state, &indexPrev)); + EXPECT_FALSE(ContextualCheckBlock(block, state, Params(), &indexPrev)); // Setting to an incorrect height should fail mtx.vin[0].scriptSig = CScript() << 2 << OP_0; CTransaction tx3 {mtx}; block.vtx[0] = tx3; EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-height", false)).Times(1); - EXPECT_FALSE(ContextualCheckBlock(block, state, &indexPrev)); + EXPECT_FALSE(ContextualCheckBlock(block, state, Params(), &indexPrev)); // After correcting the scriptSig, should pass mtx.vin[0].scriptSig = CScript() << 1 << OP_0; CTransaction tx4 {mtx}; block.vtx[0] = tx4; - EXPECT_TRUE(ContextualCheckBlock(block, state, &indexPrev)); + EXPECT_TRUE(ContextualCheckBlock(block, state, Params(), &indexPrev)); } // TEST PLAN: first, check that each ruleset accepts its own transaction type. diff --git a/src/gtest/test_checktransaction.cpp b/src/gtest/test_checktransaction.cpp index 3a9bd3af44f..bbb0dfcc7dd 100644 --- a/src/gtest/test_checktransaction.cpp +++ b/src/gtest/test_checktransaction.cpp @@ -167,7 +167,7 @@ TEST(checktransaction_tests, BadTxnsOversize) { // ... but fails contextual ones! EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-oversize", false)).Times(1); - EXPECT_FALSE(ContextualCheckTransaction(tx, state, 1, 100)); + EXPECT_FALSE(ContextualCheckTransaction(tx, state, Params(), 1, 100)); } { @@ -188,7 +188,7 @@ TEST(checktransaction_tests, BadTxnsOversize) { MockCValidationState state; EXPECT_TRUE(CheckTransactionWithoutProofVerification(tx, state)); - EXPECT_TRUE(ContextualCheckTransaction(tx, state, 1, 100)); + EXPECT_TRUE(ContextualCheckTransaction(tx, state, Params(), 1, 100)); // Revert to default RegtestDeactivateSapling(); @@ -496,6 +496,7 @@ TEST(checktransaction_tests, bad_txns_prevout_null) { TEST(checktransaction_tests, bad_txns_invalid_joinsplit_signature) { SelectParams(CBaseChainParams::REGTEST); + auto chainparams = Params(); CMutableTransaction mtx = GetValidTransaction(); mtx.joinSplitSig[0] += 1; @@ -504,13 +505,14 @@ TEST(checktransaction_tests, bad_txns_invalid_joinsplit_signature) { MockCValidationState state; // during initial block download, DoS ban score should be zero, else 100 EXPECT_CALL(state, DoS(0, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1); - ContextualCheckTransaction(tx, state, 0, 100, []() { return true; }); + ContextualCheckTransaction(tx, state, chainparams, 0, 100, [](const CChainParams&) { return true; }); EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1); - ContextualCheckTransaction(tx, state, 0, 100, []() { return false; }); + ContextualCheckTransaction(tx, state, chainparams, 0, 100, [](const CChainParams&) { return false; }); } TEST(checktransaction_tests, non_canonical_ed25519_signature) { SelectParams(CBaseChainParams::REGTEST); + auto chainparams = Params(); CMutableTransaction mtx = GetValidTransaction(); @@ -518,7 +520,7 @@ TEST(checktransaction_tests, non_canonical_ed25519_signature) { { CTransaction tx(mtx); MockCValidationState state; - EXPECT_TRUE(ContextualCheckTransaction(tx, state, 0, 100)); + EXPECT_TRUE(ContextualCheckTransaction(tx, state, chainparams, 0, 100)); } // Copied from libsodium/crypto_sign/ed25519/ref10/open.c @@ -540,9 +542,9 @@ TEST(checktransaction_tests, non_canonical_ed25519_signature) { MockCValidationState state; // during initial block download, DoS ban score should be zero, else 100 EXPECT_CALL(state, DoS(0, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1); - ContextualCheckTransaction(tx, state, 0, 100, []() { return true; }); + ContextualCheckTransaction(tx, state, chainparams, 0, 100, [](const CChainParams&) { return true; }); EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1); - ContextualCheckTransaction(tx, state, 0, 100, []() { return false; }); + ContextualCheckTransaction(tx, state, chainparams, 0, 100, [](const CChainParams&) { return false; }); } TEST(checktransaction_tests, OverwinterConstructors) { @@ -797,7 +799,7 @@ TEST(checktransaction_tests, OverwinterVersionNumberHigh) { UNSAFE_CTransaction tx(mtx); MockCValidationState state; EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-tx-overwinter-version-too-high", false)).Times(1); - ContextualCheckTransaction(tx, state, 1, 100); + ContextualCheckTransaction(tx, state, Params(), 1, 100); // Revert to default UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); @@ -822,6 +824,7 @@ TEST(checktransaction_tests, OverwinterBadVersionGroupId) { // This tests an Overwinter transaction checked against Sprout TEST(checktransaction_tests, OverwinterNotActive) { SelectParams(CBaseChainParams::TESTNET); + auto chainparams = Params(); CMutableTransaction mtx = GetValidTransaction(); mtx.fOverwintered = true; @@ -833,9 +836,9 @@ TEST(checktransaction_tests, OverwinterNotActive) { MockCValidationState state; // during initial block download, DoS ban score should be zero, else 100 EXPECT_CALL(state, DoS(0, false, REJECT_INVALID, "tx-overwinter-not-active", false)).Times(1); - ContextualCheckTransaction(tx, state, 1, 100, []() { return true; }); + ContextualCheckTransaction(tx, state, chainparams, 1, 100, [](const CChainParams&) { return true; }); EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "tx-overwinter-not-active", false)).Times(1); - ContextualCheckTransaction(tx, state, 1, 100, []() { return false; }); + ContextualCheckTransaction(tx, state, chainparams, 1, 100, [](const CChainParams&) { return false; }); } // This tests a transaction without the fOverwintered flag set, against the Overwinter consensus rule set. @@ -852,7 +855,7 @@ TEST(checktransaction_tests, OverwinterFlagNotSet) { CTransaction tx(mtx); MockCValidationState state; EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "tx-overwinter-flag-not-set", false)).Times(1); - ContextualCheckTransaction(tx, state, 1, 100); + ContextualCheckTransaction(tx, state, Params(), 1, 100); // Revert to default UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); diff --git a/src/gtest/test_merkletree.cpp b/src/gtest/test_merkletree.cpp index 23c39c04467..d55cb13179c 100644 --- a/src/gtest/test_merkletree.cpp +++ b/src/gtest/test_merkletree.cpp @@ -249,7 +249,7 @@ TEST(merkletree, EmptyrootsSapling) { } TEST(merkletree, emptyroot) { - // This literal is the depth-20 empty tree root with the bytes reversed to + // This literal is the depth-29 empty tree root with the bytes reversed to // account for the fact that uint256S() loads a big-endian representation of // an integer which converted to little-endian internally. uint256 expected = uint256S("59d2cde5e65c1414c32ba54f0fe4bdb3d67618125286e6a191317917c812c6d7"); @@ -258,7 +258,7 @@ TEST(merkletree, emptyroot) { } TEST(merkletree, EmptyrootSapling) { - // This literal is the depth-20 empty tree root with the bytes reversed to + // This literal is the depth-32 empty tree root with the bytes reversed to // account for the fact that uint256S() loads a big-endian representation of // an integer which converted to little-endian internally. uint256 expected = uint256S("3e49b5f954aa9d3545bc6c37744661eea48d7c34e3000d82b7f0010c30f4c2fb"); diff --git a/src/gtest/test_transaction_builder.cpp b/src/gtest/test_transaction_builder.cpp index 6676ef21eec..5ebf1d737c6 100644 --- a/src/gtest/test_transaction_builder.cpp +++ b/src/gtest/test_transaction_builder.cpp @@ -93,7 +93,7 @@ TEST(TransactionBuilder, TransparentToSapling) // Create a shielding transaction from transparent to Sapling // 0.0005 t-ZEC in, 0.0004 z-ZEC out, 0.0001 t-ZEC fee - auto builder = TransactionBuilder(consensusParams, 1, &keystore); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore); builder.AddTransparentInput(COutPoint(), scriptPubKey, 50000); builder.AddSaplingOutput(fvk_from.ovk, pk, 40000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -106,7 +106,7 @@ TEST(TransactionBuilder, TransparentToSapling) EXPECT_EQ(tx.valueBalance, -40000); CValidationState state; - EXPECT_TRUE(ContextualCheckTransaction(tx, state, 2, 0)); + EXPECT_TRUE(ContextualCheckTransaction(tx, state, Params(), 2, 0)); EXPECT_EQ(state.GetRejectReason(), ""); // Revert to default @@ -125,7 +125,7 @@ TEST(TransactionBuilder, SaplingToSapling) { // Create a Sapling-only transaction // 0.0004 z-ZEC in, 0.00025 z-ZEC out, 0.0001 t-ZEC fee, 0.00005 z-ZEC change - auto builder = TransactionBuilder(consensusParams, 2); + auto builder = TransactionBuilder(consensusParams, 2, expiryDelta); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); // Check that trying to add a different anchor fails @@ -143,7 +143,7 @@ TEST(TransactionBuilder, SaplingToSapling) { EXPECT_EQ(tx.valueBalance, 10000); CValidationState state; - EXPECT_TRUE(ContextualCheckTransaction(tx, state, 3, 0)); + EXPECT_TRUE(ContextualCheckTransaction(tx, state, Params(), 3, 0)); EXPECT_EQ(state.GetRejectReason(), ""); // Revert to default @@ -166,7 +166,7 @@ TEST(TransactionBuilder, SaplingToSprout) { // - 0.0004 Sapling-ZEC in - 0.00025 Sprout-ZEC out // - 0.00005 Sapling-ZEC change // - 0.0001 t-ZEC fee - auto builder = TransactionBuilder(consensusParams, 2, nullptr, params); + auto builder = TransactionBuilder(consensusParams, 2, expiryDelta, nullptr, params); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSproutOutput(sproutAddr, 25000); auto tx = builder.Build().GetTxOrThrow(); @@ -181,7 +181,7 @@ TEST(TransactionBuilder, SaplingToSprout) { EXPECT_EQ(tx.valueBalance, 35000); CValidationState state; - EXPECT_TRUE(ContextualCheckTransaction(tx, state, 3, 0)); + EXPECT_TRUE(ContextualCheckTransaction(tx, state, Params(), 3, 0)); EXPECT_EQ(state.GetRejectReason(), ""); // Revert to default @@ -218,7 +218,7 @@ TEST(TransactionBuilder, SproutToSproutAndSapling) { // - 0.00005 Sprout-ZEC change // - 0.00005 Sapling-ZEC out // - 0.00005 t-ZEC fee - auto builder = TransactionBuilder(consensusParams, 2, nullptr, params, &view); + auto builder = TransactionBuilder(consensusParams, 2, expiryDelta, nullptr, params, &view); builder.SetFee(5000); builder.AddSproutInput(sproutSk, sproutNote, sproutWitness); builder.AddSproutOutput(sproutAddr, 6000); @@ -242,7 +242,7 @@ TEST(TransactionBuilder, SproutToSproutAndSapling) { EXPECT_EQ(tx.valueBalance, -5000); CValidationState state; - EXPECT_TRUE(ContextualCheckTransaction(tx, state, 4, 0)); + EXPECT_TRUE(ContextualCheckTransaction(tx, state, Params(), 4, 0)); EXPECT_EQ(state.GetRejectReason(), ""); // Revert to default @@ -255,7 +255,7 @@ TEST(TransactionBuilder, ThrowsOnSproutOutputWithoutParams) auto sk = libzcash::SproutSpendingKey::random(); auto addr = sk.address(); - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); ASSERT_THROW(builder.AddSproutOutput(addr, 10), std::runtime_error); } @@ -264,7 +264,7 @@ TEST(TransactionBuilder, ThrowsOnTransparentInputWithoutKeyStore) SelectParams(CBaseChainParams::REGTEST); auto consensusParams = Params().GetConsensus(); - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); ASSERT_THROW(builder.AddTransparentInput(COutPoint(), CScript(), 1), std::runtime_error); } @@ -275,7 +275,7 @@ TEST(TransactionBuilder, RejectsInvalidTransparentOutput) // Default CTxDestination type is an invalid address CTxDestination taddr; - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); ASSERT_THROW(builder.AddTransparentOutput(taddr, 50), UniValue); } @@ -286,7 +286,7 @@ TEST(TransactionBuilder, RejectsInvalidTransparentChangeAddress) // Default CTxDestination type is an invalid address CTxDestination taddr; - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); ASSERT_THROW(builder.SendChangeTo(taddr), UniValue); } @@ -311,13 +311,13 @@ TEST(TransactionBuilder, FailsWithNegativeChange) // Fail if there is only a Sapling output // 0.0005 z-ZEC out, 0.0001 t-ZEC fee - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); builder.AddSaplingOutput(fvk.ovk, pa, 50000, {}); EXPECT_EQ("Change cannot be negative", builder.Build().GetError()); // Fail if there is only a transparent output // 0.0005 t-ZEC out, 0.0001 t-ZEC fee - builder = TransactionBuilder(consensusParams, 1, &keystore); + builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore); builder.AddTransparentOutput(taddr, 50000); EXPECT_EQ("Change cannot be negative", builder.Build().GetError()); @@ -359,14 +359,14 @@ TEST(TransactionBuilder, ChangeOutput) // No change address and no Sapling spends { - auto builder = TransactionBuilder(consensusParams, 1, &keystore); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore); builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000); EXPECT_EQ("Could not determine change address", builder.Build().GetError()); } // Change to the same address as the first Sapling spend { - auto builder = TransactionBuilder(consensusParams, 1, &keystore); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore); builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); auto tx = builder.Build().GetTxOrThrow(); @@ -381,7 +381,7 @@ TEST(TransactionBuilder, ChangeOutput) // Change to a Sapling address { - auto builder = TransactionBuilder(consensusParams, 1, &keystore); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore); builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000); builder.SendChangeTo(zChangeAddr, fvkOut.ovk); auto tx = builder.Build().GetTxOrThrow(); @@ -396,7 +396,7 @@ TEST(TransactionBuilder, ChangeOutput) // Change to a transparent address { - auto builder = TransactionBuilder(consensusParams, 1, &keystore); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore); builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000); builder.SendChangeTo(taddr); auto tx = builder.Build().GetTxOrThrow(); @@ -428,7 +428,7 @@ TEST(TransactionBuilder, SetFee) // Default fee { - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -443,7 +443,7 @@ TEST(TransactionBuilder, SetFee) // Configured fee { - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); builder.SetFee(20000); @@ -472,7 +472,7 @@ TEST(TransactionBuilder, CheckSaplingTxVersion) auto pk = sk.default_address(); // Cannot add Sapling outputs to a non-Sapling transaction - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); try { builder.AddSaplingOutput(uint256(), pk, 12345, {}); } catch (std::runtime_error const & err) { diff --git a/src/gtest/test_validation.cpp b/src/gtest/test_validation.cpp index 4e937d04266..0f66b8dcfb6 100644 --- a/src/gtest/test_validation.cpp +++ b/src/gtest/test_validation.cpp @@ -7,7 +7,12 @@ extern ZCJoinSplit* params; -extern bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos); +extern bool ReceivedBlockTransactions( + const CBlock &block, + CValidationState& state, + const CChainParams& chainparams, + CBlockIndex *pindexNew, + const CDiskBlockPos& pos); void ExpectOptionalAmount(CAmount expected, boost::optional actual) { EXPECT_TRUE((bool)actual); @@ -87,6 +92,7 @@ TEST(Validation, ContextualCheckInputsPassesWithCoinbase) { } TEST(Validation, ReceivedBlockTransactions) { + auto chainParams = Params(); auto sk = libzcash::SproutSpendingKey::random(); // Create a fake genesis block @@ -122,7 +128,7 @@ TEST(Validation, ReceivedBlockTransactions) { // Mark the second block's transactions as received first CValidationState state; - EXPECT_TRUE(ReceivedBlockTransactions(block2, state, &fakeIndex2, pos2)); + EXPECT_TRUE(ReceivedBlockTransactions(block2, state, chainParams, &fakeIndex2, pos2)); EXPECT_FALSE(fakeIndex1.IsValid(BLOCK_VALID_TRANSACTIONS)); EXPECT_TRUE(fakeIndex2.IsValid(BLOCK_VALID_TRANSACTIONS)); @@ -137,7 +143,7 @@ TEST(Validation, ReceivedBlockTransactions) { EXPECT_FALSE((bool)fakeIndex2.nChainSproutValue); // Now mark the first block's transactions as received - EXPECT_TRUE(ReceivedBlockTransactions(block1, state, &fakeIndex1, pos1)); + EXPECT_TRUE(ReceivedBlockTransactions(block1, state, chainParams, &fakeIndex1, pos1)); EXPECT_TRUE(fakeIndex1.IsValid(BLOCK_VALID_TRANSACTIONS)); EXPECT_TRUE(fakeIndex2.IsValid(BLOCK_VALID_TRANSACTIONS)); diff --git a/src/init.cpp b/src/init.cpp index 475c40f33b6..e351556291e 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -633,6 +633,7 @@ void CleanupBlockRevFiles() void ThreadImport(std::vector vImportFiles) { + const CChainParams& chainparams = Params(); RenameThread("zcash-loadblk"); // -reindex if (fReindex) { @@ -646,14 +647,14 @@ void ThreadImport(std::vector vImportFiles) if (!file) break; // This error is logged in OpenBlockFile LogPrintf("Reindexing block file blk%05u.dat...\n", (unsigned int)nFile); - LoadExternalBlockFile(file, &pos); + LoadExternalBlockFile(chainparams, file, &pos); nFile++; } pblocktree->WriteReindexing(false); fReindex = false; LogPrintf("Reindexing finished\n"); // To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked): - InitBlockIndex(); + InitBlockIndex(chainparams); } // hardcoded $DATADIR/bootstrap.dat @@ -664,7 +665,7 @@ void ThreadImport(std::vector vImportFiles) CImportingNow imp; boost::filesystem::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old"; LogPrintf("Importing bootstrap.dat...\n"); - LoadExternalBlockFile(file); + LoadExternalBlockFile(chainparams, file); RenameOver(pathBootstrap, pathBootstrapOld); } else { LogPrintf("Warning: Could not open bootstrap file %s\n", pathBootstrap.string()); @@ -677,7 +678,7 @@ void ThreadImport(std::vector vImportFiles) if (file) { CImportingNow imp; LogPrintf("Importing blocks file %s...\n", path.string()); - LoadExternalBlockFile(file); + LoadExternalBlockFile(chainparams, file); } else { LogPrintf("Warning: Could not open blocks file %s\n", path.string()); } @@ -1554,7 +1555,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?")); // Initialize the block index (no-op if non-empty database was already loaded) - if (!InitBlockIndex()) { + if (!InitBlockIndex(chainparams)) { strLoadError = _("Error initializing block database"); break; } @@ -1591,7 +1592,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) LogPrintf("Prune: pruned datadir may not have more than %d blocks; -checkblocks=%d may fail\n", MIN_BLOCKS_TO_KEEP, GetArg("-checkblocks", 288)); } - if (!CVerifyDB().VerifyDB(pcoinsdbview, GetArg("-checklevel", 3), + if (!CVerifyDB().VerifyDB(chainparams, pcoinsdbview, GetArg("-checklevel", 3), GetArg("-checkblocks", 288))) { strLoadError = _("Corrupted block database detected"); break; @@ -1862,7 +1863,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) uiInterface.InitMessage(_("Activating best chain...")); // scan for better chains in the block chain database, that are not yet connected in the active best chain CValidationState state; - if (!ActivateBestChain(state)) + if (!ActivateBestChain(state, chainparams)) strErrors << "Failed to connect best block"; std::vector vImportFiles; @@ -2050,7 +2051,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) #ifdef ENABLE_MINING // Generate coins in the background - GenerateBitcoins(GetBoolArg("-gen", false), GetArg("-genproclimit", 1), Params()); + GenerateBitcoins(GetBoolArg("-gen", false), GetArg("-genproclimit", 1), chainparams); #endif // ********************************************************* Step 11: finished diff --git a/src/main.cpp b/src/main.cpp index dd53ec392f4..b2b820cafaa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -112,7 +112,7 @@ void EraseOrphansFor(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main); * in the last Consensus::Params::nMajorityWindow blocks, starting at pstart and going backwards. */ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned nRequired, const Consensus::Params& consensusParams); -static void CheckBlockIndex(); +static void CheckBlockIndex(const Consensus::Params& consensusParams); /** Constant stuff for coinbase transactions we create: */ CScript COINBASE_FLAGS; @@ -208,10 +208,10 @@ namespace { /** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */ struct QueuedBlock { uint256 hash; - CBlockIndex *pindex; //! Optional. - int64_t nTime; //! Time of "getdata" request in microseconds. - bool fValidatedHeaders; //! Whether this block has validated headers at the time of request. - int64_t nTimeDisconnect; //! The timeout for this block request (for disconnecting a slow peer) + CBlockIndex* pindex; //!< Optional. + int64_t nTime; //!< Time of "getdata" request in microseconds. + bool fValidatedHeaders; //!< Whether this block has validated headers at the time of request. + int64_t nTimeDisconnect; //!< The timeout for this block request (for disconnecting a slow peer) }; map::iterator> > mapBlocksInFlight; @@ -663,10 +663,10 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) EXCLUSIVE_LOCKS_REQUIRE } -bool IsStandardTx(const CTransaction& tx, string& reason, const int nHeight) +bool IsStandardTx(const CTransaction& tx, string& reason, const CChainParams& chainparams, const int nHeight) { - bool overwinterActive = NetworkUpgradeActive(nHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER); - bool saplingActive = NetworkUpgradeActive(nHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING); + bool overwinterActive = NetworkUpgradeActive(nHeight, chainparams.GetConsensus(), Consensus::UPGRADE_OVERWINTER); + bool saplingActive = NetworkUpgradeActive(nHeight, chainparams.GetConsensus(), Consensus::UPGRADE_SAPLING); if (saplingActive) { // Sapling standard rules apply @@ -953,18 +953,19 @@ int GetIXConfirmations(uint256 nTXHash) bool ContextualCheckTransaction( const CTransaction& tx, CValidationState &state, + const CChainParams& chainparams, const int nHeight, const int dosLevel, - bool (*isInitBlockDownload)()) + bool (*isInitBlockDownload)(const CChainParams&)) { - bool overwinterActive = NetworkUpgradeActive(nHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER); - bool saplingActive = NetworkUpgradeActive(nHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING); - bool cosmosActive = NetworkUpgradeActive(nHeight, Params().GetConsensus(), Consensus::UPGRADE_COSMOS); + bool overwinterActive = NetworkUpgradeActive(nHeight, chainparams.GetConsensus(), Consensus::UPGRADE_OVERWINTER); + bool saplingActive = NetworkUpgradeActive(nHeight, chainparams.GetConsensus(), Consensus::UPGRADE_SAPLING); + bool cosmosActive = NetworkUpgradeActive(nHeight, chainparams.GetConsensus(), Consensus::UPGRADE_COSMOS); bool isSprout = !overwinterActive; // If Sprout rules apply, reject transactions which are intended for Overwinter and beyond if (isSprout && tx.fOverwintered) { - return state.DoS(isInitBlockDownload() ? 0 : dosLevel, + return state.DoS(isInitBlockDownload(chainparams) ? 0 : dosLevel, error("ContextualCheckTransaction(): overwinter is not active yet"), REJECT_INVALID, "tx-overwinter-not-active"); } @@ -978,7 +979,7 @@ bool ContextualCheckTransaction( // Reject transactions with non-Sapling version group ID if (tx.fOverwintered && tx.nVersionGroupId != SAPLING_VERSION_GROUP_ID) { - return state.DoS(isInitBlockDownload() ? 0 : dosLevel, + return state.DoS(isInitBlockDownload(chainparams) ? 0 : dosLevel, error("CheckTransaction(): invalid Sapling tx version"), REJECT_INVALID, "bad-sapling-tx-version-group-id"); } @@ -1003,7 +1004,7 @@ bool ContextualCheckTransaction( // Reject transactions with non-Overwinter version group ID if (tx.fOverwintered && tx.nVersionGroupId != OVERWINTER_VERSION_GROUP_ID) { - return state.DoS(isInitBlockDownload() ? 0 : dosLevel, + return state.DoS(isInitBlockDownload(chainparams) ? 0 : dosLevel, error("CheckTransaction(): invalid Overwinter tx version"), REJECT_INVALID, "bad-overwinter-tx-version-group-id"); } @@ -1054,7 +1055,7 @@ bool ContextualCheckTransaction( !tx.vShieldedSpend.empty() || !tx.vShieldedOutput.empty()) { - auto consensusBranchId = CurrentEpochBranchId(nHeight, Params().GetConsensus()); + auto consensusBranchId = CurrentEpochBranchId(nHeight, chainparams.GetConsensus()); // Empty output script. CScript scriptCode; try { @@ -1075,7 +1076,7 @@ bool ContextualCheckTransaction( dataToBeSigned.begin(), 32, tx.joinSplitPubKey.begin() ) != 0) { - return state.DoS(isInitBlockDownload() ? 0 : 100, + return state.DoS(isInitBlockDownload(chainparams) ? 0 : 100, error("CheckTransaction(): invalid joinsplit signature"), REJECT_INVALID, "bad-txns-invalid-joinsplit-signature"); } @@ -1454,7 +1455,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // DoS level set to 10 to be more forgiving. // Check transaction contextually against the set of consensus rules which apply in the next block to be mined. - if (!ContextualCheckTransaction(tx, state, nextBlockHeight, 10)) { + if (!ContextualCheckTransaction(tx, state, Params(), nextBlockHeight, 10)) { return error("AcceptToMemoryPool: ContextualCheckTransaction failed"); } @@ -1472,7 +1473,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Rather not work on nonstandard transactions (unless -testnet/-regtest) string reason; - if (Params().RequireStandard() && !IsStandardTx(tx, reason, nextBlockHeight)) + if (Params().RequireStandard() && !IsStandardTx(tx, reason, Params(), nextBlockHeight)) return state.DoS(0, error("AcceptToMemoryPool: nonstandard transaction: %s", reason), REJECT_NONSTANDARD, reason); @@ -1670,7 +1671,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } // Store transaction in memory - pool.addUnchecked(hash, entry, !IsInitialBlockDownload()); + pool.addUnchecked(hash, entry, !IsInitialBlockDownload(Params())); // Add memory address index if (fAddressIndex) { @@ -1938,7 +1939,7 @@ bool GetAddressUnspent(uint160 addressHash, int type, } /** Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */ -bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow) +bool GetTransaction(const uint256 &hash, CTransaction &txOut, const Consensus::Params& consensusParams, uint256 &hashBlock, bool fAllowSlow) { CBlockIndex *pindexSlow = NULL; @@ -1984,7 +1985,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock if (pindexSlow) { CBlock block; - if (ReadBlockFromDisk(block, pindexSlow)) { + if (ReadBlockFromDisk(block, pindexSlow, consensusParams)) { BOOST_FOREACH(const CTransaction &tx, block.vtx) { if (tx.GetHash() == hash) { txOut = tx; @@ -2008,7 +2009,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock // CBlock and CBlockIndex // -bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart) +bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart) { // Open history file to append CAutoFile fileout(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION); @@ -2029,7 +2030,7 @@ bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos, const CMessageHeader::M return true; } -bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos) +bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus::Params& consensusParams) { block.SetNull(); @@ -2047,16 +2048,16 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos) } // Check the header - if (!(CheckEquihashSolution(&block, Params()) && - CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus()))) + if (!(CheckEquihashSolution(&block, consensusParams) && + CheckProofOfWork(block.GetHash(), block.nBits, consensusParams))) return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString()); return true; } -bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex) +bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams) { - if (!ReadBlockFromDisk(block, pindex->GetBlockPos())) + if (!ReadBlockFromDisk(block, pindex->GetBlockPos(), consensusParams)) return false; if (block.GetHash() != pindex->GetBlockHash()) return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s", @@ -2100,10 +2101,8 @@ int64_t GetZeronodePayment(int nHeight, int64_t blockValue, int nZeronodeCount) return ret; } -bool IsInitialBlockDownload() +bool IsInitialBlockDownload(const CChainParams& chainParams) { - const CChainParams& chainParams = Params(); - // Once this function has returned false, it must remain false. static std::atomic latchToFalse{false}; // Optimization: pre-test latch before taking the lock. @@ -2131,12 +2130,12 @@ bool fLargeWorkInvalidChainFound = false; static CBlockIndex *pindexBestForkTip = NULL; static CBlockIndex *pindexBestForkBase = NULL; -void CheckForkWarningConditions() +void CheckForkWarningConditions(const CChainParams& chainParams) { AssertLockHeld(cs_main); // Before we get past initial download, we cannot reliably alert about forks // (we assume we don't get stuck on a fork before finishing our initial sync) - if (IsInitialBlockDownload()) + if (IsInitialBlockDownload(chainParams)) return; // If our best fork is no longer within 288 blocks (+/- 12 hours if no one mines it) @@ -2174,7 +2173,7 @@ void CheckForkWarningConditions() } } -void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip) +void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip, const CChainParams& chainParams) { AssertLockHeld(cs_main); // If we are on a fork that is sufficiently large, set a warning flag @@ -2204,7 +2203,7 @@ void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip) pindexBestForkBase = pfork; } - CheckForkWarningConditions(); + CheckForkWarningConditions(chainParams); } // Requires cs_main. @@ -2227,7 +2226,7 @@ void Misbehaving(NodeId pnode, int howmuch) LogPrintf("%s: %s (%d -> %d)\n", __func__, state->name, state->nMisbehavior-howmuch, state->nMisbehavior); } -void static InvalidChainFound(CBlockIndex* pindexNew) +void static InvalidChainFound(CBlockIndex* pindexNew, const CChainParams& chainParams) { if (!pindexBestInvalid || pindexNew->nChainWork > pindexBestInvalid->nChainWork) pindexBestInvalid = pindexNew; @@ -2241,10 +2240,10 @@ void static InvalidChainFound(CBlockIndex* pindexNew) LogPrintf("%s: current best=%s height=%d log2_work=%.8g date=%s\n", __func__, tip->GetBlockHash().ToString(), chainActive.Height(), log(tip->nChainWork.getdouble())/log(2.0), DateTimeStrFormat("%Y-%m-%d %H:%M:%S", tip->GetBlockTime())); - CheckForkWarningConditions(); + CheckForkWarningConditions(chainParams); } -void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) { +void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state, const CChainParams& chainParams) { int nDoS = 0; if (state.IsInvalid(nDoS)) { std::map::iterator it = mapBlockSource.find(pindex->GetBlockHash()); @@ -2259,7 +2258,7 @@ void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state pindex->nStatus |= BLOCK_FAILED_VALID; setDirtyBlockIndex.insert(pindex); setBlockIndexCandidates.erase(pindex); - InvalidChainFound(pindex); + InvalidChainFound(pindex, chainParams); } } @@ -2573,7 +2572,8 @@ enum DisconnectResult * The addressIndex and spentIndex will be updated if requested. */ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& state, - const CBlockIndex* pindex, CCoinsViewCache& view, bool const updateIndices) + const CBlockIndex* pindex, CCoinsViewCache& view, const CChainParams& chainparams, + const bool updateIndices) { assert(pindex->GetBlockHash() == view.GetBestBlock()); @@ -2608,8 +2608,8 @@ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& s if (fAddressIndex && updateIndices) { for (unsigned int k = tx.vout.size(); k-- > 0;) { const CTxOut &out = tx.vout[k]; - int const scriptType = out.scriptPubKey.Type(); - if (scriptType > 0) { + CScript::ScriptType scriptType = out.scriptPubKey.GetType(); + if (scriptType != CScript::UNKNOWN) { uint160 const addrHash = out.scriptPubKey.AddressHash(); // undo receiving activity @@ -2696,8 +2696,8 @@ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& s const CTxIn input = tx.vin[j]; if (fAddressIndex && updateIndices) { const CTxOut &prevout = view.GetOutputFor(input); - int const scriptType = prevout.scriptPubKey.Type(); - if (scriptType > 0) { + CScript::ScriptType scriptType = prevout.scriptPubKey.GetType(); + if (scriptType != CScript::UNKNOWN) { uint160 const addrHash = prevout.scriptPubKey.AddressHash(); // undo spending activity @@ -2730,7 +2730,7 @@ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& s // However, this is only reliable if the last block was on or after // the Sapling activation height. Otherwise, the last anchor was the // empty root. - if (NetworkUpgradeActive(pindex->pprev->nHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) { + if (NetworkUpgradeActive(pindex->pprev->nHeight, chainparams.GetConsensus(), Consensus::UPGRADE_SAPLING)) { view.PopAnchor(pindex->pprev->hashFinalSaplingRoot, SAPLING); } else { view.PopAnchor(SaplingMerkleTree::empty_root(), SAPLING); @@ -2797,10 +2797,11 @@ void ThreadScriptCheck() { // we're being fed a bad chain (blocks being generated much // too slowly or too quickly). // -void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const CBlockIndex *const &bestHeader, +void PartitionCheck(bool (*initialDownloadCheck)(const CChainParams&), + CCriticalSection& cs, const CBlockIndex *const &bestHeader, int64_t nPowTargetSpacing) { - if (bestHeader == NULL || initialDownloadCheck()) return; + if (bestHeader == NULL || initialDownloadCheck(Params())) return; static int64_t lastAlertTime = 0; int64_t now = GetAdjustedTime(); @@ -2860,9 +2861,9 @@ static int64_t nTimeIndex = 0; static int64_t nTimeCallbacks = 0; static int64_t nTimeTotal = 0; -bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck) +bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, + CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck) { - const CChainParams& chainparams = Params(); AssertLockHeld(cs_main); bool fExpensiveChecks = true; @@ -2878,7 +2879,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin auto disabledVerifier = libzcash::ProofVerifier::Disabled(); // Check it again to verify JoinSplit proofs, and in case a previous version let a bad block in - if (!CheckBlock(block, state, fExpensiveChecks ? verifier : disabledVerifier, !fJustCheck, !fJustCheck)) + if (!CheckBlock(block, state, chainparams, fExpensiveChecks ? verifier : disabledVerifier, !fJustCheck, !fJustCheck)) return false; // verify that the view's current state corresponds to the previous block @@ -2979,7 +2980,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin assert(view.GetSaplingAnchorAt(view.GetBestAnchor(SAPLING), sapling_tree)); // Grab the consensus branch ID for the block's height - auto consensusBranchId = CurrentEpochBranchId(pindex->nHeight, Params().GetConsensus()); + auto consensusBranchId = CurrentEpochBranchId(pindex->nHeight, chainparams.GetConsensus()); std::vector txdata; txdata.reserve(block.vtx.size()); // Required so that pointers to individual PrecomputedTransactionData don't get invalidated @@ -3012,9 +3013,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin const CTxIn input = tx.vin[j]; const CTxOut &prevout = view.GetOutputFor(tx.vin[j]); - int const scriptType = prevout.scriptPubKey.Type(); + CScript::ScriptType scriptType = prevout.scriptPubKey.GetType(); const uint160 addrHash = prevout.scriptPubKey.AddressHash(); - if (fAddressIndex && scriptType > 0) { + if (fAddressIndex && scriptType != CScript::UNKNOWN) { // record spending activity addressIndex.push_back(make_pair( CAddressIndexKey(scriptType, addrHash, pindex->nHeight, i, hash, j, true), @@ -3064,8 +3065,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (fAddressIndex) { for (unsigned int k = 0; k < tx.vout.size(); k++) { const CTxOut &out = tx.vout[k]; - int const scriptType = out.scriptPubKey.Type(); - if (scriptType > 0) { + CScript::ScriptType scriptType = out.scriptPubKey.GetType(); + if (scriptType != CScript::UNKNOWN) { uint160 const addrHash = out.scriptPubKey.AddressHash(); // record receiving activity @@ -3157,7 +3158,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // Move this if BLOCK_VALID_CONSENSUS is ever altered. static_assert(BLOCK_VALID_CONSENSUS == BLOCK_VALID_SCRIPTS, "nCachedBranchId must be set after all consensus rules have been validated."); - if (IsActivationHeightForAnyUpgrade(pindex->nHeight, Params().GetConsensus())) { + if (IsActivationHeightForAnyUpgrade(pindex->nHeight, chainparams.GetConsensus())) { pindex->nStatus |= BLOCK_ACTIVATES_UPGRADE; pindex->nCachedBranchId = CurrentEpochBranchId(pindex->nHeight, chainparams.GetConsensus()); } else if (pindex->pprev) { @@ -3239,6 +3240,7 @@ enum FlushStateMode { * or always and in all cases if we're in prune mode and are deleting files. */ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) { + const CChainParams& chainparams = Params(); LOCK2(cs_main, cs_LastBlockFile); static int64_t nLastWrite = 0; static int64_t nLastFlush = 0; @@ -3247,7 +3249,7 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) { bool fFlushForPrune = false; try { if (fPruneMode && fCheckForPruning && !fReindex) { - FindFilesToPrune(setFilesToPrune); + FindFilesToPrune(setFilesToPrune, chainparams.PruneAfterHeight()); fCheckForPruning = false; if (!setFilesToPrune.empty()) { fFlushForPrune = true; @@ -3346,8 +3348,7 @@ void PruneAndFlush() { } /** Update chainActive and related internal data structures. */ -void static UpdateTip(CBlockIndex *pindexNew) { - const CChainParams& chainParams = Params(); +void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { chainActive.SetTip(pindexNew); // New best block @@ -3360,41 +3361,19 @@ void static UpdateTip(CBlockIndex *pindexNew) { Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip()), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize()); cvBlockChange.notify_all(); - - // Check the version of the last 100 blocks to see if we need to upgrade: - static bool fWarned = false; - if (!IsInitialBlockDownload() && !fWarned) - { - int nUpgraded = 0; - const CBlockIndex* pindex = chainActive.Tip(); - for (int i = 0; i < 100 && pindex != NULL; i++) - { - if (pindex->nVersion > CBlock::CURRENT_VERSION) - ++nUpgraded; - pindex = pindex->pprev; - } - if (nUpgraded > 0) - LogPrintf("%s: %d of last 100 blocks above version %d\n", __func__, nUpgraded, (int)CBlock::CURRENT_VERSION); - if (nUpgraded > 100/2) - { - // strMiscWarning is read by GetWarnings(), called by the JSON-RPC code to warn the user: - strMiscWarning = _("Warning: This version is obsolete; upgrade required!"); - CAlert::Notify(strMiscWarning, true); - fWarned = true; - } - } } /** * Disconnect chainActive's tip. You probably want to call mempool.removeForReorg and * mempool.removeWithoutBranchId after this, with cs_main held. */ -bool static DisconnectTip(CValidationState &state, bool fBare = false) { +bool static DisconnectTip(CValidationState &state, const CChainParams& chainparams, bool fBare = false) +{ CBlockIndex *pindexDelete = chainActive.Tip(); assert(pindexDelete); // Read block from disk. CBlock block; - if (!ReadBlockFromDisk(block, pindexDelete)) + if (!ReadBlockFromDisk(block, pindexDelete, chainparams.GetConsensus())) return AbortNode(state, "Failed to read block"); // Apply the block atomically to the chain state. uint256 sproutAnchorBeforeDisconnect = pcoinsTip->GetBestAnchor(SPROUT); @@ -3403,7 +3382,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) { { CCoinsViewCache view(pcoinsTip); // insightexplorer: update indices (true) - if (DisconnectBlock(block, state, pindexDelete, view, true) != DISCONNECT_OK) + if (DisconnectBlock(block, state, pindexDelete, view, chainparams, true) != DISCONNECT_OK) return error("DisconnectTip(): DisconnectBlock %s failed", pindexDelete->GetBlockHash().ToString()); assert(view.Flush()); } @@ -3436,7 +3415,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) { } // Update chainActive and related variables. - UpdateTip(pindexDelete->pprev); + UpdateTip(pindexDelete->pprev, chainparams); // Get the current commitment tree SproutMerkleTree newSproutTree; SaplingMerkleTree newSaplingTree; @@ -3463,13 +3442,14 @@ static int64_t nTimePostConnect = 0; * corresponding to pindexNew, to bypass loading it again from disk. * You probably want to call mempool.removeWithoutBranchId after this, with cs_main held. */ -bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *pblock) { +bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const CBlock* pblock) +{ assert(pindexNew->pprev == chainActive.Tip()); // Read block from disk. int64_t nTime1 = GetTimeMicros(); CBlock block; if (!pblock) { - if (!ReadBlockFromDisk(block, pindexNew)) + if (!ReadBlockFromDisk(block, pindexNew, chainparams.GetConsensus())) return AbortNode(state, "Failed to read block"); pblock = █ } @@ -3484,11 +3464,11 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * LogPrint("bench", " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001); { CCoinsViewCache view(pcoinsTip); - bool rv = ConnectBlock(*pblock, state, pindexNew, view); + bool rv = ConnectBlock(*pblock, state, pindexNew, view, chainparams); GetMainSignals().BlockChecked(*pblock, state); if (!rv) { if (state.IsInvalid()) - InvalidBlockFound(pindexNew, state); + InvalidBlockFound(pindexNew, state, chainparams); return error("ConnectTip(): ConnectBlock %s failed", pindexNew->GetBlockHash().ToString()); } mapBlockSource.erase(pindexNew->GetBlockHash()); @@ -3505,13 +3485,13 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * LogPrint("bench", " - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001); // Remove conflicting transactions from the mempool. list txConflicted; - mempool.removeForBlock(pblock->vtx, pindexNew->nHeight, txConflicted, !IsInitialBlockDownload()); + mempool.removeForBlock(pblock->vtx, pindexNew->nHeight, txConflicted, !IsInitialBlockDownload(chainparams)); // Remove transactions that expire at new block height from mempool mempool.removeExpired(pindexNew->nHeight); // Update chainActive & related variables. - UpdateTip(pindexNew); + UpdateTip(pindexNew, chainparams); // Tell wallet about transactions that went from mempool // to conflicted: BOOST_FOREACH(const CTransaction &tx, txConflicted) { @@ -3535,12 +3515,12 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * bool DisconnectBlocksAndReprocess(int blocks) { LOCK(cs_main); - + const CChainParams& chainparams = Params(); CValidationState state; LogPrintf("DisconnectBlocksAndReprocess: Got command to replay %d blocks\n", blocks); for (int i = 0; i <= blocks; i++) - DisconnectTip(state); + DisconnectTip(state, chainparams); return true; } @@ -3619,7 +3599,8 @@ static void PruneBlockIndexCandidates() { * Try to make some progress towards making pindexMostWork the active block. * pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork. */ -static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork, CBlock *pblock) { +static bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const CBlock* pblock) +{ AssertLockHeld(cs_main); bool fInvalidFound = false; const CBlockIndex *pindexOldTip = chainActive.Tip(); @@ -3653,7 +3634,7 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo // Disconnect active blocks which are no longer in the best chain. bool fBlocksDisconnected = false; while (chainActive.Tip() && chainActive.Tip() != pindexFork) { - if (!DisconnectTip(state)) + if (!DisconnectTip(state, chainparams)) return false; fBlocksDisconnected = true; } @@ -3677,11 +3658,11 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo // Connect new blocks. BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) { - if (!ConnectTip(state, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL)) { + if (!ConnectTip(state, chainparams, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL)) { if (state.IsInvalid()) { // The block violates a consensus rule. if (!state.CorruptionPossible()) - InvalidChainFound(vpindexToConnect.back()); + InvalidChainFound(vpindexToConnect.back(), chainparams); state = CValidationState(); fInvalidFound = true; fContinue = false; @@ -3705,14 +3686,14 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS); } mempool.removeWithoutBranchId( - CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, Params().GetConsensus())); + CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, chainparams.GetConsensus())); mempool.check(pcoinsTip); // Callbacks/notifications for a new best chain. if (fInvalidFound) - CheckForkWarningConditionsOnNewFork(vpindexToConnect.back()); + CheckForkWarningConditionsOnNewFork(vpindexToConnect.back(), chainparams); else - CheckForkWarningConditions(); + CheckForkWarningConditions(chainparams); return true; } @@ -3722,10 +3703,10 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo * or an activated best chain. pblock is either NULL or a pointer to a block * that is already loaded (to avoid loading it again from disk). */ -bool ActivateBestChain(CValidationState &state, CBlock *pblock) { +bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, const CBlock* pblock) +{ CBlockIndex *pindexNewTip = NULL; CBlockIndex *pindexMostWork = NULL; - const CChainParams& chainParams = Params(); do { boost::this_thread::interruption_point(); @@ -3738,11 +3719,11 @@ bool ActivateBestChain(CValidationState &state, CBlock *pblock) { if (pindexMostWork == NULL || pindexMostWork == chainActive.Tip()) return true; - if (!ActivateBestChainStep(state, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : NULL)) + if (!ActivateBestChainStep(state, chainparams, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : NULL)) return false; pindexNewTip = chainActive.Tip(); - fInitialDownload = IsInitialBlockDownload(); + fInitialDownload = IsInitialBlockDownload(chainparams); } // When we reach this point, we switched to a new tip (stored in pindexNewTip). @@ -3752,7 +3733,7 @@ bool ActivateBestChain(CValidationState &state, CBlock *pblock) { // Relay inventory, but don't relay old inventory during initial block download. int nBlockEstimate = 0; if (fCheckpointsEnabled) - nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(chainParams.Checkpoints()); + nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(chainparams.Checkpoints()); { LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) @@ -3764,7 +3745,7 @@ bool ActivateBestChain(CValidationState &state, CBlock *pblock) { uiInterface.NotifyBlockTip(hashNewTip); } } while(pindexMostWork != chainActive.Tip()); - CheckBlockIndex(); + CheckBlockIndex(chainparams.GetConsensus()); // Write changes periodically to disk, after relay. if (!FlushStateToDisk(state, FLUSH_STATE_PERIODIC)) { @@ -3774,7 +3755,8 @@ bool ActivateBestChain(CValidationState &state, CBlock *pblock) { return true; } -bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) { +bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex) +{ AssertLockHeld(cs_main); // Mark the block itself as invalid. @@ -3789,10 +3771,10 @@ bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) { setBlockIndexCandidates.erase(pindexWalk); // ActivateBestChain considers blocks already in chainActive // unconditionally valid already, so force disconnect away from it. - if (!DisconnectTip(state)) { + if (!DisconnectTip(state, chainparams)) { mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS); mempool.removeWithoutBranchId( - CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, Params().GetConsensus())); + CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, chainparams.GetConsensus())); return false; } } @@ -3807,10 +3789,10 @@ bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) { it++; } - InvalidChainFound(pindex); + InvalidChainFound(pindex, chainparams); mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS); mempool.removeWithoutBranchId( - CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, Params().GetConsensus())); + CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, chainparams.GetConsensus())); return true; } @@ -3921,9 +3903,13 @@ void FallbackSproutValuePoolBalance( } /** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */ -bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos) +bool ReceivedBlockTransactions( + const CBlock &block, + CValidationState& state, + const CChainParams& chainparams, + CBlockIndex *pindexNew, + const CDiskBlockPos& pos) { - const CChainParams& chainparams = Params(); pindexNew->nTx = block.vtx.size(); pindexNew->nChainTx = 0; CAmount sproutValue = 0; @@ -4092,7 +4078,11 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne return true; } -bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW) +bool CheckBlockHeader( + const CBlockHeader& block, + CValidationState& state, + const CChainParams& chainparams, + bool fCheckPOW) { bool cosmosActive = NetworkUpgradeActive(chainActive.Height()+1, Params().GetConsensus(), Consensus::UPGRADE_COSMOS); @@ -4103,12 +4093,12 @@ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool f REJECT_INVALID, "version-too-low"); // Check Equihash solution is valid - if (fCheckPOW && !CheckEquihashSolution(&block, Params())) + if (fCheckPOW && !CheckEquihashSolution(&block, chainparams.GetConsensus())) return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"), REJECT_INVALID, "invalid-solution"); // Check proof of work matches claimed amount - if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) + if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) return state.DoS(50, error("CheckBlockHeader(): proof of work failed"), REJECT_INVALID, "high-hash"); @@ -4124,6 +4114,7 @@ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool f } bool CheckBlock(const CBlock& block, CValidationState& state, + const CChainParams& chainparams, libzcash::ProofVerifier& verifier, bool fCheckPOW, bool fCheckMerkleRoot) { @@ -4131,7 +4122,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, // Check that the header is valid (particularly PoW). This is mostly // redundant with the call in AcceptBlockHeader. - if (!CheckBlockHeader(block, state, fCheckPOW)) + if (!CheckBlockHeader(block, state, chainparams, fCheckPOW)) return false; // Check the merkle root. @@ -4208,7 +4199,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, // but issue an initial reject message. // The case also exists that the sending peer could not have enough data to see // that this block is invalid, so don't issue an outright ban. - if (nHeight != 0 && !IsInitialBlockDownload()) { + if (nHeight != 0 && !IsInitialBlockDownload(chainparams)) { if (!IsBlockPayeeValid(block, nHeight)) { mapRejectedBlocks.insert(make_pair(block.GetHash(), GetTime())); return state.DoS(0, error("CheckBlock() : Couldn't find zeronode/budget payment"), @@ -4237,9 +4228,10 @@ bool CheckBlock(const CBlock& block, CValidationState& state, return true; } -bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex * const pindexPrev) +bool ContextualCheckBlockHeader( + const CBlockHeader& block, CValidationState& state, + const CChainParams& chainParams, CBlockIndex * const pindexPrev) { - const CChainParams& chainParams = Params(); const Consensus::Params& consensusParams = chainParams.GetConsensus(); uint256 hash = block.GetHash(); if (hash == consensusParams.hashGenesisBlock) @@ -4275,16 +4267,18 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta return true; } -bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex * const pindexPrev) +bool ContextualCheckBlock( + const CBlock& block, CValidationState& state, + const CChainParams& chainparams, CBlockIndex * const pindexPrev) { const int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1; - const Consensus::Params& consensusParams = Params().GetConsensus(); + const Consensus::Params& consensusParams = chainparams.GetConsensus(); // Check that all transactions are finalized BOOST_FOREACH(const CTransaction& tx, block.vtx) { // Check transaction contextually against consensus rules at block height - if (!ContextualCheckTransaction(tx, state, nHeight, 100)) { + if (!ContextualCheckTransaction(tx, state, chainparams, nHeight, 100)) { return false; // Failure reason has been set in validation state object } @@ -4319,7 +4313,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn bool found = false; BOOST_FOREACH(const CTxOut& output, block.vtx[0].vout) { - if (output.scriptPubKey == Params().GetFoundersRewardScriptAtHeight(nHeight)) { + if (output.scriptPubKey == chainparams.GetFoundersRewardScriptAtHeight(nHeight)) { if (output.nValue == (GetBlockSubsidy(nHeight, consensusParams) * 0.075)) { found = true; break; @@ -4335,9 +4329,8 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn return true; } -bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex** ppindex) +static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex=NULL) { - const CChainParams& chainparams = Params(); AssertLockHeld(cs_main); // Check for duplicate uint256 hash = block.GetHash(); @@ -4353,7 +4346,7 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc return true; } - if (!CheckBlockHeader(block, state)) + if (!CheckBlockHeader(block, state, chainparams)) return false; // Get prev block index @@ -4367,7 +4360,7 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc return state.DoS(100, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk"); } - if (!ContextualCheckBlockHeader(block, state, pindexPrev)) + if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev)) return false; if (pindex == NULL) @@ -4379,14 +4372,20 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc return true; } -bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, bool fRequested, CDiskBlockPos* dbp) +/** + * Store block on disk. + * JoinSplit proofs are never verified, because: + * - AcceptBlock doesn't perform script checks either. + * - The only caller of AcceptBlock verifies JoinSplit proofs elsewhere. + * If dbp is non-NULL, the file is known to already reside on disk + */ +static bool AcceptBlock(const CBlock& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, CDiskBlockPos* dbp) { - const CChainParams& chainparams = Params(); AssertLockHeld(cs_main); CBlockIndex *&pindex = *ppindex; - if (!AcceptBlockHeader(block, state, &pindex)) + if (!AcceptBlockHeader(block, state, chainparams, &pindex)) return false; // Try to process all requested blocks that we don't have, but only @@ -4412,7 +4411,7 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, // See method docstring for why this is always disabled auto verifier = libzcash::ProofVerifier::Disabled(); - if ((!CheckBlock(block, state, verifier)) || !ContextualCheckBlock(block, state, pindex->pprev)) { + if ((!CheckBlock(block, state, chainparams, verifier)) || !ContextualCheckBlock(block, state, chainparams, pindex->pprev)) { if (state.IsInvalid() && !state.CorruptionPossible()) { pindex->nStatus |= BLOCK_FAILED_VALID; setDirtyBlockIndex.insert(pindex); @@ -4433,7 +4432,7 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, if (dbp == NULL) if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart())) AbortNode(state, "Failed to write block"); - if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) + if (!ReceivedBlockTransactions(block, state, chainparams, pindex, blockPos)) return error("AcceptBlock(): ReceivedBlockTransactions failed"); } catch (const std::runtime_error& e) { return AbortNode(state, std::string("System error: ") + e.what()); @@ -4458,11 +4457,11 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned } -bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp) +bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, CDiskBlockPos* dbp) { // Preliminary checks auto verifier = libzcash::ProofVerifier::Disabled(); - bool checked = CheckBlock(*pblock, state, verifier); + bool checked = CheckBlock(*pblock, state, chainparams, verifier); { LOCK(cs_main); @@ -4474,16 +4473,16 @@ bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, bool // Store to disk CBlockIndex *pindex = NULL; - bool ret = AcceptBlock(*pblock, state, &pindex, fRequested, dbp); + bool ret = AcceptBlock(*pblock, state, chainparams, &pindex, fRequested, dbp); if (pindex && pfrom) { mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId(); } - CheckBlockIndex(); + CheckBlockIndex(chainparams.GetConsensus()); if (!ret) return error("%s: AcceptBlock FAILED", __func__); } - if (!ActivateBestChain(state, pblock)) + if (!ActivateBestChain(state, chainparams, pblock)) return error("%s: ActivateBestChain failed", __func__); if (!fLiteMode) { @@ -4495,7 +4494,7 @@ bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, bool return true; } -bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex * const pindexPrev, bool fCheckPOW, bool fCheckMerkleRoot) +bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW, bool fCheckMerkleRoot) { AssertLockHeld(cs_main); assert(pindexPrev == chainActive.Tip()); @@ -4508,13 +4507,13 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex auto verifier = libzcash::ProofVerifier::Disabled(); // NOTE: CheckBlockHeader is called by CheckBlock - if (!ContextualCheckBlockHeader(block, state, pindexPrev)) + if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev)) return false; - if (!CheckBlock(block, state, verifier, fCheckPOW, fCheckMerkleRoot)) + if (!CheckBlock(block, state, chainparams, verifier, fCheckPOW, fCheckMerkleRoot)) return false; - if (!ContextualCheckBlock(block, state, pindexPrev)) + if (!ContextualCheckBlock(block, state, chainparams, pindexPrev)) return false; - if (!ConnectBlock(block, state, &indexDummy, viewNew, true)) + if (!ConnectBlock(block, state, &indexDummy, viewNew, chainparams, true)) return false; assert(state.IsValid()); @@ -4579,13 +4578,13 @@ void UnlinkPrunedFiles(std::set& setFilesToPrune) } /* Calculate the block/rev files that should be deleted to remain under target*/ -void FindFilesToPrune(std::set& setFilesToPrune) +void FindFilesToPrune(std::set& setFilesToPrune, uint64_t nPruneAfterHeight) { LOCK2(cs_main, cs_LastBlockFile); if (chainActive.Tip() == NULL || nPruneTarget == 0) { return; } - if (chainActive.Tip()->nHeight <= Params().PruneAfterHeight()) { + if (chainActive.Tip()->nHeight <= nPruneAfterHeight) { return; } @@ -4696,8 +4695,7 @@ CBlockIndex * InsertBlockIndex(uint256 hash) bool static LoadBlockIndexDB() { const CChainParams& chainparams = Params(); - - if (!pblocktree->LoadBlockIndexGuts()) + if (!pblocktree->LoadBlockIndexGuts(InsertBlockIndex)) return false; boost::this_thread::interruption_point(); @@ -4877,7 +4875,7 @@ CVerifyDB::~CVerifyDB() uiInterface.ShowProgress("", 100); } -bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth) +bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, int nCheckLevel, int nCheckDepth) { LOCK(cs_main); if (chainActive.Tip() == NULL || chainActive.Tip()->pprev == NULL) @@ -4905,10 +4903,10 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth break; CBlock block; // check level 0: read from disk - if (!ReadBlockFromDisk(block, pindex)) + if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus())) return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); // check level 1: verify block validity - if (nCheckLevel >= 1 && !CheckBlock(block, state, verifier)) + if (nCheckLevel >= 1 && !CheckBlock(block, state, chainparams, verifier)) return error("VerifyDB(): *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); // check level 2: verify undo validity if (nCheckLevel >= 2 && pindex) { @@ -4922,7 +4920,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth // check level 3: check for inconsistencies during memory-only disconnect of tip blocks if (nCheckLevel >= 3 && pindex == pindexState && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) { // insightexplorer: do not update indices (false) - DisconnectResult res = DisconnectBlock(block, state, pindex, coins, false); + DisconnectResult res = DisconnectBlock(block, state, pindex, coins, chainparams, false); if (res == DISCONNECT_FAILED) { return error("VerifyDB(): *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); } @@ -4948,9 +4946,9 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, 100 - (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * 50)))); pindex = chainActive.Next(pindex); CBlock block; - if (!ReadBlockFromDisk(block, pindex)) + if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus())) return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); - if (!ConnectBlock(block, state, pindex, coins)) + if (!ConnectBlock(block, state, pindex, coins, chainparams)) return error("VerifyDB(): *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); } } @@ -4960,7 +4958,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth return true; } -bool RewindBlockIndex(const CChainParams& params, bool& clearWitnessCaches) +bool RewindBlockIndex(const CChainParams& chainparams, bool& clearWitnessCaches) { LOCK(cs_main); @@ -4973,8 +4971,8 @@ bool RewindBlockIndex(const CChainParams& params, bool& clearWitnessCaches) // // - BLOCK_ACTIVATES_UPGRADE is set only on blocks that activate upgrades. // - nCachedBranchId for each block matches what we expect. - auto sufficientlyValidated = [¶ms](const CBlockIndex* pindex) { - auto consensus = params.GetConsensus(); + auto sufficientlyValidated = [&chainparams](const CBlockIndex* pindex) { + auto consensus = chainparams.GetConsensus(); bool fFlagSet = pindex->nStatus & BLOCK_ACTIVATES_UPGRADE; bool fFlagExpected = IsActivationHeightForAnyUpgrade(pindex->nHeight, consensus); return fFlagSet == fFlagExpected && @@ -4997,7 +4995,7 @@ bool RewindBlockIndex(const CChainParams& params, bool& clearWitnessCaches) if (rewindLength > 0) { LogPrintf("*** First insufficiently validated block at height %d, rewind length %d\n", nHeight, rewindLength); const uint256 *phashFirstInsufValidated = chainActive[nHeight]->phashBlock; - auto networkID = params.NetworkIDString(); + auto networkID = chainparams.NetworkIDString(); // This is true when we intend to do a long rewind. bool intendedRewind = @@ -5044,7 +5042,7 @@ bool RewindBlockIndex(const CChainParams& params, bool& clearWitnessCaches) // of the blockchain). break; } - if (!DisconnectTip(state, true)) { + if (!DisconnectTip(state, chainparams, true)) { return error("RewindBlockIndex: unable to disconnect block at height %i", pindex->nHeight); } // Occasionally flush state to disk. @@ -5106,7 +5104,7 @@ bool RewindBlockIndex(const CChainParams& params, bool& clearWitnessCaches) PruneBlockIndexCandidates(); - CheckBlockIndex(); + CheckBlockIndex(chainparams.GetConsensus()); if (!FlushStateToDisk(state, FLUSH_STATE_ALWAYS)) { return false; @@ -5154,9 +5152,8 @@ bool LoadBlockIndex() return true; } - -bool InitBlockIndex() { - const CChainParams& chainparams = Params(); +bool InitBlockIndex(const CChainParams& chainparams) +{ LOCK(cs_main); // Initialize global variables that cannot be constructed at startup. @@ -5182,7 +5179,7 @@ bool InitBlockIndex() { // Only add the genesis block if not reindexing (in which case we reuse the one already on disk) if (!fReindex) { try { - CBlock &block = const_cast(Params().GenesisBlock()); + CBlock &block = const_cast(chainparams.GenesisBlock()); // Start new block file unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); CDiskBlockPos blockPos; @@ -5192,9 +5189,9 @@ bool InitBlockIndex() { if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart())) return error("LoadBlockIndex(): writing genesis block to disk failed"); CBlockIndex *pindex = AddToBlockIndex(block); - if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) + if (!ReceivedBlockTransactions(block, state, chainparams, pindex, blockPos)) return error("LoadBlockIndex(): genesis block not accepted"); - if (!ActivateBestChain(state, &block)) + if (!ActivateBestChain(state, chainparams, &block)) return error("LoadBlockIndex(): genesis block cannot be activated"); // Force a chainstate write so that when we VerifyDB in a moment, it doesn't check stale data return FlushStateToDisk(state, FLUSH_STATE_ALWAYS); @@ -5206,11 +5203,8 @@ bool InitBlockIndex() { return true; } - - -bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) +bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp) { - const CChainParams& chainparams = Params(); // Map of disk positions for blocks with unknown parent (only used for reindex) static std::multimap mapBlocksUnknownParent; int64_t nStart = GetTimeMillis(); @@ -5230,10 +5224,10 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) try { // locate a header unsigned char buf[MESSAGE_START_SIZE]; - blkdat.FindByte(Params().MessageStart()[0]); + blkdat.FindByte(chainparams.MessageStart()[0]); nRewind = blkdat.GetPos()+1; blkdat >> FLATDATA(buf); - if (memcmp(buf, Params().MessageStart(), MESSAGE_START_SIZE)) + if (memcmp(buf, chainparams.MessageStart(), MESSAGE_START_SIZE)) continue; // read size blkdat >> nSize; @@ -5267,7 +5261,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) // process in case the block isn't known yet if (mapBlockIndex.count(hash) == 0 || (mapBlockIndex[hash]->nStatus & BLOCK_HAVE_DATA) == 0) { CValidationState state; - if (ProcessNewBlock(state, NULL, &block, true, dbp)) + if (ProcessNewBlock(state, chainparams, NULL, &block, true, dbp)) nLoaded++; if (state.IsError()) break; @@ -5284,12 +5278,12 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) std::pair::iterator, std::multimap::iterator> range = mapBlocksUnknownParent.equal_range(head); while (range.first != range.second) { std::multimap::iterator it = range.first; - if (ReadBlockFromDisk(block, it->second)) + if (ReadBlockFromDisk(block, it->second, chainparams.GetConsensus())) { LogPrintf("%s: Processing out of order child %s of %s\n", __func__, block.GetHash().ToString(), head.ToString()); CValidationState dummy; - if (ProcessNewBlock(dummy, NULL, &block, true, &it->second)) + if (ProcessNewBlock(dummy, chainparams, NULL, &block, true, &it->second)) { nLoaded++; queue.push_back(block.GetHash()); @@ -5311,9 +5305,8 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) return nLoaded > 0; } -void static CheckBlockIndex() +void static CheckBlockIndex(const Consensus::Params& consensusParams) { - const Consensus::Params& consensusParams = Params().GetConsensus(); if (!fCheckBlockIndex) { return; } @@ -5643,7 +5636,7 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main) return true; } -void static ProcessGetData(CNode* pfrom) +void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParams) { int currentHeight = GetHeight(); @@ -5678,7 +5671,7 @@ void static ProcessGetData(CNode* pfrom) // best equivalent proof of work) than the best header chain we know about. send = mi->second->IsValid(BLOCK_VALID_SCRIPTS) && (pindexBestHeader != NULL) && (pindexBestHeader->GetBlockTime() - mi->second->GetBlockTime() < nOneMonth) && - (GetBlockProofEquivalentTime(*pindexBestHeader, *mi->second, *pindexBestHeader, Params().GetConsensus()) < nOneMonth); + (GetBlockProofEquivalentTime(*pindexBestHeader, *mi->second, *pindexBestHeader, consensusParams) < nOneMonth); if (!send) { LogPrintf("%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom->GetId()); } @@ -5690,7 +5683,7 @@ void static ProcessGetData(CNode* pfrom) { // Send block from disk CBlock block; - if (!ReadBlockFromDisk(block, (*mi).second)) + if (!ReadBlockFromDisk(block, (*mi).second, consensusParams)) assert(!"cannot load block from disk"); if (inv.type == MSG_BLOCK) pfrom->PushMessage("block", block); @@ -5922,14 +5915,14 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } // Reject incoming connections from nodes that don't know about the current epoch - const Consensus::Params& params = Params().GetConsensus(); - auto currentEpoch = CurrentEpoch(GetHeight(), params); - if (pfrom->nVersion < params.vUpgrades[currentEpoch].nProtocolVersion) + const Consensus::Params& consensusParams = chainparams.GetConsensus(); + auto currentEpoch = CurrentEpoch(GetHeight(), consensusParams); + if (pfrom->nVersion < consensusParams.vUpgrades[currentEpoch].nProtocolVersion) { LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, pfrom->nVersion); pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", - params.vUpgrades[currentEpoch].nProtocolVersion)); + consensusParams.vUpgrades[currentEpoch].nProtocolVersion)); pfrom->fDisconnect = true; return false; } @@ -5979,7 +5972,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (!pfrom->fInbound) { // Advertise our address - if (fListen && !IsInitialBlockDownload()) + if (fListen && !IsInitialBlockDownload(chainparams)) { CAddress addr = GetLocalAddress(&pfrom->addr); if (addr.IsRoutable()) @@ -6217,7 +6210,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, LogPrint("net", "received getdata for: %s peer=%d\n", vInv[0].ToString(), pfrom->id); pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end()); - ProcessGetData(pfrom); + ProcessGetData(pfrom, chainparams.GetConsensus()); } @@ -6273,7 +6266,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, LOCK(cs_main); - if (IsInitialBlockDownload()) + if (IsInitialBlockDownload(chainparams)) return true; CBlockIndex* pindex = NULL; @@ -6470,7 +6463,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, Misbehaving(pfrom->GetId(), 20); return error("non-continuous headers sequence"); } - if (!AcceptBlockHeader(header, state, &pindexLast)) { + if (!AcceptBlockHeader(header, state, chainparams, &pindexLast)) { int nDoS; if (state.IsInvalid(nDoS)) { if (nDoS > 0) @@ -6491,7 +6484,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->PushMessage("getheaders", chainActive.GetLocator(pindexLast), uint256()); } - CheckBlockIndex(); + CheckBlockIndex(chainparams.GetConsensus()); } else if (strCommand == "block" && !fImporting && !fReindex) // Ignore blocks received while importing @@ -6509,8 +6502,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // unless we're still syncing with the network. // Such an unrequested block may still be processed, subject to the // conditions in AcceptBlock(). - bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload(); - ProcessNewBlock(state, pfrom, &block, forceProcessing, NULL); + bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload(chainparams); + ProcessNewBlock(state, chainparams, pfrom, &block, forceProcessing, NULL); int nDoS; if (state.IsInvalid(nDoS)) { pfrom->PushMessage("reject", strCommand, state.GetRejectCode(), @@ -6666,7 +6659,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, uint256 alertHash = alert.GetHash(); if (pfrom->setKnown.count(alertHash) == 0) { - if (alert.ProcessAlert(Params().AlertKey())) + if (alert.ProcessAlert(chainparams.AlertKey())) { // Relay pfrom->setKnown.insert(alertHash); @@ -6810,6 +6803,7 @@ int ActiveProtocol() // requires LOCK(cs_vRecvMsg) bool ProcessMessages(CNode* pfrom) { + const CChainParams& chainparams = Params(); //if (fDebug) // LogPrintf("%s(%u messages)\n", __func__, pfrom->vRecvMsg.size()); @@ -6824,7 +6818,7 @@ bool ProcessMessages(CNode* pfrom) bool fOk = true; if (!pfrom->vRecvGetData.empty()) - ProcessGetData(pfrom); + ProcessGetData(pfrom, chainparams.GetConsensus()); // this maintains the order of responses if (!pfrom->vRecvGetData.empty()) return fOk; @@ -6851,7 +6845,7 @@ bool ProcessMessages(CNode* pfrom) it++; // Scan for message start - if (memcmp(msg.hdr.pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE) != 0) { + if (memcmp(msg.hdr.pchMessageStart, chainparams.MessageStart(), MESSAGE_START_SIZE) != 0) { LogPrintf("PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.hdr.GetCommand()), pfrom->id); fOk = false; break; @@ -6859,7 +6853,7 @@ bool ProcessMessages(CNode* pfrom) // Read header CMessageHeader& hdr = msg.hdr; - if (!hdr.IsValid(Params().MessageStart())) + if (!hdr.IsValid(chainparams.MessageStart())) { LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->id); continue; @@ -6930,7 +6924,8 @@ bool ProcessMessages(CNode* pfrom) bool SendMessages(CNode* pto, bool fSendTrickle) { - const Consensus::Params& consensusParams = Params().GetConsensus(); + const CChainParams& chainParams = Params(); + const Consensus::Params& consensusParams = chainParams.GetConsensus(); { // Don't send anything until we get its version message if (pto->nVersion == 0) @@ -6971,7 +6966,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) // Address refresh broadcast static int64_t nLastRebroadcast; - if (!IsInitialBlockDownload() && (GetTime() - nLastRebroadcast > 24 * 60 * 60)) + if (!IsInitialBlockDownload(chainParams) && (GetTime() - nLastRebroadcast > 24 * 60 * 60)) { LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) @@ -7051,7 +7046,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) // Resend wallet transactions that haven't gotten in a block yet // Except during reindex, importing and IBD, when old wallet // transactions become unconfirmed and spams other nodes. - if (!fReindex && !fImporting && !IsInitialBlockDownload()) + if (!fReindex && !fImporting && !IsInitialBlockDownload(chainParams)) { GetMainSignals().Broadcast(nTimeBestReceived); } @@ -7140,7 +7135,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) // Message: getdata (blocks) // vector vGetData; - if (!pto->fDisconnect && !pto->fClient && (fFetch || !IsInitialBlockDownload()) && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) { + if (!pto->fDisconnect && !pto->fClient && (fFetch || !IsInitialBlockDownload(chainParams)) && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) { vector vToDownload; NodeId staller = -1; FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller); @@ -7214,12 +7209,19 @@ static class CMainCleanup // Set default values of new CMutableTransaction based on consensus rules at given height. CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight) { - CMutableTransaction mtx; + return CreateNewContextualCMutableTransaction(consensusParams, nHeight, expiryDelta); +} +CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight, int nExpiryDelta) { + CMutableTransaction mtx; bool isOverwintered = NetworkUpgradeActive(nHeight, consensusParams, Consensus::UPGRADE_OVERWINTER); if (isOverwintered) { mtx.fOverwintered = true; - mtx.nExpiryHeight = nHeight + expiryDelta; + mtx.nExpiryHeight = nHeight + nExpiryDelta; + + if (mtx.nExpiryHeight <= 0 || mtx.nExpiryHeight >= TX_EXPIRY_HEIGHT_THRESHOLD) { + throw new std::runtime_error("CreateNewContextualCMutableTransaction: invalid expiry height"); + } // NOTE: If the expiry height crosses into an incompatible consensus epoch, and it is changed to the last block // of the current epoch (see below: Overwinter->Sapling), the transaction will be rejected if it falls within diff --git a/src/main.h b/src/main.h index 631d9b408ff..88678060bce 100644 --- a/src/main.h +++ b/src/main.h @@ -46,6 +46,7 @@ class CBlockIndex; class CBlockTreeDB; class CSporkDB; class CBloomFilter; +class CChainParams; class CInv; class CScriptCheck; class CValidationInterface; @@ -215,7 +216,7 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals); * @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location. * @return True if state.IsValid() */ -bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp); +bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, const CNode* pfrom, const CBlock* pblock, bool fForceProcessing, CDiskBlockPos* dbp); /** Check whether enough disk space is available for an incoming block */ bool CheckDiskSpace(uint64_t nAdditionalBytes = 0); /** Open a block file (blk?????.dat) */ @@ -225,9 +226,9 @@ FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false); /** Translation to a filesystem path */ boost::filesystem::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix); /** Import blocks from an external file */ -bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp = NULL); +bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp = NULL); /** Initialize a new block tree database + block data on disk */ -bool InitBlockIndex(); +bool InitBlockIndex(const CChainParams& chainparams); /** Load the block tree and coins database from disk */ bool LoadBlockIndex(); /** Unload database information */ @@ -244,18 +245,18 @@ bool SendMessages(CNode* pto, bool fSendTrickle); /** Run an instance of the script checking thread */ void ThreadScriptCheck(); /** Try to detect Partition (network isolation) attacks against us */ -void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const CBlockIndex *const &bestHeader, int64_t nPowTargetSpacing); +void PartitionCheck(bool (*initialDownloadCheck)(const CChainParams&), CCriticalSection& cs, const CBlockIndex *const &bestHeader, int64_t nPowTargetSpacing); /** Check whether we are doing an initial block download (synchronizing from disk or network) */ -bool IsInitialBlockDownload(); +bool IsInitialBlockDownload(const CChainParams& chainParams); /** Format a string that describes several potential problems detected by the core */ std::string GetWarnings(const std::string& strFor); /** Retrieve a transaction (from memory pool, or from disk, if possible) */ -bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, bool fAllowSlow = false); +bool GetTransaction(const uint256 &hash, CTransaction &tx, const Consensus::Params& params, uint256 &hashBlock, bool fAllowSlow = false); bool DisconnectBlocksAndReprocess(int blocks); /** Find the best known block, and make it the tip of the block chain */ -bool ActivateBestChain(CValidationState &state, CBlock *pblock = NULL); +bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, const CBlock* pblock = NULL); CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams); /** @@ -273,7 +274,7 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams); * * @param[out] setFilesToPrune The set of file indices that can be unlinked will be returned */ -void FindFilesToPrune(std::set& setFilesToPrune); +void FindFilesToPrune(std::set& setFilesToPrune, uint64_t nPruneAfterHeight); int64_t GetZeronodePayment(int nHeight, int64_t blockValue, int nZeronodeCount = 0); /** * Actually unlink the specified files @@ -308,362 +309,6 @@ struct CNodeStateStats { std::vector vHeightInFlight; }; -// struct CTimestampIndexIteratorKey { -// unsigned int timestamp; -// -// size_t GetSerializeSize(int nType, int nVersion) const { -// return 4; -// } -// template -// void Serialize(Stream& s) const { -// ser_writedata32be(s, timestamp); -// } -// template -// void Unserialize(Stream& s) { -// timestamp = ser_readdata32be(s); -// } -// -// CTimestampIndexIteratorKey(unsigned int time) { -// timestamp = time; -// } -// -// CTimestampIndexIteratorKey() { -// SetNull(); -// } -// -// void SetNull() { -// timestamp = 0; -// } -// }; - -// struct CTimestampIndexKey { -// unsigned int timestamp; -// uint256 blockHash; -// -// size_t GetSerializeSize(int nType, int nVersion) const { -// return 36; -// } -// template -// void Serialize(Stream& s) const { -// ser_writedata32be(s, timestamp); -// blockHash.Serialize(s); -// } -// template -// void Unserialize(Stream& s) { -// timestamp = ser_readdata32be(s); -// blockHash.Unserialize(s); -// } -// -// CTimestampIndexKey(unsigned int time, uint256 hash) { -// timestamp = time; -// blockHash = hash; -// } -// -// CTimestampIndexKey() { -// SetNull(); -// } -// -// void SetNull() { -// timestamp = 0; -// blockHash.SetNull(); -// } -// }; - -// struct CTimestampBlockIndexKey { -// uint256 blockHash; -// -// size_t GetSerializeSize(int nType, int nVersion) const { -// return 32; -// } -// -// template -// void Serialize(Stream& s) const { -// blockHash.Serialize(s); -// } -// -// template -// void Unserialize(Stream& s) { -// blockHash.Unserialize(s); -// } -// -// CTimestampBlockIndexKey(uint256 hash) { -// blockHash = hash; -// } -// -// CTimestampBlockIndexKey() { -// SetNull(); -// } -// -// void SetNull() { -// blockHash.SetNull(); -// } -// }; - -// struct CTimestampBlockIndexValue { -// unsigned int ltimestamp; -// size_t GetSerializeSize(int nType, int nVersion) const { -// return 4; -// } -// -// template -// void Serialize(Stream& s) const { -// ser_writedata32be(s, ltimestamp); -// } -// -// template -// void Unserialize(Stream& s) { -// ltimestamp = ser_readdata32be(s); -// } -// -// CTimestampBlockIndexValue (unsigned int time) { -// ltimestamp = time; -// } -// -// CTimestampBlockIndexValue() { -// SetNull(); -// } -// -// void SetNull() { -// ltimestamp = 0; -// } -// }; - -// struct CAddressUnspentKey { -// unsigned int type; -// uint160 hashBytes; -// uint256 txhash; -// size_t index; -// -// size_t GetSerializeSize(int nType, int nVersion) const { -// return 57; -// } -// template -// void Serialize(Stream& s) const { -// ser_writedata8(s, type); -// hashBytes.Serialize(s); -// txhash.Serialize(s); -// ser_writedata32(s, index); -// } -// template -// void Unserialize(Stream& s) { -// type = ser_readdata8(s); -// hashBytes.Unserialize(s); -// txhash.Unserialize(s); -// index = ser_readdata32(s); -// } -// -// CAddressUnspentKey(unsigned int addressType, uint160 addressHash, uint256 txid, size_t indexValue) { -// type = addressType; -// hashBytes = addressHash; -// txhash = txid; -// index = indexValue; -// } -// -// CAddressUnspentKey() { -// SetNull(); -// } -// -// void SetNull() { -// type = 0; -// hashBytes.SetNull(); -// txhash.SetNull(); -// index = 0; -// } -// }; - -// struct CAddressUnspentValue { -// CAmount satoshis; -// CScript script; -// int blockHeight; -// -// ADD_SERIALIZE_METHODS; -// -// template -// inline void SerializationOp(Stream& s, Operation ser_action) { -// READWRITE(satoshis); -// READWRITE(*(CScriptBase*)(&script)); -// READWRITE(blockHeight); -// } -// -// CAddressUnspentValue(CAmount sats, CScript scriptPubKey, int height) { -// satoshis = sats; -// script = scriptPubKey; -// blockHeight = height; -// } -// -// CAddressUnspentValue() { -// SetNull(); -// } -// -// void SetNull() { -// satoshis = -1; -// script.clear(); -// blockHeight = 0; -// } -// -// bool IsNull() const { -// return (satoshis == -1); -// } -// }; - -// struct CAddressIndexKey { -// unsigned int type; -// uint160 hashBytes; -// int blockHeight; -// unsigned int txindex; -// uint256 txhash; -// size_t index; -// bool spending; -// -// size_t GetSerializeSize(int nType, int nVersion) const { -// return 66; -// } -// template -// void Serialize(Stream& s) const { -// ser_writedata8(s, type); -// hashBytes.Serialize(s); -// // Heights are stored big-endian for key sorting in LevelDB -// ser_writedata32be(s, blockHeight); -// ser_writedata32be(s, txindex); -// txhash.Serialize(s); -// ser_writedata32(s, index); -// char f = spending; -// ser_writedata8(s, f); -// } -// template -// void Unserialize(Stream& s) { -// type = ser_readdata8(s); -// hashBytes.Unserialize(s); -// blockHeight = ser_readdata32be(s); -// txindex = ser_readdata32be(s); -// txhash.Unserialize(s); -// index = ser_readdata32(s); -// char f = ser_readdata8(s); -// spending = f; -// } -// -// CAddressIndexKey(unsigned int addressType, uint160 addressHash, int height, int blockindex, -// uint256 txid, size_t indexValue, bool isSpending) { -// type = addressType; -// hashBytes = addressHash; -// blockHeight = height; -// txindex = blockindex; -// txhash = txid; -// index = indexValue; -// spending = isSpending; -// } -// -// CAddressIndexKey() { -// SetNull(); -// } -// -// void SetNull() { -// type = 0; -// hashBytes.SetNull(); -// blockHeight = 0; -// txindex = 0; -// txhash.SetNull(); -// index = 0; -// spending = false; -// } -// -// }; - -// struct CAddressIndexIteratorKey { -// unsigned int type; -// uint160 hashBytes; -// -// size_t GetSerializeSize(int nType, int nVersion) const { -// return 21; -// } -// template -// void Serialize(Stream& s) const { -// ser_writedata8(s, type); -// hashBytes.Serialize(s); -// } -// template -// void Unserialize(Stream& s) { -// type = ser_readdata8(s); -// hashBytes.Unserialize(s); -// } -// -// CAddressIndexIteratorKey(unsigned int addressType, uint160 addressHash) { -// type = addressType; -// hashBytes = addressHash; -// } -// -// CAddressIndexIteratorKey() { -// SetNull(); -// } -// -// void SetNull() { -// type = 0; -// hashBytes.SetNull(); -// } -// }; - -// struct CAddressIndexIteratorHeightKey { -// unsigned int type; -// uint160 hashBytes; -// int blockHeight; -// -// size_t GetSerializeSize(int nType, int nVersion) const { -// return 25; -// } -// template -// void Serialize(Stream& s) const { -// ser_writedata8(s, type); -// hashBytes.Serialize(s); -// ser_writedata32be(s, blockHeight); -// } -// template -// void Unserialize(Stream& s) { -// type = ser_readdata8(s); -// hashBytes.Unserialize(s); -// blockHeight = ser_readdata32be(s); -// } -// -// CAddressIndexIteratorHeightKey(unsigned int addressType, uint160 addressHash, int height) { -// type = addressType; -// hashBytes = addressHash; -// blockHeight = height; -// } -// -// CAddressIndexIteratorHeightKey() { -// SetNull(); -// } -// -// void SetNull() { -// type = 0; -// hashBytes.SetNull(); -// blockHeight = 0; -// } -// }; - -struct CDiskTxPos : public CDiskBlockPos -{ - unsigned int nTxOffset; // after header - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(*(CDiskBlockPos*)this); - READWRITE(VARINT(nTxOffset)); - } - - CDiskTxPos(const CDiskBlockPos &blockIn, unsigned int nTxOffsetIn) : CDiskBlockPos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) { - } - - CDiskTxPos() { - SetNull(); - } - - void SetNull() { - CDiskBlockPos::SetNull(); - nTxOffset = 0; - } -}; CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree); @@ -715,8 +360,9 @@ bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, cons std::vector *pvChecks = NULL); /** Check a transaction contextually against a set of consensus rules */ -bool ContextualCheckTransaction(const CTransaction& tx, CValidationState &state, int nHeight, int dosLevel, - bool (*isInitBlockDownload)() = IsInitialBlockDownload); +bool ContextualCheckTransaction(const CTransaction& tx, CValidationState &state, + const CChainParams& chainparams, int nHeight, int dosLevel, + bool (*isInitBlockDownload)(const CChainParams&) = IsInitialBlockDownload); /** Apply the effects of this transaction on the UTXO set represented by view */ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight); @@ -730,7 +376,7 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio /** Check for standard transaction types * @return True if all outputs (scriptPubKeys) use only standard transaction forms */ -bool IsStandardTx(const CTransaction& tx, std::string& reason, int nHeight = 0); +bool IsStandardTx(const CTransaction& tx, std::string& reason, const CChainParams& chainparams, int nHeight = 0); namespace Consensus { @@ -819,39 +465,37 @@ bool GetAddressUnspent(uint160 addressHash, int type, std::vector > &unspentOutputs); /** Functions for disk access for blocks */ -bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart); -bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos); -bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex); - +bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart); +bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus::Params& consensusParams); +bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams); /** Functions for validating blocks and updating the block tree */ -/** Apply the effects of this block (with given index) on the UTXO set represented by coins */ -bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false); - /** Context-independent validity checks */ -bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true); +bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, + const CChainParams& chainparams, + bool fCheckPOW = true); bool CheckBlock(const CBlock& block, CValidationState& state, + const CChainParams& chainparams, libzcash::ProofVerifier& verifier, bool fCheckPOW = true, bool fCheckMerkleRoot = true); -/** Context-dependent validity checks */ -bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex *pindexPrev); -bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex *pindexPrev); +/** Context-dependent validity checks. + * By "context", we mean only the previous block headers, but not the UTXO + * set; UTXO-related validity checks are done in ConnectBlock(). */ +bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, + const CChainParams& chainparams, CBlockIndex *pindexPrev); +bool ContextualCheckBlock(const CBlock& block, CValidationState& state, + const CChainParams& chainparams, CBlockIndex *pindexPrev); -/** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */ -bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex *pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true); - -/** - * Store block on disk. - * JoinSplit proofs are never verified, because: - * - AcceptBlock doesn't perform script checks either. - * - The only caller of AcceptBlock verifies JoinSplit proofs elsewhere. - * If dbp is non-NULL, the file is known to already reside on disk - */ -bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex **pindex, bool fRequested, CDiskBlockPos* dbp); -bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL); +/** Apply the effects of this block (with given index) on the UTXO set represented by coins. + * Validity checks that depend on the UTXO set are also done; ConnectBlock() + * can fail if those validity checks fail (among other reasons). */ +bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, + const CChainParams& chainparams, bool fJustCheck = false); +/** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */ +bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true); /** @@ -862,75 +506,21 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc * clearWitnessCaches is an output parameter that will be set to true iff * witness caches should be cleared in order to handle an intended long rewind. */ -bool RewindBlockIndex(const CChainParams& params, bool& clearWitnessCaches); - -class CBlockFileInfo -{ -public: - unsigned int nBlocks; //! number of blocks stored in file - unsigned int nSize; //! number of used bytes of block file - unsigned int nUndoSize; //! number of used bytes in the undo file - unsigned int nHeightFirst; //! lowest height of block in file - unsigned int nHeightLast; //! highest height of block in file - uint64_t nTimeFirst; //! earliest time of block in file - uint64_t nTimeLast; //! latest time of block in file - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(VARINT(nBlocks)); - READWRITE(VARINT(nSize)); - READWRITE(VARINT(nUndoSize)); - READWRITE(VARINT(nHeightFirst)); - READWRITE(VARINT(nHeightLast)); - READWRITE(VARINT(nTimeFirst)); - READWRITE(VARINT(nTimeLast)); - } - - void SetNull() { - nBlocks = 0; - nSize = 0; - nUndoSize = 0; - nHeightFirst = 0; - nHeightLast = 0; - nTimeFirst = 0; - nTimeLast = 0; - } - - CBlockFileInfo() { - SetNull(); - } - - std::string ToString() const; - - /** update statistics (does not update nSize) */ - void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) { - if (nBlocks==0 || nHeightFirst > nHeightIn) - nHeightFirst = nHeightIn; - if (nBlocks==0 || nTimeFirst > nTimeIn) - nTimeFirst = nTimeIn; - nBlocks++; - if (nHeightIn > nHeightLast) - nHeightLast = nHeightIn; - if (nTimeIn > nTimeLast) - nTimeLast = nTimeIn; - } -}; +bool RewindBlockIndex(const CChainParams& chainparams, bool& clearWitnessCaches); /** RAII wrapper for VerifyDB: Verify consistency of the block and coin databases */ class CVerifyDB { public: CVerifyDB(); ~CVerifyDB(); - bool VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth); + bool VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, int nCheckLevel, int nCheckDepth); }; /** Find the last common block between the parameter chain and a locator. */ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator); /** Mark a block as invalid. */ -bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex); +bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex); /** Remove invalidity status from a block and its descendants. */ bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex); @@ -955,7 +545,10 @@ int GetSpendHeight(const CCoinsViewCache& inputs); uint64_t CalculateCurrentUsage(); -/** Return a CMutableTransaction with contextual default values based on set of consensus rules at height */ +/** Return a CMutableTransaction with contextual default values based on set of consensus rules at nHeight, and the default expiry delta. */ CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight); +/** Return a CMutableTransaction with contextual default values based on set of consensus rules at nHeight, and given expiry delta. */ +CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight, int nExpiryDelta); + #endif // BITCOIN_MAIN_H diff --git a/src/metrics.cpp b/src/metrics.cpp index b02b14ad532..a109664c468 100644 --- a/src/metrics.cpp +++ b/src/metrics.cpp @@ -219,7 +219,7 @@ int printStats(bool mining) } auto localsolps = GetLocalSolPS(); - if (IsInitialBlockDownload()) { + if (IsInitialBlockDownload(Params())) { int netheight = EstimateNetHeight(height, tipmediantime, Params()); int downloadPercent = height * 100 / netheight; std::cout << " " << _("Downloading blocks") << " | " << height << " / ~" << netheight << " (" << downloadPercent << "%)" << std::endl; @@ -256,7 +256,7 @@ int printMiningStatus(bool mining) } if (fvNodesEmpty) { std::cout << _("Mining is paused while waiting for connections.") << std::endl; - } else if (IsInitialBlockDownload()) { + } else if (IsInitialBlockDownload(Params())) { std::cout << _("Mining is paused while downloading blocks.") << std::endl; } else { std::cout << _("Mining is paused (a JoinSplit may be in progress).") << std::endl; diff --git a/src/miner.cpp b/src/miner.cpp index 9cfe1acc918..192596f5811 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -113,9 +113,8 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, } } -CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) +CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& scriptPubKeyIn) { - const CChainParams& chainparams = Params(); // Create new block std::unique_ptr pblocktemplate(new CBlockTemplate()); if(!pblocktemplate.get()) @@ -124,7 +123,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) // -regtest only: allow overriding block.nVersion with // -blockversion=N to test forking scenarios - if (Params().MineBlocksOnDemand()) + if (chainparams.MineBlocksOnDemand()) pblock->nVersion = GetArg("-blockversion", pblock->nVersion); // Add dummy coinbase tx as first transaction @@ -331,7 +330,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) // create only contains transactions that are valid in new blocks. CValidationState state; PrecomputedTransactionData txdata(tx); - if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId)) + if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, chainparams.GetConsensus(), consensusBranchId)) continue; if (chainparams.ZIP209Enabled() && monitoring_pool_balances) { @@ -435,13 +434,13 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) // Fill in header pblock->hashPrevBlock = pindexPrev->GetBlockHash(); pblock->hashFinalSaplingRoot = sapling_tree.root(); - UpdateTime(pblock, Params().GetConsensus(), pindexPrev); - pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus()); + UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); + pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus()); pblock->nSolution.clear(); pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]); CValidationState state; - if (!TestBlockValidity(state, *pblock, pindexPrev, false, false)) + if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) throw std::runtime_error("CreateNewBlock(): TestBlockValidity failed"); } @@ -479,7 +478,7 @@ void GetScriptForMinerAddress(boost::shared_ptr &script) script->reserveScript = CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG; } -void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce) +void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce) { // Update nExtraNonce static uint256 hashPrevBlock; @@ -498,7 +497,7 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& pblock->hashMerkleRoot = pblock->BuildMerkleTree(); } -static bool ProcessBlockFound(CBlock* pblock, const CChainParams& chainparams) +static bool ProcessBlockFound(const CBlock* pblock, const CChainParams& chainparams) { LogPrintf("%s\n", pblock->ToString()); LogPrintf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue)); @@ -515,7 +514,7 @@ static bool ProcessBlockFound(CBlock* pblock, const CChainParams& chainparams) // Process this block the same as if we had received it from another node CValidationState state; - if (!ProcessNewBlock(state, NULL, pblock, true, NULL)) + if (!ProcessNewBlock(state, chainparams, NULL, pblock, true, NULL)) return error("ZcashMiner: ProcessNewBlock, block not accepted"); TrackMinedBlock(pblock->GetHash()); @@ -535,8 +534,8 @@ void static BitcoinMiner(const CChainParams& chainparams) boost::shared_ptr coinbaseScript; GetMainSignals().ScriptForMining(coinbaseScript); - unsigned int n = chainparams.EquihashN(); - unsigned int k = chainparams.EquihashK(); + unsigned int n = chainparams.GetConsensus().nEquihashN; + unsigned int k = chainparams.GetConsensus().nEquihashK; std::string solver = GetArg("-equihashsolver", "default"); assert(solver == "tromp" || solver == "default"); @@ -568,7 +567,7 @@ void static BitcoinMiner(const CChainParams& chainparams) LOCK(cs_vNodes); fvNodesEmpty = vNodes.empty(); } - if (!fvNodesEmpty && !IsInitialBlockDownload()) + if (!fvNodesEmpty && !IsInitialBlockDownload(chainparams)) break; MilliSleep(1000); } while (true); @@ -581,7 +580,7 @@ void static BitcoinMiner(const CChainParams& chainparams) unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); CBlockIndex* pindexPrev = chainActive.Tip(); - unique_ptr pblocktemplate(CreateNewBlock(coinbaseScript->reserveScript)); + unique_ptr pblocktemplate(CreateNewBlock(chainparams, coinbaseScript->reserveScript)); if (!pblocktemplate.get()) { if (GetArg("-mineraddress", "").empty()) { diff --git a/src/miner.h b/src/miner.h index 07098905445..9059be633e5 100644 --- a/src/miner.h +++ b/src/miner.h @@ -24,13 +24,13 @@ struct CBlockTemplate }; /** Generate a new block, without valid proof-of-work */ -CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn); +CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& scriptPubKeyIn); #ifdef ENABLE_MINING /** Get script for -mineraddress */ void GetScriptForMinerAddress(boost::shared_ptr &script); /** Modify the extranonce in a block */ -void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce); +void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce); /** Run the miner threads */ void GenerateBitcoins(bool fGenerate, int nThreads, const CChainParams& chainparams); #endif diff --git a/src/policy/fees.h b/src/policy/fees.h index ee865c67911..52b0c36cdc7 100644 --- a/src/policy/fees.h +++ b/src/policy/fees.h @@ -259,8 +259,8 @@ class CBlockPolicyEstimator void Read(CAutoFile& filein); private: - CFeeRate minTrackedFee; //! Passed to constructor to avoid dependency on main - double minTrackedPriority; //! Set to AllowFreeThreshold + CFeeRate minTrackedFee; //!< Passed to constructor to avoid dependency on main + double minTrackedPriority; //!< Set to AllowFreeThreshold unsigned int nBestSeenHeight; struct TxStatsInfo { diff --git a/src/pow.cpp b/src/pow.cpp index 743df08ee30..ec0410acca2 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -91,10 +91,10 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg, return bnNew.GetCompact(); } -bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams& params) +bool CheckEquihashSolution(const CBlockHeader *pblock, const Consensus::Params& params) { - unsigned int n = params.EquihashN(); - unsigned int k = params.EquihashK(); + unsigned int n = params.nEquihashN; + unsigned int k = params.nEquihashK; // Hash state crypto_generichash_blake2b_state state; diff --git a/src/pow.h b/src/pow.h index 30d0f5e63b7..e3cf822d8dd 100644 --- a/src/pow.h +++ b/src/pow.h @@ -22,7 +22,7 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg, const Consensus::Params&); /** Check whether the Equihash solution in a block header is valid */ -bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams&); +bool CheckEquihashSolution(const CBlockHeader *pblock, const Consensus::Params&); /** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */ bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&); diff --git a/src/rest.cpp b/src/rest.cpp index 4f92bbb0af7..e70ce517aac 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -3,6 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "chainparams.h" #include "primitives/block.h" #include "primitives/transaction.h" #include "main.h" @@ -214,7 +215,7 @@ static bool rest_block(HTTPRequest* req, if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not available (pruned data)"); - if (!ReadBlockFromDisk(block, pblockindex)) + if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found"); } @@ -355,7 +356,7 @@ static bool rest_tx(HTTPRequest* req, const std::string& strURIPart) CTransaction tx; uint256 hashBlock = uint256(); - if (!GetTransaction(hash, tx, hashBlock, true)) + if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true)) return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found"); CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 005779e0600..1e0a67fc593 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -444,7 +444,7 @@ UniValue getblockdeltas(const UniValue& params, bool fHelp) if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); - if(!ReadBlockFromDisk(block, pblockindex)) + if(!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); return blockToDeltasJSON(block, pblockindex); @@ -703,7 +703,7 @@ UniValue getblock(const UniValue& params, bool fHelp) if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); - if(!ReadBlockFromDisk(block, pblockindex)) + if(!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); if (verbosity == 0) @@ -860,7 +860,7 @@ UniValue verifychain(const UniValue& params, bool fHelp) if (params.size() > 1) nCheckDepth = params[1].get_int(); - return CVerifyDB().VerifyDB(pcoinsTip, nCheckLevel, nCheckDepth); + return CVerifyDB().VerifyDB(Params(), pcoinsTip, nCheckLevel, nCheckDepth); } /** Implementation of IsSuperMajority with better feedback */ @@ -1186,11 +1186,11 @@ UniValue invalidateblock(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); CBlockIndex* pblockindex = mapBlockIndex[hash]; - InvalidateBlock(state, pblockindex); + InvalidateBlock(state, Params(), pblockindex); } if (state.IsValid()) { - ActivateBestChain(state); + ActivateBestChain(state, Params()); } if (!state.IsValid()) { @@ -1229,7 +1229,7 @@ UniValue reconsiderblock(const UniValue& params, bool fHelp) } if (state.IsValid()) { - ActivateBestChain(state); + ActivateBestChain(state, Params()); } if (!state.IsValid()) { diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index cebf79cb499..701664ff768 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -17,8 +17,8 @@ using namespace std; class CRPCConvertParam { public: - std::string methodName; //! method whose params want conversion - int paramIdx; //! 0-based idx of param to convert + std::string methodName; //!< method whose params want conversion + int paramIdx; //!< 0-based idx of param to convert }; static const CRPCConvertParam vRPCConvertParams[] = diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 45502541f09..97fd41228bf 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -197,11 +197,11 @@ UniValue generate(const UniValue& params, bool fHelp) } unsigned int nExtraNonce = 0; UniValue blockHashes(UniValue::VARR); - unsigned int n = Params().EquihashN(); - unsigned int k = Params().EquihashK(); + unsigned int n = Params().GetConsensus().nEquihashN; + unsigned int k = Params().GetConsensus().nEquihashK; while (nHeight < nHeightEnd) { - std::unique_ptr pblocktemplate(CreateNewBlock(coinbaseScript->reserveScript)); + std::unique_ptr pblocktemplate(CreateNewBlock(Params(), coinbaseScript->reserveScript)); if (!pblocktemplate.get()) throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block"); CBlock *pblock = &pblocktemplate->block; @@ -249,7 +249,7 @@ UniValue generate(const UniValue& params, bool fHelp) } endloop: CValidationState state; - if (!ProcessNewBlock(state, NULL, pblock, true, NULL)) + if (!ProcessNewBlock(state, Params(), NULL, pblock, true, NULL)) throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted"); ++nHeight; blockHashes.push_back(pblock->GetHash().GetHex()); @@ -539,7 +539,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) if (block.hashPrevBlock != pindexPrev->GetBlockHash()) return "inconclusive-not-best-prevblk"; CValidationState state; - TestBlockValidity(state, block, pindexPrev, false, true); + TestBlockValidity(state, Params(), block, pindexPrev, false, true); return BIP22ValidationResult(state); } } @@ -550,7 +550,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) if (vNodes.empty()) throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "ZERO is not connected!"); - if (IsInitialBlockDownload()) + if (IsInitialBlockDownload(Params())) throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "ZERO is downloading blocks..."); static unsigned int nTransactionsUpdatedLast; @@ -630,7 +630,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) if (!coinbaseScript->reserveScript.size()) throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available (mining requires a wallet or -mineraddress)"); - pblocktemplate = CreateNewBlock(coinbaseScript->reserveScript); + pblocktemplate = CreateNewBlock(Params(), coinbaseScript->reserveScript); if (!pblocktemplate) throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); @@ -836,7 +836,7 @@ UniValue submitblock(const UniValue& params, bool fHelp) CValidationState state; submitblock_StateCatcher sc(block.GetHash()); RegisterValidationInterface(&sc); - bool fAccepted = ProcessNewBlock(state, NULL, &block, true, NULL); + bool fAccepted = ProcessNewBlock(state, Params(), NULL, &block, true, NULL); UnregisterValidationInterface(&sc); if (fBlockPresent) { diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 98ffd7e1c82..39dedfebc62 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -150,7 +150,7 @@ UniValue TxShieldedOutputsToJSON(const CTransaction& tx) { void TxToJSONExpanded(const CTransaction& tx, const uint256 hashBlock, UniValue& entry, int nHeight = 0, int nConfirmations = 0, int nBlockTime = 0) { - uint256 txid = tx.GetHash(); + const uint256 txid = tx.GetHash(); entry.push_back(Pair("txid", txid.GetHex())); entry.push_back(Pair("overwintered", tx.fOverwintered)); entry.push_back(Pair("version", tx.nVersion)); @@ -180,13 +180,13 @@ void TxToJSONExpanded(const CTransaction& tx, const uint256 hashBlock, UniValue& if (GetSpentIndex(spentKey, spentInfo)) { in.push_back(Pair("value", ValueFromAmount(spentInfo.satoshis))); in.push_back(Pair("valueZat", spentInfo.satoshis)); - if (spentInfo.addressType == 1) { - in.push_back(Pair("address", EncodeDestination(CKeyID(spentInfo.addressHash)))); - } else if (spentInfo.addressType == 2) { - in.push_back(Pair("address", EncodeDestination(CScriptID(spentInfo.addressHash)))); + + boost::optional dest = + DestFromAddressHash(spentInfo.addressType, spentInfo.addressHash); + if (dest) { + in.push_back(Pair("address", EncodeDestination(*dest))); } } - } in.push_back(Pair("sequence", (int64_t)txin.nSequence)); vin.push_back(in); @@ -211,7 +211,6 @@ void TxToJSONExpanded(const CTransaction& tx, const uint256 hashBlock, UniValue& out.push_back(Pair("spentIndex", (int)spentInfo.inputIndex)); out.push_back(Pair("spentHeight", spentInfo.blockHeight)); } - vout.push_back(out); } entry.push_back(Pair("vout", vout)); @@ -400,14 +399,14 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp) + HelpExampleRpc("getrawtransaction", "\"mytxid\", 1") ); - //LOCK(cs_main); - uint256 hash = ParseHashV(params[0], "parameter 1"); bool fVerbose = false; if (params.size() > 1) fVerbose = (params[1].get_int() != 0); + LOCK(cs_main); + CTransaction tx; uint256 hashBlock; int nHeight = 0; @@ -416,7 +415,7 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp) { LOCK(cs_main); - if (!GetTransaction(hash, tx, hashBlock, true)) + if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction"); BlockMap::iterator mi = mapBlockIndex.find(hashBlock); @@ -502,7 +501,7 @@ UniValue gettxoutproof(const UniValue& params, bool fHelp) if (pblockindex == NULL) { CTransaction tx; - if (!GetTransaction(oneTxid, tx, hashBlock, false) || hashBlock.IsNull()) + if (!GetTransaction(oneTxid, tx, Params().GetConsensus(), hashBlock, false) || hashBlock.IsNull()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not yet in block"); if (!mapBlockIndex.count(hashBlock)) throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction index corrupt"); @@ -510,7 +509,7 @@ UniValue gettxoutproof(const UniValue& params, bool fHelp) } CBlock block; - if(!ReadBlockFromDisk(block, pblockindex)) + if(!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); unsigned int ntxFound = 0; diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index ec1ac52551f..6719443d0b7 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -965,12 +965,12 @@ namespace { */ class CTransactionSignatureSerializer { private: - const CTransaction &txTo; //! reference to the spending transaction (the one being serialized) - const CScript &scriptCode; //! output script being consumed - const unsigned int nIn; //! input index of txTo being signed - const bool fAnyoneCanPay; //! whether the hashtype has the SIGHASH_ANYONECANPAY flag set - const bool fHashSingle; //! whether the hashtype is SIGHASH_SINGLE - const bool fHashNone; //! whether the hashtype is SIGHASH_NONE + const CTransaction& txTo; //!< reference to the spending transaction (the one being serialized) + const CScript& scriptCode; //!< output script being consumed + const unsigned int nIn; //!< input index of txTo being signed + const bool fAnyoneCanPay; //!< whether the hashtype has the SIGHASH_ANYONECANPAY flag set + const bool fHashSingle; //!< whether the hashtype is SIGHASH_SINGLE + const bool fHashNone; //!< whether the hashtype is SIGHASH_NONE public: CTransactionSignatureSerializer(const CTransaction &txToIn, const CScript &scriptCodeIn, unsigned int nInIn, int nHashTypeIn) : diff --git a/src/script/script.cpp b/src/script/script.cpp index a365058349d..7ce08b475ad 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -267,14 +267,14 @@ bool CScript::IsPushOnly() const } // insightexplorer -int CScript::Type() const +CScript::ScriptType CScript::GetType() const { if (this->IsPayToPublicKeyHash()) - return 1; + return CScript::P2PKH; if (this->IsPayToScriptHash()) - return 2; + return CScript::P2SH; // We don't know this script - return 0; + return CScript::UNKNOWN; } // insightexplorer diff --git a/src/script/script.h b/src/script/script.h index 4f8a588ec81..c3cd1ca8a2c 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -569,10 +569,15 @@ class CScript : public CScriptBase bool IsNormalPaymentScript() const; + // insightexplorer, there may be more script types in the future + enum ScriptType : int { + UNKNOWN = 0, + P2PKH = 1, + P2SH = 2, + }; bool IsPayToPublicKeyHash() const; bool IsPayToScriptHash() const; - - int Type() const; + ScriptType GetType() const; uint160 AddressHash() const; /** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */ diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 88cde36988a..12df6d8556a 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -320,3 +320,16 @@ CScript GetScriptForMultisig(int nRequired, const std::vector& keys) bool IsValidDestination(const CTxDestination& dest) { return dest.which() != 0; } + +// insightexplorer +boost::optional DestFromAddressHash(int scriptType, uint160& addressHash) +{ + switch (scriptType) { + case CScript::P2PKH: + return CTxDestination(CKeyID(addressHash)); + case CScript::P2SH: + return CTxDestination(CScriptID(addressHash)); + default: + return boost::none; + } +} diff --git a/src/script/standard.h b/src/script/standard.h index fdb02f7c74f..40b3c329d6c 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -25,7 +25,7 @@ class CScriptID : public uint160 CScriptID(const uint160& in) : uint160(in) {} }; -static const unsigned int MAX_OP_RETURN_RELAY = 80; //! bytes +static const unsigned int MAX_OP_RETURN_RELAY = 80; //!< bytes extern unsigned nMaxDatacarrierBytes; /** @@ -96,4 +96,7 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std:: CScript GetScriptForDestination(const CTxDestination& dest); CScript GetScriptForMultisig(int nRequired, const std::vector& keys); +// insightexplorer +boost::optional DestFromAddressHash(int scriptType, uint160& addressHash); + #endif // BITCOIN_SCRIPT_STANDARD_H diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index a0b49b4ddc2..18acf1f67c5 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -383,7 +383,7 @@ BOOST_AUTO_TEST_CASE(AlertDisablesRPC) mapAlerts.clear(); } -static bool falseFunc() { return false; } +static bool falseFunc(const CChainParams&) { return false; } BOOST_AUTO_TEST_CASE(PartitionAlert) { diff --git a/src/test/checkblock_tests.cpp b/src/test/checkblock_tests.cpp index c813c9af9ae..dc906282034 100644 --- a/src/test/checkblock_tests.cpp +++ b/src/test/checkblock_tests.cpp @@ -58,7 +58,7 @@ BOOST_AUTO_TEST_CASE(May15) // After May 15'th, big blocks are OK: forkingBlock.nTime = tMay15; // Invalidates PoW auto verifier = libzcash::ProofVerifier::Strict(); - BOOST_CHECK(CheckBlock(forkingBlock, state, verifier, false, false)); + BOOST_CHECK(CheckBlock(forkingBlock, state, Params(), verifier, false, false)); } SetMockTime(0); diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 3f6a0af77ea..23e7634abbd 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -138,6 +138,7 @@ struct { // NOTE: These tests rely on CreateNewBlock doing its own self-validation! BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) { + const CChainParams& chainparams = Params(CBaseChainParams::MAIN); CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG; CBlockTemplate *pblocktemplate; CMutableTransaction tx,tx2; @@ -158,7 +159,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) for (unsigned int i = 0; i < sizeof(blockinfo)/sizeof(*blockinfo); ++i) { // Simple block creation, nothing special yet: - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); CBlock *pblock = &pblocktemplate->block; // pointer for convenience pblock->nVersion = 4; @@ -182,8 +183,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) /* { arith_uint256 try_nonce(0); - unsigned int n = Params().EquihashN(); - unsigned int k = Params().EquihashK(); + unsigned int n = Params().GetConsensus().nEquihashN; + unsigned int k = Params().GetConsensus().nEquihashK; // Hash state crypto_generichash_blake2b_state eh_state; @@ -264,7 +265,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) pblock->hashFinalSaplingRoot = uint256(); CValidationState state; - BOOST_CHECK(ProcessNewBlock(state, NULL, pblock, true, NULL)); + BOOST_CHECK(ProcessNewBlock(state, chainparams, NULL, pblock, true, NULL)); BOOST_CHECK_MESSAGE(state.IsValid(), state.GetRejectReason()); pblock->hashPrevBlock = pblock->GetHash(); @@ -273,7 +274,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) } // Just to make sure we can still make simple blocks - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; // block sigops > limit: 1000 CHECKMULTISIG + 1 @@ -292,7 +293,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); tx.vin[0].prevout.hash = hash; } - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; mempool.clear(); @@ -313,14 +314,14 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); tx.vin[0].prevout.hash = hash; } - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; mempool.clear(); // orphan in mempool hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Time(GetTime()).FromTx(tx)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; mempool.clear(); @@ -338,7 +339,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue = 49000LL; hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; mempool.clear(); @@ -349,7 +350,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue = 0; hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; mempool.clear(); @@ -367,7 +368,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue -= 10000; hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; mempool.clear(); @@ -381,17 +382,17 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].scriptPubKey = CScript() << OP_2; hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; mempool.clear(); // subsidy changing int nHeight = chainActive.Height(); chainActive.Tip()->nHeight = 209999; - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; chainActive.Tip()->nHeight = 210000; - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); delete pblocktemplate; chainActive.Tip()->nHeight = nHeight; @@ -423,7 +424,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(true).FromTx(tx2)); BOOST_CHECK(!CheckFinalTx(tx2, LOCKTIME_MEDIAN_TIME_PAST)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); // Neither tx should have made it into the template. BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 1); @@ -438,7 +439,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) //BOOST_CHECK(CheckFinalTx(tx)); //BOOST_CHECK(CheckFinalTx(tx2)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey)); BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 2); delete pblocktemplate; diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index 97240f4894c..d02663fd02a 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -1302,7 +1302,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_taddr_to_sapling) pwalletMain->AddToWallet(wtx, true, NULL); // Context that z_sendmany requires - auto builder = TransactionBuilder(consensusParams, nextBlockHeight, pwalletMain); + auto builder = TransactionBuilder(consensusParams, nextBlockHeight, expiryDelta, pwalletMain); mtx = CreateNewContextualCMutableTransaction(consensusParams, nextBlockHeight); std::vector recipients = { SendManyRecipient(zaddr1, 1 * COIN, "ABCD") }; diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index fac63dbf564..80e293675a1 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -95,7 +95,7 @@ BOOST_DATA_TEST_CASE(sign, boost::unit_test::data::xrange(static_cast(Conse txFrom.vout[i+4].scriptPubKey = standardScripts[i]; txFrom.vout[i+4].nValue = COIN; } - BOOST_CHECK(IsStandardTx(txFrom, reason)); + BOOST_CHECK(IsStandardTx(txFrom, reason, Params())); CMutableTransaction txTo[8]; // Spending transactions for (int i = 0; i < 8; i++) @@ -198,7 +198,7 @@ BOOST_DATA_TEST_CASE(set, boost::unit_test::data::xrange(static_cast(Consen txFrom.vout[i].scriptPubKey = outer[i]; txFrom.vout[i].nValue = CENT; } - BOOST_CHECK(IsStandardTx(txFrom, reason)); + BOOST_CHECK(IsStandardTx(txFrom, reason, Params())); CMutableTransaction txTo[4]; // Spending transactions for (int i = 0; i < 4; i++) @@ -216,7 +216,7 @@ BOOST_DATA_TEST_CASE(set, boost::unit_test::data::xrange(static_cast(Consen for (int i = 0; i < 4; i++) { BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL, consensusBranchId), strprintf("SignSignature %d", i)); - BOOST_CHECK_MESSAGE(IsStandardTx(txTo[i], reason), strprintf("txTo[%d].IsStandard", i)); + BOOST_CHECK_MESSAGE(IsStandardTx(txTo[i], reason, Params()), strprintf("txTo[%d].IsStandard", i)); } } diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 10a86c54ffa..fa74031a1eb 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -87,6 +87,7 @@ BasicTestingSetup::~BasicTestingSetup() TestingSetup::TestingSetup() { + const CChainParams& chainparams = Params(); // Ideally we'd move all the RPC tests to the functional testing framework // instead of unit tests, but for now we need these here. RegisterAllCoreRPCCommands(tableRPC); @@ -105,7 +106,7 @@ TestingSetup::TestingSetup() pblocktree = new CBlockTreeDB(1 << 20, true); pcoinsdbview = new CCoinsViewDB(1 << 23, true); pcoinsTip = new CCoinsViewCache(pcoinsdbview); - InitBlockIndex(); + InitBlockIndex(chainparams); #ifdef ENABLE_WALLET bool fFirstRun; pwalletMain = new CWallet("wallet.zero"); diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 88f390c1774..4219e01f4ce 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -491,7 +491,7 @@ void test_simple_joinsplit_invalidity(uint32_t consensusBranchId, CMutableTransa jsdesc->nullifiers[1] = GetRandHash(); BOOST_CHECK(CheckTransactionWithoutProofVerification(newTx, state)); - BOOST_CHECK(!ContextualCheckTransaction(newTx, state, 0, 100)); + BOOST_CHECK(!ContextualCheckTransaction(newTx, state, Params(), 0, 100)); BOOST_CHECK(state.GetRejectReason() == "bad-txns-invalid-joinsplit-signature"); // Empty output script. @@ -505,7 +505,7 @@ void test_simple_joinsplit_invalidity(uint32_t consensusBranchId, CMutableTransa ) == 0); BOOST_CHECK(CheckTransactionWithoutProofVerification(newTx, state)); - BOOST_CHECK(ContextualCheckTransaction(newTx, state, 0, 100)); + BOOST_CHECK(ContextualCheckTransaction(newTx, state, Params(), 0, 100)); } { // Ensure that values within the joinsplit are well-formed. @@ -748,6 +748,7 @@ BOOST_AUTO_TEST_CASE(test_big_overwinter_transaction) { BOOST_AUTO_TEST_CASE(test_IsStandard) { LOCK(cs_main); + auto chainparams = Params(); CBasicKeyStore keystore; CCoinsView coinsDummy; CCoinsViewCache coins(&coinsDummy); @@ -765,48 +766,49 @@ BOOST_AUTO_TEST_CASE(test_IsStandard) t.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID()); string reason; - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(t, reason, chainparams)); t.vout[0].nValue = 53; // dust - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(t, reason, chainparams)); t.vout[0].nValue = 2730; // not dust - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(t, reason, chainparams)); t.vout[0].scriptPubKey = CScript() << OP_1; - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(t, reason, chainparams)); // 80-byte TX_NULL_DATA (standard) t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"); - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(t, reason, chainparams)); // 81-byte TX_NULL_DATA (non-standard) t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3800"); - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(t, reason, chainparams)); // TX_NULL_DATA w/o PUSHDATA t.vout.resize(1); t.vout[0].scriptPubKey = CScript() << OP_RETURN; - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(t, reason, chainparams)); // Only one TX_NULL_DATA permitted in all cases t.vout.resize(2); t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"); t.vout[1].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"); - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(t, reason, chainparams)); t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"); t.vout[1].scriptPubKey = CScript() << OP_RETURN; - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(t, reason, chainparams)); t.vout[0].scriptPubKey = CScript() << OP_RETURN; t.vout[1].scriptPubKey = CScript() << OP_RETURN; - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(t, reason, chainparams)); } BOOST_AUTO_TEST_CASE(test_IsStandardV2) { LOCK(cs_main); + auto chainparams = Params(); CBasicKeyStore keystore; CCoinsView coinsDummy; CCoinsViewCache coins(&coinsDummy); @@ -826,33 +828,33 @@ BOOST_AUTO_TEST_CASE(test_IsStandardV2) string reason; // A v2 transaction with no JoinSplits is still standard. t.nVersion = 2; - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(t, reason, chainparams)); // ... and with one JoinSplit. t.vjoinsplit.push_back(JSDescription()); - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(t, reason, chainparams)); // ... and when that JoinSplit takes from a transparent input. JSDescription *jsdesc = &t.vjoinsplit[0]; jsdesc->vpub_old = 10*CENT; t.vout[0].nValue -= 10*CENT; - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(t, reason, chainparams)); // A v2 transaction with JoinSplits but no transparent inputs is standard. jsdesc->vpub_old = 0; jsdesc->vpub_new = 100*CENT; t.vout[0].nValue = 90*CENT; t.vin.resize(0); - BOOST_CHECK(IsStandardTx(t, reason)); + BOOST_CHECK(IsStandardTx(t, reason, chainparams)); // v2 transactions can still be non-standard for the same reasons as v1. t.vout[0].nValue = 53; // dust - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(t, reason, chainparams)); // v3 is not standard. t.nVersion = 3; t.vout[0].nValue = 90*CENT; - BOOST_CHECK(!IsStandardTx(t, reason)); + BOOST_CHECK(!IsStandardTx(t, reason, chainparams)); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/transaction_builder.cpp b/src/transaction_builder.cpp index fbe1043a5f6..687c1a42024 100644 --- a/src/transaction_builder.cpp +++ b/src/transaction_builder.cpp @@ -50,6 +50,7 @@ std::string TransactionBuilderResult::GetError() { TransactionBuilder::TransactionBuilder( const Consensus::Params& consensusParams, int nHeight, + int nExpiryDelta, CKeyStore* keystore, ZCJoinSplit* sproutParams, CCoinsViewCache* coinsView, @@ -61,7 +62,7 @@ TransactionBuilder::TransactionBuilder( coinsView(coinsView), cs_coinsView(cs_coinsView) { - mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight); + mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight, nExpiryDelta); } // This exception is thrown in certain scenarios when building JoinSplits fails. @@ -524,6 +525,10 @@ void TransactionBuilder::CreateJSDescriptions() // Update tree state with previous joinsplit SproutMerkleTree tree; { + // assert that coinsView is not null + assert(coinsView); + // We do not check cs_coinView because we do not set this in testing + // assert(cs_coinsView); LOCK(cs_coinsView); auto it = intermediates.find(prevJoinSplit.anchor); if (it != intermediates.end()) { @@ -673,7 +678,7 @@ void TransactionBuilder::CreateJSDescription( std::array& inputMap, std::array& outputMap) { - LogPrint("zrpcunsafe", "%s: creating joinsplit at index %d (vpub_old=%s, vpub_new=%s, in[0]=%s, in[1]=%s, out[0]=%s, out[1]=%s)\n", + LogPrint("zrpcunsafe", "CreateJSDescription: creating joinsplit at index %d (vpub_old=%s, vpub_new=%s, in[0]=%s, in[1]=%s, out[0]=%s, out[1]=%s)\n", mtx.vjoinsplit.size(), FormatMoney(vpub_old), FormatMoney(vpub_new), FormatMoney(vjsin[0].note.value()), FormatMoney(vjsin[1].note.value()), diff --git a/src/transaction_builder.h b/src/transaction_builder.h index ee3c4e7ae45..46f38481ecc 100644 --- a/src/transaction_builder.h +++ b/src/transaction_builder.h @@ -95,6 +95,7 @@ class TransactionBuilder TransactionBuilder( const Consensus::Params& consensusParams, int nHeight, + int nExpiryDelta, CKeyStore* keyStore = nullptr, ZCJoinSplit* sproutParams = nullptr, CCoinsViewCache* coinsView = nullptr, diff --git a/src/txdb.cpp b/src/txdb.cpp index f14dd565884..4b6dfcd3649 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -456,17 +456,7 @@ bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) { return true; } -bool CBlockTreeDB::blockOnchainActive(const uint256 &hash) { - CBlockIndex* pblockindex = mapBlockIndex[hash]; - - if (!chainActive.Contains(pblockindex)) { - return false; - } - - return true; -} - -bool CBlockTreeDB::LoadBlockIndexGuts() +bool CBlockTreeDB::LoadBlockIndexGuts(boost::function insertBlockIndex) { boost::scoped_ptr pcursor(NewIterator()); @@ -480,8 +470,8 @@ bool CBlockTreeDB::LoadBlockIndexGuts() CDiskBlockIndex diskindex; if (pcursor->GetValue(diskindex)) { // Construct block index object - CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash()); - pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev); + CBlockIndex* pindexNew = insertBlockIndex(diskindex.GetBlockHash()); + pindexNew->pprev = insertBlockIndex(diskindex.hashPrev); pindexNew->nHeight = diskindex.nHeight; pindexNew->nFile = diskindex.nFile; pindexNew->nDataPos = diskindex.nDataPos; diff --git a/src/txdb.h b/src/txdb.h index e7f2515f9b0..c079a711a42 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -8,15 +8,16 @@ #include "coins.h" #include "dbwrapper.h" +#include "chain.h" #include #include #include #include -class CBlockFileInfo; +#include + class CBlockIndex; -struct CDiskTxPos; // START insightexplorer struct CAddressUnspentKey; @@ -45,6 +46,31 @@ static const int64_t nMaxDbCache = sizeof(void*) > 4 ? 16384 : 1024; //! min. -dbcache in (MiB) static const int64_t nMinDbCache = 4; +struct CDiskTxPos : public CDiskBlockPos +{ + unsigned int nTxOffset; // after header + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(*(CDiskBlockPos*)this); + READWRITE(VARINT(nTxOffset)); + } + + CDiskTxPos(const CDiskBlockPos &blockIn, unsigned int nTxOffsetIn) : CDiskBlockPos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) { + } + + CDiskTxPos() { + SetNull(); + } + + void SetNull() { + CDiskBlockPos::SetNull(); + nTxOffset = 0; + } +}; + /** CCoinsView backed by the coin database (chainstate/) */ class CCoinsViewDB : public CCoinsView { @@ -108,8 +134,7 @@ class CBlockTreeDB : public CDBWrapper bool WriteFlag(const std::string &name, bool fValue); bool ReadFlag(const std::string &name, bool &fValue); - bool LoadBlockIndexGuts(); - bool blockOnchainActive(const uint256 &hash); + bool LoadBlockIndexGuts(boost::function insertBlockIndex); }; #endif // BITCOIN_TXDB_H diff --git a/src/txmempool.h b/src/txmempool.h index 7efd53d8ad4..7b98b9dad26 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -43,17 +43,17 @@ class CTxMemPoolEntry { private: CTransaction tx; - CAmount nFee; //! Cached to avoid expensive parent-transaction lookups - size_t nTxSize; //! ... and avoid recomputing tx size - size_t nModSize; //! ... and modified size for priority - size_t nUsageSize; //! ... and total memory usage - CFeeRate feeRate; //! ... and fee per kB - int64_t nTime; //! Local time when entering the mempool - double dPriority; //! Priority when entering the mempool - unsigned int nHeight; //! Chain height when entering the mempool - bool hadNoDependencies; //! Not dependent on any other txs when it entered the mempool - bool spendsCoinbase; //! keep track of transactions that spend a coinbase - uint32_t nBranchId; //! Branch ID this transaction is known to commit to, cached for efficiency + CAmount nFee; //!< Cached to avoid expensive parent-transaction lookups + size_t nTxSize; //!< ... and avoid recomputing tx size + size_t nModSize; //!< ... and modified size for priority + size_t nUsageSize; //!< ... and total memory usage + CFeeRate feeRate; //!< ... and fee per kB + int64_t nTime; //!< Local time when entering the mempool + double dPriority; //!< Priority when entering the mempool + unsigned int nHeight; //!< Chain height when entering the mempool + bool hadNoDependencies; //!< Not dependent on any other txs when it entered the mempool + bool spendsCoinbase; //!< keep track of transactions that spend a coinbase + uint32_t nBranchId; //!< Branch ID this transaction is known to commit to, cached for efficiency public: CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee, @@ -126,12 +126,12 @@ class CInPoint class CTxMemPool { private: - uint32_t nCheckFrequency; //! Value n means that n times in 2^32 we check. + uint32_t nCheckFrequency; //!< Value n means that n times in 2^32 we check. unsigned int nTransactionsUpdated; CBlockPolicyEstimator* minerPolicyEstimator; - uint64_t totalTxSize = 0; //! sum of all mempool tx' byte sizes - uint64_t cachedInnerUsage; //! sum of dynamic memory usage of all the map elements (NOT the maps themselves) + uint64_t totalTxSize = 0; //!< sum of all mempool tx' byte sizes + uint64_t cachedInnerUsage; //!< sum of dynamic memory usage of all the map elements (NOT the maps themselves) std::map mapSproutNullifiers; std::map mapSaplingNullifiers; diff --git a/src/utiltest.cpp b/src/utiltest.cpp index 8eb23249f27..e62c5611be3 100644 --- a/src/utiltest.cpp +++ b/src/utiltest.cpp @@ -232,7 +232,7 @@ CWalletTx GetValidSaplingReceive(const Consensus::Params& consensusParams, auto fvk = sk.expsk.full_viewing_key(); auto pa = sk.DefaultAddress(); - auto builder = TransactionBuilder(consensusParams, 1, &keyStore); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keyStore); builder.SetFee(0); builder.AddTransparentInput(COutPoint(), scriptPubKey, value); builder.AddSaplingOutput(fvk.ovk, pa, value, {}); diff --git a/src/utiltime.cpp b/src/utiltime.cpp index f1a408a31d4..5d0b284fdf8 100644 --- a/src/utiltime.cpp +++ b/src/utiltime.cpp @@ -15,7 +15,7 @@ using namespace std; -static int64_t nMockTime = 0; //! For unit testing +static int64_t nMockTime = 0; //!< For unit testing int64_t GetTime() { diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index 78a245c31d2..8e0ecc77bde 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -645,7 +645,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() wtxHeight = mapBlockIndex[wtx.hashBlock]->nHeight; wtxDepth = wtx.GetDepthInMainChain(); } - LogPrint("zrpcunsafe", "%s: spending note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, height=%d, confirmations=%d)\n", + LogPrint("zrpcunsafe", "%s: spending note (txid=%s, vjoinsplit=%d, jsoutindex=%d, amount=%s, height=%d, confirmations=%d)\n", getId(), jso.hash.ToString().substr(0, 10), jso.js, diff --git a/src/wallet/asyncrpcoperation_saplingmigration.cpp b/src/wallet/asyncrpcoperation_saplingmigration.cpp index ab44bf76077..d99bc539fe0 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.cpp +++ b/src/wallet/asyncrpcoperation_saplingmigration.cpp @@ -9,9 +9,11 @@ #include "tinyformat.h" #include "transaction_builder.h" #include "util.h" +#include "utilmoneystr.h" #include "wallet.h" const CAmount FEE = 10000; +const int MIGRATION_EXPIRY_DELTA = 450; AsyncRPCOperation_saplingmigration::AsyncRPCOperation_saplingmigration(int targetHeight) : targetHeight_(targetHeight) {} @@ -66,7 +68,8 @@ void AsyncRPCOperation_saplingmigration::main() { } bool AsyncRPCOperation_saplingmigration::main_impl() { - std::vector sproutEntries; + LogPrint("zrpcunsafe", "%s: Beginning AsyncRPCOperation_saplingmigration.\n", getId()); + std::vector sproutEntries; std::vector saplingEntries; { LOCK2(cs_main, pwalletMain->cs_wallet); @@ -76,12 +79,14 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, "", 11); } CAmount availableFunds = 0; - for (const CSproutNotePlaintextEntry& sproutEntry : sproutEntries) { - availableFunds = sproutEntry.plaintext.value(); + for (const SproutNoteEntry& sproutEntry : sproutEntries) { + availableFunds += sproutEntry.note.value(); } // If the remaining amount to be migrated is less than 0.01 ZEC, end the migration. if (availableFunds < CENT) { - setMigrationResult(0); + LogPrint("zrpcunsafe", "%s: Available Sprout balance (%s) less than required minimum (%s). Stopping.\n", + getId(), FormatMoney(availableFunds), FormatMoney(CENT)); + setMigrationResult(0, 0, std::vector()); return true; } @@ -92,20 +97,33 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { // Up to the limit of 5, as many transactions are sent as are needed to migrate the remaining funds int numTxCreated = 0; + CAmount amountMigrated = 0; + std::vector migrationTxIds; int noteIndex = 0; + CCoinsViewCache coinsView(pcoinsTip); do { CAmount amountToSend = chooseAmount(availableFunds); - auto builder = TransactionBuilder(consensusParams, targetHeight_, pwalletMain, pzcashParams); - std::vector fromNotes; + auto builder = TransactionBuilder(consensusParams, targetHeight_, MIGRATION_EXPIRY_DELTA, pwalletMain, pzcashParams, + &coinsView, &cs_main); + LogPrint("zrpcunsafe", "%s: Beginning creating transaction with Sapling output amount=%s\n", getId(), FormatMoney(amountToSend - FEE)); + std::vector fromNotes; CAmount fromNoteAmount = 0; while (fromNoteAmount < amountToSend) { auto sproutEntry = sproutEntries[noteIndex++]; fromNotes.push_back(sproutEntry); - fromNoteAmount += sproutEntry.plaintext.value(); + fromNoteAmount += sproutEntry.note.value(); } availableFunds -= fromNoteAmount; - for (const CSproutNotePlaintextEntry& sproutEntry : fromNotes) { - libzcash::SproutNote sproutNote = sproutEntry.plaintext.note(sproutEntry.address); + for (const SproutNoteEntry& sproutEntry : fromNotes) { + std::string data(sproutEntry.memo.begin(), sproutEntry.memo.end()); + LogPrint("zrpcunsafe", "%s: Adding Sprout note input (txid=%s, vjoinsplit=%d, jsoutindex=%d, amount=%s, memo=%s)\n", + getId(), + sproutEntry.jsop.hash.ToString().substr(0, 10), + sproutEntry.jsop.js, + int(sproutEntry.jsop.n), // uint8_t + FormatMoney(sproutEntry.note.value()), + HexStr(data).substr(0, 10) + ); libzcash::SproutSpendingKey sproutSk; pwalletMain->GetSproutSpendingKey(sproutEntry.address, sproutSk); std::vector vOutPoints = {sproutEntry.jsop}; @@ -115,7 +133,7 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { uint256 inputAnchor; std::vector> vInputWitnesses; pwalletMain->GetSproutNoteWitnesses(vOutPoints, vInputWitnesses, inputAnchor); - builder.AddSproutInput(sproutSk, sproutNote, vInputWitnesses[0].get()); + builder.AddSproutInput(sproutSk, sproutEntry.note, vInputWitnesses[0].get()); } // The amount chosen *includes* the 0.0001 ZEC fee for this transaction, i.e. // the value of the Sapling output will be 0.0001 ZEC less. @@ -123,19 +141,30 @@ bool AsyncRPCOperation_saplingmigration::main_impl() { builder.AddSaplingOutput(ovkForShieldingFromTaddr(seed), migrationDestAddress, amountToSend - FEE); CTransaction tx = builder.Build().GetTxOrThrow(); if (isCancelled()) { + LogPrint("zrpcunsafe", "%s: Canceled. Stopping.\n", getId()); break; } pwalletMain->AddPendingSaplingMigrationTx(tx); + LogPrint("zrpcunsafe", "%s: Added pending migration transaction with txid=%s\n", getId(), tx.GetHash().ToString()); ++numTxCreated; + amountMigrated += amountToSend - FEE; + migrationTxIds.push_back(tx.GetHash().ToString()); } while (numTxCreated < 5 && availableFunds > CENT); - setMigrationResult(numTxCreated); + LogPrint("zrpcunsafe", "%s: Created %d transactions with total Sapling output amount=%s\n", getId(), numTxCreated, FormatMoney(amountMigrated)); + setMigrationResult(numTxCreated, amountMigrated, migrationTxIds); return true; } -void AsyncRPCOperation_saplingmigration::setMigrationResult(int numTxCreated) { +void AsyncRPCOperation_saplingmigration::setMigrationResult(int numTxCreated, const CAmount& amountMigrated, const std::vector& migrationTxIds) { UniValue res(UniValue::VOBJ); res.push_back(Pair("num_tx_created", numTxCreated)); + res.push_back(Pair("amount_migrated", FormatMoney(amountMigrated))); + UniValue txIds(UniValue::VARR); + for (const std::string& txId : migrationTxIds) { + txIds.push_back(txId); + } + res.push_back(Pair("migration_txids", txIds)); set_result(res); } @@ -177,7 +206,7 @@ libzcash::SaplingPaymentAddress AsyncRPCOperation_saplingmigration::getMigration libzcash::SaplingExtendedSpendingKey xsk = m_32h_cth.Derive(0 | ZIP32_HARDENED_KEY_LIMIT); libzcash::SaplingPaymentAddress toAddress = xsk.DefaultAddress(); - + // Refactor: this is similar logic as in the visitor HaveSpendingKeyForPaymentAddress and is used elsewhere libzcash::SaplingIncomingViewingKey ivk; libzcash::SaplingFullViewingKey fvk; @@ -191,6 +220,10 @@ libzcash::SaplingPaymentAddress AsyncRPCOperation_saplingmigration::getMigration return toAddress; } +void AsyncRPCOperation_saplingmigration::cancel() { + set_state(OperationStatus::CANCELLED); +} + UniValue AsyncRPCOperation_saplingmigration::getStatus() const { UniValue v = AsyncRPCOperation::getStatus(); UniValue obj = v.get_obj(); diff --git a/src/wallet/asyncrpcoperation_saplingmigration.h b/src/wallet/asyncrpcoperation_saplingmigration.h index e077c8eca32..6e0c452f932 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.h +++ b/src/wallet/asyncrpcoperation_saplingmigration.h @@ -20,6 +20,8 @@ class AsyncRPCOperation_saplingmigration : public AsyncRPCOperation virtual void main(); + virtual void cancel(); + virtual UniValue getStatus() const; private: @@ -27,7 +29,7 @@ class AsyncRPCOperation_saplingmigration : public AsyncRPCOperation bool main_impl(); - void setMigrationResult(int numTxCreated); + void setMigrationResult(int numTxCreated, const CAmount& amountMigrated, const std::vector& migrationTxIds); CAmount chooseAmount(const CAmount& availableFunds); }; diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index b4fa9dc24f8..1f1392a55c9 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -784,7 +784,7 @@ bool AsyncRPCOperation_sendmany::main_impl() { wtxHeight = mapBlockIndex[wtx.hashBlock]->nHeight; wtxDepth = wtx.GetDepthInMainChain(); } - LogPrint("zrpcunsafe", "%s: spending note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, height=%d, confirmations=%d)\n", + LogPrint("zrpcunsafe", "%s: spending note (txid=%s, vjoinsplit=%d, jsoutindex=%d, amount=%s, height=%d, confirmations=%d)\n", getId(), jso.hash.ToString().substr(0, 10), jso.js, @@ -1029,7 +1029,7 @@ bool AsyncRPCOperation_sendmany::find_utxos(bool fAcceptCoinbase=false) { bool AsyncRPCOperation_sendmany::find_unspent_notes() { - std::vector sproutEntries; + std::vector sproutEntries; std::vector saplingEntries; { LOCK2(cs_main, pwalletMain->cs_wallet); @@ -1045,15 +1045,15 @@ bool AsyncRPCOperation_sendmany::find_unspent_notes() { saplingEntries.clear(); } - for (CSproutNotePlaintextEntry & entry : sproutEntries) { - z_sprout_inputs_.push_back(SendManyInputJSOP(entry.jsop, entry.plaintext.note(boost::get(frompaymentaddress_)), CAmount(entry.plaintext.value()))); - std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end()); - LogPrint("zrpcunsafe", "%s: found unspent Sprout note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, memo=%s)\n", + for (SproutNoteEntry & entry : sproutEntries) { + z_sprout_inputs_.push_back(SendManyInputJSOP(entry.jsop, entry.note, CAmount(entry.note.value()))); + std::string data(entry.memo.begin(), entry.memo.end()); + LogPrint("zrpcunsafe", "%s: found unspent Sprout note (txid=%s, vjoinsplit=%d, jsoutindex=%d, amount=%s, memo=%s)\n", getId(), entry.jsop.hash.ToString().substr(0, 10), entry.jsop.js, int(entry.jsop.n), // uint8_t - FormatMoney(entry.plaintext.value()), + FormatMoney(entry.note.value()), HexStr(data).substr(0, 10) ); } diff --git a/src/wallet/gtest/test_wallet.cpp b/src/wallet/gtest/test_wallet.cpp index eb11998970d..c4eecac32dc 100644 --- a/src/wallet/gtest/test_wallet.cpp +++ b/src/wallet/gtest/test_wallet.cpp @@ -188,7 +188,7 @@ TEST(WalletTests, FindUnspentSproutNotes) { EXPECT_FALSE(wallet.IsSproutSpent(nullifier)); // We currently have an unspent and unconfirmed note in the wallet (depth of -1) - std::vector sproutEntries; + std::vector sproutEntries; std::vector saplingEntries; wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 0); EXPECT_EQ(0, sproutEntries.size()); @@ -379,7 +379,7 @@ TEST(WalletTests, SetSaplingNoteAddrsInCWalletTx) { ASSERT_TRUE(nf); uint256 nullifier = nf.get(); - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); builder.AddSaplingSpend(expsk, note, anchor, witness); builder.AddSaplingOutput(fvk.ovk, pk, 50000, {}); builder.SetFee(0); @@ -506,7 +506,7 @@ TEST(WalletTests, FindMySaplingNotes) { auto testNote = GetTestSaplingNote(pa, 50000); // Generate transaction - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -638,7 +638,7 @@ TEST(WalletTests, GetConflictedSaplingNotes) { auto witness = saplingTree.witness(); // Generate tx to create output note B - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); builder.AddSaplingSpend(expsk, note, anchor, witness); builder.AddSaplingOutput(fvk.ovk, pk, 35000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -692,13 +692,13 @@ TEST(WalletTests, GetConflictedSaplingNotes) { anchor = saplingTree.root(); // Create transaction to spend note B - auto builder2 = TransactionBuilder(consensusParams, 2); + auto builder2 = TransactionBuilder(consensusParams, 2, expiryDelta); builder2.AddSaplingSpend(expsk, note2, anchor, spend_note_witness); builder2.AddSaplingOutput(fvk.ovk, pk, 20000, {}); auto tx2 = builder2.Build().GetTxOrThrow(); // Create conflicting transaction which also spends note B - auto builder3 = TransactionBuilder(consensusParams, 2); + auto builder3 = TransactionBuilder(consensusParams, 2, expiryDelta); builder3.AddSaplingSpend(expsk, note2, anchor, spend_note_witness); builder3.AddSaplingOutput(fvk.ovk, pk, 19999, {}); auto tx3 = builder3.Build().GetTxOrThrow(); @@ -785,7 +785,7 @@ TEST(WalletTests, SaplingNullifierIsSpent) { auto testNote = GetTestSaplingNote(pa, 50000); // Generate transaction - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -868,7 +868,7 @@ TEST(WalletTests, NavigateFromSaplingNullifierToNote) { auto testNote = GetTestSaplingNote(pa, 50000); // Generate transaction - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingOutput(fvk.ovk, pa, 25000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -996,7 +996,7 @@ TEST(WalletTests, SpentSaplingNoteIsFromMe) { auto witness = saplingTree.witness(); // Generate transaction, which sends funds to note B - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); builder.AddSaplingSpend(expsk, note, anchor, witness); builder.AddSaplingOutput(fvk.ovk, pk, 25000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -1066,7 +1066,7 @@ TEST(WalletTests, SpentSaplingNoteIsFromMe) { anchor = saplingTree.root(); // Create transaction to spend note B - auto builder2 = TransactionBuilder(consensusParams, 2); + auto builder2 = TransactionBuilder(consensusParams, 2, expiryDelta); builder2.AddSaplingSpend(expsk, note2, anchor, spend_note_witness); builder2.AddSaplingOutput(fvk.ovk, pk, 12500, {}); auto tx2 = builder2.Build().GetTxOrThrow(); @@ -1771,7 +1771,7 @@ TEST(WalletTests, UpdatedSaplingNoteData) { auto testNote = GetTestSaplingNote(pa, 50000); // Generate transaction - auto builder = TransactionBuilder(consensusParams, 1); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta); builder.AddSaplingSpend(expsk, testNote.note, testNote.tree.root(), testNote.tree.witness()); builder.AddSaplingOutput(fvk.ovk, pa2, 25000, {}); auto tx = builder.Build().GetTxOrThrow(); @@ -1912,7 +1912,7 @@ TEST(WalletTests, MarkAffectedSaplingTransactionsDirty) { // Generate shielding tx from transparent to Sapling // 0.0005 t-ZEC in, 0.0004 z-ZEC out, 0.0001 t-ZEC fee - auto builder = TransactionBuilder(consensusParams, 1, &keystore); + auto builder = TransactionBuilder(consensusParams, 1, expiryDelta, &keystore); builder.AddTransparentInput(COutPoint(), scriptPubKey, 50000); builder.AddSaplingOutput(fvk.ovk, pk, 40000, {}); auto tx1 = builder.Build().GetTxOrThrow(); @@ -1967,7 +1967,7 @@ TEST(WalletTests, MarkAffectedSaplingTransactionsDirty) { // Create a Sapling-only transaction // 0.0004 z-ZEC in, 0.00025 z-ZEC out, 0.0001 t-ZEC fee, 0.00005 z-ZEC change - auto builder2 = TransactionBuilder(consensusParams, 2); + auto builder2 = TransactionBuilder(consensusParams, 2, expiryDelta); builder2.AddSaplingSpend(expsk, note, anchor, witness); builder2.AddSaplingOutput(fvk.ovk, pk, 25000, {}); auto tx2 = builder2.Build().GetTxOrThrow(); diff --git a/src/wallet/rpcdisclosure.cpp b/src/wallet/rpcdisclosure.cpp index df35bb6ddf2..82d20b76ce2 100644 --- a/src/wallet/rpcdisclosure.cpp +++ b/src/wallet/rpcdisclosure.cpp @@ -82,7 +82,7 @@ UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp) uint256 hashBlock; // Check txid has been seen - if (!GetTransaction(hash, tx, hashBlock, true)) { + if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction"); } @@ -210,7 +210,7 @@ UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp) CTransaction tx; uint256 hashBlock; // Check if we have seen the transaction - if (!GetTransaction(hash, tx, hashBlock, true)) { + if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction"); } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 2366b584cce..38081206ae6 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2567,7 +2567,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp) UniValue results(UniValue::VARR); if (zaddrs.size() > 0) { - std::vector sproutEntries; + std::vector sproutEntries; std::vector saplingEntries; pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, zaddrs, nMinDepth, nMaxDepth, true, !fIncludeWatchonly, false); std::set> nullifierSet = pwalletMain->GetNullifiersForAddresses(zaddrs); @@ -2581,8 +2581,8 @@ UniValue z_listunspent(const UniValue& params, bool fHelp) bool hasSproutSpendingKey = pwalletMain->HaveSproutSpendingKey(boost::get(entry.address)); obj.push_back(Pair("spendable", hasSproutSpendingKey)); obj.push_back(Pair("address", EncodePaymentAddress(entry.address))); - obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value())))); - std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end()); + obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.note.value())))); + std::string data(entry.memo.begin(), entry.memo.end()); obj.push_back(Pair("memo", HexStr(data))); if (hasSproutSpendingKey) { obj.push_back(Pair("change", pwalletMain->IsNoteSproutChange(nullifierSet, entry.address, entry.jsop))); @@ -3273,12 +3273,12 @@ CAmount getBalanceTaddr(std::string transparentAddress, int minDepth, bool ignor CAmount getBalanceZaddr(std::string address, int minDepth, bool ignoreUnspendable) { CAmount balance = 0; - std::vector sproutEntries; + std::vector sproutEntries; std::vector saplingEntries; LOCK2(cs_main, pwalletMain->cs_wallet); pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, address, minDepth, true, ignoreUnspendable); for (auto & entry : sproutEntries) { - balance += CAmount(entry.plaintext.value()); + balance += CAmount(entry.note.value()); } for (auto & entry : saplingEntries) { balance += CAmount(entry.note.value()); @@ -3338,7 +3338,7 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp) } UniValue result(UniValue::VARR); - std::vector sproutEntries; + std::vector sproutEntries; std::vector saplingEntries; pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, fromaddress, nMinDepth, false, false); @@ -3349,11 +3349,11 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp) } if (boost::get(&zaddr) != nullptr) { - for (CSproutNotePlaintextEntry & entry : sproutEntries) { + for (SproutNoteEntry & entry : sproutEntries) { UniValue obj(UniValue::VOBJ); obj.push_back(Pair("txid", entry.jsop.hash.ToString())); - obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value())))); - std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end()); + obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.note.value())))); + std::string data(entry.memo.begin(), entry.memo.end()); obj.push_back(Pair("memo", HexStr(data))); obj.push_back(Pair("jsindex", entry.jsop.js)); obj.push_back(Pair("jsoutindex", entry.jsop.n)); @@ -3875,7 +3875,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) // Builder (used if Sapling addresses are involved) boost::optional builder; if (noSproutAddrs) { - builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, pwalletMain); + builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, expiryDelta, pwalletMain); } // Contextual transaction we will build on @@ -3908,7 +3908,7 @@ UniValue z_setmigration(const UniValue& params, bool fHelp) { "Sprout balance, this process may take several weeks. The migration works by sending, up to 5, as many\n" "transactions as possible whenever the blockchain reaches a height equal to 499 modulo 500. The transaction\n" "amounts are picked according to the random distribution specified in ZIP 308. The migration will end once\n" - "the wallet’s Sprout balance is below" + strprintf("%s %s", FormatMoney(CENT), CURRENCY_UNIT) + ".\n" + "the wallet’s Sprout balance is below " + strprintf("%s %s", FormatMoney(CENT), CURRENCY_UNIT) + ".\n" "\nArguments:\n" "1. enabled (boolean, required) 'true' or 'false' to enable or disable respectively.\n" ); @@ -3924,9 +3924,8 @@ UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) { throw runtime_error( "z_getmigrationstatus\n" "Returns information about the status of the Sprout to Sapling migration.\n" - "In the result a transactions is defined as finalized if and only if it has\n" - "at least ten confirmations.\n" - "Note: It is possible that manually created transactions involving this wallet\n" + "Note: A transaction is defined as finalized if it has at least ten confirmations.\n" + "Also, it is possible that manually created transactions involving this wallet\n" "will be included in the result.\n" "\nResult:\n" "{\n" @@ -3952,12 +3951,15 @@ UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) { // account failed transactions, that were not mined within their expiration // height. { - std::vector sproutEntries; + std::vector sproutEntries; std::vector saplingEntries; - pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, "", 1); + std::set noFilter; + // Here we are looking for any and all Sprout notes for which we have the spending key, including those + // which are locked and/or only exist in the mempool, as they should be included in the unmigrated amount. + pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, noFilter, 0, INT_MAX, true, true, false); CAmount unmigratedAmount = 0; for (const auto& sproutEntry : sproutEntries) { - unmigratedAmount += sproutEntry.plaintext.value(); + unmigratedAmount += sproutEntry.note.value(); } migrationStatus.push_back(Pair("unmigrated_amount", FormatMoney(unmigratedAmount))); } @@ -3987,7 +3989,6 @@ UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) { continue; } migrationTxids.push_back(txPair.first.ToString()); - CBlockIndex* blockIndex = mapBlockIndex[tx.hashBlock]; // A transaction is "finalized" iff it has at least 10 confirmations. // TODO: subject to change, if the recommended number of confirmations changes. if (tx.GetDepthInMainChain() >= 10) { @@ -3996,6 +3997,11 @@ UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) { } else { unfinalizedMigratedAmount -= tx.valueBalance; } + // If the transaction is in the mempool it will not be associated with a block yet + if (tx.hashBlock.IsNull() || mapBlockIndex[tx.hashBlock] == nullptr) { + continue; + } + CBlockIndex* blockIndex = mapBlockIndex[tx.hashBlock]; // The value of "time_started" is the earliest Unix timestamp of any known // migration transaction involving this wallet; if there is no such transaction, // then the field is absent. @@ -4212,7 +4218,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp) // Builder (used if Sapling addresses are involved) TransactionBuilder builder = TransactionBuilder( - Params().GetConsensus(), nextBlockHeight, pwalletMain); + Params().GetConsensus(), nextBlockHeight, expiryDelta, pwalletMain); // Contextual transaction we will build on // (used if no Sapling addresses are involved) @@ -4282,7 +4288,9 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) " - \"ANY_TADDR\": Merge UTXOs from any taddrs belonging to the wallet.\n" " - \"ANY_SPROUT\": Merge notes from any Sprout zaddrs belonging to the wallet.\n" " - \"ANY_SAPLING\": Merge notes from any Sapling zaddrs belonging to the wallet.\n" - " If a special string is given, any given addresses of that type will be counted as duplicates and cause an error.\n" + " While it is possible to use a variety of different combinations of addresses and the above values,\n" + " it is not possible to send funds from both sprout and sapling addresses simultaneously. If a special\n" + " string is given, any given addresses of that type will be counted as duplicates and cause an error.\n" " [\n" " \"address\" (string) Can be a taddr or a zaddr\n" " ,...\n" @@ -4512,7 +4520,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) if (useAnySprout || useAnySapling || zaddrs.size() > 0) { // Get available notes - std::vector sproutEntries; + std::vector sproutEntries; std::vector saplingEntries; pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, zaddrs); @@ -4520,8 +4528,15 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) if (!saplingActive && saplingEntries.size() > 0) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated"); } + // Do not include Sprout/Sapling notes if using "ANY_SAPLING"/"ANY_SPROUT" respectively + if (useAnySprout) { + saplingEntries.clear(); + } + if (useAnySapling) { + sproutEntries.clear(); + } // Sending from both Sprout and Sapling is currently unsupported using z_mergetoaddress - if (sproutEntries.size() > 0 && saplingEntries.size() > 0) { + if ((sproutEntries.size() > 0 && saplingEntries.size() > 0) || (useAnySprout && useAnySapling)) { throw JSONRPCError( RPC_INVALID_PARAMETER, "Cannot send from both Sprout and Sapling addresses using z_mergetoaddress"); @@ -4534,9 +4549,9 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) } // Find unspent notes and update estimated size - for (const CSproutNotePlaintextEntry& entry : sproutEntries) { + for (const SproutNoteEntry& entry : sproutEntries) { noteCounter++; - CAmount nValue = entry.plaintext.value(); + CAmount nValue = entry.note.value(); if (!maxedOutNotesFlag) { // If we haven't added any notes yet and the merge is to a @@ -4551,7 +4566,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) auto zaddr = entry.address; SproutSpendingKey zkey; pwalletMain->GetSproutSpendingKey(zaddr, zkey); - sproutNoteInputs.emplace_back(entry.jsop, entry.plaintext.note(zaddr), nValue, zkey); + sproutNoteInputs.emplace_back(entry.jsop, entry.note, nValue, zkey); mergedNoteValue += nValue; } } @@ -4633,7 +4648,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) // Builder (used if Sapling addresses are involved) boost::optional builder; if (isToSaplingZaddr || saplingNoteInputs.size() > 0) { - builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, pwalletMain); + builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, expiryDelta, pwalletMain); } // Create operation and add to global queue std::shared_ptr q = getAsyncRPCQueue(); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index ddf3e9bbbf0..1fa9af6b154 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -584,7 +584,13 @@ void CWallet::ChainTip(const CBlockIndex *pindex, { if (added) { ChainTipAdded(pindex, pblock, sproutTree, saplingTree); - RunSaplingMigration(pindex->nHeight); + // Prevent migration transactions from being created when node is syncing after launch, + // and also when node wakes up from suspension/hibernation and incoming blocks are old. + if (!IsInitialBlockDownload(Params()) && + pblock->GetBlockTime() > GetAdjustedTime() - 3 * 60 * 60) + { + RunSaplingMigration(pindex->nHeight); + } } else { DecrementNoteWitnesses(pindex); UpdateSaplingNullifierNoteMapForBlock(pblock); @@ -606,17 +612,20 @@ void CWallet::RunSaplingMigration(int blockHeight) { // height N, implementations SHOULD start generating the transactions at around // height N-5 if (blockHeight % 500 == 495) { - if (saplingMigrationOperation != nullptr) { - saplingMigrationOperation->cancel(); + std::shared_ptr q = getAsyncRPCQueue(); + std::shared_ptr lastOperation = q->getOperationForId(saplingMigrationOperationId); + if (lastOperation != nullptr) { + lastOperation->cancel(); } pendingSaplingMigrationTxs.clear(); - std::shared_ptr q = getAsyncRPCQueue(); std::shared_ptr operation(new AsyncRPCOperation_saplingmigration(blockHeight + 5)); - saplingMigrationOperation = operation; + saplingMigrationOperationId = operation->getId(); q->addOperation(operation); } else if (blockHeight % 500 == 499) { - if (saplingMigrationOperation != nullptr) { - saplingMigrationOperation->cancel(); + std::shared_ptr q = getAsyncRPCQueue(); + std::shared_ptr lastOperation = q->getOperationForId(saplingMigrationOperationId); + if (lastOperation != nullptr) { + lastOperation->cancel(); } for (const CTransaction& transaction : pendingSaplingMigrationTxs) { // The following is taken from z_sendmany/z_mergetoaddress @@ -1195,7 +1204,7 @@ void CWallet::IncrementNoteWitnesses(const CBlockIndex* pindex, const CBlock* pblock {pblockIn}; CBlock block; if (!pblock) { - ReadBlockFromDisk(block, pindex); + ReadBlockFromDisk(block, pindex, Params().GetConsensus()); pblock = █ } @@ -2650,7 +2659,7 @@ void CWallet::WitnessNoteCommitment(std::vector commitments, while (pindex) { CBlock block; - ReadBlockFromDisk(block, pindex); + ReadBlockFromDisk(block, pindex, Params().GetConsensus()); BOOST_FOREACH(const CTransaction& tx, block.vtx) { @@ -2729,7 +2738,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex, false) - dProgressStart) / (dProgressTip - dProgressStart) * 100)))); CBlock block; - ReadBlockFromDisk(block, pindex); + ReadBlockFromDisk(block, pindex, Params().GetConsensus()); BOOST_FOREACH(CTransaction& tx, block.vtx) { if (AddToWalletIfInvolvingMe(tx, &block, fUpdate)) { @@ -4955,7 +4964,7 @@ bool CMerkleTx::IsTransactionLockTimedOut() const * These notes are decrypted and added to the output parameter vector, outEntries. */ void CWallet::GetFilteredNotes( - std::vector& sproutEntries, + std::vector& sproutEntries, std::vector& saplingEntries, std::string address, int minDepth, @@ -4977,7 +4986,7 @@ void CWallet::GetFilteredNotes( * These notes are decrypted and added to the output parameter vector, outEntries. */ void CWallet::GetFilteredNotes( - std::vector& sproutEntries, + std::vector& sproutEntries, std::vector& saplingEntries, std::set& filterAddresses, int minDepth, @@ -5044,7 +5053,8 @@ void CWallet::GetFilteredNotes( hSig, (unsigned char) j); - sproutEntries.push_back(CSproutNotePlaintextEntry{jsop, pa, plaintext, wtx.GetDepthInMainChain()}); + sproutEntries.push_back(SproutNoteEntry { + jsop, pa, plaintext.note(pa), plaintext.memo(), wtx.GetDepthInMainChain() }); } catch (const note_decryption_failed &err) { // Couldn't decrypt with this spending key diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 6e7cbb8c0d2..403d38aadbd 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -326,12 +326,13 @@ class SaplingNoteData typedef std::map mapSproutNoteData_t; typedef std::map mapSaplingNoteData_t; -/** Decrypted note, its location in a transaction, and number of confirmations. */ -struct CSproutNotePlaintextEntry +/** Sprout note, its location in a transaction, and number of confirmations. */ +struct SproutNoteEntry { JSOutPoint jsop; libzcash::SproutPaymentAddress address; - libzcash::SproutNotePlaintext plaintext; + libzcash::SproutNote note; + std::array memo; int confirmations; }; @@ -420,11 +421,11 @@ class CWalletTx : public CMerkleTx mapSaplingNoteData_t mapSaplingNoteData; std::vector > vOrderForm; unsigned int fTimeReceivedIsTxTime; - unsigned int nTimeReceived; //! time received by this node + unsigned int nTimeReceived; //!< time received by this node unsigned int nTimeSmart; char fFromMe; std::string strFromAccount; - int64_t nOrderPos; //! position in ordered transaction list + int64_t nOrderPos; //!< position in ordered transaction list // memory only mutable bool fDebitCached; @@ -542,7 +543,7 @@ class CWalletTx : public CMerkleTx } READWRITE(*(CMerkleTx*)this); - std::vector vUnused; //! Used to be vtxPrev + std::vector vUnused; //!< Used to be vtxPrev READWRITE(vUnused); READWRITE(mapValue); READWRITE(mapSproutNoteData); @@ -711,7 +712,7 @@ class CAccountingEntry std::string strOtherAccount; std::string strComment; mapValue_t mapValue; - int64_t nOrderPos; //! position in ordered transaction list + int64_t nOrderPos; //!< position in ordered transaction list uint64_t nEntryNo; CAccountingEntry() @@ -821,7 +822,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface TxNullifiers mapTxSaplingNullifiers; std::vector pendingSaplingMigrationTxs; - std::shared_ptr saplingMigrationOperation = nullptr; + AsyncRPCOperationId saplingMigrationOperationId; void AddToTransparentSpends(const COutPoint& outpoint, const uint256& wtxid); void AddToSproutSpends(const uint256& nullifier, const uint256& wtxid); @@ -1405,7 +1406,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool LoadCryptedHDSeed(const uint256& seedFp, const std::vector& seed); /* Find notes filtered by payment address, min depth, ability to spend */ - void GetFilteredNotes(std::vector& sproutEntries, + void GetFilteredNotes(std::vector& sproutEntries, std::vector& saplingEntries, std::string address, int minDepth=1, @@ -1414,7 +1415,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface /* Find notes filtered by payment addresses, min depth, max depth, if they are spent, if a spending key is required, and if they are locked */ - void GetFilteredNotes(std::vector& sproutEntries, + void GetFilteredNotes(std::vector& sproutEntries, std::vector& saplingEntries, std::set& filterAddresses, int minDepth=1, diff --git a/src/zcbenchmarks.cpp b/src/zcbenchmarks.cpp index d91e36d730a..cb4cc181258 100644 --- a/src/zcbenchmarks.cpp +++ b/src/zcbenchmarks.cpp @@ -172,8 +172,9 @@ double benchmark_solve_equihash() CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << I; - unsigned int n = Params(CBaseChainParams::MAIN).EquihashN(); - unsigned int k = Params(CBaseChainParams::MAIN).EquihashK(); + auto params = Params(CBaseChainParams::MAIN).GetConsensus(); + unsigned int n = params.nEquihashN; + unsigned int k = params.nEquihashK; crypto_generichash_blake2b_state eh_state; EhInitialiseState(n, k, eh_state); crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size()); @@ -217,11 +218,11 @@ std::vector benchmark_solve_equihash_threaded(int nThreads) double benchmark_verify_equihash() { CChainParams params = Params(CBaseChainParams::MAIN); - CBlock genesis = Params(CBaseChainParams::MAIN).GenesisBlock(); + CBlock genesis = params.GenesisBlock(); CBlockHeader genesis_header = genesis.GetBlockHeader(); struct timeval tv_start; timer_start(tv_start); - CheckEquihashSolution(&genesis_header, params); + CheckEquihashSolution(&genesis_header, params.GetConsensus()); return timer_stop(tv_start); } @@ -555,7 +556,7 @@ double benchmark_connectblock_slow() CValidationState state; struct timeval tv_start; timer_start(tv_start); - assert(ConnectBlock(block, state, &index, view, true)); + assert(ConnectBlock(block, state, &index, view, Params(), true)); auto duration = timer_stop(tv_start); // Undo alterations to global state diff --git a/src/zeronode/budget.cpp b/src/zeronode/budget.cpp index 0ff44f4d41f..5632c906442 100644 --- a/src/zeronode/budget.cpp +++ b/src/zeronode/budget.cpp @@ -41,7 +41,7 @@ bool IsBudgetCollateralValid(uint256 nTxCollateralHash, uint256 nExpectedHash, s { CTransaction txCollateral; uint256 nBlockHash; - if (!GetTransaction(nTxCollateralHash, txCollateral, nBlockHash, true)) { + if (!GetTransaction(nTxCollateralHash, txCollateral, Params().GetConsensus(), nBlockHash, true)) { strError = strprintf("Can't find collateral tx %s", txCollateral.ToString()); LogPrint("zeronode","CBudgetProposalBroadcast::IsBudgetCollateralValid - %s\n", strError); return false; @@ -203,7 +203,7 @@ void CBudgetManager::SubmitFinalBudget() CTransaction txCollateral; uint256 nBlockHash; - if (!GetTransaction(txidCollateral, txCollateral, nBlockHash, true)) { + if (!GetTransaction(txidCollateral, txCollateral, Params().GetConsensus(), nBlockHash, true)) { LogPrint("zeronode","CBudgetManager::SubmitFinalBudget - Can't find collateral tx %s", txidCollateral.ToString()); return; } diff --git a/src/zeronode/obfuscation.cpp b/src/zeronode/obfuscation.cpp index 8ec3799c180..260f6ba28ac 100644 --- a/src/zeronode/obfuscation.cpp +++ b/src/zeronode/obfuscation.cpp @@ -52,7 +52,7 @@ bool CObfuScationSigner::IsVinAssociatedWithPubkey(CTxIn& vin, CPubKey& pubkey) CTransaction txVin; uint256 hash; - if (GetTransaction(vin.prevout.hash, txVin, hash, true)) { + if (GetTransaction(vin.prevout.hash, txVin, Params().GetConsensus(), hash, true)) { BOOST_FOREACH (CTxOut out, txVin.vout) { if (out.nValue == 10000 * COIN) { if (out.scriptPubKey == payee2) return true; diff --git a/src/zeronode/spork.cpp b/src/zeronode/spork.cpp index 18735aee935..725e8cfa5f8 100644 --- a/src/zeronode/spork.cpp +++ b/src/zeronode/spork.cpp @@ -168,7 +168,7 @@ void ReprocessBlocks(int nBlocks) } if (state.IsValid()) { - ActivateBestChain(state); + ActivateBestChain(state, Params()); } } diff --git a/src/zeronode/swifttx.cpp b/src/zeronode/swifttx.cpp index f25a4e6ef28..4651bc4ad22 100644 --- a/src/zeronode/swifttx.cpp +++ b/src/zeronode/swifttx.cpp @@ -180,7 +180,7 @@ bool IsIXTXValid(const CTransaction& txCollateral) BOOST_FOREACH (const CTxIn i, txCollateral.vin) { CTransaction tx2; uint256 hash; - if (GetTransaction(i.prevout.hash, tx2, hash, true)) { + if (GetTransaction(i.prevout.hash, tx2, Params().GetConsensus(), hash, true)) { if (tx2.vout.size() > i.prevout.n) { nValueIn += tx2.vout[i.prevout.n].nValue; } diff --git a/src/zeronode/zeronode.cpp b/src/zeronode/zeronode.cpp index d5b4555add2..e13b5f6918a 100644 --- a/src/zeronode/zeronode.cpp +++ b/src/zeronode/zeronode.cpp @@ -608,7 +608,7 @@ bool CZeronodeBroadcast::CheckInputsAndAdd(int& nDoS) // should be at least not earlier than block when 10000 ZER tx got ZERONODE_MIN_CONFIRMATIONS uint256 hashBlock = uint256(); CTransaction tx2; - GetTransaction(vin.prevout.hash, tx2, hashBlock, true); + GetTransaction(vin.prevout.hash, tx2, Params().GetConsensus(), hashBlock, true); BlockMap::iterator mi = mapBlockIndex.find(hashBlock); if (mi != mapBlockIndex.end() && (*mi).second) { CBlockIndex* pMNIndex = (*mi).second; // block for 1000 Zero tx -> 1 confirmation diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp index 4567f25b1f9..28cf2e597dc 100644 --- a/src/zmq/zmqpublishnotifier.cpp +++ b/src/zmq/zmqpublishnotifier.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "chainparams.h" #include "zmqpublishnotifier.h" #include "main.h" #include "util.h" @@ -164,11 +165,12 @@ bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex) { LogPrint("zmq", "zmq: Publish rawblock %s\n", pindex->GetBlockHash().GetHex()); + const Consensus::Params& consensusParams = Params().GetConsensus(); CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); { LOCK(cs_main); CBlock block; - if(!ReadBlockFromDisk(block, pindex)) + if(!ReadBlockFromDisk(block, pindex, consensusParams)) { zmqError("Can't read block from disk"); return false; diff --git a/zcutil/release-notes.py b/zcutil/release-notes.py index 6e0f277df32..b1a262232e1 100755 --- a/zcutil/release-notes.py +++ b/zcutil/release-notes.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + import re, os, os.path import subprocess import argparse @@ -20,14 +22,19 @@ ] author_aliases = { - 'Simon': 'Simon Liu', - 'bitcartel': 'Simon Liu', - 'EthanHeilman': 'Ethan Heilman', 'Ariel': 'Ariel Gabizon', 'arielgabizon': 'Ariel Gabizon', + 'bitcartel': 'Simon Liu', 'Charlie OKeefe': 'Charlie O\'Keefe', + 'Duke Leto': 'Jonathan \"Duke\" Leto', + 'Eirik0': 'Eirik Ogilvie-Wigley', + 'EthanHeilman': 'Ethan Heilman', + 'MarcoFalke': 'Marco Falke', + 'mdr0id': 'Marshall Gaucher', + 'paveljanik': 'Pavel Janík', + 'Simon': 'Simon Liu', 'str4d': 'Jack Grigg', - 'Duke Leto': 'Jonathan \"Duke\" Leto' + 'zebambam': 'Benjamin Winston' } def apply_author_aliases(name): From d0d00518393e00ae59ad2ccba7919f4b9ef89bfa Mon Sep 17 00:00:00 2001 From: cryptoforge Date: Sat, 21 Dec 2019 19:50:17 -0800 Subject: [PATCH 367/395] update checkpoints --- src/chainparams.cpp | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index cd3a90c7b14..67e1fdf9e8a 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -126,7 +126,7 @@ class CMainParams : public CChainParams { Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; // The best chain should have at least this much work. - consensus.nMinimumChainWork = uint256S("0x00"); + consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000000000000000023297bef3cd"); /** * The message start string should be awesome! @@ -208,21 +208,22 @@ class CMainParams : public CChainParams { ( 300000, uint256S("0x000001e0b15c1f74af391c39bcb2d61ea879238b53ba738a45303cccd84c2c3f")) ( 400000, uint256S("0x000001ebcc62c257dd00d70bb7fbc210580875e8dbc9f1f9c9aafdb4dc1d8a4e")) ( 500000, uint256S("0x000000c642fda400a464c50dcf310e65efa2627799b9b0c378524205ba2307b7")) - ( 550000, uint256S("0x000003cb1f3c128819bdf84632fd31058014542af64eea8959d5139fc26c21cd")), - 1553590617, // * UNIX timestamp of last checkpoint block - 1067556, // * total number of transactions between genesis and last checkpoint + ( 600000, uint256S("0x000000a0e6efed6a536c2c5063c666102fb2f9ddb4a226b34a0894c723519e48")) + ( 700000, uint256S("0x000001bee8c5bc29fb8d6c3642662ecb479ec85df648e851edaaa0e090b2c797")), + 1571551061, // * UNIX timestamp of last checkpoint block + 1376076, // * total number of transactions between genesis and last checkpoint // (the tx=... number in the SetBestChain debug.log lines) - 1118 // * estimated number of transactions per day after checkpoint + 1132 // * estimated number of transactions per day after checkpoint // total number of tx / (checkpoint block height / (24 * 24)) }; // Hardcoded fallback value for the Sprout shielded value pool balance // for nodes that have not reindexed since the introduction of monitoring // in #2795. - nSproutValuePoolCheckpointHeight = 520633; - nSproutValuePoolCheckpointBalance = 22145062442933; + nSproutValuePoolCheckpointHeight = 492850; + nSproutValuePoolCheckpointBalance = 7517901832365; fZIP209Enabled = true; - hashSproutValuePoolCheckpointBlock = uint256S("0000000000c7b46b6bc04b4cbf87d8bb08722aebd51232619b214f7273f8460e"); + hashSproutValuePoolCheckpointBlock = uint256S("0000004c1c7583dfda0e37d1f52a00f0452dba3054444011c332858ad48b5e66"); // Founders reward script expects a vector of 2-of-3 multisig addresses vFoundersRewardAddress = { @@ -280,21 +281,21 @@ class CTestNetParams : public CChainParams { Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion = 170005; consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = 50; - consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].hashActivationBlock = - uint256S("0000257c4331b098045023fcfbfa2474681f4564ab483f84e4e1ad078e4acf44"); + // consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].hashActivationBlock = + // uint256S("0000257c4331b098045023fcfbfa2474681f4564ab483f84e4e1ad078e4acf44"); consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nProtocolVersion = 170007; consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = 50; - consensus.vUpgrades[Consensus::UPGRADE_SAPLING].hashActivationBlock = - uint256S("000420e7fcc3a49d729479fb0b560dd7b8617b178a08e9e389620a9d1dd6361a"); + // consensus.vUpgrades[Consensus::UPGRADE_SAPLING].hashActivationBlock = + // uint256S("000420e7fcc3a49d729479fb0b560dd7b8617b178a08e9e389620a9d1dd6361a"); consensus.vUpgrades[Consensus::UPGRADE_COSMOS].nProtocolVersion = 170008; consensus.vUpgrades[Consensus::UPGRADE_COSMOS].nActivationHeight =47925; - consensus.vUpgrades[Consensus::UPGRADE_COSMOS].hashActivationBlock = - uint256S("00367515ef2e781b8c9358b443b6329572599edd02c59e8af67db9785122f298"); + // consensus.vUpgrades[Consensus::UPGRADE_COSMOS].hashActivationBlock = + // uint256S("00367515ef2e781b8c9358b443b6329572599edd02c59e8af67db9785122f298"); consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].nProtocolVersion = 170009; consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight = Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; - consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].hashActivationBlock = - uint256S("00367515ef2e781b8c9358b443b6329572599edd02c59e8af67db9785122f298"); + // consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].hashActivationBlock = + // uint256S("00367515ef2e781b8c9358b443b6329572599edd02c59e8af67db9785122f298"); // The best chain should have at least this much work. From ff058b8f2015c8adde1a99fba80a4557f023c939 Mon Sep 17 00:00:00 2001 From: cryptoforge Date: Thu, 6 Feb 2020 12:12:21 -0800 Subject: [PATCH 368/395] Compact Wallet --- src/wallet/db.cpp | 51 ++++++++++++++++++++++++++++++++++++++++- src/wallet/db.h | 1 + src/wallet/walletdb.cpp | 5 ++++ src/wallet/walletdb.h | 1 + 4 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index e0ef27e7864..d0070519188 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -89,7 +89,7 @@ bool CDBEnv::Open(const boost::filesystem::path& pathIn) nEnvFlags |= DB_PRIVATE; dbenv->set_lg_dir(pathLogDir.string().c_str()); - dbenv->set_cachesize(0, 0x100000, 1); // 1 MiB should be enough for just the wallet + dbenv->set_cachesize(1, 0x100000, 1); // 1 MiB should be enough for just the wallet, Increased by 1 GB dbenv->set_lg_bsize(0x10000); dbenv->set_lg_max(1048576); dbenv->set_lk_max_locks(40000); @@ -165,6 +165,55 @@ CDBEnv::VerifyResult CDBEnv::Verify(const std::string& strFile, bool (*recoverFu return (fRecovered ? RECOVER_OK : RECOVER_FAIL); } +bool CDBEnv::Compact(const std::string& strFile) +{ + LOCK(cs_db); + + DB_COMPACT dbcompact; + dbcompact.compact_fillpercent = 80; + dbcompact.compact_pages = DB_MAX_PAGES; + dbcompact.compact_timeout = 0; + + DB_COMPACT *pdbcompact; + pdbcompact = &dbcompact; + + int result = 1; + if (mapDb[strFile] != NULL) { + Db* pdb = mapDb[strFile]; + result = pdb->compact(NULL, NULL, NULL, pdbcompact, DB_FREE_SPACE, NULL); + delete pdb; + mapDb[strFile] = NULL; + + switch (result) + { + case DB_LOCK_DEADLOCK: + LogPrint("db","Deadlock %i\n", result); + break; + case DB_LOCK_NOTGRANTED: + LogPrint("db","Lock Not Granted %i\n", result); + break; + case DB_REP_HANDLE_DEAD: + LogPrint("db","Handle Dead %i\n", result); + break; + case DB_REP_LOCKOUT: + LogPrint("db","Rep Lockout %i\n", result); + break; + case EACCES: + LogPrint("db","Eacces %i\n", result); + break; + case EINVAL: + LogPrint("db","Error Invalid %i\n", result); + break; + case 0: + LogPrint("db","Wallet Compact Sucessful\n"); + break; + default: + LogPrint("db","Compact result int %i\n", result); + } + } + return (result == 0); +} + bool CDBEnv::Salvage(const std::string& strFile, bool fAggressive, std::vector& vResult) { LOCK(cs_db); diff --git a/src/wallet/db.h b/src/wallet/db.h index 1ae5a03b591..39e99b24d12 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -63,6 +63,7 @@ class CDBEnv * NOTE: reads the entire database into memory, so cannot be used * for huge databases. */ + bool Compact(const std::string& strFile); typedef std::pair, std::vector > KeyValPair; bool Salvage(const std::string& strFile, bool fAggressive, std::vector& vResult); diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 00b1e18a5c7..98ea076ca6b 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -1165,6 +1165,11 @@ bool BackupWallet(const CWallet& wallet, const string& strDest) return false; } +bool CWalletDB::Compact(CDBEnv& dbenv, const std::string& strFile) +{ + bool fSuccess = dbenv.Compact(strFile); + return fSuccess; +} // // Try to (very carefully!) recover wallet.zero if there is a problem. // diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 33a14b6f34a..e58bb0c9cc2 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -174,6 +174,7 @@ class CWalletDB : public CDB DBErrors LoadWallet(CWallet* pwallet); DBErrors FindWalletTxToZap(CWallet* pwallet, std::vector& vTxHash, std::vector& vWtx); DBErrors ZapWalletTx(CWallet* pwallet, std::vector& vWtx); + static bool Compact(CDBEnv& dbenv, const std::string& strFile); static bool Recover(CDBEnv& dbenv, const std::string& filename, bool fOnlyKeys); static bool Recover(CDBEnv& dbenv, const std::string& filename); From bf12a78d45bab0c1d8738b79c65f3758ac290207 Mon Sep 17 00:00:00 2001 From: cryptoforge Date: Thu, 6 Feb 2020 12:50:38 -0800 Subject: [PATCH 369/395] Delete & Witnesses 1. Add functionality to delete wallet transactions 2. Rework when witnesses are calculated. --- src/init.cpp | 27 +- src/wallet/gtest/test_wallet.cpp | 45 +- src/wallet/wallet.cpp | 920 ++++++++++++++++++++++++------- src/wallet/wallet.h | 60 +- 4 files changed, 815 insertions(+), 237 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index bef20ac4dfd..7a68a4e30f1 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -427,6 +427,10 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-keypool=", strprintf(_("Set key pool size to (default: %u)"), 100)); strUsage += HelpMessageOpt("-migration", _("Enable the Sprout to Sapling migration")); strUsage += HelpMessageOpt("-migrationdestaddress=", _("Set the Sapling migration address")); + strUsage += HelpMessageOpt("-deletetx", _("Enable Old Transaction Deletion")); + strUsage += HelpMessageOpt("-deleteinterval", strprintf(_("Delete transaction every blocks during inital block download (default: %i)"), DEFAULT_TX_DELETE_INTERVAL)); + strUsage += HelpMessageOpt("-keeptxnum", strprintf(_("Keep the last transactions (default: %i)"), DEFAULT_TX_RETENTION_LASTTX)); + strUsage += HelpMessageOpt("-keeptxfornblocks", strprintf(_("Keep transactions for at least blocks (default: %i)"), DEFAULT_TX_RETENTION_BLOCKS)); if (showDebug) strUsage += HelpMessageOpt("-mintxfee=", strprintf("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)", CURRENCY_UNIT, FormatMoney(CWallet::minTxFee.GetFeePerK()))); @@ -477,7 +481,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", 0)); strUsage += HelpMessageOpt("-nuparams=hexBranchId:activationHeight", "Use given activation height for specified network upgrade (regtest-only)"); } - string debugCategories = "addrman, alert, bench, coindb, db, estimatefee, http, libevent, lock, mempool, net, partitioncheck, pow, proxy, prune, " + string debugCategories = "addrman, alert, bench, coindb, db, deletetx, estimatefee, http, libevent, lock, mempool, net, partitioncheck, pow, proxy, prune, " "rand, reindex, rpc, selectcoins, tor, zmq, zrpc, zrpcunsafe (implies zrpc)"; // Don't translate these strUsage += HelpMessageOpt("-debug=", strprintf(_("Output debugging information (default: %u, supplying is optional)"), 0) + ". " + _("If is not supplied or if = 1, output all debugging information.") + " " + _(" can be:") + " " + debugCategories + "."); @@ -1725,6 +1729,27 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // Set sapling migration status pwalletMain->fSaplingMigrationEnabled = GetBoolArg("-migration", false); + //Set Transaction Deletion Options + fTxDeleteEnabled = GetBoolArg("-deletetx", false); + fTxConflictDeleteEnabled = GetBoolArg("-deleteconflicttx", true); + + fDeleteInterval = GetArg("-deleteinterval", DEFAULT_TX_DELETE_INTERVAL); + if (fDeleteInterval < 1) + return InitError("deleteinterval must be greater than 0"); + + fKeepLastNTransactions = GetArg("-keeptxnum", DEFAULT_TX_RETENTION_LASTTX); + if (fKeepLastNTransactions < 1) + return InitError("keeptxnum must be greater than 0"); + + fDeleteTransactionsAfterNBlocks = GetArg("-keeptxfornblocks", DEFAULT_TX_RETENTION_BLOCKS); + if (fDeleteTransactionsAfterNBlocks < 1) + return InitError("keeptxfornblocks must be greater than 0"); + + if (fDeleteTransactionsAfterNBlocks < MAX_REORG_LENGTH + 1 ) { + LogPrintf("keeptxfornblock is less the MAX_REORG_LENGTH, Setting to %i\n", MAX_REORG_LENGTH + 1); + fDeleteTransactionsAfterNBlocks = MAX_REORG_LENGTH + 1; + } + if (fFirstRun) { // Create new keyUser and set as default key diff --git a/src/wallet/gtest/test_wallet.cpp b/src/wallet/gtest/test_wallet.cpp index 897c46ab429..f8c886c5360 100644 --- a/src/wallet/gtest/test_wallet.cpp +++ b/src/wallet/gtest/test_wallet.cpp @@ -51,11 +51,8 @@ class TestWallet : public CWallet { return CCryptoKeyStore::Unlock(vMasterKeyIn); } - void IncrementNoteWitnesses(const CBlockIndex* pindex, - const CBlock* pblock, - SproutMerkleTree& sproutTree, - SaplingMerkleTree& saplingTree) { - CWallet::IncrementNoteWitnesses(pindex, pblock, sproutTree, saplingTree); + void BuildWitnessCache(const CBlockIndex* pindex, bool witnessOnly) { + CWallet::BuildWitnessCache(pindex, witnessOnly); } void DecrementNoteWitnesses(const CBlockIndex* pindex) { CWallet::DecrementNoteWitnesses(pindex); @@ -130,7 +127,7 @@ std::pair CreateValidBlock(TestWallet& wallet, wallet.AddToWallet(wtx, true, NULL); block.vtx.push_back(wtx); - wallet.IncrementNoteWitnesses(&index, &block, sproutTree, saplingTree); + wallet.BuildWitnessCache(&index, false); return std::make_pair(jsoutpt, saplingNotes[0]); } @@ -682,8 +679,8 @@ TEST(WalletTests, GetConflictedSaplingNotes) { wallet.AddToWallet(wtx, true, NULL); // Simulate receiving new block and ChainTip signal - wallet.IncrementNoteWitnesses(&fakeIndex, &block, sproutTree, saplingTree); - wallet.UpdateSaplingNullifierNoteMapForBlock(&block); + wallet.BuildWitnessCache(&fakeIndex, false); + wallet.UpdateNullifierNoteMapForBlock(&block); // Retrieve the updated wtx from wallet uint256 hash = wtx.GetHash(); @@ -934,8 +931,8 @@ TEST(WalletTests, NavigateFromSaplingNullifierToNote) { } // Simulate receiving new block and ChainTip signal - wallet.IncrementNoteWitnesses(&fakeIndex, &block, sproutTree, testNote.tree); - wallet.UpdateSaplingNullifierNoteMapForBlock(&block); + wallet.BuildWitnessCache(&fakeIndex, false); + wallet.UpdateNullifierNoteMapForBlock(&block); // Retrieve the updated wtx from wallet uint256 hash = wtx.GetHash(); @@ -1044,8 +1041,8 @@ TEST(WalletTests, SpentSaplingNoteIsFromMe) { // Simulate receiving new block and ChainTip signal. // This triggers calculation of nullifiers for notes belonging to this wallet // in the output descriptions of wtx. - wallet.IncrementNoteWitnesses(&fakeIndex, &block, sproutTree, saplingTree); - wallet.UpdateSaplingNullifierNoteMapForBlock(&block); + wallet.BuildWitnessCache(&fakeIndex, false); + wallet.UpdateNullifierNoteMapForBlock(&block); // Retrieve the updated wtx from wallet wtx = wallet.mapWallet[wtx.GetHash()]; @@ -1178,7 +1175,7 @@ TEST(WalletTests, CachedWitnessesEmptyChain) { CBlockIndex index(block); SproutMerkleTree sproutTree; SaplingMerkleTree saplingTree; - wallet.IncrementNoteWitnesses(&index, &block, sproutTree, saplingTree); + wallet.BuildWitnessCache(&index, false); ::GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); @@ -1248,7 +1245,7 @@ TEST(WalletTests, CachedWitnessesChainTip) { index2.nHeight = 2; SproutMerkleTree sproutTree2 {sproutTree}; SaplingMerkleTree saplingTree2 {saplingTree}; - wallet.IncrementNoteWitnesses(&index2, &block2, sproutTree2, saplingTree2); + wallet.BuildWitnessCache(&index2, false); auto anchors2 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); EXPECT_NE(anchors2.first, anchors2.second); @@ -1269,7 +1266,7 @@ TEST(WalletTests, CachedWitnessesChainTip) { EXPECT_NE(anchors1.second, anchors3.second); // Re-incrementing with the same block should give the same result - wallet.IncrementNoteWitnesses(&index2, &block2, sproutTree, saplingTree); + wallet.BuildWitnessCache(&index2, false); auto anchors4 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); EXPECT_NE(anchors4.first, anchors4.second); @@ -1279,7 +1276,7 @@ TEST(WalletTests, CachedWitnessesChainTip) { EXPECT_EQ(anchors2.second, anchors4.second); // Incrementing with the same block again should not change the cache - wallet.IncrementNoteWitnesses(&index2, &block2, sproutTree, saplingTree); + wallet.BuildWitnessCache(&index2, false); std::vector> sproutWitnesses5; std::vector> saplingWitnesses5; @@ -1362,7 +1359,7 @@ TEST(WalletTests, CachedWitnessesDecrementFirst) { EXPECT_NE(anchors2.second, anchors4.second); // Re-incrementing with the same block should give the same result - wallet.IncrementNoteWitnesses(&index2, &block2, sproutTree, saplingTree); + wallet.BuildWitnessCache(&index2, false); auto anchors5 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); @@ -1419,7 +1416,7 @@ TEST(WalletTests, CachedWitnessesCleanIndex) { for (size_t i = 0; i < numBlocks; i++) { SproutMerkleTree sproutRiPrevTree {sproutRiTree}; SaplingMerkleTree saplingRiPrevTree {saplingRiTree}; - wallet.IncrementNoteWitnesses(&(indices[i]), &(blocks[i]), sproutRiTree, saplingRiTree); + wallet.BuildWitnessCache(&indices[i], false); auto anchors = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); for (size_t j = 0; j < numBlocks; j++) { @@ -1446,7 +1443,7 @@ TEST(WalletTests, CachedWitnessesCleanIndex) { } { - wallet.IncrementNoteWitnesses(&(indices[i]), &(blocks[i]), sproutRiPrevTree, saplingRiPrevTree); + wallet.BuildWitnessCache(&indices[i], false); auto anchors = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); for (size_t j = 0; j < numBlocks; j++) { EXPECT_TRUE((bool) sproutWitnesses[j]); @@ -1820,8 +1817,8 @@ TEST(WalletTests, UpdatedSaplingNoteData) { wallet.AddToWallet(wtx, true, NULL); // Simulate receiving new block and ChainTip signal - wallet.IncrementNoteWitnesses(&fakeIndex, &block, sproutTree, testNote.tree); - wallet.UpdateSaplingNullifierNoteMapForBlock(&block); + wallet.BuildWitnessCache(&fakeIndex, false); + wallet.UpdateNullifierNoteMapForBlock(&block); // Retrieve the updated wtx from wallet uint256 hash = wtx.GetHash(); @@ -1849,7 +1846,7 @@ TEST(WalletTests, UpdatedSaplingNoteData) { EXPECT_EQ(2, wtx2.mapSaplingNoteData.size()); EXPECT_EQ(1, wtx2.mapSaplingNoteData[sop0].witnesses.size()); // wtx2 has fake witness for payment output - EXPECT_EQ(0, wtx2.mapSaplingNoteData[sop1].witnesses.size()); // wtx2 never had incrementnotewitness called + EXPECT_EQ(0, wtx2.mapSaplingNoteData[sop1].witnesses.size()); // wtx2 never had BuildWitnessCache called // After updating, they should be the same EXPECT_TRUE(wallet.UpdatedNoteData(wtx2, wtx)); @@ -1965,8 +1962,8 @@ TEST(WalletTests, MarkAffectedSaplingTransactionsDirty) { wallet.AddToWallet(wtx, true, NULL); // Simulate receiving new block and ChainTip signal - wallet.IncrementNoteWitnesses(&fakeIndex, &block, sproutTree, saplingTree); - wallet.UpdateSaplingNullifierNoteMapForBlock(&block); + wallet.BuildWitnessCache(&fakeIndex, false); + wallet.UpdateNullifierNoteMapForBlock(&block); // Retrieve the updated wtx from wallet uint256 hash = wtx.GetHash(); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 25c1463f63e..6bdfe0fd716 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -48,6 +48,11 @@ unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET; bool bSpendZeroConfChange = true; bool fSendFreeTransactions = false; bool fPayAtLeastCustomFee = true; +bool fTxDeleteEnabled = false; +bool fTxConflictDeleteEnabled = false; +int fDeleteInterval = DEFAULT_TX_DELETE_INTERVAL; +unsigned int fDeleteTransactionsAfterNBlocks = DEFAULT_TX_RETENTION_BLOCKS; +unsigned int fKeepLastNTransactions = DEFAULT_TX_RETENTION_LASTTX; /** * Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) @@ -565,15 +570,6 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, return false; } -void CWallet::ChainTipAdded(const CBlockIndex *pindex, - const CBlock *pblock, - SproutMerkleTree sproutTree, - SaplingMerkleTree saplingTree) -{ - IncrementNoteWitnesses(pindex, pblock, sproutTree, saplingTree); - UpdateSaplingNullifierNoteMapForBlock(pblock); -} - void CWallet::ChainTip(const CBlockIndex *pindex, const CBlock *pblock, SproutMerkleTree sproutTree, @@ -581,17 +577,25 @@ void CWallet::ChainTip(const CBlockIndex *pindex, bool added) { if (added) { - ChainTipAdded(pindex, pblock, sproutTree, saplingTree); - // Prevent migration transactions from being created when node is syncing after launch, // and also when node wakes up from suspension/hibernation and incoming blocks are old. - if (!IsInitialBlockDownload(Params()) && - pblock->GetBlockTime() > GetAdjustedTime() - 3 * 60 * 60) + bool initialDownloadCheck = IsInitialBlockDownload(Params()); + if (!initialDownloadCheck && + pblock->GetBlockTime() > GetAdjustedTime() - 8640) //Last 144 blocks 2.4 * 60 * 60 { + BuildWitnessCache(pindex, false); RunSaplingMigration(pindex->nHeight); + DeleteWalletTransactions(pindex); + } else { + //Build intial witnesses on every block + BuildWitnessCache(pindex, true); + if (initialDownloadCheck && pindex->nHeight % fDeleteInterval == 0) { + DeleteWalletTransactions(pindex); + } } + } else { DecrementNoteWitnesses(pindex); - UpdateSaplingNullifierNoteMapForBlock(pblock); + UpdateNullifierNoteMapForBlock(pblock); } } @@ -929,6 +933,22 @@ bool CWallet::IsSpent(const uint256& hash, unsigned int n) const return false; } +unsigned int CWallet::GetSpendDepth(const uint256& hash, unsigned int n) const +{ + const COutPoint outpoint(hash, n); + pair range; + range = mapTxSpends.equal_range(outpoint); + + for (TxSpends::const_iterator it = range.first; it != range.second; ++it) + { + const uint256& wtxid = it->second; + std::map::const_iterator mit = mapWallet.find(wtxid); + if (mit != mapWallet.end() && mit->second.GetDepthInMainChain() >= 0) + return mit->second.GetDepthInMainChain(); // Spent + } + return 0; +} + /** * Note is spent if any non-conflicted transaction * spends it: @@ -947,6 +967,20 @@ bool CWallet::IsSproutSpent(const uint256& nullifier) const { return false; } +unsigned int CWallet::GetSproutSpendDepth(const uint256& nullifier) const { + pair range; + range = mapTxSproutNullifiers.equal_range(nullifier); + + for (TxNullifiers::const_iterator it = range.first; it != range.second; ++it) { + const uint256& wtxid = it->second; + std::map::const_iterator mit = mapWallet.find(wtxid); + if (mit != mapWallet.end() && mit->second.GetDepthInMainChain() >= 0) { + return mit->second.GetDepthInMainChain(); // Spent + } + } + return 0; +} + bool CWallet::IsSaplingSpent(const uint256& nullifier) const { pair range; range = mapTxSaplingNullifiers.equal_range(nullifier); @@ -961,6 +995,20 @@ bool CWallet::IsSaplingSpent(const uint256& nullifier) const { return false; } +unsigned int CWallet::GetSaplingSpendDepth(const uint256& nullifier) const { + pair range; + range = mapTxSaplingNullifiers.equal_range(nullifier); + + for (TxNullifiers::const_iterator it = range.first; it != range.second; ++it) { + const uint256& wtxid = it->second; + std::map::const_iterator mit = mapWallet.find(wtxid); + if (mit != mapWallet.end() && mit->second.GetDepthInMainChain() >= 0) { + return mit->second.GetDepthInMainChain(); // Spent + } + } + return 0; +} + void CWallet::AddToTransparentSpends(const COutPoint& outpoint, const uint256& wtxid) { mapTxSpends.insert(make_pair(outpoint, wtxid)); @@ -1088,222 +1136,365 @@ void CWallet::ClearNoteWitnessCache() item.second.witnessHeight = -1; } } - nWitnessCacheSize = 0; } -template -void CopyPreviousWitnesses(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize) +void CWallet::DecrementNoteWitnesses(const CBlockIndex* pindex) { - for (auto& item : noteDataMap) { - auto* nd = &(item.second); - // Only increment witnesses that are behind the current height - if (nd->witnessHeight < indexHeight) { - // Check the validity of the cache - // The only time a note witnessed above the current height - // would be invalid here is during a reindex when blocks - // have been decremented, and we are incrementing the blocks - // immediately after. - assert(nWitnessCacheSize >= nd->witnesses.size()); - // Witnesses being incremented should always be either -1 - // (never incremented or decremented) or one below indexHeight - assert((nd->witnessHeight == -1) || (nd->witnessHeight == indexHeight - 1)); - // Copy the witness for the previous block if we have one - if (nd->witnesses.size() > 0) { - nd->witnesses.push_front(nd->witnesses.front()); + LOCK(cs_wallet); + for (std::pair& wtxItem : mapWallet) { + //Sprout + for (auto& item : wtxItem.second.mapSproutNoteData) { + auto* nd = &(item.second); + if (nd->nullifier && pwalletMain->GetSproutSpendDepth(*item.second.nullifier) <= WITNESS_CACHE_SIZE) { + // Only decrement witnesses that are not above the current height + if (nd->witnessHeight <= pindex->nHeight) { + if (nd->witnesses.size() > 1) { + // indexHeight is the height of the block being removed, so + // the new witness cache height is one below it. + nd->witnesses.pop_front(); + nd->witnessHeight = pindex->nHeight - 1; + } + } } - if (nd->witnesses.size() > WITNESS_CACHE_SIZE) { - nd->witnesses.pop_back(); + } + //Sapling + for (auto& item : wtxItem.second.mapSaplingNoteData) { + auto* nd = &(item.second); + if (nd->nullifier && pwalletMain->GetSaplingSpendDepth(*item.second.nullifier) <= WITNESS_CACHE_SIZE) { + // Only decrement witnesses that are not above the current height + if (nd->witnessHeight <= pindex->nHeight) { + if (nd->witnesses.size() > 1) { + // indexHeight is the height of the block being removed, so + // the new witness cache height is one below it. + nd->witnesses.pop_front(); + nd->witnessHeight = pindex->nHeight - 1; + } + } } } } } -template -void AppendNoteCommitment(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize, const uint256& note_commitment) +template +void ClearSingleNoteWitnessCache(NoteData* nd) { - for (auto& item : noteDataMap) { - auto* nd = &(item.second); - if (nd->witnessHeight < indexHeight && nd->witnesses.size() > 0) { - // Check the validity of the cache - // See comment in CopyPreviousWitnesses about validity. - assert(nWitnessCacheSize >= nd->witnesses.size()); - nd->witnesses.front().append(note_commitment); - } - } + nd->witnesses.clear(); + nd->witnessHeight = -1; + nd->witnessRootValidated = false; } -template -void WitnessNoteIfMine(std::map& noteDataMap, int indexHeight, int64_t nWitnessCacheSize, const OutPoint& key, const Witness& witness) +int CWallet::SproutWitnessMinimumHeight(const uint256& nullifier, int nWitnessHeight, int nMinimumHeight) { - if (noteDataMap.count(key) && noteDataMap[key].witnessHeight < indexHeight) { - auto* nd = &(noteDataMap[key]); - if (nd->witnesses.size() > 0) { - // We think this can happen because we write out the - // witness cache state after every block increment or - // decrement, but the block index itself is written in - // batches. So if the node crashes in between these two - // operations, it is possible for IncrementNoteWitnesses - // to be called again on previously-cached blocks. This - // doesn't affect existing cached notes because of the - // NoteData::witnessHeight checks. See #1378 for details. - LogPrintf("Inconsistent witness cache state found for %s\n- Cache size: %d\n- Top (height %d): %s\n- New (height %d): %s\n", - key.ToString(), nd->witnesses.size(), - nd->witnessHeight, - nd->witnesses.front().root().GetHex(), - indexHeight, - witness.root().GetHex()); - nd->witnesses.clear(); - } - nd->witnesses.push_front(witness); - // Set height to one less than pindex so it gets incremented - nd->witnessHeight = indexHeight - 1; - // Check the validity of the cache - assert(nWitnessCacheSize >= nd->witnesses.size()); + if (GetSproutSpendDepth(nullifier) <= WITNESS_CACHE_SIZE) { + nMinimumHeight = min(nWitnessHeight, nMinimumHeight); } + return nMinimumHeight; } - -template -void UpdateWitnessHeights(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize) +int CWallet::SaplingWitnessMinimumHeight(const uint256& nullifier, int nWitnessHeight, int nMinimumHeight) { - for (auto& item : noteDataMap) { - auto* nd = &(item.second); - if (nd->witnessHeight < indexHeight) { - nd->witnessHeight = indexHeight; - // Check the validity of the cache - // See comment in CopyPreviousWitnesses about validity. - assert(nWitnessCacheSize >= nd->witnesses.size()); - } + if (GetSaplingSpendDepth(nullifier) <= WITNESS_CACHE_SIZE) { + nMinimumHeight = min(nWitnessHeight, nMinimumHeight); } + return nMinimumHeight; } -void CWallet::IncrementNoteWitnesses(const CBlockIndex* pindex, - const CBlock* pblockIn, - SproutMerkleTree& sproutTree, - SaplingMerkleTree& saplingTree) +int CWallet::VerifyAndSetInitialWitness(const CBlockIndex* pindex, bool witnessOnly) { - LOCK(cs_wallet); - for (std::pair& wtxItem : mapWallet) { - ::CopyPreviousWitnesses(wtxItem.second.mapSproutNoteData, pindex->nHeight, nWitnessCacheSize); - ::CopyPreviousWitnesses(wtxItem.second.mapSaplingNoteData, pindex->nHeight, nWitnessCacheSize); - } + LOCK2(cs_wallet,cs_main); - if (nWitnessCacheSize < WITNESS_CACHE_SIZE) { - nWitnessCacheSize += 1; - } + int nWitnessTxIncrement = 0; + int nWitnessTotalTxCount = mapWallet.size(); + int nMinimumHeight = pindex->nHeight; - const CBlock* pblock {pblockIn}; - CBlock block; - if (!pblock) { - ReadBlockFromDisk(block, pindex, Params().GetConsensus()); + for (std::pair& wtxItem : mapWallet) { + nWitnessTxIncrement += 1; + + if (wtxItem.second.mapSproutNoteData.empty() && wtxItem.second.mapSaplingNoteData.empty()) + continue; + + if (wtxItem.second.GetDepthInMainChain() > 0) { + auto wtxHash = wtxItem.second.GetHash(); + int wtxHeight = mapBlockIndex[wtxItem.second.hashBlock]->nHeight; + + for (mapSproutNoteData_t::value_type& item : wtxItem.second.mapSproutNoteData) { + + auto op = item.first; + auto* nd = &(item.second); + CBlockIndex* pblockindex; + uint256 blockRoot; + uint256 witnessRoot; + + if (!nd->nullifier) + ::ClearSingleNoteWitnessCache(nd); + + if (!nd->witnesses.empty() && nd->witnessHeight > 0) { + + //Skip all functions for validated witness while witness only = true + if (nd->witnessRootValidated && witnessOnly) + continue; + + //Skip Validation when witness root has been validated + if (nd->witnessRootValidated) { + nMinimumHeight = SproutWitnessMinimumHeight(*item.second.nullifier, nd->witnessHeight, nMinimumHeight); + continue; + } + + //Skip Validation when witness height is greater that block height + if (nd->witnessHeight > pindex->nHeight - 1) { + nMinimumHeight = SproutWitnessMinimumHeight(*item.second.nullifier, nd->witnessHeight, nMinimumHeight); + continue; + } + + //Validate the witness at the witness height + witnessRoot = nd->witnesses.front().root(); + pblockindex = chainActive[nd->witnessHeight]; + blockRoot = pblockindex->hashFinalSproutRoot; + if (witnessRoot == blockRoot) { + nd->witnessRootValidated = true; + nMinimumHeight = SproutWitnessMinimumHeight(*item.second.nullifier, nd->witnessHeight, nMinimumHeight); + continue; + } + } + + //Clear witness Cache for all other scenarios + pblockindex = chainActive[wtxHeight]; + ::ClearSingleNoteWitnessCache(nd); + + LogPrintf("Setting Inital Sprout Witness for tx %s, %i of %i\n", wtxHash.ToString(), nWitnessTxIncrement, nWitnessTotalTxCount); + + SproutMerkleTree sproutTree; + blockRoot = pblockindex->pprev->hashFinalSproutRoot; + pcoinsTip->GetSproutAnchorAt(blockRoot, sproutTree); + + //Cycle through blocks and transactions building sprout tree until the commitment needed is reached + const CBlock* pblock; + CBlock block; + ReadBlockFromDisk(block, pblockindex, Params().GetConsensus()); pblock = █ - } - for (const CTransaction& tx : pblock->vtx) { - auto hash = tx.GetHash(); - bool txIsOurs = mapWallet.count(hash); - // Sprout - for (size_t i = 0; i < tx.vJoinSplit.size(); i++) { + for (const CTransaction& tx : block.vtx) { + auto hash = tx.GetHash(); + + for (size_t i = 0; i < tx.vJoinSplit.size(); i++) { const JSDescription& jsdesc = tx.vJoinSplit[i]; for (uint8_t j = 0; j < jsdesc.commitments.size(); j++) { - const uint256& note_commitment = jsdesc.commitments[j]; - sproutTree.append(note_commitment); + const uint256& note_commitment = jsdesc.commitments[j]; - // Increment existing witnesses - for (std::pair& wtxItem : mapWallet) { - ::AppendNoteCommitment(wtxItem.second.mapSproutNoteData, pindex->nHeight, nWitnessCacheSize, note_commitment); - } + // Increment existing witness until the end of the block + if (!nd->witnesses.empty()) { + nd->witnesses.front().append(note_commitment); + } + + //Only needed for intial witness + if (nd->witnesses.empty()) { + sproutTree.append(note_commitment); // If this is our note, witness it - if (txIsOurs) { - JSOutPoint jsoutpt {hash, i, j}; - ::WitnessNoteIfMine(mapWallet[hash].mapSproutNoteData, pindex->nHeight, nWitnessCacheSize, jsoutpt, sproutTree.witness()); + if (hash == wtxHash) { + JSOutPoint outPoint {hash, i, j}; + if (op == outPoint) { + nd->witnesses.push_front(sproutTree.witness()); + } } + } } + } } - // Sapling - for (uint32_t i = 0; i < tx.vShieldedOutput.size(); i++) { + + nd->witnessHeight = pblockindex->nHeight; + UpdateSproutNullifierNoteMapWithTx(wtxItem.second); + nMinimumHeight = SproutWitnessMinimumHeight(*item.second.nullifier, nd->witnessHeight, nMinimumHeight); + } + + for (mapSaplingNoteData_t::value_type& item : wtxItem.second.mapSaplingNoteData) { + + auto op = item.first; + auto* nd = &(item.second); + CBlockIndex* pblockindex; + uint256 blockRoot; + uint256 witnessRoot; + + if (!nd->nullifier) + ::ClearSingleNoteWitnessCache(nd); + + if (!nd->witnesses.empty() && nd->witnessHeight > 0) { + + //Skip all functions for validated witness while witness only = true + if (nd->witnessRootValidated && witnessOnly) + continue; + + //Skip Validation when witness root has been validated + if (nd->witnessRootValidated) { + nMinimumHeight = SaplingWitnessMinimumHeight(*item.second.nullifier, nd->witnessHeight, nMinimumHeight); + continue; + } + + //Skip Validation when witness height is greater that block height + if (nd->witnessHeight > pindex->nHeight - 1) { + nMinimumHeight = SaplingWitnessMinimumHeight(*item.second.nullifier, nd->witnessHeight, nMinimumHeight); + continue; + } + + //Validate the witness at the witness height + witnessRoot = nd->witnesses.front().root(); + pblockindex = chainActive[nd->witnessHeight]; + blockRoot = pblockindex->hashFinalSaplingRoot; + if (witnessRoot == blockRoot) { + nd->witnessRootValidated = true; + nMinimumHeight = SaplingWitnessMinimumHeight(*item.second.nullifier, nd->witnessHeight, nMinimumHeight); + continue; + } + } + + //Clear witness Cache for all other scenarios + pblockindex = chainActive[wtxHeight]; + ::ClearSingleNoteWitnessCache(nd); + + LogPrintf("Setting Inital Sapling Witness for tx %s, %i of %i\n", wtxHash.ToString(), nWitnessTxIncrement, nWitnessTotalTxCount); + + SaplingMerkleTree saplingTree; + blockRoot = pblockindex->pprev->hashFinalSaplingRoot; + pcoinsTip->GetSaplingAnchorAt(blockRoot, saplingTree); + + //Cycle through blocks and transactions building sapling tree until the commitment needed is reached + const CBlock* pblock; + CBlock block; + ReadBlockFromDisk(block, pblockindex, Params().GetConsensus()); + pblock = █ + + for (const CTransaction& tx : block.vtx) { + auto hash = tx.GetHash(); + + // Sapling + for (uint32_t i = 0; i < tx.vShieldedOutput.size(); i++) { const uint256& note_commitment = tx.vShieldedOutput[i].cm; - saplingTree.append(note_commitment); - // Increment existing witnesses - for (std::pair& wtxItem : mapWallet) { - ::AppendNoteCommitment(wtxItem.second.mapSaplingNoteData, pindex->nHeight, nWitnessCacheSize, note_commitment); + // Increment existing witness until the end of the block + if (!nd->witnesses.empty()) { + nd->witnesses.front().append(note_commitment); } - // If this is our note, witness it - if (txIsOurs) { + //Only needed for intial witness + if (nd->witnesses.empty()) { + saplingTree.append(note_commitment); + + // If this is our note, witness it + if (hash == wtxHash) { SaplingOutPoint outPoint {hash, i}; - ::WitnessNoteIfMine(mapWallet[hash].mapSaplingNoteData, pindex->nHeight, nWitnessCacheSize, outPoint, saplingTree.witness()); + if (op == outPoint) { + nd->witnesses.push_front(saplingTree.witness()); + } + } } + } } + nd->witnessHeight = pblockindex->nHeight; + UpdateSaplingNullifierNoteMapWithTx(wtxItem.second); + nMinimumHeight = SaplingWitnessMinimumHeight(*item.second.nullifier, nd->witnessHeight, nMinimumHeight); + } } + } - // Update witness heights - for (std::pair& wtxItem : mapWallet) { - ::UpdateWitnessHeights(wtxItem.second.mapSproutNoteData, pindex->nHeight, nWitnessCacheSize); - ::UpdateWitnessHeights(wtxItem.second.mapSaplingNoteData, pindex->nHeight, nWitnessCacheSize); - } - - // For performance reasons, we write out the witness cache in - // CWallet::SetBestChain() (which also ensures that overall consistency - // of the wallet.dat is maintained). + return nMinimumHeight; } -template -void DecrementNoteWitnesses(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize) +void CWallet::BuildWitnessCache(const CBlockIndex* pindex, bool witnessOnly) { - for (auto& item : noteDataMap) { - auto* nd = &(item.second); - // Only decrement witnesses that are not above the current height - if (nd->witnessHeight <= indexHeight) { - // Check the validity of the cache - // See comment below (this would be invalid if there were a - // prior decrement). - assert(nWitnessCacheSize >= nd->witnesses.size()); - // Witnesses being decremented should always be either -1 - // (never incremented or decremented) or equal to the height - // of the block being removed (indexHeight) - assert((nd->witnessHeight == -1) || (nd->witnessHeight == indexHeight)); - if (nd->witnesses.size() > 0) { - nd->witnesses.pop_front(); + + LOCK2(cs_wallet,cs_main); + + int startHeight = VerifyAndSetInitialWitness(pindex, witnessOnly) + 1; + + if (startHeight > pindex->nHeight || witnessOnly) { + return; + } + + uint256 sproutRoot; + uint256 saplingRoot; + CBlockIndex* pblockindex = chainActive[startHeight]; + int height = chainActive.Height(); + + while (pblockindex) { + + if (pblockindex->nHeight % 100 == 0 && pblockindex->nHeight < height - 5) { + LogPrintf("Building Witnesses for block %i %.4f complete\n", pblockindex->nHeight, pblockindex->nHeight / double(height)); + } + + SproutMerkleTree sproutTree; + sproutRoot = pblockindex->pprev->hashFinalSproutRoot; + pcoinsTip->GetSproutAnchorAt(sproutRoot, sproutTree); + + SaplingMerkleTree saplingTree; + saplingRoot = pblockindex->pprev->hashFinalSaplingRoot; + pcoinsTip->GetSaplingAnchorAt(saplingRoot, saplingTree); + + //Cycle through blocks and transactions building sapling tree until the commitment needed is reached + CBlock block; + ReadBlockFromDisk(block, pblockindex, Params().GetConsensus()); + + for (std::pair& wtxItem : mapWallet) { + + if (wtxItem.second.mapSproutNoteData.empty() && wtxItem.second.mapSaplingNoteData.empty()) + continue; + + if (wtxItem.second.GetDepthInMainChain() > 0) { + + //Sprout + for (mapSproutNoteData_t::value_type& item : wtxItem.second.mapSproutNoteData) { + auto* nd = &(item.second); + if (nd->nullifier && nd->witnessHeight == pblockindex->nHeight - 1 + && GetSproutSpendDepth(*item.second.nullifier) <= WITNESS_CACHE_SIZE) { + + + nd->witnesses.push_front(nd->witnesses.front()); + while (nd->witnesses.size() > WITNESS_CACHE_SIZE) { + nd->witnesses.pop_back(); } - // indexHeight is the height of the block being removed, so - // the new witness cache height is one below it. - nd->witnessHeight = indexHeight - 1; + + for (const CTransaction& tx : block.vtx) { + for (size_t i = 0; i < tx.vJoinSplit.size(); i++) { + const JSDescription& jsdesc = tx.vJoinSplit[i]; + for (uint8_t j = 0; j < jsdesc.commitments.size(); j++) { + const uint256& note_commitment = jsdesc.commitments[j]; + nd->witnesses.front().append(note_commitment); + } + } + } + nd->witnessHeight = pblockindex->nHeight; + } } - // Check the validity of the cache - // Technically if there are notes witnessed above the current - // height, their cache will now be invalid (relative to the new - // value of nWitnessCacheSize). However, this would only occur - // during a reindex, and by the time the reindex reaches the tip - // of the chain again, the existing witness caches will be valid - // again. - // We don't set nWitnessCacheSize to zero at the start of the - // reindex because the on-disk blocks had already resulted in a - // chain that didn't trigger the assertion below. - if (nd->witnessHeight < indexHeight) { - // Subtract 1 to compare to what nWitnessCacheSize will be after - // decrementing. - assert((nWitnessCacheSize - 1) >= nd->witnesses.size()); + + //Sapling + for (mapSaplingNoteData_t::value_type& item : wtxItem.second.mapSaplingNoteData) { + auto* nd = &(item.second); + if (nd->nullifier && nd->witnessHeight == pblockindex->nHeight - 1 + && GetSaplingSpendDepth(*item.second.nullifier) <= WITNESS_CACHE_SIZE) { + + nd->witnesses.push_front(nd->witnesses.front()); + while (nd->witnesses.size() > WITNESS_CACHE_SIZE) { + nd->witnesses.pop_back(); + } + + for (const CTransaction& tx : block.vtx) { + for (uint32_t i = 0; i < tx.vShieldedOutput.size(); i++) { + const uint256& note_commitment = tx.vShieldedOutput[i].cm; + nd->witnesses.front().append(note_commitment); + } + } + nd->witnessHeight = pblockindex->nHeight; + } } + } } -} -void CWallet::DecrementNoteWitnesses(const CBlockIndex* pindex) -{ - LOCK(cs_wallet); - for (std::pair& wtxItem : mapWallet) { - ::DecrementNoteWitnesses(wtxItem.second.mapSproutNoteData, pindex->nHeight, nWitnessCacheSize); - ::DecrementNoteWitnesses(wtxItem.second.mapSaplingNoteData, pindex->nHeight, nWitnessCacheSize); - } - nWitnessCacheSize -= 1; - // TODO: If nWitnessCache is zero, we need to regenerate the caches (#1302) - assert(nWitnessCacheSize > 0); + if (pblockindex == pindex) + break; + + pblockindex = chainActive.Next(pblockindex); + + } - // For performance reasons, we write out the witness cache in - // CWallet::SetBestChain() (which also ensures that overall consistency - // of the wallet.dat is maintained). } bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) @@ -1504,6 +1695,48 @@ void CWallet::UpdateNullifierNoteMapWithTx(const CWalletTx& wtx) } } +/** + * Update mapSproutNullifiersToNotes, computing the nullifier from a cached witness if necessary. + */ +void CWallet::UpdateSproutNullifierNoteMapWithTx(CWalletTx& wtx) { + LOCK(cs_wallet); + + ZCNoteDecryption dec; + for (mapSproutNoteData_t::value_type& item : wtx.mapSproutNoteData) { + SproutNoteData nd = item.second; + + if (nd.witnesses.empty()) { + // If there are no witnesses, erase the nullifier and associated mapping. + if (nd.nullifier) { + mapSproutNullifiersToNotes.erase(nd.nullifier.get()); + } + nd.nullifier = boost::none; + } + else { + if (GetNoteDecryptor(nd.address, dec)) { + auto i = item.first.js; + auto hSig = wtx.vJoinSplit[i].h_sig( + *pzcashParams, wtx.joinSplitPubKey); + auto optNullifier = GetSproutNoteNullifier( + wtx.vJoinSplit[i], + item.second.address, + dec, + hSig, + item.first.n); + + if (!optNullifier) { + // This should not happen. If it does, maybe the position has been corrupted or miscalculated? + assert(false); + } + + uint256 nullifier = optNullifier.get(); + mapSproutNullifiersToNotes[nullifier] = item.first; + item.second.nullifier = nullifier; + } + } + } +} + /** * Update mapSaplingNullifiersToNotes, computing the nullifier from a cached witness if necessary. */ @@ -1551,13 +1784,14 @@ void CWallet::UpdateSaplingNullifierNoteMapWithTx(CWalletTx& wtx) { * Iterate over transactions in a block and update the cached Sapling nullifiers * for transactions which belong to the wallet. */ -void CWallet::UpdateSaplingNullifierNoteMapForBlock(const CBlock *pblock) { +void CWallet::UpdateNullifierNoteMapForBlock(const CBlock *pblock) { LOCK(cs_wallet); for (const CTransaction& tx : pblock->vtx) { auto hash = tx.GetHash(); bool txIsOurs = mapWallet.count(hash); if (txIsOurs) { + UpdateSproutNullifierNoteMapWithTx(mapWallet[hash]); UpdateSaplingNullifierNoteMapWithTx(mapWallet[hash]); } } @@ -2703,6 +2937,298 @@ void CWallet::WitnessNoteCommitment(std::vector commitments, } } } +/** + * Reorder the transactions based on block hieght and block index. + * Transactions can get out of order when they are deleted and subsequently + * re-added during intial load rescan. + */ + +void CWallet::ReorderWalletTransactions(std::map, CWalletTx> &mapSorted, int64_t &maxOrderPos) { + LOCK2(cs_wallet,cs_main); + + int maxSortNumber = chainActive.Tip()->nHeight + 1; + + for (map::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + { + CWalletTx wtx = it->second; + int confirms = wtx.GetDepthInMainChain(); + maxOrderPos = max(maxOrderPos, wtx.nOrderPos); + + if (confirms > 0) { + int wtxHeight = mapBlockIndex[wtx.hashBlock]->nHeight; + auto key = std::make_pair(wtxHeight, wtx.nIndex); + mapSorted.insert(make_pair(key, wtx)); + } + else { + auto key = std::make_pair(maxSortNumber, 0); + mapSorted.insert(std::make_pair(key, wtx)); + maxSortNumber++; + } + } +} + /**Update the nOrderPos with passed in ordered map. + */ + +void CWallet::UpdateWalletTransactionOrder(std::map, CWalletTx> &mapSorted, bool resetOrder) { + LOCK2(cs_wallet,cs_main); + + int64_t previousPosition = 0; + std::map mapUpdatedTxs; + + //Check the postion of each transaction relative to the previous one. + for (map, CWalletTx>::iterator it = mapSorted.begin(); it != mapSorted.end(); ++it) { + CWalletTx wtx = it->second; + const uint256 wtxid = wtx.GetHash(); + + if (wtx.nOrderPos <= previousPosition || resetOrder) { + previousPosition++; + wtx.nOrderPos = previousPosition; + mapUpdatedTxs.insert(std::make_pair(wtxid, wtx)); + } + else { + previousPosition = wtx.nOrderPos; + } + } + + //Update transactions nOrderPos for transactions that changed + CWalletDB walletdb(strWalletFile, "r+", false); + for (map::iterator it = mapUpdatedTxs.begin(); it != mapUpdatedTxs.end(); ++it) { + CWalletTx wtx = it->second; + LogPrint("deletetx","Reorder Tx - Updating Positon to %i for Tx %s\n ", wtx.nOrderPos, wtx.GetHash().ToString()); + wtx.WriteToDisk(&walletdb); + mapWallet[wtx.GetHash()].nOrderPos = wtx.nOrderPos; + } + + //Update Next Wallet Tx Positon + nOrderPosNext = previousPosition++; + CWalletDB(strWalletFile).WriteOrderPosNext(nOrderPosNext); + LogPrint("deletetx","Reorder Tx - Total Transactions Reordered %i, Next Position %i\n ", mapUpdatedTxs.size(), nOrderPosNext); + +} + +/** + * Delete transactions from the Wallet + */ +void CWallet::DeleteTransactions(std::vector &removeTxs) { + LOCK(cs_wallet); + + CWalletDB walletdb(strWalletFile, "r+", false); + + for (int i = 0; i< removeTxs.size(); i++) { + if (mapWallet.erase(removeTxs[i])) { + walletdb.EraseTx(removeTxs[i]); + LogPrint("deletetx","Delete Tx - Deleting tx %s, %i.\n", removeTxs[i].ToString(),i); + } else { + LogPrint("deletetx","Delete Tx - Deleting tx %failed.\n", removeTxs[i].ToString()); + return; + } + } +} + +void CWallet::DeleteWalletTransactions(const CBlockIndex* pindex) { + + LOCK2(cs_wallet,cs_main); + + int nDeleteAfter = (int)fDeleteTransactionsAfterNBlocks; + bool runCompact = false; + + if (pindex && fTxDeleteEnabled) { + + //Check for acentries - exit function if found + { + std::list acentries; + CWalletDB walletdb(strWalletFile); + walletdb.ListAccountCreditDebit("*", acentries); + if (acentries.size() > 0) { + LogPrintf("deletetx not compatible to account entries\n"); + return; + } + } + //delete transactions + + //Sort Transactions by block and block index + int64_t maxOrderPos = 0; + std::map, CWalletTx> mapSorted; + ReorderWalletTransactions(mapSorted, maxOrderPos); + if (maxOrderPos > int64_t(mapSorted.size())*10) { + //reset the postion when the max postion is 10x bigger than the + //number of transactions in the wallet + LogPrint("deletetx","Reorder Tx - maxOrderPos %i mapSorted Size %i\n", maxOrderPos, int64_t(mapSorted.size())*10); + UpdateWalletTransactionOrder(mapSorted, true); + } + else { + UpdateWalletTransactionOrder(mapSorted, false); + } + + //Process Transactions in sorted order + int txConflictCount = 0; + int txUnConfirmed = 0; + int txCount = 0; + int txSaveCount = 0; + std::vector removeTxs; + + for (auto & item : mapSorted) + { + + CWalletTx& wtx = item.second; + const uint256& wtxid = wtx.GetHash(); + bool deleteTx = true; + txCount += 1; + int wtxDepth = wtx.GetDepthInMainChain(); + + //Keep anything newer than N Blocks + if (wtxDepth == 0) + txUnConfirmed++; + + if (wtxDepth < nDeleteAfter && wtxDepth >= 0) { + LogPrint("deletetx","DeleteTx - Transaction above minimum depth, tx %s\n", wtx.GetHash().ToString()); + deleteTx = false; + txSaveCount++; + continue; + } else if (wtxDepth == -1) { + //Enabled by default + if (!fTxConflictDeleteEnabled) { + LogPrint("deletetx","DeleteTx - Conflict delete is not enabled tx %s\n", wtx.GetHash().ToString()); + deleteTx = false; + txSaveCount++; + continue; + } else { + txConflictCount++; + } + } else { + + //Check for unspent inputs or spend less than N Blocks ago. (Sapling) + for (auto & pair : wtx.mapSaplingNoteData) { + SaplingNoteData nd = pair.second; + if (!nd.nullifier || pwalletMain->GetSaplingSpendDepth(*nd.nullifier) <= fDeleteTransactionsAfterNBlocks) { + LogPrint("deletetx","DeleteTx - Unspent sapling input tx %s\n", wtx.GetHash().ToString()); + deleteTx = false; + continue; + } + } + + if (!deleteTx) { + txSaveCount++; + continue; + } + + //Check for outputs that no longer have parents in the wallet. Exclude parents that are in the same transaction. (Sapling) + for (int i = 0; i < wtx.vShieldedSpend.size(); i++) { + const SpendDescription& spendDesc = wtx.vShieldedSpend[i]; + if (pwalletMain->IsSaplingNullifierFromMe(spendDesc.nullifier)) { + const uint256& parentHash = pwalletMain->mapSaplingNullifiersToNotes[spendDesc.nullifier].hash; + const CWalletTx* parent = pwalletMain->GetWalletTx(parentHash); + if (parent != NULL && parentHash != wtxid) { + LogPrint("deletetx","DeleteTx - Parent of sapling tx %s found\n", wtx.GetHash().ToString()); + deleteTx = false; + continue; + } + } + } + + if (!deleteTx) { + txSaveCount++; + continue; + } + + //Check for unspent inputs or spend less than N Blocks ago. (Sprout) + for (auto & pair : wtx.mapSproutNoteData) { + SproutNoteData nd = pair.second; + if (!nd.nullifier || pwalletMain->GetSproutSpendDepth(*nd.nullifier) <= fDeleteTransactionsAfterNBlocks) { + LogPrint("deletetx","DeleteTx - Unspent sprout input tx %s\n", wtx.GetHash().ToString()); + deleteTx = false; + continue; + } + } + + if (!deleteTx) { + txSaveCount++; + continue; + } + + //Check for outputs that no longer have parents in the wallet. Exclude parents that are in the same transaction. (Sprout) + for (int i = 0; i < wtx.vJoinSplit.size(); i++) { + const JSDescription& jsdesc = wtx.vJoinSplit[i]; + for (const uint256 &nullifier : jsdesc.nullifiers) { + // JSOutPoint op = pwalletMain->mapSproutNullifiersToNotes[nullifier]; + if (pwalletMain->IsSproutNullifierFromMe(nullifier)) { + const uint256& parentHash = pwalletMain->mapSproutNullifiersToNotes[nullifier].hash; + const CWalletTx* parent = pwalletMain->GetWalletTx(parentHash); + if (parent != NULL && parentHash != wtxid) { + LogPrint("deletetx","DeleteTx - Parent of sprout tx %s found\n", wtx.GetHash().ToString()); + deleteTx = false; + continue; + } + } + } + } + + if (!deleteTx) { + txSaveCount++; + continue; + } + + //Check for unspent inputs or spend less than N Blocks ago. (Transparent) + for (unsigned int i = 0; i < wtx.vout.size(); i++) { + CTxDestination address; + ExtractDestination(wtx.vout[i].scriptPubKey, address); + if(IsMine(wtx.vout[i])) { + if (pwalletMain->GetSpendDepth(wtx.GetHash(), i) <= fDeleteTransactionsAfterNBlocks) { + LogPrint("deletetx","DeleteTx - Unspent transparent input tx %s\n", wtx.GetHash().ToString()); + deleteTx = false; + continue; + } + } + } + + if (!deleteTx) { + txSaveCount++; + continue; + } + + //Chcek for output with that no longer have parents in the wallet. (Transparent) + for (int i = 0; i < wtx.vin.size(); i++) { + const CTxIn& txin = wtx.vin[i]; + const uint256& parentHash = txin.prevout.hash; + const CWalletTx* parent = pwalletMain->GetWalletTx(txin.prevout.hash); + if (parent != NULL && parentHash != wtxid) { + LogPrint("deletetx","DeleteTx - Parent of transparent tx %s found\n", wtx.GetHash().ToString()); + deleteTx = false; + continue; + } + } + + if (!deleteTx) { + txSaveCount++; + continue; + } + + //Keep Last N Transactions + if (mapSorted.size() - txCount < fKeepLastNTransactions + txConflictCount + txUnConfirmed) { + LogPrint("deletetx","DeleteTx - Transaction set position %i, tx %s\n", mapSorted.size() - txCount, wtxid.ToString()); + deleteTx = false; + txSaveCount++; + continue; + } + } + + //Collect everything else for deletion + if (deleteTx && int(removeTxs.size()) < MAX_DELETE_TX_SIZE) { + removeTxs.push_back(wtxid); + runCompact = true; + } + } + + //Delete Transactions from wallet + DeleteTransactions(removeTxs); + LogPrintf("Delete Tx - Total Transaction Count %i, Transactions Deleted %i\n ", txCount, int(removeTxs.size())); + + //Compress Wallet + if (runCompact) + CWalletDB::Compact(bitdb,strWalletFile); + } +} + /** * Scan the block chain (starting in pindexStart) for transactions @@ -2717,8 +3243,6 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) CBlockIndex* pindex = pindexStart; - std::vector myTxHashes; - { LOCK2(cs_main, cs_wallet); @@ -2730,6 +3254,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup double dProgressStart = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex, false); double dProgressTip = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip(), false); + while (pindex) { if (pindex->nHeight % 100 == 0 && dProgressTip - dProgressStart > 0.0) @@ -2740,7 +3265,6 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) BOOST_FOREACH(CTransaction& tx, block.vtx) { if (AddToWalletIfInvolvingMe(tx, &block, fUpdate)) { - myTxHashes.push_back(tx.GetHash()); ret++; } } @@ -2755,27 +3279,22 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) assert(pcoinsTip->GetSaplingAnchorAt(pindex->pprev->hashFinalSaplingRoot, saplingTree)); } } - // Increment note witness caches - ChainTipAdded(pindex, &block, sproutTree, saplingTree); - pindex = chainActive.Next(pindex); + // Build inital witness caches + BuildWitnessCache(pindex, true); + + //Delete Transactions + if (pindex->nHeight % fDeleteInterval == 0) + DeleteWalletTransactions(pindex); + if (GetTime() >= nNow + 60) { nNow = GetTime(); LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex)); } + pindex = chainActive.Next(pindex); } - - // After rescanning, persist Sapling note data that might have changed, e.g. nullifiers. - // Do not flush the wallet here for performance reasons. - CWalletDB walletdb(strWalletFile, "r+", false); - for (auto hash : myTxHashes) { - CWalletTx wtx = mapWallet[hash]; - if (!wtx.mapSaplingNoteData.empty()) { - if (!wtx.WriteToDisk(&walletdb)) { - LogPrintf("Rescanning... WriteToDisk failed to update Sapling note data for: %s\n", hash.ToString()); - } - } - } + //Update all witness caches + BuildWitnessCache(chainActive.Tip(), false); ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI } @@ -2816,7 +3335,10 @@ void CWallet::ReacceptWalletTransactions() bool CWalletTx::RelayWalletTransaction(std::string strCommand) { - assert(pwallet->GetBroadcastTransactions()); + { + LOCK(pwalletMain->cs_wallet); + assert(pwalletMain->GetBroadcastTransactions()); + } if (!IsCoinBase()) { if (GetDepthInMainChain() == 0) { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 3ab7b4d71d4..ae8766fcfd9 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -48,6 +48,12 @@ extern unsigned int nTxConfirmTarget; extern bool bSpendZeroConfChange; extern bool fSendFreeTransactions; extern bool fPayAtLeastCustomFee; +extern bool fTxDeleteEnabled; +extern bool fTxConflictDeleteEnabled; +extern int fDeleteInterval; +extern unsigned int fDeleteTransactionsAfterNBlocks; +extern unsigned int fKeepLastNTransactions; + //! -paytxfee default static const CAmount DEFAULT_TRANSACTION_FEE = 0; @@ -69,6 +75,18 @@ static const unsigned int WITNESS_CACHE_SIZE = MAX_REORG_LENGTH + 1; //! Size of HD seed in bytes static const size_t HD_WALLET_SEED_LENGTH = 32; +//Default Transaction Rentention N-BLOCKS +static const int DEFAULT_TX_DELETE_INTERVAL = 1000; + +//Default Transaction Rentention N-BLOCKS +static const unsigned int DEFAULT_TX_RETENTION_BLOCKS = 10000; + +//Default Retenion Last N-Transactions +static const unsigned int DEFAULT_TX_RETENTION_LASTTX = 200; + +//Amount of transactions to delete per run while syncing +static const int MAX_DELETE_TX_SIZE = 50000; + class CBlockIndex; class CCoinControl; class COutput; @@ -250,15 +268,18 @@ class SproutNoteData * -1 as a placeholder. The next time CWallet::ChainTip is called, we can * determine what height the witness cache for this note is valid for (even * if no witnesses were cached), and so can set the correct value in - * CWallet::IncrementNoteWitnesses and CWallet::DecrementNoteWitnesses. + * CWallet::BuildWitnessCache and CWallet::DecrementNoteWitnesses. */ int witnessHeight; - SproutNoteData() : address(), nullifier(), witnessHeight {-1} { } + //In Memory Only + bool witnessRootValidated; + + SproutNoteData() : address(), nullifier(), witnessHeight {-1}, witnessRootValidated {false} { } SproutNoteData(libzcash::SproutPaymentAddress a) : - address {a}, nullifier(), witnessHeight {-1} { } + address {a}, nullifier(), witnessHeight {-1}, witnessRootValidated {false} { } SproutNoteData(libzcash::SproutPaymentAddress a, uint256 n) : - address {a}, nullifier {n}, witnessHeight {-1} { } + address {a}, nullifier {n}, witnessHeight {-1}, witnessRootValidated {false} { } ADD_SERIALIZE_METHODS; @@ -291,15 +312,18 @@ class SaplingNoteData * We initialize the height to -1 for the same reason as we do in SproutNoteData. * See the comment in that class for a full description. */ - SaplingNoteData() : witnessHeight {-1}, nullifier() { } - SaplingNoteData(libzcash::SaplingIncomingViewingKey ivk) : ivk {ivk}, witnessHeight {-1}, nullifier() { } - SaplingNoteData(libzcash::SaplingIncomingViewingKey ivk, uint256 n) : ivk {ivk}, witnessHeight {-1}, nullifier(n) { } + SaplingNoteData() : witnessHeight {-1}, nullifier(), witnessRootValidated {false} { } + SaplingNoteData(libzcash::SaplingIncomingViewingKey ivk) : ivk {ivk}, witnessHeight {-1}, nullifier(), witnessRootValidated {false} { } + SaplingNoteData(libzcash::SaplingIncomingViewingKey ivk, uint256 n) : ivk {ivk}, witnessHeight {-1}, nullifier(n), witnessRootValidated {false} { } std::list witnesses; int witnessHeight; libzcash::SaplingIncomingViewingKey ivk; boost::optional nullifier; + //In Memory Only + bool witnessRootValidated; + ADD_SERIALIZE_METHODS; template @@ -844,17 +868,20 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface */ int64_t nWitnessCacheSize; bool fSaplingMigrationEnabled = false; + bool fSaplingConsolidationEnabled = false; void ClearNoteWitnessCache(); protected: + + int SproutWitnessMinimumHeight(const uint256& nullifier, int nWitnessHeight, int nMinimumHeight); + int SaplingWitnessMinimumHeight(const uint256& nullifier, int nWitnessHeight, int nMinimumHeight); + /** * pindex is the new tip being connected. */ - void IncrementNoteWitnesses(const CBlockIndex* pindex, - const CBlock* pblock, - SproutMerkleTree& sproutTree, - SaplingMerkleTree& saplingTree); + int VerifyAndSetInitialWitness(const CBlockIndex* pindex, bool witnessOnly); + void BuildWitnessCache(const CBlockIndex* pindex, bool witnessOnly); /** * pindex is the old tip being disconnected. */ @@ -909,7 +936,6 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface private: template void SyncMetaData(std::pair::iterator, typename TxSpendMap::iterator>); - void ChainTipAdded(const CBlockIndex *pindex, const CBlock *pblock, SproutMerkleTree sproutTree, SaplingMerkleTree saplingTree); protected: bool UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx); @@ -1050,8 +1076,11 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, std::vector vCoins, std::set >& setCoinsRet, CAmount& nValueRet) const; bool IsSpent(const uint256& hash, unsigned int n) const; + unsigned int GetSpendDepth(const uint256& hash, unsigned int n) const; bool IsSproutSpent(const uint256& nullifier) const; + unsigned int GetSproutSpendDepth(const uint256& nullifier) const; bool IsSaplingSpent(const uint256& nullifier) const; + unsigned int GetSaplingSpendDepth(const uint256& nullifier) const; bool IsLockedCoin(uint256 hash, unsigned int n) const; void LockCoin(COutPoint& output); @@ -1204,8 +1233,9 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface void MarkDirty(); bool UpdateNullifierNoteMap(); void UpdateNullifierNoteMapWithTx(const CWalletTx& wtx); + void UpdateSproutNullifierNoteMapWithTx(CWalletTx& wtx); void UpdateSaplingNullifierNoteMapWithTx(CWalletTx& wtx); - void UpdateSaplingNullifierNoteMapForBlock(const CBlock* pblock); + void UpdateNullifierNoteMapForBlock(const CBlock* pblock); bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb); void SyncTransaction(const CTransaction& tx, const CBlock* pblock); bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate); @@ -1214,6 +1244,10 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface std::vector commitments, std::vector>& witnesses, uint256 &final_anchor); + void ReorderWalletTransactions(std::map, CWalletTx> &mapSorted, int64_t &maxOrderPos); + void UpdateWalletTransactionOrder(std::map, CWalletTx> &mapSorted, bool resetOrder); + void DeleteTransactions(std::vector &removeTxs); + void DeleteWalletTransactions(const CBlockIndex* pindex); int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); void ReacceptWalletTransactions(); void ResendWalletTransactions(int64_t nBestBlockTime); From 07f3a55ee17cdf9afdb0ba4870fedc8d5a52b96e Mon Sep 17 00:00:00 2001 From: cryptoforge Date: Thu, 6 Feb 2020 12:52:31 -0800 Subject: [PATCH 370/395] Sapling Consolidation --- src/Makefile.am | 2 + src/init.cpp | 19 ++ ...asyncrpcoperation_saplingconsolidation.cpp | 214 ++++++++++++++++++ .../asyncrpcoperation_saplingconsolidation.h | 37 +++ src/wallet/wallet.cpp | 32 +++ src/wallet/wallet.h | 5 + 6 files changed, 309 insertions(+) create mode 100644 src/wallet/asyncrpcoperation_saplingconsolidation.cpp create mode 100644 src/wallet/asyncrpcoperation_saplingconsolidation.h diff --git a/src/Makefile.am b/src/Makefile.am index 45df8080b85..82060c868ab 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -219,6 +219,7 @@ BITCOIN_CORE_H = \ wallet/asyncrpcoperation_common.h \ wallet/asyncrpcoperation_mergetoaddress.h \ wallet/asyncrpcoperation_saplingmigration.h \ + wallet/asyncrpcoperation_saplingconsolidation.h \ wallet/asyncrpcoperation_sendmany.h \ wallet/asyncrpcoperation_shieldcoinbase.h \ wallet/crypter.h \ @@ -320,6 +321,7 @@ libbitcoin_wallet_a_SOURCES = \ wallet/asyncrpcoperation_common.cpp \ wallet/asyncrpcoperation_mergetoaddress.cpp \ wallet/asyncrpcoperation_saplingmigration.cpp \ + wallet/asyncrpcoperation_saplingconsolidation.cpp \ wallet/asyncrpcoperation_sendmany.cpp \ wallet/asyncrpcoperation_shieldcoinbase.cpp \ wallet/crypter.cpp \ diff --git a/src/init.cpp b/src/init.cpp index 7a68a4e30f1..fd7dfe88a33 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -48,6 +48,7 @@ #include "key_io.h" #include "wallet/wallet.h" #include "wallet/walletdb.h" +#include "wallet/asyncrpcoperation_saplingconsolidation.h" #endif #include #include @@ -427,6 +428,9 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-keypool=", strprintf(_("Set key pool size to (default: %u)"), 100)); strUsage += HelpMessageOpt("-migration", _("Enable the Sprout to Sapling migration")); strUsage += HelpMessageOpt("-migrationdestaddress=", _("Set the Sapling migration address")); + strUsage += HelpMessageOpt("-consolidation", _("Enable auto Sapling note consolidation")); + strUsage += HelpMessageOpt("-consolidatesaplingaddress=", _("Specify Sapling Address to Consolidate. (default: all)")); + strUsage += HelpMessageOpt("-consolidationtxfee", strprintf(_("Fee amount in Satoshis used send consolidation transactions. (default %i)"), DEFAULT_CONSOLIDATION_FEE)); strUsage += HelpMessageOpt("-deletetx", _("Enable Old Transaction Deletion")); strUsage += HelpMessageOpt("-deleteinterval", strprintf(_("Delete transaction every blocks during inital block download (default: %i)"), DEFAULT_TX_DELETE_INTERVAL)); strUsage += HelpMessageOpt("-keeptxnum", strprintf(_("Keep the last transactions (default: %i)"), DEFAULT_TX_RETENTION_LASTTX)); @@ -1729,6 +1733,21 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // Set sapling migration status pwalletMain->fSaplingMigrationEnabled = GetBoolArg("-migration", false); + //Set Sapling Consolidation + pwalletMain->fSaplingConsolidationEnabled = GetBoolArg("-consolidation", false); + fConsolidationTxFee = GetArg("-consolidationtxfee", DEFAULT_CONSOLIDATION_FEE); + fConsolidationMapUsed = !mapMultiArgs["-consolidatesaplingaddress"].empty(); + + //Validate Sapling Addresses + vector& vaddresses = mapMultiArgs["-consolidatesaplingaddress"]; + for (int i = 0; i < vaddresses.size(); i++) { + LogPrintf("Consolidating Sapling Address: %s\n", vaddresses[i]); + auto zAddress = DecodePaymentAddress(vaddresses[i]); + if (!IsValidPaymentAddress(zAddress)) { + return InitError("Invalid consolidation address"); + } + } + //Set Transaction Deletion Options fTxDeleteEnabled = GetBoolArg("-deletetx", false); fTxConflictDeleteEnabled = GetBoolArg("-deleteconflicttx", true); diff --git a/src/wallet/asyncrpcoperation_saplingconsolidation.cpp b/src/wallet/asyncrpcoperation_saplingconsolidation.cpp new file mode 100644 index 00000000000..cd804a4929b --- /dev/null +++ b/src/wallet/asyncrpcoperation_saplingconsolidation.cpp @@ -0,0 +1,214 @@ +#include "assert.h" +#include "boost/variant/static_visitor.hpp" +#include "asyncrpcoperation_saplingconsolidation.h" +#include "init.h" +#include "key_io.h" +#include "rpc/protocol.h" +#include "random.h" +#include "sync.h" +#include "tinyformat.h" +#include "transaction_builder.h" +#include "util.h" +#include "utilmoneystr.h" +#include "wallet.h" + +CAmount fConsolidationTxFee = DEFAULT_CONSOLIDATION_FEE; +bool fConsolidationMapUsed = false; +const int CONSOLIDATION_EXPIRY_DELTA = 15; + + +AsyncRPCOperation_saplingconsolidation::AsyncRPCOperation_saplingconsolidation(int targetHeight) : targetHeight_(targetHeight) {} + +AsyncRPCOperation_saplingconsolidation::~AsyncRPCOperation_saplingconsolidation() {} + +void AsyncRPCOperation_saplingconsolidation::main() { + if (isCancelled()) + return; + + set_state(OperationStatus::EXECUTING); + start_execution_clock(); + + bool success = false; + + try { + success = main_impl(); + } catch (const UniValue& objError) { + int code = find_value(objError, "code").get_int(); + std::string message = find_value(objError, "message").get_str(); + set_error_code(code); + set_error_message(message); + } catch (const runtime_error& e) { + set_error_code(-1); + set_error_message("runtime error: " + string(e.what())); + } catch (const logic_error& e) { + set_error_code(-1); + set_error_message("logic error: " + string(e.what())); + } catch (const exception& e) { + set_error_code(-1); + set_error_message("general exception: " + string(e.what())); + } catch (...) { + set_error_code(-2); + set_error_message("unknown error"); + } + + stop_execution_clock(); + + if (success) { + set_state(OperationStatus::SUCCESS); + } else { + set_state(OperationStatus::FAILED); + } + + std::string s = strprintf("%s: Sapling Consolidation transaction created. (status=%s", getId(), getStateAsString()); + if (success) { + s += strprintf(", success)\n"); + } else { + s += strprintf(", error=%s)\n", getErrorMessage()); + } + + LogPrintf("%s", s); +} + +bool AsyncRPCOperation_saplingconsolidation::main_impl() { + LogPrint("zrpcunsafe", "%s: Beginning AsyncRPCOperation_saplingconsolidation.\n", getId()); + auto consensusParams = Params().GetConsensus(); + auto nextActivationHeight = NextActivationHeight(targetHeight_, consensusParams); + if (nextActivationHeight && targetHeight_ + CONSOLIDATION_EXPIRY_DELTA >= nextActivationHeight.get()) { + LogPrint("zrpcunsafe", "%s: Consolidation txs would be created before a NU activation but may expire after. Skipping this round.\n", getId()); + setConsolidationResult(0, 0, std::vector()); + return true; + } + + std::vector sproutEntries; + std::vector saplingEntries; + std::set addresses; + { + LOCK2(cs_main, pwalletMain->cs_wallet); + // We set minDepth to 11 to avoid unconfirmed notes and in anticipation of specifying + // an anchor at height N-10 for each Sprout JoinSplit description + // Consider, should notes be sorted? + pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, "", 11); + if (fConsolidationMapUsed) { + const vector& v = mapMultiArgs["-consolidatesaplingaddress"]; + for(int i = 0; i < v.size(); i++) { + auto zAddress = DecodePaymentAddress(v[i]); + if (boost::get(&zAddress) != nullptr) { + libzcash::SaplingPaymentAddress saplingAddress = boost::get(zAddress); + addresses.insert(saplingAddress ); + } + } + } else { + pwalletMain->GetSaplingPaymentAddresses(addresses); + } + } + + int numTxCreated = 0; + std::vector consolidationTxIds; + CAmount amountConsolidated = 0; + CCoinsViewCache coinsView(pcoinsTip); + + for (auto addr : addresses) { + libzcash::SaplingExtendedSpendingKey extsk; + if (pwalletMain->GetSaplingExtendedSpendingKey(addr, extsk)) { + + std::vector fromNotes; + CAmount amountToSend = 0; + int maxQuantity = rand() % 35 + 10; + for (const SaplingNoteEntry& saplingEntry : saplingEntries) { + + libzcash::SaplingIncomingViewingKey ivk; + pwalletMain->GetSaplingIncomingViewingKey(boost::get(saplingEntry.address), ivk); + + //Select Notes from that same address we will be sending to. + if (ivk == extsk.expsk.full_viewing_key().in_viewing_key()) { + amountToSend += CAmount(saplingEntry.note.value()); + fromNotes.push_back(saplingEntry); + } + + //Only use a randomly determined number of notes between 10 and 45 + if (fromNotes.size() >= maxQuantity) + break; + + } + + //random minimum 2 - 12 required + int minQuantity = rand() % 10 + 2; + if (fromNotes.size() < minQuantity) + continue; + + amountConsolidated += amountToSend; + auto builder = TransactionBuilder(consensusParams, targetHeight_, pwalletMain, pzcashParams, &coinsView, &cs_main); + builder.SetExpiryHeight(targetHeight_ + CONSOLIDATION_EXPIRY_DELTA); + LogPrint("zrpcunsafe", "%s: Beginning creating transaction with Sapling output amount=%s\n", getId(), FormatMoney(amountToSend - fConsolidationTxFee)); + + // Select Sapling notes + std::vector ops; + std::vector notes; + for (auto fromNote : fromNotes) { + ops.push_back(fromNote.op); + notes.push_back(fromNote.note); + } + + // Fetch Sapling anchor and witnesses + uint256 anchor; + std::vector> witnesses; + { + LOCK2(cs_main, pwalletMain->cs_wallet); + pwalletMain->GetSaplingNoteWitnesses(ops, witnesses, anchor); + } + + // Add Sapling spends + for (size_t i = 0; i < notes.size(); i++) { + if (!witnesses[i]) { + LogPrint("zrpcunsafe", "%s: Missing Witnesses. Stopping.\n", getId()); + break; + } + builder.AddSaplingSpend(extsk.expsk, notes[i], anchor, witnesses[i].get()); + } + + builder.SetFee(fConsolidationTxFee); + builder.AddSaplingOutput(extsk.expsk.ovk, addr, amountToSend - fConsolidationTxFee); + CTransaction tx = builder.Build().GetTxOrThrow(); + + if (isCancelled()) { + LogPrint("zrpcunsafe", "%s: Canceled. Stopping.\n", getId()); + break; + } + + pwalletMain->CommitConsolidationTx(tx); + LogPrint("zrpcunsafe", "%s: Committed consolidation transaction with txid=%s\n", getId(), tx.GetHash().ToString()); + amountConsolidated += amountToSend - fConsolidationTxFee; + consolidationTxIds.push_back(tx.GetHash().ToString()); + + } + } + + LogPrint("zrpcunsafe", "%s: Created %d transactions with total Sapling output amount=%s\n", getId(), numTxCreated, FormatMoney(amountConsolidated)); + setConsolidationResult(numTxCreated, amountConsolidated, consolidationTxIds); + return true; + +} + +void AsyncRPCOperation_saplingconsolidation::setConsolidationResult(int numTxCreated, const CAmount& amountConsolidated, const std::vector& consolidationTxIds) { + UniValue res(UniValue::VOBJ); + res.push_back(Pair("num_tx_created", numTxCreated)); + res.push_back(Pair("amount_consolidated", FormatMoney(amountConsolidated))); + UniValue txIds(UniValue::VARR); + for (const std::string& txId : consolidationTxIds) { + txIds.push_back(txId); + } + res.push_back(Pair("consolidation_txids", txIds)); + set_result(res); +} + +void AsyncRPCOperation_saplingconsolidation::cancel() { + set_state(OperationStatus::CANCELLED); +} + +UniValue AsyncRPCOperation_saplingconsolidation::getStatus() const { + UniValue v = AsyncRPCOperation::getStatus(); + UniValue obj = v.get_obj(); + obj.push_back(Pair("method", "saplingconsolidation")); + obj.push_back(Pair("target_height", targetHeight_)); + return obj; +} diff --git a/src/wallet/asyncrpcoperation_saplingconsolidation.h b/src/wallet/asyncrpcoperation_saplingconsolidation.h new file mode 100644 index 00000000000..c32e17fbe8c --- /dev/null +++ b/src/wallet/asyncrpcoperation_saplingconsolidation.h @@ -0,0 +1,37 @@ +#include "amount.h" +#include "asyncrpcoperation.h" +#include "univalue.h" +#include "zcash/Address.hpp" +#include "zcash/zip32.h" + +//Default fee used for consolidation transactions +static const CAmount DEFAULT_CONSOLIDATION_FEE = 0; +extern CAmount fConsolidationTxFee; +extern bool fConsolidationMapUsed; + +class AsyncRPCOperation_saplingconsolidation : public AsyncRPCOperation +{ +public: + AsyncRPCOperation_saplingconsolidation(int targetHeight); + virtual ~AsyncRPCOperation_saplingconsolidation(); + + // We don't want to be copied or moved around + AsyncRPCOperation_saplingconsolidation(AsyncRPCOperation_saplingconsolidation const&) = delete; // Copy construct + AsyncRPCOperation_saplingconsolidation(AsyncRPCOperation_saplingconsolidation&&) = delete; // Move construct + AsyncRPCOperation_saplingconsolidation& operator=(AsyncRPCOperation_saplingconsolidation const&) = delete; // Copy assign + AsyncRPCOperation_saplingconsolidation& operator=(AsyncRPCOperation_saplingconsolidation&&) = delete; // Move assign + + virtual void main(); + + virtual void cancel(); + + virtual UniValue getStatus() const; + +private: + int targetHeight_; + + bool main_impl(); + + void setConsolidationResult(int numTxCreated, const CAmount& amountConsolidated, const std::vector& consolidationTxIds); + +}; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 6bdfe0fd716..754b3ba3fd0 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -28,6 +28,7 @@ #include "zcash/Note.hpp" #include "crypter.h" #include "wallet/asyncrpcoperation_saplingmigration.h" +#include "wallet/asyncrpcoperation_saplingconsolidation.h" #include "zcash/zip32.h" #include @@ -577,6 +578,8 @@ void CWallet::ChainTip(const CBlockIndex *pindex, bool added) { if (added) { + // Prevent witness cache building as well as migration && consolidation transactions + // from being created when node is syncing after launch, // and also when node wakes up from suspension/hibernation and incoming blocks are old. bool initialDownloadCheck = IsInitialBlockDownload(Params()); if (!initialDownloadCheck && @@ -584,6 +587,7 @@ void CWallet::ChainTip(const CBlockIndex *pindex, { BuildWitnessCache(pindex, false); RunSaplingMigration(pindex->nHeight); + RunSaplingConsolidation(pindex->nHeight); DeleteWalletTransactions(pindex); } else { //Build intial witnesses on every block @@ -643,6 +647,34 @@ void CWallet::AddPendingSaplingMigrationTx(const CTransaction& tx) { pendingSaplingMigrationTxs.push_back(tx); } +void CWallet::RunSaplingConsolidation(int blockHeight) { + if (!Params().GetConsensus().NetworkUpgradeActive(blockHeight, Consensus::UPGRADE_SAPLING)) { + return; + } + LOCK(cs_wallet); + if (!fSaplingConsolidationEnabled) { + return; + } + + int consolidateInterval = rand() % 5 + 5; + if (blockHeight % consolidateInterval == 0) { + std::shared_ptr q = getAsyncRPCQueue(); + std::shared_ptr lastOperation = q->getOperationForId(saplingConsolidationOperationId); + if (lastOperation != nullptr) { + lastOperation->cancel(); + } + pendingSaplingConsolidationTxs.clear(); + std::shared_ptr operation(new AsyncRPCOperation_saplingconsolidation(blockHeight + 5)); + saplingConsolidationOperationId = operation->getId(); + q->addOperation(operation); + } +} + +void CWallet::CommitConsolidationTx(const CTransaction& tx) { + CWalletTx wtx(this, tx); + CommitTransaction(wtx, boost::none); +} + void CWallet::SetBestChain(const CBlockLocator& loc) { CWalletDB walletdb(strWalletFile); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index ae8766fcfd9..d8cf988825b 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -848,6 +848,9 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface std::vector pendingSaplingMigrationTxs; AsyncRPCOperationId saplingMigrationOperationId; + std::vector pendingSaplingConsolidationTxs; + AsyncRPCOperationId saplingConsolidationOperationId; + void AddToTransparentSpends(const COutPoint& outpoint, const uint256& wtxid); void AddToSproutSpends(const uint256& nullifier, const uint256& wtxid); void AddToSaplingSpends(const uint256& nullifier, const uint256& wtxid); @@ -1330,6 +1333,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface void ChainTip(const CBlockIndex *pindex, const CBlock *pblock, SproutMerkleTree sproutTree, SaplingMerkleTree saplingTree, bool added); void RunSaplingMigration(int blockHeight); void AddPendingSaplingMigrationTx(const CTransaction& tx); + void RunSaplingConsolidation(int blockHeight); + void CommitConsolidationTx(const CTransaction& tx); /** Saves witness caches and best block locator to disk. */ void SetBestChain(const CBlockLocator& loc); std::set> GetNullifiersForAddresses(const std::set & addresses); From b655f6640247dcc9ce0c65eb55b3387295fc72d0 Mon Sep 17 00:00:00 2001 From: cryptoforge Date: Thu, 6 Feb 2020 12:53:24 -0800 Subject: [PATCH 371/395] disable z_sendmany until witnesses are built --- src/rpc/protocol.h | 1 + src/rpc/server.cpp | 4 ++++ src/rpc/server.h | 2 ++ src/wallet/wallet.cpp | 7 +++++++ 4 files changed, 14 insertions(+) diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h index 5e12d0a4fa2..394c0beaaab 100644 --- a/src/rpc/protocol.h +++ b/src/rpc/protocol.h @@ -50,6 +50,7 @@ enum RPCErrorCode RPC_VERIFY_REJECTED = -26, //! Transaction or block was rejected by network rules RPC_VERIFY_ALREADY_IN_CHAIN = -27, //! Transaction already in chain RPC_IN_WARMUP = -28, //! Client still warming up + RPC_DISABLED_BEFORE_WITNESSES = -31, //! Disable before Note Witnesses have been built //! Aliases for backward compatibility RPC_TRANSACTION_ERROR = RPC_VERIFY_ERROR, diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 04301ffd514..f6aaf963463 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -31,6 +31,7 @@ using namespace RPCServer; using namespace std; +bool initWitnessesBuilt = false; static bool fRPCRunning = false; static bool fRPCInWarmup = true; static std::string rpcWarmupStatus("RPC server started"); @@ -441,6 +442,9 @@ UniValue CRPCTable::execute(const std::string &strMethod, const UniValue ¶ms if (!pcmd) throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found"); + if (!initWitnessesBuilt && pcmd->name == "z_sendmany") + throw JSONRPCError(RPC_DISABLED_BEFORE_WITNESSES, "RPC Command disabled until witnesses are built."); + g_rpcSignals.PreCommand(*pcmd); try diff --git a/src/rpc/server.h b/src/rpc/server.h index 63758f9dd93..bdcdc710603 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -20,6 +20,8 @@ #include +extern bool initWitnessesBuilt; + class AsyncRPCQueue; class CRPCCommand; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 754b3ba3fd0..d22d4cad041 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1238,6 +1238,7 @@ int CWallet::VerifyAndSetInitialWitness(const CBlockIndex* pindex, bool witnessO int nWitnessTxIncrement = 0; int nWitnessTotalTxCount = mapWallet.size(); int nMinimumHeight = pindex->nHeight; + bool walletHasNotes = false; //Use to enable z_sendmany when no notes are present for (std::pair& wtxItem : mapWallet) { nWitnessTxIncrement += 1; @@ -1246,6 +1247,7 @@ int CWallet::VerifyAndSetInitialWitness(const CBlockIndex* pindex, bool witnessO continue; if (wtxItem.second.GetDepthInMainChain() > 0) { + walletHasNotes = true; auto wtxHash = wtxItem.second.GetHash(); int wtxHeight = mapBlockIndex[wtxItem.second.hashBlock]->nHeight; @@ -1427,6 +1429,9 @@ int CWallet::VerifyAndSetInitialWitness(const CBlockIndex* pindex, bool witnessO } } } + //enable z_sendmany when the wallet has no Notes + if (!walletHasNotes) + initWitnessesBuilt = true; return nMinimumHeight; } @@ -1527,6 +1532,8 @@ void CWallet::BuildWitnessCache(const CBlockIndex* pindex, bool witnessOnly) } + //Set witnessBuilt to true to allow zsendmany to run + initWitnessesBuilt = true; } bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) From 3266db3132cfc9b829082c50569b8714942f58ee Mon Sep 17 00:00:00 2001 From: cryptoforge Date: Thu, 6 Feb 2020 12:54:19 -0800 Subject: [PATCH 372/395] Initalization update --- src/init.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index fd7dfe88a33..22c70762420 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -510,7 +510,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-regtest", "Enter regression test mode, which uses a special chain in which blocks can be solved instantly. " "This is intended for regression testing tools and app development."); } - // strUsage += HelpMessageOpt("-shrinkdebugfile", _("Shrink debug.log file on client startup (default: 1 when no -debug)")); + strUsage += HelpMessageOpt("-shrinkdebugfile", _("Shrink debug.log file on client startup (default: 1 when no -debug)")); strUsage += HelpMessageOpt("-testnet", _("Use the test network")); strUsage += HelpMessageGroup(_("Zeronode options:")); @@ -979,6 +979,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // ********************************************************* Step 3: parameter-to-internal-flags + fDebug = !mapMultiArgs["-debug"].empty(); // Special-case: if -debug=0/-nodebug is set, turn off debugging messages const vector& categories = mapMultiArgs["-debug"]; @@ -1259,12 +1260,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) threadGroup.create_thread(&ThreadScriptCheck); } - if (mapArgs.count("-sporkkey")) // spork priv key - { - if (!sporkManager.SetPrivKey(GetArg("-sporkkey", ""))) - return InitError(_("Unable to sign spork message, wrong key?")); - } - // Start the lightweight task scheduler thread CScheduler::Function serviceLoop = boost::bind(&CScheduler::serviceQueue, &scheduler); threadGroup.create_thread(boost::bind(&TraceThread, "scheduler", serviceLoop)); @@ -1280,9 +1275,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) threadGroup.create_thread(&ThreadShowMetricsScreen); } - // Initialize Zcash circuit parameters - ZC_LoadParams(chainparams); - /* Start the RPC server already. It will be started in "warmup" mode * and not really process calls already (but it will signify connections * that the server is there and will be ready later). Warmup mode will @@ -1294,6 +1286,16 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (!AppInitServers(threadGroup)) return InitError(_("Unable to start HTTP server. See debug log for details.")); } + uiInterface.InitMessage(_("Initializing...")); + + // Initialize Zcash circuit parameters + ZC_LoadParams(chainparams); + + if (mapArgs.count("-sporkkey")) // spork priv key + { + if (!sporkManager.SetPrivKey(GetArg("-sporkkey", ""))) + return InitError(_("Unable to sign spork message, wrong key?")); + } int64_t nStart; From 47e28af44ebbfdcc8bf5e1e99308ff4893c67cf2 Mon Sep 17 00:00:00 2001 From: cryptoforge Date: Thu, 6 Feb 2020 12:54:34 -0800 Subject: [PATCH 373/395] logging --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index ea7ac1f2c78..3ba398a69c5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4261,7 +4261,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, } } else { if (fDebug) - LogPrintf("CheckBlock(): Zeronode payment check skipped on sync - skipping IsBlockPayeeValid()\n"); + LogPrint("zeronode","CheckBlock(): Zeronode payment check skipped on sync - skipping IsBlockPayeeValid()\n"); } } From b86b3014d9c7c44d2c45d5f2b6d6fad036e367e2 Mon Sep 17 00:00:00 2001 From: cryptoforge Date: Thu, 6 Feb 2020 12:55:10 -0800 Subject: [PATCH 374/395] reduce MAX_REORG_LENGTH --- src/main.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.h b/src/main.h index 4ce919b9b9a..18e905cd1c1 100644 --- a/src/main.h +++ b/src/main.h @@ -66,7 +66,7 @@ static const bool DEFAULT_ALERTS = true; /** Minimum alert priority for enabling safe mode. */ static const int ALERT_PRIORITY_SAFE_MODE = 4000; /** Maximum reorg length we will accept before we shut down and alert the user. */ -static const unsigned int MAX_REORG_LENGTH = COINBASE_MATURITY - 1; +static const unsigned int MAX_REORG_LENGTH = 100 - 1; //COINBASE_MATURITY of 720 is too much /** Maximum number of signature check operations in an IsStandard() P2SH script */ static const unsigned int MAX_P2SH_SIGOPS = 15; /** The maximum number of sigops we're willing to relay/mine in a single tx */ From b6d25dd2d01e51d76101bce0edfbc24397530aad Mon Sep 17 00:00:00 2001 From: cryptoforge Date: Thu, 13 Feb 2020 21:35:48 -0800 Subject: [PATCH 375/395] Witness rework cleanup --- src/wallet/db.cpp | 6 +++--- src/wallet/wallet.cpp | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index d0070519188..61a79a4400e 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -89,7 +89,7 @@ bool CDBEnv::Open(const boost::filesystem::path& pathIn) nEnvFlags |= DB_PRIVATE; dbenv->set_lg_dir(pathLogDir.string().c_str()); - dbenv->set_cachesize(1, 0x100000, 1); // 1 MiB should be enough for just the wallet, Increased by 1 GB + dbenv->set_cachesize(0, 0x100000, 1); // 1 MiB should be enough for just the wallet dbenv->set_lg_bsize(0x10000); dbenv->set_lg_max(1048576); dbenv->set_lk_max_locks(40000); @@ -181,8 +181,8 @@ bool CDBEnv::Compact(const std::string& strFile) if (mapDb[strFile] != NULL) { Db* pdb = mapDb[strFile]; result = pdb->compact(NULL, NULL, NULL, pdbcompact, DB_FREE_SPACE, NULL); - delete pdb; - mapDb[strFile] = NULL; + // delete pdb; + // mapDb[strFile] = NULL; switch (result) { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index d22d4cad041..749bb353074 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1233,7 +1233,7 @@ int CWallet::SaplingWitnessMinimumHeight(const uint256& nullifier, int nWitnessH int CWallet::VerifyAndSetInitialWitness(const CBlockIndex* pindex, bool witnessOnly) { - LOCK2(cs_wallet,cs_main); + LOCK2(cs_main, cs_wallet); int nWitnessTxIncrement = 0; int nWitnessTotalTxCount = mapWallet.size(); @@ -1439,7 +1439,7 @@ int CWallet::VerifyAndSetInitialWitness(const CBlockIndex* pindex, bool witnessO void CWallet::BuildWitnessCache(const CBlockIndex* pindex, bool witnessOnly) { - LOCK2(cs_wallet,cs_main); + LOCK2(cs_main, cs_wallet); int startHeight = VerifyAndSetInitialWitness(pindex, witnessOnly) + 1; @@ -2983,7 +2983,7 @@ void CWallet::WitnessNoteCommitment(std::vector commitments, */ void CWallet::ReorderWalletTransactions(std::map, CWalletTx> &mapSorted, int64_t &maxOrderPos) { - LOCK2(cs_wallet,cs_main); + LOCK2(cs_main, cs_wallet); int maxSortNumber = chainActive.Tip()->nHeight + 1; @@ -3009,7 +3009,7 @@ void CWallet::ReorderWalletTransactions(std::map, CWalletTx> */ void CWallet::UpdateWalletTransactionOrder(std::map, CWalletTx> &mapSorted, bool resetOrder) { - LOCK2(cs_wallet,cs_main); + LOCK2(cs_main, cs_wallet); int64_t previousPosition = 0; std::map mapUpdatedTxs; @@ -3066,7 +3066,7 @@ void CWallet::DeleteTransactions(std::vector &removeTxs) { void CWallet::DeleteWalletTransactions(const CBlockIndex* pindex) { - LOCK2(cs_wallet,cs_main); + LOCK2(cs_main, cs_wallet); int nDeleteAfter = (int)fDeleteTransactionsAfterNBlocks; bool runCompact = false; From bc0e6b3fe5d13106016c7c51e602b4a54db30546 Mon Sep 17 00:00:00 2001 From: cryptoforge Date: Thu, 13 Feb 2020 21:37:12 -0800 Subject: [PATCH 376/395] Reset saplingAccountCounter for wallets with different original bip44CoinType --- src/wallet/asyncrpcoperation_saplingmigration.cpp | 2 +- src/wallet/wallet.cpp | 7 ++++++- src/wallet/wallet.h | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/wallet/asyncrpcoperation_saplingmigration.cpp b/src/wallet/asyncrpcoperation_saplingmigration.cpp index 3bb57fab8b4..7e358cdc898 100644 --- a/src/wallet/asyncrpcoperation_saplingmigration.cpp +++ b/src/wallet/asyncrpcoperation_saplingmigration.cpp @@ -221,7 +221,7 @@ libzcash::SaplingPaymentAddress AsyncRPCOperation_saplingmigration::getMigration pwalletMain->GetSaplingFullViewingKey(ivk, fvk) && pwalletMain->HaveSaplingSpendingKey(fvk))) { // Sapling account 0 must be the first address returned by GenerateNewSaplingZKey - assert(pwalletMain->GenerateNewSaplingZKey() == toAddress); + assert(pwalletMain->GenerateNewSaplingZKey(true) == toAddress); } return toAddress; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 749bb353074..8dc5bb76100 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -116,7 +116,7 @@ libzcash::SproutPaymentAddress CWallet::GenerateNewSproutZKey() } // Generate a new Sapling spending key and return its public payment address -SaplingPaymentAddress CWallet::GenerateNewSaplingZKey() +SaplingPaymentAddress CWallet::GenerateNewSaplingZKey(bool resetCounter) { AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata @@ -140,6 +140,11 @@ SaplingPaymentAddress CWallet::GenerateNewSaplingZKey() // Derive account key at next index, skip keys already known to the wallet libzcash::SaplingExtendedSpendingKey xsk; + + //reset saplingAccountCounter + if (resetCounter) + hdChain.saplingAccountCounter = 0; + do { xsk = m_32h_cth.Derive(hdChain.saplingAccountCounter | ZIP32_HARDENED_KEY_LIMIT); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index d8cf988825b..fa334c17c0f 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1179,7 +1179,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * Sapling ZKeys */ //! Generates new Sapling key - libzcash::SaplingPaymentAddress GenerateNewSaplingZKey(); + libzcash::SaplingPaymentAddress GenerateNewSaplingZKey(bool resetCounter = false); //! Adds Sapling spending key to the store, and saves it to disk bool AddSaplingZKey( const libzcash::SaplingExtendedSpendingKey &key, From 58b05de90d06817d9bd47fe6b9adeaceccf3c95a Mon Sep 17 00:00:00 2001 From: miodragpop Date: Fri, 14 Feb 2020 18:00:58 +0100 Subject: [PATCH 377/395] resource friendly tx reorder --- src/wallet/wallet.cpp | 98 +++++++++++++++++++++---------------------- src/wallet/wallet.h | 4 +- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 8dc5bb76100..47ec90b689d 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2986,61 +2986,61 @@ void CWallet::WitnessNoteCommitment(std::vector commitments, * Transactions can get out of order when they are deleted and subsequently * re-added during intial load rescan. */ - -void CWallet::ReorderWalletTransactions(std::map, CWalletTx> &mapSorted, int64_t &maxOrderPos) { +void CWallet::ReorderWalletTransactions(std::map, CWalletTx*> &mapSorted, int64_t &maxOrderPos) +{ LOCK2(cs_main, cs_wallet); int maxSortNumber = chainActive.Tip()->nHeight + 1; for (map::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { - CWalletTx wtx = it->second; - int confirms = wtx.GetDepthInMainChain(); - maxOrderPos = max(maxOrderPos, wtx.nOrderPos); + CWalletTx* pwtx = &(it->second); + int confirms = pwtx->GetDepthInMainChain(); + maxOrderPos = max(maxOrderPos, pwtx->nOrderPos); if (confirms > 0) { - int wtxHeight = mapBlockIndex[wtx.hashBlock]->nHeight; - auto key = std::make_pair(wtxHeight, wtx.nIndex); - mapSorted.insert(make_pair(key, wtx)); + int wtxHeight = mapBlockIndex[pwtx->hashBlock]->nHeight; + auto key = std::make_pair(wtxHeight, pwtx->nIndex); + mapSorted.insert(make_pair(key, pwtx)); } else { - auto key = std::make_pair(maxSortNumber, 0); - mapSorted.insert(std::make_pair(key, wtx)); - maxSortNumber++; + auto key = std::make_pair(maxSortNumber, 0); + mapSorted.insert(std::make_pair(key, pwtx)); + maxSortNumber++; } } } /**Update the nOrderPos with passed in ordered map. */ -void CWallet::UpdateWalletTransactionOrder(std::map, CWalletTx> &mapSorted, bool resetOrder) { +void CWallet::UpdateWalletTransactionOrder(std::map, CWalletTx*> &mapSorted, bool resetOrder) { LOCK2(cs_main, cs_wallet); int64_t previousPosition = 0; - std::map mapUpdatedTxs; + std::map mapUpdatedTxs; //Check the postion of each transaction relative to the previous one. - for (map, CWalletTx>::iterator it = mapSorted.begin(); it != mapSorted.end(); ++it) { - CWalletTx wtx = it->second; - const uint256 wtxid = wtx.GetHash(); + for (map, CWalletTx*>::iterator it = mapSorted.begin(); it != mapSorted.end(); ++it) { + CWalletTx* pwtx = it->second; + const uint256 wtxid = pwtx->GetHash(); - if (wtx.nOrderPos <= previousPosition || resetOrder) { + if (pwtx->nOrderPos <= previousPosition || resetOrder) { previousPosition++; - wtx.nOrderPos = previousPosition; - mapUpdatedTxs.insert(std::make_pair(wtxid, wtx)); + pwtx->nOrderPos = previousPosition; + mapUpdatedTxs.insert(std::make_pair(wtxid, pwtx)); } else { - previousPosition = wtx.nOrderPos; + previousPosition = pwtx->nOrderPos; } } //Update transactions nOrderPos for transactions that changed CWalletDB walletdb(strWalletFile, "r+", false); - for (map::iterator it = mapUpdatedTxs.begin(); it != mapUpdatedTxs.end(); ++it) { - CWalletTx wtx = it->second; - LogPrint("deletetx","Reorder Tx - Updating Positon to %i for Tx %s\n ", wtx.nOrderPos, wtx.GetHash().ToString()); - wtx.WriteToDisk(&walletdb); - mapWallet[wtx.GetHash()].nOrderPos = wtx.nOrderPos; + for (map::iterator it = mapUpdatedTxs.begin(); it != mapUpdatedTxs.end(); ++it) { + CWalletTx* pwtx = it->second; + LogPrint("deletetx","Reorder Tx - Updating Positon to %i for Tx %s\n ", pwtx->nOrderPos, pwtx->GetHash().ToString()); + pwtx->WriteToDisk(&walletdb); + mapWallet[pwtx->GetHash()].nOrderPos = pwtx->nOrderPos; } //Update Next Wallet Tx Positon @@ -3092,7 +3092,7 @@ void CWallet::DeleteWalletTransactions(const CBlockIndex* pindex) { //Sort Transactions by block and block index int64_t maxOrderPos = 0; - std::map, CWalletTx> mapSorted; + std::map, CWalletTx*> mapSorted; ReorderWalletTransactions(mapSorted, maxOrderPos); if (maxOrderPos > int64_t(mapSorted.size())*10) { //reset the postion when the max postion is 10x bigger than the @@ -3114,25 +3114,25 @@ void CWallet::DeleteWalletTransactions(const CBlockIndex* pindex) { for (auto & item : mapSorted) { - CWalletTx& wtx = item.second; - const uint256& wtxid = wtx.GetHash(); + CWalletTx* pwtx = item.second; + const uint256& wtxid = pwtx->GetHash(); bool deleteTx = true; txCount += 1; - int wtxDepth = wtx.GetDepthInMainChain(); + int wtxDepth = pwtx->GetDepthInMainChain(); //Keep anything newer than N Blocks if (wtxDepth == 0) txUnConfirmed++; if (wtxDepth < nDeleteAfter && wtxDepth >= 0) { - LogPrint("deletetx","DeleteTx - Transaction above minimum depth, tx %s\n", wtx.GetHash().ToString()); + LogPrint("deletetx","DeleteTx - Transaction above minimum depth, tx %s\n", pwtx->GetHash().ToString()); deleteTx = false; txSaveCount++; continue; } else if (wtxDepth == -1) { //Enabled by default if (!fTxConflictDeleteEnabled) { - LogPrint("deletetx","DeleteTx - Conflict delete is not enabled tx %s\n", wtx.GetHash().ToString()); + LogPrint("deletetx","DeleteTx - Conflict delete is not enabled tx %s\n", pwtx->GetHash().ToString()); deleteTx = false; txSaveCount++; continue; @@ -3142,10 +3142,10 @@ void CWallet::DeleteWalletTransactions(const CBlockIndex* pindex) { } else { //Check for unspent inputs or spend less than N Blocks ago. (Sapling) - for (auto & pair : wtx.mapSaplingNoteData) { + for (auto & pair : pwtx->mapSaplingNoteData) { SaplingNoteData nd = pair.second; if (!nd.nullifier || pwalletMain->GetSaplingSpendDepth(*nd.nullifier) <= fDeleteTransactionsAfterNBlocks) { - LogPrint("deletetx","DeleteTx - Unspent sapling input tx %s\n", wtx.GetHash().ToString()); + LogPrint("deletetx","DeleteTx - Unspent sapling input tx %s\n", pwtx->GetHash().ToString()); deleteTx = false; continue; } @@ -3157,13 +3157,13 @@ void CWallet::DeleteWalletTransactions(const CBlockIndex* pindex) { } //Check for outputs that no longer have parents in the wallet. Exclude parents that are in the same transaction. (Sapling) - for (int i = 0; i < wtx.vShieldedSpend.size(); i++) { - const SpendDescription& spendDesc = wtx.vShieldedSpend[i]; + for (int i = 0; i < pwtx->vShieldedSpend.size(); i++) { + const SpendDescription& spendDesc = pwtx->vShieldedSpend[i]; if (pwalletMain->IsSaplingNullifierFromMe(spendDesc.nullifier)) { const uint256& parentHash = pwalletMain->mapSaplingNullifiersToNotes[spendDesc.nullifier].hash; const CWalletTx* parent = pwalletMain->GetWalletTx(parentHash); if (parent != NULL && parentHash != wtxid) { - LogPrint("deletetx","DeleteTx - Parent of sapling tx %s found\n", wtx.GetHash().ToString()); + LogPrint("deletetx","DeleteTx - Parent of sapling tx %s found\n", pwtx->GetHash().ToString()); deleteTx = false; continue; } @@ -3176,10 +3176,10 @@ void CWallet::DeleteWalletTransactions(const CBlockIndex* pindex) { } //Check for unspent inputs or spend less than N Blocks ago. (Sprout) - for (auto & pair : wtx.mapSproutNoteData) { + for (auto & pair : pwtx->mapSproutNoteData) { SproutNoteData nd = pair.second; if (!nd.nullifier || pwalletMain->GetSproutSpendDepth(*nd.nullifier) <= fDeleteTransactionsAfterNBlocks) { - LogPrint("deletetx","DeleteTx - Unspent sprout input tx %s\n", wtx.GetHash().ToString()); + LogPrint("deletetx","DeleteTx - Unspent sprout input tx %s\n", pwtx->GetHash().ToString()); deleteTx = false; continue; } @@ -3191,15 +3191,15 @@ void CWallet::DeleteWalletTransactions(const CBlockIndex* pindex) { } //Check for outputs that no longer have parents in the wallet. Exclude parents that are in the same transaction. (Sprout) - for (int i = 0; i < wtx.vJoinSplit.size(); i++) { - const JSDescription& jsdesc = wtx.vJoinSplit[i]; + for (int i = 0; i < pwtx->vJoinSplit.size(); i++) { + const JSDescription& jsdesc = pwtx->vJoinSplit[i]; for (const uint256 &nullifier : jsdesc.nullifiers) { // JSOutPoint op = pwalletMain->mapSproutNullifiersToNotes[nullifier]; if (pwalletMain->IsSproutNullifierFromMe(nullifier)) { const uint256& parentHash = pwalletMain->mapSproutNullifiersToNotes[nullifier].hash; const CWalletTx* parent = pwalletMain->GetWalletTx(parentHash); if (parent != NULL && parentHash != wtxid) { - LogPrint("deletetx","DeleteTx - Parent of sprout tx %s found\n", wtx.GetHash().ToString()); + LogPrint("deletetx","DeleteTx - Parent of sprout tx %s found\n", pwtx->GetHash().ToString()); deleteTx = false; continue; } @@ -3213,12 +3213,12 @@ void CWallet::DeleteWalletTransactions(const CBlockIndex* pindex) { } //Check for unspent inputs or spend less than N Blocks ago. (Transparent) - for (unsigned int i = 0; i < wtx.vout.size(); i++) { + for (unsigned int i = 0; i < pwtx->vout.size(); i++) { CTxDestination address; - ExtractDestination(wtx.vout[i].scriptPubKey, address); - if(IsMine(wtx.vout[i])) { - if (pwalletMain->GetSpendDepth(wtx.GetHash(), i) <= fDeleteTransactionsAfterNBlocks) { - LogPrint("deletetx","DeleteTx - Unspent transparent input tx %s\n", wtx.GetHash().ToString()); + ExtractDestination(pwtx->vout[i].scriptPubKey, address); + if(IsMine(pwtx->vout[i])) { + if (pwalletMain->GetSpendDepth(pwtx->GetHash(), i) <= fDeleteTransactionsAfterNBlocks) { + LogPrint("deletetx","DeleteTx - Unspent transparent input tx %s\n", pwtx->GetHash().ToString()); deleteTx = false; continue; } @@ -3231,12 +3231,12 @@ void CWallet::DeleteWalletTransactions(const CBlockIndex* pindex) { } //Chcek for output with that no longer have parents in the wallet. (Transparent) - for (int i = 0; i < wtx.vin.size(); i++) { - const CTxIn& txin = wtx.vin[i]; + for (int i = 0; i < pwtx->vin.size(); i++) { + const CTxIn& txin = pwtx->vin[i]; const uint256& parentHash = txin.prevout.hash; const CWalletTx* parent = pwalletMain->GetWalletTx(txin.prevout.hash); if (parent != NULL && parentHash != wtxid) { - LogPrint("deletetx","DeleteTx - Parent of transparent tx %s found\n", wtx.GetHash().ToString()); + LogPrint("deletetx","DeleteTx - Parent of transparent tx %s found\n", pwtx->GetHash().ToString()); deleteTx = false; continue; } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index fa334c17c0f..639614b315c 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1247,8 +1247,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface std::vector commitments, std::vector>& witnesses, uint256 &final_anchor); - void ReorderWalletTransactions(std::map, CWalletTx> &mapSorted, int64_t &maxOrderPos); - void UpdateWalletTransactionOrder(std::map, CWalletTx> &mapSorted, bool resetOrder); + void ReorderWalletTransactions(std::map, CWalletTx*> &mapSorted, int64_t &maxOrderPos); + void UpdateWalletTransactionOrder(std::map, CWalletTx*> &mapSorted, bool resetOrder); void DeleteTransactions(std::vector &removeTxs); void DeleteWalletTransactions(const CBlockIndex* pindex); int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); From 791103780117cdfb258c6b88ea23547327ab689b Mon Sep 17 00:00:00 2001 From: miodragpop Date: Mon, 17 Feb 2020 17:20:29 +0100 Subject: [PATCH 378/395] force freed memory to return back to the OS --- src/wallet/wallet.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 47ec90b689d..5423c15ef98 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -37,6 +37,8 @@ #include #include +#include + using namespace std; using namespace libzcash; @@ -3067,6 +3069,9 @@ void CWallet::DeleteTransactions(std::vector &removeTxs) { return; } } + + // Miodrag: release memory back to the OS + malloc_trim(0); } void CWallet::DeleteWalletTransactions(const CBlockIndex* pindex) { From 31d85addbcb53f1c54e5a177e3fef6ec76f68e64 Mon Sep 17 00:00:00 2001 From: cryptoforge Date: Sat, 29 Feb 2020 12:48:22 -0800 Subject: [PATCH 379/395] fix disable z_sendmany --- src/wallet/wallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 5423c15ef98..97db282a562 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1437,7 +1437,7 @@ int CWallet::VerifyAndSetInitialWitness(const CBlockIndex* pindex, bool witnessO } } //enable z_sendmany when the wallet has no Notes - if (!walletHasNotes) + if (!walletHasNotes || nMinimumHeight == pindex->nHeight) initWitnessesBuilt = true; return nMinimumHeight; From 5cbeb980882a19784dd1f2cd51a31e4732988776 Mon Sep 17 00:00:00 2001 From: cryptoforge Date: Mon, 9 Mar 2020 20:20:49 -0700 Subject: [PATCH 380/395] malloc_trim only on linux --- src/wallet/wallet.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 97db282a562..83339ed2b13 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -37,7 +37,9 @@ #include #include +#ifdef __linux__ //linux only #include +#endif using namespace std; using namespace libzcash; @@ -3069,9 +3071,11 @@ void CWallet::DeleteTransactions(std::vector &removeTxs) { return; } } - - // Miodrag: release memory back to the OS + + // Miodrag: release memory back to the OS, only works on linux + #ifdef __linux__ malloc_trim(0); + #endif } void CWallet::DeleteWalletTransactions(const CBlockIndex* pindex) { From 2251872bfd34420fcd43ef0c08599a6c71bd284b Mon Sep 17 00:00:00 2001 From: cryptoforge Date: Mon, 9 Mar 2020 20:40:52 -0700 Subject: [PATCH 381/395] bump version --- README.md | 16 ++++++++-------- configure.ac | 4 ++-- doc/man/zero-cli.1 | 6 +++--- doc/man/zero-tx.1 | 6 +++--- doc/man/zerod.1 | 6 +++--- src/clientversion.cpp | 2 +- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index a7bef02a6d3..8a503d00aa7 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,30 @@ ![alt text](https://github.com/zerocurrencycoin/Zero/blob/master/art/zero%203d%20mountain.png?raw=true) -[ZERO](https://zerocurrency.io) - [Pavo:3.0.2](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.0.2) +[ZERO](https://zerocurrency.io) - [Pegasus:3.1.0](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.1.0) ||FAST|| ||DECENTRALISED|| ||ANONYMOUS|| ||SECURE|| ||ASIC RESISTANT|| - LAUNCE DATE: 2017-02-19 GENESIS BLOCK - 19th Feb 2017 11:26:40 - 068cbb5db6bc11be5b93479ea4df41fa7e012e92ca8603c315f9b1a2202205c6 -Download the latest version here - [ZERO - Latest Version - Pavo:3.0.2](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.0.2) +Download the latest version here - [ZERO - Latest Version - Pegasus:3.1.0](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.1.0) ------------------------------------------ ❓ What is ZERO? -------------- -[ZERO](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.0.2) is a revolutionary cryptocurrency and transaction platform based on Zcash. +[ZERO](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.1.0) is a revolutionary cryptocurrency and transaction platform based on Zcash. -[ZERO](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.0.2) offers total payment confidentiality, while still maintaining a decentralised network using a public blockchain. +[ZERO](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.1.0) offers total payment confidentiality, while still maintaining a decentralised network using a public blockchain. -[ZERO](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.0.2) combines Bitcoin’s security with Zcash’s anonymity and privacy. +[ZERO](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.1.0) combines Bitcoin’s security with Zcash’s anonymity and privacy. -[ZERO](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.0.2) stands out from the competition as a fully working product that has already +[ZERO](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.1.0) stands out from the competition as a fully working product that has already implemented a set of special features not found in any other cryptocurrency. Our main focus as a team and community is to remain as transparent as we can possibly be and to maintain an interactive relationship with everyone involved. We are fully open about the project, listening to all suggestions from investors, miners and supporters. -This software is the [ZERO](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.0.2) node. It downloads and stores the entire history of ZERO's transactions, about 1.2GB at this point. +This software is the [ZERO](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.1.0) node. It downloads and stores the entire history of ZERO's transactions, about 1.2GB at this point. Depending on the speed of your computer and network connection, the synchronization process could take several hours. ------------------------------------------ @@ -128,7 +128,7 @@ See important security warnings on the 📒 Deprecation Policy ------------------ -Disabledeprecation flag has been removed. Old nodes will automatically be shut down and must be upgraded upon reaching the deprecation block height, which will occur approximately 26 weeks (6/27/2020) from the release of v3.0.2. +Disabledeprecation flag has been removed. Old nodes will automatically be shut down and must be upgraded upon reaching the deprecation block height, which will occur approximately 26 weeks (6/27/2020) from the release of v3.1.0. 🔧 Building diff --git a/configure.ac b/configure.ac index eb667eb287f..8efaaa98ed5 100644 --- a/configure.ac +++ b/configure.ac @@ -1,8 +1,8 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 3) -define(_CLIENT_VERSION_MINOR, 0) -define(_CLIENT_VERSION_REVISION, 2) +define(_CLIENT_VERSION_MINOR, 1) +define(_CLIENT_VERSION_REVISION, 0) define(_CLIENT_VERSION_BUILD, 50) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) diff --git a/doc/man/zero-cli.1 b/doc/man/zero-cli.1 index f77d64dbb44..fa12b9300af 100644 --- a/doc/man/zero-cli.1 +++ b/doc/man/zero-cli.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZERO-CLI "1" "December 2019" "zero-cli v3.0.2-79779934a" "User Commands" +.TH ZERO-CLI "1" "December 2019" "zero-cli v3.1.0-79779934a" "User Commands" .SH NAME -zero-cli \- manual page for zero-cli v3.0.2-79779934a +zero-cli \- manual page for zero-cli v3.1.0-79779934a .SH DESCRIPTION -Zero RPC client version v3.0.2\-79779934a +Zero RPC client version v3.1.0\-79779934a .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . diff --git a/doc/man/zero-tx.1 b/doc/man/zero-tx.1 index c514629cf06..6f31dceaf25 100644 --- a/doc/man/zero-tx.1 +++ b/doc/man/zero-tx.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZERO-TX "1" "December 2019" "zero-tx v3.0.2-79779934a" "User Commands" +.TH ZERO-TX "1" "December 2019" "zero-tx v3.1.0-79779934a" "User Commands" .SH NAME -zero-tx \- manual page for zero-tx v3.0.2-79779934a +zero-tx \- manual page for zero-tx v3.1.0-79779934a .SH DESCRIPTION -Zero zero\-tx utility version v3.0.2\-79779934a +Zero zero\-tx utility version v3.1.0\-79779934a .SS "Usage:" .TP zero\-tx [options] [commands] diff --git a/doc/man/zerod.1 b/doc/man/zerod.1 index 49057213f2c..ad38bf5e49e 100644 --- a/doc/man/zerod.1 +++ b/doc/man/zerod.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZEROD "1" "December 2019" "zerod v3.0.2-79779934a" "User Commands" +.TH ZEROD "1" "December 2019" "zerod v3.1.0-79779934a" "User Commands" .SH NAME -zerod \- manual page for zerod v3.0.2-79779934a +zerod \- manual page for zerod v3.1.0-79779934a .SH DESCRIPTION -Zero Daemon version v3.0.2\-79779934a +Zero Daemon version v3.1.0\-79779934a .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . diff --git a/src/clientversion.cpp b/src/clientversion.cpp index 340acaf9cc4..71ce160cc32 100644 --- a/src/clientversion.cpp +++ b/src/clientversion.cpp @@ -19,7 +19,7 @@ * for both bitcoind and bitcoin-core, to make it harder for attackers to * target servers or GUI users specifically. */ -const std::string CLIENT_NAME("Pavo"); +const std::string CLIENT_NAME("Pegasus"); /** * Client version number From 182ae06fcffbe2d495d2b08257db2166ce2e2f3f Mon Sep 17 00:00:00 2001 From: cryptoforge Date: Tue, 10 Mar 2020 19:34:20 -0700 Subject: [PATCH 382/395] size_t to uint64_t --- src/transaction_builder.cpp | 12 ++++++------ src/transaction_builder.h | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/transaction_builder.cpp b/src/transaction_builder.cpp index ed1768c25be..7aeaae728b0 100644 --- a/src/transaction_builder.cpp +++ b/src/transaction_builder.cpp @@ -466,8 +466,8 @@ void TransactionBuilder::CreateJSDescriptions() vpub_old += vjsout[n].value; } - std::array inputMap; - std::array outputMap; + std::array inputMap; + std::array outputMap; CreateJSDescription(vpub_old, 0, vjsin, vjsout, inputMap, outputMap); } return; @@ -662,8 +662,8 @@ void TransactionBuilder::CreateJSDescriptions() LogPrint("zrpcunsafe", "generating note for change (amount=%s)\n", FormatMoney(jsChange)); } - std::array inputMap; - std::array outputMap; + std::array inputMap; + std::array outputMap; CreateJSDescription(vpub_old, vpub_new, vjsin, vjsout, inputMap, outputMap); if (jsChange > 0) { @@ -683,8 +683,8 @@ void TransactionBuilder::CreateJSDescription( uint64_t vpub_new, std::array vjsin, std::array vjsout, - std::array& inputMap, - std::array& outputMap) + std::array& inputMap, + std::array& outputMap) { LogPrint("zrpcunsafe", "CreateJSDescription: creating joinsplit at index %d (vpub_old=%s, vpub_new=%s, in[0]=%s, in[1]=%s, out[0]=%s, out[1]=%s)\n", mtx.vJoinSplit.size(), diff --git a/src/transaction_builder.h b/src/transaction_builder.h index 8db064c7f16..6970e191ec8 100644 --- a/src/transaction_builder.h +++ b/src/transaction_builder.h @@ -151,8 +151,8 @@ class TransactionBuilder uint64_t vpub_new, std::array vjsin, std::array vjsout, - std::array& inputMap, - std::array& outputMap); + std::array& inputMap, + std::array& outputMap); }; #endif /* TRANSACTION_BUILDER_H */ From 4d27ef39c3acec40f91acaacc65f7fb9fe4c984e Mon Sep 17 00:00:00 2001 From: cryptoforge Date: Sat, 21 Mar 2020 21:48:13 -0700 Subject: [PATCH 383/395] getsupply rpc --- src/rpc/client.cpp | 2 ++ src/wallet/rpczerowallet.cpp | 65 ++++++++++++++++++++++++++++++++++++ src/wallet/rpczerowallet.h | 1 + 3 files changed, 68 insertions(+) diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 8e5909196a5..c73e3f5f2a0 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -168,6 +168,8 @@ static const CRPCConvertParam vRPCConvertParams[] = { "zs_listspentbyaddress", 3}, { "zs_listspentbyaddress", 4}, { "zs_listspentbyaddress", 5}, + { "getsupply", 0}, + { "getsupply", 1}, }; diff --git a/src/wallet/rpczerowallet.cpp b/src/wallet/rpczerowallet.cpp index 1cb6d45a057..bf143a2aae6 100644 --- a/src/wallet/rpczerowallet.cpp +++ b/src/wallet/rpczerowallet.cpp @@ -1790,6 +1790,70 @@ UniValue getalldata(const UniValue& params, bool fHelp) return returnObj; } +UniValue getsupply(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() > 1) + throw runtime_error( + "getsupply \"height \"\n" + "\n" + "This function returns the coin supply at a specific height." + "\n" + "\nArguments:\n" + "1. \"height\" (integer, required) \n" + "\nResult:\n" + "{\n" + " \"supplyzats\": n, (numeric) Total supply in zatoshis\n" + " \"supply\": n, (numeric) Total supply\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("getsupply", "0") + + HelpExampleRpc("getsupply", "0") + ); + + LOCK2(cs_main, pwalletMain->cs_wallet); + + int nHeight = 0; + uint64_t supply = 0; + + if (params.size() > 0) { + nHeight = params[0].get_int64(); + } else { + nHeight = chainActive.Height(); + } + + auto consensusParams = Params().GetConsensus(); + unsigned int halving = consensusParams.nPreBlossomSubsidyHalvingInterval; + int halvings = nHeight/halving; + + for (int i = 0; i <= halvings; i++ ) { + + int loopHeight = 0; + if (i < halvings) { + loopHeight = (halving * (i + 1)) - 1; + } else { + loopHeight = nHeight; + } + + if (i == 0) { + if (nHeight >= consensusParams.nFeeStartBlockHeight) { + supply = GetBlockSubsidy(1, consensusParams) * (consensusParams.nFeeStartBlockHeight - 1); + supply += GetBlockSubsidy(loopHeight, consensusParams) * (loopHeight - consensusParams.nFeeStartBlockHeight + 1); + } else { + supply = GetBlockSubsidy(loopHeight, consensusParams) * loopHeight; + } + } else { + supply += GetBlockSubsidy(loopHeight, consensusParams) * (loopHeight - ((halving * i) -1)); + } + } + +UniValue ret(UniValue::VOBJ); + +ret.push_back(Pair("supplyzats", supply)); +ret.push_back(Pair("supply", ValueFromAmount(supply))); + +return ret; + +} static const CRPCCommand commands[] = { // category name actor (function) okSafeMode @@ -1800,6 +1864,7 @@ static const CRPCCommand commands[] = { "zero Exclusive", "zs_listreceivedbyaddress", &zs_listreceivedbyaddress, true }, { "zero Exclusive", "zs_listsentbyaddress", &zs_listsentbyaddress, true }, { "zero Exclusive", "getalldata", &getalldata, true }, + { "zero Exclusive", "getsupply", &getsupply, true }, }; void RegisterZeroExclusiveRPCCommands(CRPCTable &tableRPC) diff --git a/src/wallet/rpczerowallet.h b/src/wallet/rpczerowallet.h index e9d837f6fcc..3352a8bf6e9 100644 --- a/src/wallet/rpczerowallet.h +++ b/src/wallet/rpczerowallet.h @@ -16,6 +16,7 @@ void zsTxSpendsToJSON(const CWalletTx& wtx, UniValue& spends, CAmount& totalSpen void zsTxReceivedToJSON(const CWalletTx& wtx, UniValue& received, CAmount& totalReceived, const std::string& strAddress, bool filterByAddress); void zsTxSendsToJSON(const CWalletTx& wtx, UniValue& sends, CAmount& totalSends, const std::string& strAddress, bool filterByAddress); void zsWalletTxJSON(const CWalletTx& wtx, UniValue& ret, const std::string strAddress, bool fBool, const int returnType); +UniValue getsupply(const UniValue& params, bool fHelp); class CRPCTable; From bb5eedcdd67153dd996788a02b02087d265690ef Mon Sep 17 00:00:00 2001 From: cryptoforge Date: Sun, 22 Mar 2020 20:47:14 -0700 Subject: [PATCH 384/395] zeronodestats rpc --- src/rpc/zeronode.cpp | 124 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/src/rpc/zeronode.cpp b/src/rpc/zeronode.cpp index 756af555c47..52acbf6ec7f 100644 --- a/src/rpc/zeronode.cpp +++ b/src/rpc/zeronode.cpp @@ -15,6 +15,7 @@ #include "zeronode/zeronode-sync.h" #include "rpc/server.h" #include "utilmoneystr.h" +#include "wallet/rpczerowallet.h" #include @@ -977,6 +978,128 @@ UniValue zeronode(const UniValue& params, bool fHelp) return NullUniValue; } +UniValue zeronodestats(const UniValue& params, bool fHelp) + +{ + if (fHelp || (params.size() > 0)) + throw runtime_error( + "zeronodestats\n" + "\nThis function returns Zeronode & Blockchain statistics.\n" + + "\nResults:\n" + "{\n" + " chainStats:\n" + " {\n" + " \"height\": n, (numeric) Block height\n" + " \"supply\": n, (numeric) Total supply at block height\n" + " \"supplyzats\": n, (numeric) Total supply in zatoshis\n" + " \"sproutpool\": n, (numeric) Value of sprout pool\n" + " \"sproutpoolzats\": n, (numeric) Value of sprout pool in zatoshis\n" + " \"saplingpool\": n, (numeric) Value of sapling pool\n" + " \"saplingpoolzats\": n, (numeric) Value of sapling pool in zatoshis\n" + " \"blockreward\": n, (numeric) Value of blockreward\n" + " \"blockrewardzats\": n, (numeric) Value of blockreward in zatoshis\n" + " \"zeronodepayment\": n, (numeric) Value of zeronode payments\n" + " \"zeronodepaymentzats\": n, (numeric) Value of zeronode payments in zatoshis\n" + " \"developmentfee\": n, (numeric) Value of development fee\n" + " \"developmentfeezats\": n, (numeric) Value of development fee in zatoshis\n" + " },\n" + " nodeCount:\n" + " {\n" + " \"total\": n, (numeric) Total zeronodes\n" + " \"stable\": n, (numeric) Stable count\n" + " \"obfcompat\": n, (numeric) Obfuscation Compatible\n" + " \"enabled\": n, (numeric) Enabled zeronodes\n" + " \"inqueue\": n (numeric) Zeronodes in queue\n" + " \"ipv4\": n, (numeric) Zeronodes using ipv4\n" + " \"ipv6\": n, (numeric) Zeronodes using ipv6\n" + " \"onion\": n, (numeric) Zeronodes using onion\n" + " },\n" + " nodeList:\n" + " [\n" + " {\n" + " \"rank\": n, (numeric) Zeronode Rank (or 0 if not enabled)\n" + " \"txhash\": \"hash\", (string) Collateral transaction hash\n" + " \"outidx\": n, (numeric) Collateral transaction output index\n" + " \"status\": s, (string) Status (ENABLED/EXPIRED/REMOVE/etc)\n" + " \"addr\": \"addr\", (string) Zeronode Zero address\n" + " \"version\": v, (numeric) Zeronode protocol version\n" + " \"lastseen\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last seen\n" + " \"activetime\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) zeronode has been active\n" + " \"lastpaid\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) zeronode was last paid\n" + " }\n" + " ,...\n" + " ]\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("zeronodestats", "") + HelpExampleRpc("zeronodestats", "")); + + UniValue ret(UniValue::VOBJ); + UniValue newParams(UniValue::VARR); + UniValue ct = getzeronodecount(newParams, false); + UniValue supply = getsupply(newParams, false); + + int nHeight = 0; + CAmount blockValue = 0; + CAmount zeronodePayment = 0; + CAmount vFoundersReward = 0; + boost::optional saplingPool = 0; + boost::optional sproutPool = 0; + CAmount supplyzats = 0; + CAmount transaparentpoolzats = 0; + + { + LOCK(cs_main); + nHeight = chainActive.Height(); + blockValue = GetBlockSubsidy(nHeight, Params().GetConsensus()); + zeronodePayment = GetZeronodePayment(nHeight, blockValue); + vFoundersReward = blockValue * 7.5 / 100; + supplyzats = supply["supplyzats"].get_int64(); + transaparentpoolzats = supplyzats; + CBlockIndex* tip = chainActive.Tip(); + if (tip->nChainSaplingValue) + saplingPool = tip->nChainSaplingValue; + if (tip->nChainSproutValue) + sproutPool = tip->nChainSproutValue; + } + + UniValue chain(UniValue::VOBJ); + chain.push_back(Pair("height", nHeight)); + chain.push_back(Pair("supply", ValueFromAmount(supplyzats))); + chain.push_back(Pair("supplyzats", supplyzats)); + if (sproutPool) { + chain.push_back(Pair("sproutpool", ValueFromAmount(*sproutPool))); + chain.push_back(Pair("sproutpoolzats", *sproutPool)); + } else { + chain.push_back(Pair("sproutpool", 0)); + chain.push_back(Pair("sproutpoolzats", 0)); + } + if (saplingPool) { + chain.push_back(Pair("saplingpool", ValueFromAmount(*saplingPool))); + chain.push_back(Pair("saplingpoolzats", *saplingPool)); + } else { + chain.push_back(Pair("saplingpool", 0)); + chain.push_back(Pair("saplingpoolzats", 0)); + } + chain.push_back(Pair("blockreward", ValueFromAmount(blockValue))); + chain.push_back(Pair("blockrewardzats", blockValue)); + chain.push_back(Pair("zeronodepayment", ValueFromAmount(zeronodePayment))); + chain.push_back(Pair("zeronodepaymentzats", zeronodePayment)); + chain.push_back(Pair("developmentfee", ValueFromAmount(vFoundersReward))); + chain.push_back(Pair("developmentfeezats", vFoundersReward)); + + ret.push_back(Pair("chainStats", chain)); + ret.push_back(Pair("nodeCount", ct)); + ret.push_back(Pair("nodeList", listzeronodes(newParams, false))); + + int iq = ct["inqueue"].get_int(); + LogPrintf("Node Count %i\n", iq); + + return ret; + +} + + static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // --------------------- ------------------------ ----------------------- ---------- @@ -996,6 +1119,7 @@ static const CRPCCommand commands[] = {"zeronode", "getzeronodescores", &getzeronodescores, true}, {"zeronode", "zeronode", &zeronode, true}, {"zeronode", "znsync", &znsync, true}, + {"zeronode", "zeronodestats", &zeronodestats, true}, }; From bec7079ceb432b11bce1adab772b4f8f8e1b594a Mon Sep 17 00:00:00 2001 From: cryptoforge Date: Sun, 1 Dec 2019 11:04:30 -0800 Subject: [PATCH 385/395] zeroverse rpcs --- src/Makefile.am | 2 + src/rpc/client.cpp | 8 + src/rpc/register.h | 3 + src/wallet/witness.cpp | 338 +++++++++++++++++++++++++++++++++++++++++ src/wallet/witness.h | 12 ++ 5 files changed, 363 insertions(+) create mode 100644 src/wallet/witness.cpp create mode 100644 src/wallet/witness.h diff --git a/src/Makefile.am b/src/Makefile.am index 82060c868ab..e9f9d482f53 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -231,6 +231,7 @@ BITCOIN_CORE_H = \ wallet/wallet.h \ wallet/wallet_ismine.h \ wallet/walletdb.h \ + wallet/witness.h \ zmq/zmqabstractnotifier.h \ zmq/zmqconfig.h\ zmq/zmqnotificationinterface.h \ @@ -342,6 +343,7 @@ libbitcoin_wallet_a_SOURCES = \ wallet/wallet.cpp \ wallet/wallet_ismine.cpp \ wallet/walletdb.cpp \ + wallet/witness.cpp \ $(BITCOIN_CORE_H) \ $(LIBZCASH_H) diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index c73e3f5f2a0..7b80293dc8c 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -170,6 +170,14 @@ static const CRPCConvertParam vRPCConvertParams[] = { "zs_listspentbyaddress", 5}, { "getsupply", 0}, { "getsupply", 1}, + { "getsaplingwitness", 1}, + { "getsaplingwitness", 2}, + { "getsaplingwitnessatheight", 1}, + { "getsaplingwitnessatheight", 2}, + { "getsaplingwitnessatheight", 3}, + { "getsaplingblocks", 0}, + { "getsaplingblocks", 1}, + { "getsaplingblocks", 2}, }; diff --git a/src/rpc/register.h b/src/rpc/register.h index 34e2aded88b..b24ebf4ea89 100644 --- a/src/rpc/register.h +++ b/src/rpc/register.h @@ -28,6 +28,8 @@ void RegisterSporkRPCCommands(CRPCTable &tableRPC); /** Register Experimental RPC commands */ void RegisterZeroExclusiveRPCCommands(CRPCTable &tableRPC); +void RegisterZeroExperimentalRPCCommands(CRPCTable &tableRPC); + static inline void RegisterAllCoreRPCCommands(CRPCTable &tableRPC) { RegisterBlockchainRPCCommands(tableRPC); @@ -39,6 +41,7 @@ static inline void RegisterAllCoreRPCCommands(CRPCTable &tableRPC) //RegisterBudgetRPCCommands(tableRPC); //Disabled for now RegisterSporkRPCCommands(tableRPC); RegisterZeroExclusiveRPCCommands(tableRPC); + RegisterZeroExperimentalRPCCommands(tableRPC); } #endif diff --git a/src/wallet/witness.cpp b/src/wallet/witness.cpp new file mode 100644 index 00000000000..0219313b00d --- /dev/null +++ b/src/wallet/witness.cpp @@ -0,0 +1,338 @@ +// Copyright (c) 2019 Cryptoforge +// Copyright (c) 2019 The Zero developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "init.h" +#include "rpc/server.h" +#include "wallet.h" +#include "witness.h" +#include "utilmoneystr.h" +#include "coins.h" + +using namespace std; +using namespace libzcash; + +bool EnsureWalletIsAvailable(bool avoidException); + +UniValue getsaplingwitness(const UniValue& params, bool fHelp) { + + if (!EnsureWalletIsAvailable(fHelp)) + return NullUniValue; + + if (fHelp || params.size() != 2) + throw runtime_error( + "getsaplingwitness txid sheildedOutputIndex\n" + + HelpExampleCli("getsaplingwitness","26d4c79aab980bc39ac0deb1d8224c399249a6f5d6d3b3a6d58e6374750854c1 0") + + HelpExampleRpc("getsaplingwitness","26d4c79aab980bc39ac0deb1d8224c399249a6f5d6d3b3a6d58e6374750854c1 0") + ); + + LOCK2(cs_main, pwalletMain->cs_wallet); + + //UniValue obj to be returned + UniValue wit(UniValue::VOBJ); + + //Set Parameters + uint256 ctxhash; + ctxhash.SetHex(params[0].get_str()); + int64_t nSheildedOutputIndex = params[1].get_int64(); + + //get transaction with the sapling shielded output to be witnessed + UniValue ret(UniValue::VARR); + + CTransaction ctx; + uint256 hashBlock; + int nHeight = 0; + + + { + if (!GetTransaction(ctxhash, ctx, Params().GetConsensus(), hashBlock, true)) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction"); + + BlockMap::iterator mi = mapBlockIndex.find(hashBlock); + if (mi != mapBlockIndex.end() && (*mi).second) { + CBlockIndex* pindex = (*mi).second; + if (chainActive.Contains(pindex)) { + nHeight = pindex->nHeight; + } else { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "transaction not found in valid block"); + } + } + } + + //Check that sapling is active + const bool saplingActive = Params().GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_SAPLING); + if (!saplingActive) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sapling not active"); + + //Get the blocckindex of the previous block + CBlockIndex* pblockindex = chainActive[nHeight]; + + //Get the sapling tree as of the previous block + SaplingMerkleTree saplingTree; + pcoinsTip->GetSaplingAnchorAt(pblockindex->pprev->hashFinalSaplingRoot, saplingTree); + + //Cycle through block and transactions build sapling tree until the commitment needed is reached + CBlock pblock; + ReadBlockFromDisk(pblock, pblockindex, Params().GetConsensus()); + for (const CTransaction& tx : pblock.vtx) { + auto hash = tx.GetHash(); + + //Check if output exists + if (hash == ctxhash && (tx.vShieldedOutput.size() == 0 || tx.vShieldedOutput.size() < nSheildedOutputIndex + 1)) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sapling Output does not exist"); + + for (int64_t i = 0; i < tx.vShieldedOutput.size(); i++) { + const uint256& note_commitment = tx.vShieldedOutput[i].cm; + saplingTree.append(note_commitment); + + if (hash == ctxhash && i == nSheildedOutputIndex) { + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << saplingTree.witness(); + wit.push_back(Pair("height", nHeight)); + wit.push_back(Pair("txhash", hash.ToString())); + wit.push_back(Pair("sheildedoutputindex", i)); + wit.push_back(Pair("witness", HexStr(ss.begin(), ss.end()))); + } + } + } + + return wit; + +} + + +UniValue getsaplingwitnessatheight(const UniValue& params, bool fHelp) { + + if (!EnsureWalletIsAvailable(fHelp)) + return NullUniValue; + + if (fHelp || params.size() != 3) + throw runtime_error( + "getsaplingwitnessatheight txid sheildedOutputIndex\n" + + HelpExampleCli("getsaplingwitnessatheight","26d4c79aab980bc39ac0deb1d8224c399249a6f5d6d3b3a6d58e6374750854c1 0") + + HelpExampleRpc("getsaplingwitnessatheight","26d4c79aab980bc39ac0deb1d8224c399249a6f5d6d3b3a6d58e6374750854c1 0") + ); + + LOCK2(cs_main, pwalletMain->cs_wallet); + + //UniValue obj to be returned + UniValue wit(UniValue::VOBJ); + + //Set Parameters + uint256 ctxhash; + ctxhash.SetHex(params[0].get_str()); + int64_t nSheildedOutputIndex = params[1].get_int64(); + int64_t toHeight = params[2].get_int64(); + + //get transaction with the sapling shielded output to be witnessed + UniValue ret(UniValue::VARR); + + CTransaction ctx; + uint256 hashBlock; + int nHeight = 0; + + { + if (!GetTransaction(ctxhash, ctx, Params().GetConsensus(), hashBlock, true)) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction"); + + BlockMap::iterator mi = mapBlockIndex.find(hashBlock); + if (mi != mapBlockIndex.end() && (*mi).second) { + CBlockIndex* pindex = (*mi).second; + if (chainActive.Contains(pindex)) { + nHeight = pindex->nHeight; + } else { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "transaction not found in valid block"); + } + } + } + + //Check that sapling is active + const bool saplingActive = Params().GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_SAPLING); + if (!saplingActive) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sapling not active"); + + //Get the blocckindex of the previous block + CBlockIndex* pblockindex = chainActive[nHeight]; + + //Get the sapling tree as of the previous block + SaplingMerkleTree saplingTree; + auto witness = saplingTree.witness(); + pcoinsTip->GetSaplingAnchorAt(pblockindex->pprev->hashFinalSaplingRoot, saplingTree); + + //Cycle through block and transactions build sapling tree until the commitment needed is reached + CBlock pblock; + ReadBlockFromDisk(pblock, pblockindex, Params().GetConsensus()); + for (const CTransaction& tx : pblock.vtx) { + auto hash = tx.GetHash(); + + //Check if output exists + if (hash == ctxhash && (tx.vShieldedOutput.size() == 0 || tx.vShieldedOutput.size() < nSheildedOutputIndex + 1)) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sapling Output does not exist"); + + for (int64_t i = 0; i < tx.vShieldedOutput.size(); i++) { + const uint256& note_commitment = tx.vShieldedOutput[i].cm; + saplingTree.append(note_commitment); + if (hash == ctxhash && i == nSheildedOutputIndex) { + witness = saplingTree.witness(); + } + if (hash == ctxhash && i > nSheildedOutputIndex) { + witness.append(note_commitment); + } + } + } + + + for (int64_t j = nHeight + 1; j <= toHeight; j++) { + UniValue jsonblock(UniValue::VOBJ); + std::string strHash = chainActive[j]->GetBlockHash().GetHex(); + + uint256 hash(uint256S(strHash)); + + CBlock block; + CBlockIndex* pblockindex = mapBlockIndex[hash]; + + if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); + + if(!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); + + + // UniValue jsontxs(UniValue::VARR); + for (const CTransaction& tx : block.vtx) { + for (int64_t i = 0; i < tx.vShieldedOutput.size(); i++) { + const uint256& note_commitment = tx.vShieldedOutput[i].cm; + saplingTree.append(note_commitment); + witness.append(note_commitment); + } + } + + if (j == toHeight) { + wit.push_back(Pair("hash", block.GetHash().GetHex())); + wit.push_back(Pair("height", j)); + wit.push_back(Pair("finalsaplingroot", block.hashFinalSaplingRoot.GetHex())); + } + } + + CDataStream iss(SER_NETWORK, PROTOCOL_VERSION); + iss << witness; + wit.push_back(Pair("incrementedwitness", HexStr(iss.begin(), iss.end()))); + wit.push_back(Pair("incrementedroot", witness.root().GetHex())); + + return wit; +} + + +UniValue getsaplingblocks(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 2) + throw runtime_error( + "getsaplingblocks \"startheight blocksqty\" ( verbosity )\n" + + "\nExamples:\n" + + HelpExampleCli("getsaplingblocks", "12800 1") + + HelpExampleRpc("getsaplingblocks", "12800 1") + ); + + LOCK2(cs_main, pwalletMain->cs_wallet); + + int64_t nHeight = params[0].get_int64(); + int64_t nBlocks = params[1].get_int64(); + + + if (nHeight < 0 || nHeight > chainActive.Height()) { + nHeight == chainActive.Height(); + nBlocks = -1; + } + + if (nBlocks < 0) { + nBlocks = -1; + } + + if (chainActive.Height() - nHeight < nBlocks && chainActive.Height() != nHeight) { + nBlocks = chainActive.Height() - nHeight + 1; + } + + if (chainActive.Height() == nHeight) { + nBlocks = 1; + } + + UniValue result(UniValue::VARR); + for (int64_t i = 0; i < nBlocks; i++) { + UniValue jsonblock(UniValue::VOBJ); + std::string strHash = chainActive[nHeight + i]->GetBlockHash().GetHex(); + + uint256 hash(uint256S(strHash)); + + CBlock block; + CBlockIndex* pblockindex = mapBlockIndex[hash]; + + if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); + + if(!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); + + jsonblock.push_back(Pair("hash", block.GetHash().GetHex())); + jsonblock.push_back(Pair("previousblockhash", pblockindex->pprev->GetBlockHash().GetHex())); + jsonblock.push_back(Pair("height", pblockindex->nHeight)); + jsonblock.push_back(Pair("finalsaplingroot", block.hashFinalSaplingRoot.GetHex())); + + UniValue jsontxs(UniValue::VARR); + for (const CTransaction& tx : block.vtx) { + UniValue jsontx(UniValue::VOBJ); + jsontx.push_back(Pair("txid",tx.GetHash().ToString())); + + UniValue jsonShieldOutputs(UniValue::VARR); + for (int64_t i = 0; i < tx.vShieldedOutput.size(); i++) { + UniValue jsonShieldOutput(UniValue::VOBJ); + jsonShieldOutput.push_back(Pair("sheildedoutputindex", i)); + jsonShieldOutput.push_back(Pair("cv", tx.vShieldedOutput[i].cv.ToString())); + jsonShieldOutput.push_back(Pair("cm", tx.vShieldedOutput[i].cm.ToString())); + jsonShieldOutput.push_back(Pair("ephemeralKey", tx.vShieldedOutput[i].ephemeralKey.ToString())); + auto encCiphertext = tx.vShieldedOutput[i].encCiphertext; + jsonShieldOutput.push_back(Pair("encCiphertext", HexStr(encCiphertext.begin(),encCiphertext.end()))); + auto outCiphertext = tx.vShieldedOutput[i].outCiphertext; + jsonShieldOutput.push_back(Pair("outCiphertext", HexStr(outCiphertext.begin(),outCiphertext.end()))); + jsonShieldOutputs.push_back(jsonShieldOutput); + } + + UniValue jsonShieldSpends(UniValue::VARR); + for (int64_t i = 0; i < tx.vShieldedSpend.size(); i++) { + UniValue jsonShieldSpend(UniValue::VOBJ); + jsonShieldSpend.push_back(Pair("sheildedspendindex", i)); + jsonShieldSpend.push_back(Pair("nullifier", tx.vShieldedSpend[i].nullifier.ToString())); + jsonShieldSpends.push_back(jsonShieldSpend); + } + + jsontx.push_back(Pair("vShieldedOutput",jsonShieldOutputs)); + jsontx.push_back(Pair("vShieldedSpend",jsonShieldSpends)); + + if (tx.vShieldedOutput.size() > 0 || tx.vShieldedSpend.size() > 0) + jsontxs.push_back(jsontx); + + } + jsonblock.push_back(Pair("transactions",jsontxs)); + result.push_back(jsonblock); + } + + return result; +} + + + +static const CRPCCommand commands[] = +{ // category name actor (function) okSafeMode + // --------------------- ------------------------ ----------------------- ---------- + { "zero Experimental", "getsaplingwitness", &getsaplingwitness, true }, + { "zero Experimental", "getsaplingwitnessatheight", &getsaplingwitnessatheight, true }, + { "zero Experimental", "getsaplingblocks", &getsaplingblocks, true }, + +}; + +void RegisterZeroExperimentalRPCCommands(CRPCTable &tableRPC) +{ + for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) + tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); +} diff --git a/src/wallet/witness.h b/src/wallet/witness.h new file mode 100644 index 00000000000..aecd2ab3ee0 --- /dev/null +++ b/src/wallet/witness.h @@ -0,0 +1,12 @@ +// Copyright (c) 2019 Zero developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_WALLET_WITNESS_H +#define BITCOIN_WALLET_WITNESS_H + +class CRPCTable; + +void RegisterZeroExperimentalRPCCommands(CRPCTable &tableRPC); + +#endif //BITCOIN_WALLET_WITNESS_H From a55053725af3fc353dd177bfcdd96e5109fb8748 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 27 Sep 2019 11:06:11 +0100 Subject: [PATCH 386/395] RPC: z_viewtransaction --- src/wallet/rpcwallet.cpp | 167 +++++++++++++++++++++++++++++++++++++++ src/wallet/wallet.cpp | 61 ++++++++++++++ src/wallet/wallet.h | 5 ++ 3 files changed, 233 insertions(+) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 5e42528426b..5ecac863936 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3497,6 +3497,172 @@ UniValue z_gettotalbalance(const UniValue& params, bool fHelp) return result; } +UniValue z_viewtransaction(const UniValue& params, bool fHelp) +{ + if (!EnsureWalletIsAvailable(fHelp)) + return NullUniValue; + + if (fHelp || params.size() != 1) + throw runtime_error( + "z_viewtransaction \"txid\"\n" + "\nGet detailed shielded information about in-wallet transaction \n" + "\nArguments:\n" + "1. \"txid\" (string, required) The transaction id\n" + "\nResult:\n" + "{\n" + " \"txid\" : \"transactionid\", (string) The transaction id\n" + " \"spends\" : [\n" + " {\n" + " \"type\" : \"sprout|sapling\", (string) The type of address\n" + " \"js\" : n, (numeric, sprout) the index of the JSDescription within vJoinSplit\n" + " \"jsSpend\" : n, (numeric, sprout) the index of the spend within the JSDescription\n" + " \"spend\" : n, (numeric, sapling) the index of the spend within vShieldedSpend\n" + " \"txidPrev\" : \"transactionid\", (string) The id for the transaction this note was created in\n" + " \"jsPrev\" : n, (numeric, sprout) the index of the JSDescription within vJoinSplit\n" + " \"jsOutputPrev\" : n, (numeric, sprout) the index of the output within the JSDescription\n" + " \"outputPrev\" : n, (numeric, sapling) the index of the output within the vShieldedOutput\n" + " \"address\" : \"zcashaddress\", (string) The Zcash address involved in the transaction\n" + " \"value\" : x.xxx (numeric) The amount in " + CURRENCY_UNIT + "\n" + " \"valueZat\" : xxxx (numeric) The amount in zatoshis\n" + " }\n" + " ,...\n" + " ],\n" + " \"outputs\" : [\n" + " {\n" + " \"type\" : \"sprout|sapling\", (string) The type of address\n" + " \"js\" : n, (numeric, sprout) the index of the JSDescription within vJoinSplit\n" + " \"jsOutput\" : n, (numeric, sprout) the index of the output within the JSDescription\n" + " \"output\" : n, (numeric, sapling) the index of the output within the vShieldedOutput\n" + " \"address\" : \"zcashaddress\", (string) The Zcash address involved in the transaction\n" + " \"value\" : x.xxx (numeric) The amount in " + CURRENCY_UNIT + "\n" + " \"valueZat\" : xxxx (numeric) The amount in zatoshis\n" + " \"memo\" : \"hexmemo\", (string) Hexademical string representation of the memo field\n" + " }\n" + " ,...\n" + " ],\n" + "}\n" + + "\nExamples:\n" + + HelpExampleCli("z_viewtransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"") + + HelpExampleRpc("z_viewtransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"") + ); + + LOCK2(cs_main, pwalletMain->cs_wallet); + + uint256 hash; + hash.SetHex(params[0].get_str()); + + UniValue entry(UniValue::VOBJ); + if (!pwalletMain->mapWallet.count(hash)) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id"); + const CWalletTx& wtx = pwalletMain->mapWallet[hash]; + + entry.push_back(Pair("txid", hash.GetHex())); + + UniValue spends(UniValue::VARR); + UniValue outputs(UniValue::VARR); + + // Sprout spends + for (size_t i = 0; i < wtx.vJoinSplit.size(); ++i) { + for (size_t j = 0; j < wtx.vJoinSplit[i].nullifiers.size(); ++j) { + auto nullifier = wtx.vJoinSplit[i].nullifiers[j]; + + // Fetch the note that is being spent, if ours + auto res = pwalletMain->mapSproutNullifiersToNotes.find(nullifier); + if (res == pwalletMain->mapSproutNullifiersToNotes.end()) { + continue; + } + auto jsop = res->second; + auto wtxPrev = pwalletMain->mapWallet.at(jsop.hash); + + auto decrypted = wtxPrev.DecryptSproutNote(jsop); + auto notePt = decrypted.first; + auto pa = decrypted.second; + + UniValue entry(UniValue::VOBJ); + entry.push_back(Pair("type", ADDR_TYPE_SPROUT)); + entry.push_back(Pair("js", (int)i)); + entry.push_back(Pair("jsSpend", (int)j)); + entry.push_back(Pair("txidPrev", jsop.hash.GetHex())); + entry.push_back(Pair("jsPrev", (int)jsop.js)); + entry.push_back(Pair("jsOutputPrev", (int)jsop.n)); + entry.push_back(Pair("address", EncodePaymentAddress(pa))); + entry.push_back(Pair("value", ValueFromAmount(notePt.value()))); + entry.push_back(Pair("valueZat", notePt.value())); + spends.push_back(entry); + } + } + + // Sprout outputs + for (auto & pair : wtx.mapSproutNoteData) { + JSOutPoint jsop = pair.first; + + auto decrypted = wtx.DecryptSproutNote(jsop); + auto notePt = decrypted.first; + auto pa = decrypted.second; + + UniValue entry(UniValue::VOBJ); + entry.push_back(Pair("type", ADDR_TYPE_SPROUT)); + entry.push_back(Pair("js", (int)jsop.js)); + entry.push_back(Pair("jsOutput", (int)jsop.n)); + entry.push_back(Pair("address", EncodePaymentAddress(pa))); + entry.push_back(Pair("value", ValueFromAmount(notePt.value()))); + entry.push_back(Pair("valueZat", notePt.value())); + entry.push_back(Pair("memo", HexStr(notePt.memo()))); + outputs.push_back(entry); + } + + // Sapling spends + for (size_t i = 0; i < wtx.vShieldedSpend.size(); ++i) { + auto spend = wtx.vShieldedSpend[i]; + + // Fetch the note that is being spent + auto res = pwalletMain->mapSaplingNullifiersToNotes.find(spend.nullifier); + if (res == pwalletMain->mapSaplingNullifiersToNotes.end()) { + continue; + } + auto op = res->second; + auto wtxPrev = pwalletMain->mapWallet.at(op.hash); + + auto decrypted = wtxPrev.DecryptSaplingNote(op); + auto notePt = decrypted.first; + auto pa = decrypted.second; + + UniValue entry(UniValue::VOBJ); + entry.push_back(Pair("type", ADDR_TYPE_SAPLING)); + entry.push_back(Pair("spend", (int)i)); + entry.push_back(Pair("txidPrev", op.hash.GetHex())); + entry.push_back(Pair("outputPrev", (int)op.n)); + entry.push_back(Pair("address", EncodePaymentAddress(pa))); + entry.push_back(Pair("value", ValueFromAmount(notePt.value()))); + entry.push_back(Pair("valueZat", notePt.value())); + spends.push_back(entry); + } + + // Sapling outputs + for (auto & pair : wtx.mapSaplingNoteData) { + SaplingOutPoint op = pair.first; + + auto decrypted = wtx.DecryptSaplingNote(op); + auto notePt = decrypted.first; + auto pa = decrypted.second; + + UniValue entry(UniValue::VOBJ); + entry.push_back(Pair("type", ADDR_TYPE_SAPLING)); + entry.push_back(Pair("output", (int)op.n)); + entry.push_back(Pair("address", EncodePaymentAddress(pa))); + entry.push_back(Pair("value", ValueFromAmount(notePt.value()))); + entry.push_back(Pair("valueZat", notePt.value())); + entry.push_back(Pair("memo", HexStr(notePt.memo()))); + outputs.push_back(entry); + } + + entry.push_back(Pair("spends", spends)); + entry.push_back(Pair("outputs", outputs)); + + return entry; +} + UniValue z_getoperationresult(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) @@ -4826,6 +4992,7 @@ static const CRPCCommand commands[] = { "wallet", "z_importviewingkey", &z_importviewingkey, true }, { "wallet", "z_exportwallet", &z_exportwallet, true }, { "wallet", "z_importwallet", &z_importwallet, true }, + { "wallet", "z_viewtransaction", &z_viewtransaction, false }, // TODO: rearrange into another category { "disclosure", "z_getpaymentdisclosure", &z_getpaymentdisclosure, true }, { "disclosure", "z_validatepaymentdisclosure", &z_validatepaymentdisclosure, true } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 83339ed2b13..8a2beb8ac3f 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2727,6 +2727,67 @@ void CWalletTx::SetSaplingNoteData(mapSaplingNoteData_t ¬eData) } } +std::pair CWalletTx::DecryptSproutNote( + JSOutPoint jsop) const +{ + LOCK(pwallet->cs_wallet); + + auto nd = this->mapSproutNoteData.at(jsop); + SproutPaymentAddress pa = nd.address; + + // Get cached decryptor + ZCNoteDecryption decryptor; + if (!pwallet->GetNoteDecryptor(pa, decryptor)) { + // Note decryptors are created when the wallet is loaded, so it should always exist + throw std::runtime_error(strprintf( + "Could not find note decryptor for payment address %s", + EncodePaymentAddress(pa))); + } + + auto hSig = this->vJoinSplit[jsop.js].h_sig(*pzcashParams, this->joinSplitPubKey); + try { + SproutNotePlaintext plaintext = SproutNotePlaintext::decrypt( + decryptor, + this->vJoinSplit[jsop.js].ciphertexts[jsop.n], + this->vJoinSplit[jsop.js].ephemeralKey, + hSig, + (unsigned char) jsop.n); + + return std::make_pair(plaintext, pa); + } catch (const note_decryption_failed &err) { + // Couldn't decrypt with this spending key + throw std::runtime_error(strprintf( + "Could not decrypt note for payment address %s", + EncodePaymentAddress(pa))); + } catch (const std::exception &exc) { + // Unexpected failure + throw std::runtime_error(strprintf( + "Error while decrypting note for payment address %s: %s", + EncodePaymentAddress(pa), exc.what())); + } +} + +std::pair CWalletTx::DecryptSaplingNote( + SaplingOutPoint op) const +{ + auto output = this->vShieldedOutput[op.n]; + auto nd = this->mapSaplingNoteData.at(op); + + auto maybe_pt = SaplingNotePlaintext::decrypt( + output.encCiphertext, + nd.ivk, + output.ephemeralKey, + output.cm); + assert(static_cast(maybe_pt)); + auto notePt = maybe_pt.get(); + + auto maybe_pa = nd.ivk.address(notePt.d); + assert(static_cast(maybe_pa)); + auto pa = maybe_pa.get(); + + return std::make_pair(notePt, pa); +} + int64_t CWalletTx::GetTxTime() const { int64_t n = nTimeSmart; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 639614b315c..c7bbb718b74 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -619,6 +619,11 @@ class CWalletTx : public CMerkleTx void SetSproutNoteData(mapSproutNoteData_t ¬eData); void SetSaplingNoteData(mapSaplingNoteData_t ¬eData); + std::pair DecryptSproutNote( + JSOutPoint jsop) const; + std::pair DecryptSaplingNote( + SaplingOutPoint op) const; + //! filter decides which addresses will count towards the debit CAmount GetDebit(const isminefilter& filter) const; CAmount GetCredit(const isminefilter& filter) const; From 917662c3bf5cc2ec7dbaa8139710bcde5a22bcd6 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 27 Sep 2019 11:35:44 +0100 Subject: [PATCH 387/395] depends: Add utfcpp to dependencies --- contrib/debian/copyright | 4 ++++ depends/packages/packages.mk | 2 +- depends/packages/utfcpp.mk | 10 ++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 depends/packages/utfcpp.mk diff --git a/contrib/debian/copyright b/contrib/debian/copyright index 5121d906009..81a52b6ab9e 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -120,6 +120,10 @@ Files: depends/sources/qpid-proton-*.tar.gz Copyright: 2012-2017 The Apache Software Foundation License: Apache-Qpid-Proton-with-BSD-Subcomponents +Files: depends/sources/utfcpp-*.tar.gz +Copyright: 2006 Nemanja Trifunovic +License: Boost-Software-License-1.0 + Files: src/secp256k1/build-aux/m4/ax_jni_include_dir.m4 Copyright: 2008 Don Anderson License: GNU-All-permissive-License diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index b67c11e995b..6f9b1883db6 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -34,7 +34,7 @@ rust_crates := \ crate_winapi_x86_64_pc_windows_gnu rust_packages := rust $(rust_crates) librustzcash proton_packages := proton -zcash_packages := libsodium +zcash_packages := libsodium utfcpp packages := boost openssl libevent zeromq $(zcash_packages) googletest native_packages := native_ccache diff --git a/depends/packages/utfcpp.mk b/depends/packages/utfcpp.mk new file mode 100644 index 00000000000..40e6026f709 --- /dev/null +++ b/depends/packages/utfcpp.mk @@ -0,0 +1,10 @@ +package=utfcpp +$(package)_version=3.1 +$(package)_download_path=https://github.com/nemtrif/$(package)/archive/ +$(package)_file_name=$(package)-$($(package)_version).tar.gz +$(package)_download_file=v$($(package)_version).tar.gz +$(package)_sha256_hash=ab531c3fd5d275150430bfaca01d7d15e017a188183be932322f2f651506b096 + +define $(package)_stage_cmds + cp -a ./source $($(package)_staging_dir)$(host_prefix)/include +endef From 49277ec3e30873f6f21668ef54437c24dacfc60d Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 27 Sep 2019 11:45:15 +0100 Subject: [PATCH 388/395] RPC: Display valid UTF-8 memos in z_viewtransaction --- src/wallet/rpcwallet.cpp | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 5ecac863936..97c6b20e0c1 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -36,6 +36,7 @@ #include #include +#include #include @@ -3537,6 +3538,7 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp) " \"value\" : x.xxx (numeric) The amount in " + CURRENCY_UNIT + "\n" " \"valueZat\" : xxxx (numeric) The amount in zatoshis\n" " \"memo\" : \"hexmemo\", (string) Hexademical string representation of the memo field\n" + " \"memoStr\" : \"memo\", (string) Only returned if memo contains valid UTF-8 text.\n" " }\n" " ,...\n" " ],\n" @@ -3562,6 +3564,24 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp) UniValue spends(UniValue::VARR); UniValue outputs(UniValue::VARR); + auto addMemo = [](UniValue &entry, std::array &memo) { + entry.push_back(Pair("memo", HexStr(memo))); + + // If the leading byte is 0xF4 or lower, the memo field should be interpreted as a + // UTF-8-encoded text string. + if (memo[0] <= 0xf4) { + // Trim off trailing zeroes + auto end = std::find_if( + memo.rbegin(), + memo.rend(), + [](unsigned char v) { return v != 0; }); + std::string memoStr(memo.begin(), end.base()); + if (utf8::is_valid(memoStr)) { + entry.push_back(Pair("memoStr", memoStr)); + } + } + }; + // Sprout spends for (size_t i = 0; i < wtx.vJoinSplit.size(); ++i) { for (size_t j = 0; j < wtx.vJoinSplit[i].nullifiers.size(); ++j) { @@ -3600,6 +3620,7 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp) auto decrypted = wtx.DecryptSproutNote(jsop); auto notePt = decrypted.first; auto pa = decrypted.second; + auto memo = notePt.memo(); UniValue entry(UniValue::VOBJ); entry.push_back(Pair("type", ADDR_TYPE_SPROUT)); @@ -3608,7 +3629,7 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp) entry.push_back(Pair("address", EncodePaymentAddress(pa))); entry.push_back(Pair("value", ValueFromAmount(notePt.value()))); entry.push_back(Pair("valueZat", notePt.value())); - entry.push_back(Pair("memo", HexStr(notePt.memo()))); + addMemo(entry, memo); outputs.push_back(entry); } @@ -3646,6 +3667,7 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp) auto decrypted = wtx.DecryptSaplingNote(op); auto notePt = decrypted.first; auto pa = decrypted.second; + auto memo = notePt.memo(); UniValue entry(UniValue::VOBJ); entry.push_back(Pair("type", ADDR_TYPE_SAPLING)); @@ -3653,7 +3675,7 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp) entry.push_back(Pair("address", EncodePaymentAddress(pa))); entry.push_back(Pair("value", ValueFromAmount(notePt.value()))); entry.push_back(Pair("valueZat", notePt.value())); - entry.push_back(Pair("memo", HexStr(notePt.memo()))); + addMemo(entry, memo); outputs.push_back(entry); } From 7813211f5c00aaa2bad5930102c065560c252200 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 27 Sep 2019 14:54:45 +0100 Subject: [PATCH 389/395] RPC: Use OutgoingViewingKeys to recover non-wallet Sapling outputs --- src/wallet/rpcwallet.cpp | 43 ++++++++++++++++++++++++++++++++++----- src/wallet/wallet.cpp | 44 ++++++++++++++++++++++++++++++++++++++-- src/wallet/wallet.h | 9 ++++++-- 3 files changed, 87 insertions(+), 9 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 97c6b20e0c1..9d8020446bc 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3535,6 +3535,7 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp) " \"jsOutput\" : n, (numeric, sprout) the index of the output within the JSDescription\n" " \"output\" : n, (numeric, sapling) the index of the output within the vShieldedOutput\n" " \"address\" : \"zcashaddress\", (string) The Zcash address involved in the transaction\n" + " \"outgoing\" : true|false (boolean, sapling) True if the output is not for an address in the wallet\n" " \"value\" : x.xxx (numeric) The amount in " + CURRENCY_UNIT + "\n" " \"valueZat\" : xxxx (numeric) The amount in zatoshis\n" " \"memo\" : \"hexmemo\", (string) Hexademical string representation of the memo field\n" @@ -3633,6 +3634,14 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp) outputs.push_back(entry); } + // Collect OutgoingViewingKeys for recovering output information + std::set ovks; + { + // Generate the common ovk for recovering t->z outputs. + HDSeed seed = pwalletMain->GetHDSeedForRPC(); + ovks.insert(ovkForShieldingFromTaddr(seed)); + } + // Sapling spends for (size_t i = 0; i < wtx.vShieldedSpend.size(); ++i) { auto spend = wtx.vShieldedSpend[i]; @@ -3645,10 +3654,15 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp) auto op = res->second; auto wtxPrev = pwalletMain->mapWallet.at(op.hash); - auto decrypted = wtxPrev.DecryptSaplingNote(op); + auto decrypted = wtxPrev.DecryptSaplingNote(op).get(); auto notePt = decrypted.first; auto pa = decrypted.second; + // Store the OutgoingViewingKey for recovering outputs + libzcash::SaplingFullViewingKey fvk; + assert(pwalletMain->GetSaplingFullViewingKey(wtxPrev.mapSaplingNoteData.at(op).ivk, fvk)); + ovks.insert(fvk.ovk); + UniValue entry(UniValue::VOBJ); entry.push_back(Pair("type", ADDR_TYPE_SAPLING)); entry.push_back(Pair("spend", (int)i)); @@ -3661,17 +3675,36 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp) } // Sapling outputs - for (auto & pair : wtx.mapSaplingNoteData) { - SaplingOutPoint op = pair.first; + for (uint32_t i = 0; i < wtx.vShieldedOutput.size(); ++i) { + auto op = SaplingOutPoint(hash, i); + + SaplingNotePlaintext notePt; + SaplingPaymentAddress pa; + bool isOutgoing; auto decrypted = wtx.DecryptSaplingNote(op); - auto notePt = decrypted.first; - auto pa = decrypted.second; + if (decrypted) { + notePt = decrypted->first; + pa = decrypted->second; + isOutgoing = false; + } else { + // Try recovering the output + auto recovered = wtx.RecoverSaplingNote(op, ovks); + if (recovered) { + notePt = recovered->first; + pa = recovered->second; + isOutgoing = true; + } else { + // Unreadable + continue; + } + } auto memo = notePt.memo(); UniValue entry(UniValue::VOBJ); entry.push_back(Pair("type", ADDR_TYPE_SAPLING)); entry.push_back(Pair("output", (int)op.n)); + entry.push_back(Pair("outgoing", isOutgoing)); entry.push_back(Pair("address", EncodePaymentAddress(pa))); entry.push_back(Pair("value", ValueFromAmount(notePt.value()))); entry.push_back(Pair("valueZat", notePt.value())); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 8a2beb8ac3f..ea8a9e9480b 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2767,9 +2767,15 @@ std::pair CWalletTx::DecryptSproutNot } } -std::pair CWalletTx::DecryptSaplingNote( - SaplingOutPoint op) const +boost::optional> CWalletTx::DecryptSaplingNote(SaplingOutPoint op) const { + // Check whether we can decrypt this SaplingOutPoint + if (this->mapSaplingNoteData.count(op) == 0) { + return boost::none; + } + auto output = this->vShieldedOutput[op.n]; auto nd = this->mapSaplingNoteData.at(op); @@ -2788,6 +2794,40 @@ std::pair CWalletTx::DecryptSapling return std::make_pair(notePt, pa); } +boost::optional> CWalletTx::RecoverSaplingNote( + SaplingOutPoint op, std::set& ovks) const +{ + auto output = this->vShieldedOutput[op.n]; + + for (auto ovk : ovks) { + auto outPt = SaplingOutgoingPlaintext::decrypt( + output.outCiphertext, + ovk, + output.cv, + output.cm, + output.ephemeralKey); + if (!outPt) { + continue; + } + + auto maybe_pt = SaplingNotePlaintext::decrypt( + output.encCiphertext, + output.ephemeralKey, + outPt->esk, + outPt->pk_d, + output.cm); + assert(static_cast(maybe_pt)); + auto notePt = maybe_pt.get(); + + return std::make_pair(notePt, SaplingPaymentAddress(notePt.d, outPt->pk_d)); + } + + // Couldn't recover with any of the provided OutgoingViewingKeys + return boost::none; +} + int64_t CWalletTx::GetTxTime() const { int64_t n = nTimeSmart; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index c7bbb718b74..7eae4187354 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -621,8 +621,13 @@ class CWalletTx : public CMerkleTx std::pair DecryptSproutNote( JSOutPoint jsop) const; - std::pair DecryptSaplingNote( - SaplingOutPoint op) const; + boost::optional> DecryptSaplingNote(SaplingOutPoint op) const; + boost::optional> RecoverSaplingNote( + SaplingOutPoint op, std::set& ovks) const; //! filter decides which addresses will count towards the debit CAmount GetDebit(const isminefilter& filter) const; From 5eee2543e1be250cdfa0b22013dbdd8151335e33 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 19 Oct 2019 09:47:30 +1300 Subject: [PATCH 390/395] test: Check z_viewtransaction output in wallet_listreceived RPC test --- qa/rpc-tests/wallet_listreceived.py | 129 +++++++++++++++++++++++++++- 1 file changed, 125 insertions(+), 4 deletions(-) diff --git a/qa/rpc-tests/wallet_listreceived.py b/qa/rpc-tests/wallet_listreceived.py index 526a3e6cd99..d24d5d86d8c 100755 --- a/qa/rpc-tests/wallet_listreceived.py +++ b/qa/rpc-tests/wallet_listreceived.py @@ -10,7 +10,8 @@ from test_framework.util import wait_and_assert_operationid_status from decimal import Decimal -my_memo = 'c0ffee' # stay awake +my_memo_str = 'c0ffee' # stay awake +my_memo = my_memo_str.encode('hex') my_memo = my_memo + '0'*(1024-len(my_memo)) no_memo = 'f6' + ('0'*1022) # see section 5.5 of the protocol spec @@ -30,15 +31,75 @@ def run_test_release(self, release, height): self.generate_and_sync(height+1) taddr = self.nodes[1].getnewaddress() zaddr1 = self.nodes[1].z_getnewaddress(release) + zaddrExt = self.nodes[3].z_getnewaddress(release) - self.nodes[0].sendtoaddress(taddr, 2.0) + self.nodes[0].sendtoaddress(taddr, 4.0) self.generate_and_sync(height+2) # Send 1 ZEC to zaddr1 - opid = self.nodes[1].z_sendmany(taddr, - [{'address': zaddr1, 'amount': 1, 'memo': my_memo}]) + opid = self.nodes[1].z_sendmany(taddr, [ + {'address': zaddr1, 'amount': 1, 'memo': my_memo}, + {'address': zaddrExt, 'amount': 2}, + ]) txid = wait_and_assert_operationid_status(self.nodes[1], opid) self.sync_all() + + # Decrypted transaction details should be correct + pt = self.nodes[1].z_viewtransaction(txid) + assert_equal(pt['txid'], txid) + assert_equal(len(pt['spends']), 0) + assert_equal(len(pt['outputs']), 1 if release == 'sprout' else 2) + + # Output orders can be randomized, so we check the output + # positions and contents separately + outputs = [] + + assert_equal(pt['outputs'][0]['type'], release) + if release == 'sprout': + assert_equal(pt['outputs'][0]['js'], 0) + jsOutputPrev = pt['outputs'][0]['jsOutput'] + elif pt['outputs'][0]['address'] == zaddr1: + outputPrev = pt['outputs'][0]['output'] + assert_equal(pt['outputs'][0]['outgoing'], False) + assert_equal(pt['outputs'][0]['memoStr'], my_memo_str) + else: + assert_equal(pt['outputs'][0]['outgoing'], True) + outputs.append({ + 'address': pt['outputs'][0]['address'], + 'value': pt['outputs'][0]['value'], + 'valueZat': pt['outputs'][0]['valueZat'], + 'memo': pt['outputs'][0]['memo'], + }) + + if release != 'sprout': + assert_equal(pt['outputs'][1]['type'], release) + if pt['outputs'][1]['address'] == zaddr1: + outputPrev = pt['outputs'][1]['output'] + assert_equal(pt['outputs'][1]['outgoing'], False) + assert_equal(pt['outputs'][1]['memoStr'], my_memo_str) + else: + assert_equal(pt['outputs'][1]['outgoing'], True) + outputs.append({ + 'address': pt['outputs'][1]['address'], + 'value': pt['outputs'][1]['value'], + 'valueZat': pt['outputs'][1]['valueZat'], + 'memo': pt['outputs'][1]['memo'], + }) + + assert({ + 'address': zaddr1, + 'value': Decimal('1'), + 'valueZat': 100000000, + 'memo': my_memo, + } in outputs) + if release != 'sprout': + assert({ + 'address': zaddrExt, + 'value': Decimal('2'), + 'valueZat': 200000000, + 'memo': no_memo, + } in outputs) + r = self.nodes[1].z_listreceivedbyaddress(zaddr1) assert_equal(0, len(r), "Should have received no confirmed note") @@ -57,6 +118,7 @@ def run_test_release(self, release, height): assert_equal(r, self.nodes[1].z_listreceivedbyaddress(zaddr1)) # Generate some change by sending part of zaddr1 to zaddr2 + txidPrev = txid zaddr2 = self.nodes[1].z_getnewaddress(release) opid = self.nodes[1].z_sendmany(zaddr1, [{'address': zaddr2, 'amount': 0.6}]) @@ -64,6 +126,65 @@ def run_test_release(self, release, height): self.sync_all() self.generate_and_sync(height+4) + # Decrypted transaction details should be correct + pt = self.nodes[1].z_viewtransaction(txid) + assert_equal(pt['txid'], txid) + assert_equal(len(pt['spends']), 1) + assert_equal(len(pt['outputs']), 2) + + assert_equal(pt['spends'][0]['type'], release) + assert_equal(pt['spends'][0]['txidPrev'], txidPrev) + if release == 'sprout': + assert_equal(pt['spends'][0]['js'], 0) + # jsSpend is randomised during transaction creation + assert_equal(pt['spends'][0]['jsPrev'], 0) + assert_equal(pt['spends'][0]['jsOutputPrev'], jsOutputPrev) + else: + assert_equal(pt['spends'][0]['spend'], 0) + assert_equal(pt['spends'][0]['outputPrev'], 0) + assert_equal(pt['spends'][0]['address'], zaddr1) + assert_equal(pt['spends'][0]['value'], Decimal('1.0')) + assert_equal(pt['spends'][0]['valueZat'], 100000000) + + # Output orders can be randomized, so we check the output + # positions and contents separately + outputs = [] + + assert_equal(pt['outputs'][0]['type'], release) + if release == 'sapling': + assert_equal(pt['outputs'][0]['output'], 0) + assert_equal(pt['outputs'][0]['outgoing'], False) + outputs.append({ + 'address': pt['outputs'][0]['address'], + 'value': pt['outputs'][0]['value'], + 'valueZat': pt['outputs'][0]['valueZat'], + 'memo': pt['outputs'][0]['memo'], + }) + + assert_equal(pt['outputs'][1]['type'], release) + if release == 'sapling': + assert_equal(pt['outputs'][1]['output'], 1) + assert_equal(pt['outputs'][1]['outgoing'], False) + outputs.append({ + 'address': pt['outputs'][1]['address'], + 'value': pt['outputs'][1]['value'], + 'valueZat': pt['outputs'][1]['valueZat'], + 'memo': pt['outputs'][1]['memo'], + }) + + assert({ + 'address': zaddr2, + 'value': Decimal('0.6'), + 'valueZat': 60000000, + 'memo': no_memo, + } in outputs) + assert({ + 'address': zaddr1, + 'value': Decimal('0.3999'), + 'valueZat': 39990000, + 'memo': no_memo, + } in outputs) + # zaddr1 should have a note with change r = self.nodes[1].z_listreceivedbyaddress(zaddr1, 0) r = sorted(r, key = lambda received: received['amount']) From 8d0c417ca33a51ef57580a5146c7530522a8b870 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 13 Feb 2020 12:32:37 +0000 Subject: [PATCH 391/395] test: Fix pyflakes warnings --- qa/rpc-tests/wallet_listreceived.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/qa/rpc-tests/wallet_listreceived.py b/qa/rpc-tests/wallet_listreceived.py index d24d5d86d8c..3185afe6133 100755 --- a/qa/rpc-tests/wallet_listreceived.py +++ b/qa/rpc-tests/wallet_listreceived.py @@ -59,7 +59,6 @@ def run_test_release(self, release, height): assert_equal(pt['outputs'][0]['js'], 0) jsOutputPrev = pt['outputs'][0]['jsOutput'] elif pt['outputs'][0]['address'] == zaddr1: - outputPrev = pt['outputs'][0]['output'] assert_equal(pt['outputs'][0]['outgoing'], False) assert_equal(pt['outputs'][0]['memoStr'], my_memo_str) else: @@ -74,7 +73,6 @@ def run_test_release(self, release, height): if release != 'sprout': assert_equal(pt['outputs'][1]['type'], release) if pt['outputs'][1]['address'] == zaddr1: - outputPrev = pt['outputs'][1]['output'] assert_equal(pt['outputs'][1]['outgoing'], False) assert_equal(pt['outputs'][1]['memoStr'], my_memo_str) else: From 5a78f849b2c5a2cd225718f0dc01b8f2e7e55264 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 13 Feb 2020 11:53:49 +0000 Subject: [PATCH 392/395] test: Hard-code hex memo in wallet_listreceived for Python3 compatibility --- qa/rpc-tests/wallet_listreceived.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qa/rpc-tests/wallet_listreceived.py b/qa/rpc-tests/wallet_listreceived.py index 3185afe6133..a3da3d8ef32 100755 --- a/qa/rpc-tests/wallet_listreceived.py +++ b/qa/rpc-tests/wallet_listreceived.py @@ -11,7 +11,7 @@ from decimal import Decimal my_memo_str = 'c0ffee' # stay awake -my_memo = my_memo_str.encode('hex') +my_memo = '633066666565' my_memo = my_memo + '0'*(1024-len(my_memo)) no_memo = 'f6' + ('0'*1022) # see section 5.5 of the protocol spec From 05d987fc53a5e6895b56b49de5e61f2c1ff354a9 Mon Sep 17 00:00:00 2001 From: cryptoforge Date: Tue, 28 Jan 2020 12:17:21 -0800 Subject: [PATCH 393/395] add zindex and getchaintxstats --- src/chain.h | 140 ++++++++++++++++++++++++ src/coins.cpp | 7 +- src/coins.h | 2 + src/init.cpp | 9 +- src/main.cpp | 170 +++++++++++++++++++++++++++++- src/main.h | 3 + src/rpc/blockchain.cpp | 234 +++++++++++++++++++++++++++++++++++++++++ src/rpc/client.cpp | 3 +- src/txmempool.cpp | 4 + src/txmempool.h | 2 + src/wallet/wallet.cpp | 31 ++++++ src/wallet/wallet.h | 3 + 12 files changed, 603 insertions(+), 5 deletions(-) diff --git a/src/chain.h b/src/chain.h index 7512b06b448..09663905066 100644 --- a/src/chain.h +++ b/src/chain.h @@ -14,6 +14,7 @@ #include +extern bool fZindex; static const int SPROUT_VALUE_VERSION = 1001400; static const int SAPLING_VALUE_VERSION = 1010100; @@ -191,11 +192,107 @@ class CBlockIndex //! Note: in a potential headers-first mode, this number cannot be relied upon unsigned int nTx; + //! Number of notarization transactions in this block. + int64_t nNotarizations; + + //! (memory only) Number of payments (shielded or transparent) in the block + //! up to and including this block. One transaction can contain one or more + //! payments. This stat allows us to calculate ratios of shielded/transparent + //! when combined with shielded payment stats + int64_t nPayments; + + //! (memory only) Number of shielded transactions (of any kind) in the block up to and including this block. + //! A shielded transaction is defined as a transaction that contains at least 1 JoinSplit, which includes + //! shielding/de-shielding and other complex transaction possibilties including multiple taddrs/zaddrs as + //! inputs and outputs. + int64_t nShieldedTx; + + //! (memory only) Number of shielded outputs in the block up to and including this block. + int64_t nShieldedOutputs; + + //! (memory only) Number of fully shielded transactions. A fully shielded transaction is defined + //! as a transaction containing JoinSplits and only shielded inputs and outputs, i.e. no transparent + // inputs or outputs: z->z or z->(z,z) or z->(z,z,z,) etc... + int64_t nFullyShieldedTx; + + //! (memory only) Number of shielding payments. A shielding payment is defined + //! as having a shielded output but transparent input: t->z + int64_t nShieldingPayments; + + //! (memory only) Number of shielded payments. A shielded payment is defined + //! as having a shielded input or output: t->z or z->t + int64_t nShieldedPayments; + + //! (memory only) Number of fully shielded payments. A fully shielded payment is defined + //! as having a shielded input and shielded output: z->z + int64_t nFullyShieldedPayments; + + //! (memory only) Number of deshielding transactions. A deshielding transaction is defined + //! as a transaction containing JoinSplits and at least one transparent output. + int64_t nDeshieldingTx; + + //! (memory only) Number of deshielding payments. A deshielding payment is defined + //! as one transparent input and one shielded output: z->t + int64_t nDeshieldingPayments; + + //! (memory only) Number of shielding transactions. A shielding transaction is defined + //! as a transaction containing JoinSplits and at least one transparent input + // i.e. t->z or t->(z,t) or z->(z,z,t) + int64_t nShieldingTx; + //! (memory only) Number of transactions in the chain up to and including this block. //! This value will be non-zero only if and only if transactions for this block and all its parents are available. //! Change to 64-bit type when necessary; won't happen before 2030 unsigned int nChainTx; + //! Number of notarization transactions in this chain + int64_t nChainNotarizations; + + //! (memory only) Number of payments (shielded or transparent) in the chain + //! up to and including this block. One transaction can contain one or more + //! payments. This stat allows us to calculate ratios of shielded/transparent + //! when combined with shielded payment stats + int64_t nChainPayments; + + //! (memory only) Number of shielded transactions (of any kind) in the chain up to and including this block. + //! A shielded transaction is defined as a transaction that contains at least 1 JoinSplit, which includes + //! shielding/de-shielding and other complex transaction possibilties including multiple taddrs/zaddrs as + //! inputs and outputs. + int64_t nChainShieldedTx; + + //! (memory only) Number of shielded outputs in the chain up to and including this block. + int64_t nChainShieldedOutputs; + + //! (memory only) Number of fully shielded transactions. A fully shielded transaction is defined + //! as a transaction containing JoinSplits and only shielded inputs and outputs, i.e. no transparent + // inputs or outputs: z->z or z->(z,z) or z->(z,z,z,) etc... + int64_t nChainFullyShieldedTx; + + //! (memory only) Number of shielding payments. A shielding payment is defined + //! as having a shielded output but transparent input: t->z + int64_t nChainShieldingPayments; + + //! (memory only) Number of shielded payments. A shielded payment is defined + //! as having a shielded input or output: t->z or z->t + int64_t nChainShieldedPayments; + + //! (memory only) Number of fully shielded payments. A fully shielded payment is defined + //! as having a shielded input and shielded output: z->z + int64_t nChainFullyShieldedPayments; + + //! (memory only) Number of deshielding transactions. A deshielding transaction is defined + //! as a transaction containing JoinSplits and at least one transparent output. + int64_t nChainDeshieldingTx; + + //! (memory only) Number of deshielding payments. A deshielding payment is defined + //! as one transparent input and one shielded output: z->t + int64_t nChainDeshieldingPayments; + + //! (memory only) Number of shielding transactions. A shielding transaction is defined + //! as a transaction containing JoinSplits and at least one transparent input + // i.e. t->z or t->(z,t) or z->(z,z,t) + int64_t nChainShieldingTx; + //! Verification status of this block. See enum BlockStatus unsigned int nStatus; @@ -252,6 +349,33 @@ class CBlockIndex nChainWork = arith_uint256(); nTx = 0; nChainTx = 0; + + // Shieldex Index chain stats + nChainPayments = 0; + nChainShieldedTx = 0; + nChainShieldingTx = 0; + nChainDeshieldingTx = 0; + nChainNotarizations = 0; + nChainFullyShieldedTx = 0; + nChainShieldedOutputs = 0; + nChainShieldedPayments = 0; + nChainShieldingPayments = 0; + nChainDeshieldingPayments = 0; + nChainFullyShieldedPayments = 0; + + // Shieldex Index stats + nPayments = 0; + nShieldedTx = 0; + nShieldingTx = 0; + nNotarizations = 0; + nDeshieldingTx = 0; + nShieldedOutputs = 0; + nFullyShieldedTx = 0; + nShieldedPayments = 0; + nShieldingPayments = 0; + nDeshieldingPayments = 0; + nFullyShieldedPayments = 0; + nStatus = 0; nCachedBranchId = boost::none; hashSproutAnchor = uint256(); @@ -454,6 +578,22 @@ class CDiskBlockIndex : public CBlockIndex READWRITE(nSaplingValue); } + // These values only serialized when -zindex enabled + // Order is important! + if((s.GetType() & SER_DISK) && fZindex) { + READWRITE(nShieldedTx); + READWRITE(nShieldingTx); + READWRITE(nDeshieldingTx); + READWRITE(nFullyShieldedTx); + READWRITE(nPayments); + READWRITE(nNotarizations); + READWRITE(nShieldedPayments); + READWRITE(nShieldingPayments); + READWRITE(nDeshieldingPayments); + READWRITE(nFullyShieldedPayments); + READWRITE(nShieldedOutputs); + } + // If you have just added new serialized fields above, remember to add // them to CBlockTreeDB::LoadBlockIndexGuts() in txdb.cpp :) } diff --git a/src/coins.cpp b/src/coins.cpp index 09a8ccf98c5..f2e351a682a 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -34,7 +34,12 @@ void CCoins::CalcMaskSize(unsigned int &nBytes, unsigned int &nNonzeroBytes) con nBytes += nLastUsedByte; } -bool CCoins::Spend(uint32_t nPos) +CNullifiersMap CCoinsViewCache::getNullifiers() +{ + return cacheSaplingNullifiers; +} + +bool CCoins::Spend(uint32_t nPos) { if (nPos >= vout.size() || vout[nPos].IsNull()) return false; diff --git a/src/coins.h b/src/coins.h index c29c1331505..3f27f844c93 100644 --- a/src/coins.h +++ b/src/coins.h @@ -459,6 +459,8 @@ class CCoinsViewCache : public CCoinsViewBacked CCoinsViewCache(CCoinsView *baseIn); ~CCoinsViewCache(); + CNullifiersMap getNullifiers(); + // Standard CCoinsView methods bool GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const; bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const; diff --git a/src/init.cpp b/src/init.cpp index 22c70762420..2db58c34bd4 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -385,7 +385,7 @@ std::string HelpMessage(HelpMessageMode mode) // strUsage += HelpMessageOpt("-timestampindex", strprintf(_("Maintain a timestamp index for block hashes, used to query blocks hashes by a range of timestamps (default: %u)"), DEFAULT_TIMESTAMPINDEX)); // strUsage += HelpMessageOpt("-spentindex", strprintf(_("Maintain a full spent index, used to query the spending txid and input index for an outpoint (default: %u)"), DEFAULT_SPENTINDEX)); strUsage += HelpMessageOpt("-insightexplorer", strprintf(_("Maintain a full address, spent & timestamp indexes, used by insight explorer (default: %u)"), DEFAULT_SPENTINDEX)); - + strUsage += HelpMessageOpt("-zindex", strprintf(_("Maintain extra statistics about shielded transactions and payments (default: %u)"), 0)); strUsage += HelpMessageGroup(_("Connection options:")); strUsage += HelpMessageOpt("-addnode=", _("Add a node to connect to and attempt to keep the connection open")); @@ -486,7 +486,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-nuparams=hexBranchId:activationHeight", "Use given activation height for specified network upgrade (regtest-only)"); } string debugCategories = "addrman, alert, bench, coindb, db, deletetx, estimatefee, http, libevent, lock, mempool, net, partitioncheck, pow, proxy, prune, " - "rand, reindex, rpc, selectcoins, tor, zmq, zrpc, zrpcunsafe (implies zrpc)"; // Don't translate these + "rand, reindex, rpc, selectcoins, tor, zindex, zmq, zrpc, zrpcunsafe (implies zrpc)"; // Don't translate these strUsage += HelpMessageOpt("-debug=", strprintf(_("Output debugging information (default: %u, supplying is optional)"), 0) + ". " + _("If is not supplied or if = 1, output all debugging information.") + " " + _(" can be:") + " " + debugCategories + "."); strUsage += HelpMessageOpt("-experimentalfeatures", _("Enable use of experimental features")); @@ -1581,6 +1581,11 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) break; } + if (fZindex != GetBoolArg("-zindex", false)) { + strLoadError = _("You need to rebuild the database using -reindex to change -zindex"); + break; + } + // Check for changed -prune state. What we are concerned about is a user who has pruned blocks // in the past, but is now trying to run unpruned. if (fHavePruned && !fPruneMode) { diff --git a/src/main.cpp b/src/main.cpp index 3ba398a69c5..4ce968511de 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -74,6 +74,7 @@ bool fExperimentalMode = false; bool fImporting = false; bool fReindex = false; bool fTxIndex = false; +bool fZindex = false; bool fInsightExplorer = false; // insightexplorer bool fAddressIndex = false; // insightexplorer bool fSpentIndex = false; // insightexplorer @@ -1697,7 +1698,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa { // We lock to prevent other threads from accessing the mempool between adding and evicting LOCK(pool.cs); - + // Store transaction in memory pool.addUnchecked(hash, entry, !IsInitialBlockDownload(Params())); @@ -3968,6 +3969,12 @@ bool ReceivedBlockTransactions( pindexNew->nChainTx = 0; CAmount sproutValue = 0; CAmount saplingValue = 0; + bool isShieldedTx = false; + unsigned int nShieldedSpends=0,nShieldedOutputs=0,nPayments=0, nShieldedOutputsInBlock=0; + unsigned int nShieldedTx=0,nFullyShieldedTx=0,nDeshieldingTx=0,nShieldingTx=0; + unsigned int nShieldedPayments=0,nFullyShieldedPayments=0,nShieldingPayments=0,nDeshieldingPayments=0; + unsigned int nNotarizations=0; + for (auto tx : block.vtx) { // Negative valueBalance "takes" money from the transparent value pool // and adds it to the Sapling value pool. Positive valueBalance "gives" @@ -3979,7 +3986,82 @@ bool ReceivedBlockTransactions( sproutValue += js.vpub_old; sproutValue -= js.vpub_new; } + + // Ignore following stats unless -zindex enabled + if (!fZindex) + continue; + + nShieldedSpends = tx.vShieldedSpend.size(); + nShieldedOutputs = tx.vShieldedOutput.size(); + isShieldedTx = (nShieldedSpends + nShieldedOutputs) > 0 ? true : false; + + // We want to avoid full verification with a low false-positive rate + // TODO: A nefarious user could create xtns which meet these criteria and skew stats, what + // else can we look for which is not full validation? + // Can we filter on properties of tx.vout[0] ? + // if(tx.vin.size()==13 && tx.vout.size()==2 && tx.vout[1].scriptPubKey.IsOpReturn() && tx.vout[1].nValue==0) { + // nNotarizations++; + // } + + //NOTE: These are at best heuristics. Improve them as much as possible. + // You cannot compare stats generated from different sets of heuristics, so + // if you change this code, you must reindex or delete datadir + resync from scratch, or you + // will be mixing together data from two set of heuristics. + if(isShieldedTx) { + nShieldedTx++; + // NOTE: It's possible for very complex transactions to be both shielding and deshielding, + // such as (t,z)=>(t,z) Since these transactions cannot be made via RPCs currently, they + // would currently need to be made via raw transactions + if(tx.vin.size()==0 && tx.vout.size()==0) { + nFullyShieldedTx++; + } else if(tx.vin.size()>0) { + nShieldingTx++; + } else if(tx.vout.size()>0) { + nDeshieldingTx++; + } + + if (nShieldedOutputs >= 1) { + // If there are shielded outputs, count each as a payment + // By default, if there is more than 1 output, we assume 1 zaddr change output which is not a payment. + // In the case of multiple outputs which spend inputs exactly, there is no change output and this + // heuristic will undercount payments. Since this edge case is rare, this seems acceptable. + // t->(t,t,z) = 1 shielded payment + // z->(z,z) = 1 shielded payment + shielded change + // t->(z,z) = 1 shielded payment + shielded change + // t->(t,z) = 1 shielded payment + transparent change + // (z,z)->z = 1 shielded payment (has this xtn ever occurred?) + // z->(z,z,z) = 2 shielded payments + shielded change + // Assume that there is always 1 change output when there are more than one output + nShieldedPayments += nShieldedOutputs > 1 ? (nShieldedOutputs-1) : 1; + // since we have at least 1 zoutput, all transparent outputs are payments, not change + nShieldedPayments += tx.vout.size(); + + // Fully shielded do not count toward shielding/deshielding + if(tx.vin.size()==0 && tx.vout.size()==0) { + nFullyShieldedPayments += nShieldedOutputs > 1 ? (nShieldedOutputs-1) : 1; + } else { + nShieldingPayments += nShieldedOutputs > 1 ? (nShieldedOutputs-1) : 1; + // Also count remaining taddr outputs as payments + nShieldedPayments += tx.vout.size(); + } + } else if (nShieldedSpends >=1) { + // Shielded inputs with no shielded outputs. We know none are change output because + // change would flow back to the zaddr + // z->t = 1 shielded payment + // z->(t,t) = 2 shielded payments + // z->(t,t,t) = 3 shielded payments + nShieldedPayments += tx.vout.size(); + nDeshieldingPayments += tx.vout.size() > 1 ? tx.vout.size()-1 : tx.vout.size(); + } + nPayments += nShieldedPayments; + } else { + // No shielded payments, add transparent payments minus a change address + nPayments += tx.vout.size() > 1 ? tx.vout.size()-1 : tx.vout.size(); + } + // To calculate the anonset we must track the sum of zouts in every tx, in every block. -- Duke + nShieldedOutputsInBlock += nShieldedOutputs; } + pindexNew->nSproutValue = sproutValue; pindexNew->nChainSproutValue = boost::none; pindexNew->nSaplingValue = saplingValue; @@ -3991,6 +4073,21 @@ bool ReceivedBlockTransactions( pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS); setDirtyBlockIndex.insert(pindexNew); + if (fZindex) { + pindexNew->nPayments = nPayments; + pindexNew->nShieldedTx = nShieldedTx; + pindexNew->nShieldedOutputs = nShieldedOutputsInBlock; + pindexNew->nFullyShieldedTx = nFullyShieldedTx; + pindexNew->nDeshieldingTx = nDeshieldingTx; + pindexNew->nShieldingTx = nShieldingTx; + pindexNew->nShieldedPayments = nShieldedPayments; + pindexNew->nFullyShieldedPayments = nFullyShieldedPayments; + pindexNew->nDeshieldingPayments = nDeshieldingPayments; + pindexNew->nShieldingPayments = nShieldingPayments; + pindexNew->nNotarizations = nNotarizations; + } + setDirtyBlockIndex.insert(pindexNew); + if (pindexNew->pprev == NULL || pindexNew->pprev->nChainTx) { // If pindexNew is the genesis block or all parents are BLOCK_VALID_TRANSACTIONS. deque queue; @@ -4001,6 +4098,23 @@ bool ReceivedBlockTransactions( CBlockIndex *pindex = queue.front(); queue.pop_front(); pindex->nChainTx = (pindex->pprev ? pindex->pprev->nChainTx : 0) + pindex->nTx; + + if (fZindex) { + if (fDebug) + LogPrint("zindex","%s: setting blockchain zstats with zouts=%d\n", __FUNCTION__, nShieldedOutputsInBlock ); + pindex->nChainNotarizations = (pindex->pprev ? pindex->pprev->nChainNotarizations : 0) + pindex->nNotarizations; + pindex->nChainShieldedTx = (pindex->pprev ? pindex->pprev->nChainShieldedTx : 0) + pindex->nShieldedTx; + pindex->nChainShieldedOutputs = (pindex->pprev ? pindex->pprev->nChainShieldedOutputs : 0) + pindex->nShieldedOutputs; + pindex->nChainFullyShieldedTx = (pindex->pprev ? pindex->pprev->nChainFullyShieldedTx : 0) + pindex->nFullyShieldedTx; + pindex->nChainShieldingTx = (pindex->pprev ? pindex->pprev->nChainShieldingTx : 0) + pindex->nShieldingTx; + pindex->nChainDeshieldingTx = (pindex->pprev ? pindex->pprev->nChainDeshieldingTx : 0) + pindex->nDeshieldingTx; + pindex->nChainPayments = (pindex->pprev ? pindex->pprev->nChainPayments : 0) + pindex->nPayments; + pindex->nChainShieldedPayments = (pindex->pprev ? pindex->pprev->nChainShieldedPayments : 0) + pindex->nShieldedPayments; + pindex->nChainFullyShieldedPayments = (pindex->pprev ? pindex->pprev->nChainFullyShieldedPayments : 0) + pindex->nFullyShieldedPayments; + pindex->nChainShieldingPayments = (pindex->pprev ? pindex->pprev->nChainShieldingPayments : 0) + pindex->nShieldingPayments; + pindex->nChainDeshieldingPayments = (pindex->pprev ? pindex->pprev->nChainDeshieldingPayments : 0) + pindex->nDeshieldingPayments; + } + if (pindex->pprev) { if (pindex->pprev->nChainSproutValue && pindex->nSproutValue) { pindex->nChainSproutValue = *pindex->pprev->nChainSproutValue + *pindex->nSproutValue; @@ -4041,6 +4155,10 @@ bool ReceivedBlockTransactions( } } + if (fZindex) + LogPrint("zindex", "ht.%d, ShieldedPayments=%d, ShieldedTx=%d, ShieldedOutputs=%d, FullyShieldedTx=%d, ntz=%d\n", + pindexNew->nHeight, nShieldedPayments, nShieldedTx, nShieldedOutputs, nFullyShieldedTx, nNotarizations ); + return true; } @@ -4773,6 +4891,22 @@ bool static LoadBlockIndexDB() if (pindex->pprev) { if (pindex->pprev->nChainTx) { pindex->nChainTx = pindex->pprev->nChainTx + pindex->nTx; + + if (fZindex) { + pindex->nChainNotarizations = pindex->pprev->nChainNotarizations + pindex->nNotarizations; + pindex->nChainShieldedTx = pindex->pprev->nChainShieldedTx + pindex->nShieldedTx; + pindex->nChainShieldedOutputs = pindex->pprev->nChainShieldedOutputs + pindex->nShieldedOutputs; + pindex->nChainShieldedPayments = pindex->pprev->nChainShieldedPayments + pindex->nShieldedPayments; + pindex->nChainShieldingTx = pindex->pprev->nChainShieldingTx + pindex->nShieldingTx; + + pindex->nChainPayments = pindex->pprev->nChainPayments + pindex->nPayments; + pindex->nChainShieldingPayments = pindex->pprev->nChainShieldingPayments + pindex->nShieldingPayments; + pindex->nChainDeshieldingTx = pindex->pprev->nChainShieldedTx + pindex->nShieldedTx; + pindex->nChainDeshieldingPayments = pindex->pprev->nChainShieldedPayments + pindex->nShieldedPayments; + pindex->nChainFullyShieldedTx = pindex->pprev->nChainFullyShieldedTx + pindex->nFullyShieldedTx; + pindex->nChainFullyShieldedPayments = pindex->pprev->nChainFullyShieldedPayments + pindex->nFullyShieldedPayments; + } + if (pindex->pprev->nChainSproutValue && pindex->nSproutValue) { pindex->nChainSproutValue = *pindex->pprev->nChainSproutValue + *pindex->nSproutValue; } else { @@ -4785,12 +4919,37 @@ bool static LoadBlockIndexDB() } } else { pindex->nChainTx = 0; + if (fZindex) { + pindex->nChainPayments = 0; + pindex->nChainNotarizations = 0; + pindex->nChainShieldedTx = 0; + pindex->nChainShieldedOutputs = 0; + pindex->nChainFullyShieldedTx = 0; + pindex->nChainShieldedPayments = 0; + pindex->nChainShieldingPayments = 0; + pindex->nChainDeshieldingTx = 0; + pindex->nChainDeshieldingPayments = 0; + pindex->nChainFullyShieldedTx = 0; + pindex->nChainFullyShieldedPayments = 0; + } pindex->nChainSproutValue = boost::none; pindex->nChainSaplingValue = boost::none; mapBlocksUnlinked.insert(std::make_pair(pindex->pprev, pindex)); } } else { pindex->nChainTx = pindex->nTx; + if (fZindex) { + pindex->nChainPayments = pindex->nPayments; + pindex->nChainNotarizations = pindex->nNotarizations; + pindex->nChainShieldedTx = pindex->nShieldedTx; + pindex->nChainShieldedOutputs = pindex->nShieldedOutputs; + pindex->nChainShieldedPayments = pindex->nShieldedPayments; + pindex->nChainShieldingTx = pindex->nShieldingTx; + pindex->nChainShieldingPayments = pindex->nShieldingPayments; + pindex->nChainDeshieldingTx = pindex->nDeshieldingTx; + pindex->nChainDeshieldingPayments = pindex->nDeshieldingPayments; + pindex->nChainFullyShieldedPayments = pindex->nFullyShieldedPayments; + } pindex->nChainSproutValue = pindex->nSproutValue; pindex->nChainSaplingValue = pindex->nSaplingValue; } @@ -4886,6 +5045,10 @@ bool static LoadBlockIndexDB() fSpentIndex = fInsightExplorer; fTimestampIndex = fInsightExplorer; + // Check whether we have a shielded index + pblocktree->ReadFlag("zindex", fZindex); + LogPrintf("%s: shielded index %s\n", __func__, fZindex ? "enabled" : "disabled"); + // Fill in-memory data BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex) { @@ -5231,6 +5394,11 @@ bool InitBlockIndex(const CChainParams& chainparams) fSpentIndex = fInsightExplorer; fTimestampIndex = fInsightExplorer; + // Use the provided setting for -zindex in the new database + fZindex = GetBoolArg("-zindex", DEFAULT_SHIELDEDINDEX); + pblocktree->WriteFlag("zindex", fZindex); + + LogPrintf("Initializing databases...\n"); // Only add the genesis block if not reindexing (in which case we reuse the one already on disk) diff --git a/src/main.h b/src/main.h index 18e905cd1c1..edf7ab41cea 100644 --- a/src/main.h +++ b/src/main.h @@ -111,6 +111,7 @@ static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111; static const bool DEFAULT_ADDRESSINDEX = false; static const bool DEFAULT_TIMESTAMPINDEX = false; static const bool DEFAULT_SPENTINDEX = false; +static const bool DEFAULT_SHIELDEDINDEX = false; static const bool DEFAULT_DB_COMPRESSION = true; static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60; @@ -144,6 +145,8 @@ extern bool fReindex; extern int nScriptCheckThreads; extern bool fTxIndex; +extern bool fZindex; + // START insightexplorer extern bool fInsightExplorer; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index eb83d41c80f..f41b1f1dafd 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -9,6 +9,7 @@ #include "chainparams.h" #include "checkpoints.h" #include "consensus/validation.h" +#include "init.h" #include "key_io.h" #include "main.h" #include "primitives/transaction.h" @@ -17,6 +18,7 @@ #include "streams.h" #include "sync.h" #include "util.h" +#include "wallet/wallet.h" #include @@ -1214,6 +1216,237 @@ UniValue getmempoolinfo(const UniValue& params, bool fHelp) return mempoolInfoToJSON(); } +inline CBlockIndex* LookupBlockIndex(const uint256& hash) +{ + AssertLockHeld(cs_main); + BlockMap::const_iterator it = mapBlockIndex.find(hash); + return it == mapBlockIndex.end() ? nullptr : it->second; +} + +// given a transaction count X, subtract out coinbase and dpow transactions +// to give an "organic count". We return 0 instead of negative values +#define ORG(X) ( (X - blockcount - nNotarizationsDiff) > 0 ? (X - blockcount - nNotarizationsDiff) : 0 ) + +UniValue getchaintxstats(const UniValue& params, bool fHelp) +{ + //THROW_IF_SYNCING(KOMODO_INSYNC); + + if (fHelp || params.size() > 2) + throw runtime_error( + "getchaintxstats\n" + "\nCompute statistics about the total number and rate of transactions in the chain.\n" + "\nThis RPC will return a large amount of additional data if the shielded index (zindex) is enabled.\n" + "\nArguments:\n" + "1. nblocks (numeric, optional) Number of blocks in averaging window.\n" + "2. blockhash (string, optional) The hash of the block which ends the window.\n" + "\nResult:\n" + "{\n" + " \"time\": xxxxx, (numeric) The timestamp for the final block in the window in UNIX format.\n" + " \"txcount\": xxxxx, (numeric) The total number of transactions in the chain up to that point.\n" + " \"nullifiers\": xxxxx, (numeric) The total number of shielded nullifiers in the chain up to that point.\n" + " \"shielded_txcount\": xxxxx, (numeric) The total number of shielded (containing a zaddr) transactions in the chain up to that point.\n" + " \"shielded_outputs\": xxxxx, (numeric) The total number of shielded outputs in the chain up to that point.\n" + " \"shielded_pool_size\": xxxxx, (numeric) The total number of unspent shielded outputs, i.e. the Shielded Pool or Anonymity Set (anonset).\n" + " \"shielding_txcount\": xxxxx, (numeric) The total number of shielding (containing a zaddr output) transactions in the chain up to that point.\n" + " \"deshielding_txcount\": xxxxx, (numeric) The total number of deshielding (containing a zaddr input) transactions in the chain up to that point.\n" + " \"fully_shielded_txcount\": xxxxx, (numeric) The total number of z2z, AKA fully-shielded (containing only zaddr inputs+outputs) transactions in the chain up to that point.\n" + " \"payments\": xxxxx, (numeric) The total number of payments in the chain up to that point.\n" + " \"shielded_payments\": xxxxx, (numeric) The total number of shielded (containing a zaddr) payments in the chain up to that point.\n" + " \"shielding_payments\": xxxxx, (numeric) The total number of shielding (containing a zaddr output) payments in the chain up to that point.\n" + " \"deshielding_payments\": xxxxx, (numeric) The total number of deshielding (containing a zaddr input) payments in the chain up to that point.\n" + " \"fully_shielded_payments\": xxxxx, (numeric) The total number of z2z, AKA fully-shielded (containing only zaddr inputs+outputs) payments in the chain up to that point.\n" + " \"notarizations\": xxxxx, (numeric) The total number of notarization transactions in the chain up to that point.\n" + " \"window_final_block_hash\": \"...\", (string) The hash of the final block in the window.\n" + " \"window_final_block_height\": xxxxx, (numeric) Block height of final block in window.\n" + " \"window_block_count\": xxxxx, (numeric) Size of the window in number of blocks.\n" + " \"window_tx_count\": xxxxx, (numeric) The number of transactions in the window. Only returned if \"window_block_count\" is > 0.\n" + " \"window_interval\": xxxxx, (numeric) The elapsed time in the window in seconds. Only returned if \"window_block_count\" is > 0.\n" + " \"window_shielded_txcount\": xxxxx, (numeric) The total number of shielded (containing a zaddr) transactions in the chain up to that point.\n" + " \"window_shielding_txcount\": xxxxx, (numeric) The total number of shielding (containing a zaddr output) transactions in the chain up to that point.\n" + " \"window_deshielding_txcount\": xxxxx, (numeric) The total number of deshielding (containing a zaddr input) transactions in the chain up to that point.\n" + " \"window_fully_shielded_txcount\": xxxxx, (numeric) The total number of z2z, AKA fully-shielded (containing only zaddr inputs+outputs) transactions in the chain up to that point.\n" + " \"window_shielded_payments\": xxxxx, (numeric) The total number of shielded (containing a zaddr) payments in the chain up to that point.\n" + " \"window_shielding_payments\": xxxxx, (numeric) The total number of shielding (containing a zaddr output) payments in the chain up to that point.\n" + " \"window_deshielding_payments\": xxxxx, (numeric) The total number of deshielding (containing a zaddr input) payments in the chain up to that point.\n" + " \"window_fully_shielded_payments\": xxxxx, (numeric) The total number of z2z, AKA fully-shielded (containing only zaddr inputs+outputs) payments in the chain up to that point.\n" + " \"txrate\": x.xx, (numeric) The average rate of transactions per second in the window. Only returned if \"window_interval\" is > 0.\n" + " \"shielded\": { (string) The set of stats specific to only shieled transactions. \n" + " \"fully_shielded_tx_percent\": (numeric) The percentage of fully shielded transactions.\n" + " \"shielding_tx_percent\": (numeric) The percentage of shielding transactions.\n" + " \"deshielding_tx_percent\": (numeric) The percentage of deshielding transactions.\n" + " \"fully_shielded_payments_percent\": (numeric) The percentage of fully shielded payments.\n" + " \"shielding_payments_percent\": (numeric) The percentage of shielding payments.\n" + " \"deshielding_payments_percent\": (numeric) The percentage of deshielding payments.\n" + " },\n" + " \"organic\": { (string) The set of stats about organic transactions, i.e. those that are not coinbase and not notarizations\n" + " \"fully_shielded_tx_percent\": (numeric) The percentage of fully shielded organic transactions.\n" + " \"shielding_tx_percent\": (numeric) The percentage of shielding organic transactions.\n" + " \"deshielding_tx_percent\": (numeric) The percentage of deshielding organic transactions.\n" + " \"fully_shielded_payments_percent\": (numeric) The percentage of fully shielded organic payments.\n" + " \"shielding_payments_percent\": (numeric) The percentage of shielding organic payments.\n" + " \"deshielding_payments_percent\": (numeric) The percentage of deshielding organic payments.\n" + " }\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("getchaintxstats", "") + + HelpExampleRpc("getchaintxstats", "2016") + ); + + const CBlockIndex* pindex; + int blockcount = 30 * 24 * 60 * 60 / Params().GetConsensus().nPreBlossomPowTargetSpacing; // By default: 1 month + + if (params[1].isNull()) { + LOCK(cs_main); + pindex = chainActive.Tip(); + } else { + uint256 hash(ParseHashV(params[1], "blockhash")); + LOCK(cs_main); + pindex = LookupBlockIndex(hash); + if (!pindex) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + } + if (!chainActive.Contains(pindex)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Block is not in main chain"); + } + } + + assert(pindex != nullptr); + + if (params[0].isNull()) { + blockcount = std::max(0, std::min(blockcount, pindex->nHeight - 1)); + } else { + blockcount = params[0].get_int(); + + if (blockcount < 0 || (blockcount > 0 && blockcount >= pindex->nHeight)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block count: should be between 0 and the block's height - 1"); + } + } + + const CBlockIndex* pindexPast = pindex->GetAncestor(pindex->nHeight - blockcount); + int nTimeDiff = pindex->GetMedianTimePast() - pindexPast->GetMedianTimePast(); + int nTxDiff = pindex->nChainTx - pindexPast->nChainTx; + + UniValue ret(UniValue::VOBJ); + ret.push_back(Pair("time", (int64_t)pindex->nTime)); + ret.push_back(Pair("txcount", (int64_t)pindex->nChainTx)); + ret.push_back(Pair("window_final_block_hash", pindex->GetBlockHash().GetHex())); + ret.push_back(Pair("window_final_block_height", pindex->nHeight)); + ret.push_back(Pair("window_block_count", blockcount)); + + if (fZindex) { + ret.push_back(Pair("notarizations", (int64_t)pindex->nChainNotarizations)); + ret.push_back(Pair("shielded_txcount", (int64_t)pindex->nChainShieldedTx)); + ret.push_back(Pair("fully_shielded_txcount", (int64_t)pindex->nChainFullyShieldedTx)); + ret.push_back(Pair("deshielding_txcount", (int64_t)pindex->nChainDeshieldingTx)); + ret.push_back(Pair("shielding_txcount", (int64_t)pindex->nChainShieldingTx)); + ret.push_back(Pair("shielded_payments", (int64_t)pindex->nChainShieldedPayments)); + ret.push_back(Pair("fully_shielded_payments", (int64_t)pindex->nChainFullyShieldedPayments)); + ret.push_back(Pair("deshielding_payments", (int64_t)pindex->nChainDeshieldingPayments)); + ret.push_back(Pair("shielding_payments", (int64_t)pindex->nChainShieldingPayments)); + + int64_t nullifierCount = pwalletMain->NullifierCount(); + ret.push_back(Pair("nullifiers", (int64_t)nullifierCount)); + ret.push_back(Pair("shielded_pool_size", (int64_t)pindex->nChainShieldedOutputs - nullifierCount)); + ret.push_back(Pair("shielded_outputs", (int64_t)pindex->nChainShieldedOutputs)); + } + + if (blockcount > 0) { + ret.push_back(Pair("window_tx_count", nTxDiff)); + ret.push_back(Pair("window_interval", nTimeDiff)); + int64_t nPaymentsDiff = pindex->nChainPayments - pindexPast->nChainPayments; + int64_t nShieldedTxDiff = pindex->nChainShieldedTx - pindexPast->nChainShieldedTx; + int64_t nShieldingTxDiff = pindex->nChainShieldingTx - pindexPast->nChainShieldingTx; + int64_t nDeshieldingTxDiff = pindex->nChainDeshieldingTx - pindexPast->nChainDeshieldingTx; + int64_t nFullyShieldedTxDiff = pindex->nChainFullyShieldedTx - pindexPast->nChainFullyShieldedTx; + int64_t nShieldedPaymentsDiff = pindex->nChainShieldedPayments - pindexPast->nChainShieldedPayments; + int64_t nShieldingPaymentsDiff = pindex->nChainShieldingPayments - pindexPast->nChainShieldingPayments; + int64_t nDeshieldingPaymentsDiff = pindex->nChainDeshieldingPayments - pindexPast->nChainDeshieldingPayments; + int64_t nFullyShieldedPaymentsDiff = pindex->nChainFullyShieldedPayments - pindexPast->nChainFullyShieldedPayments; + int64_t nNotarizationsDiff = pindex->nChainNotarizations - pindexPast->nChainNotarizations; + + if (nTimeDiff > 0) { + ret.push_back(Pair("txrate", ((double)nTxDiff) / nTimeDiff)); + if (fZindex) { + ret.push_back(Pair("notarization_txrate", ((double)nNotarizationsDiff) / nTimeDiff)); + ret.push_back(Pair("shielded_txrate", ((double)nShieldedTxDiff) / nTimeDiff)); + ret.push_back(Pair("fully_shielded_txrate", ((double)nFullyShieldedTxDiff) / nTimeDiff)); + ret.push_back(Pair("paymentrate", ((double)nPaymentsDiff) / nTimeDiff)); + ret.push_back(Pair("shielded_paymentrate", ((double)nShieldedPaymentsDiff) / nTimeDiff)); + ret.push_back(Pair("fully_shielded_paymentrate", ((double)nFullyShieldedPaymentsDiff) / nTimeDiff)); + } + } + + if (fZindex) { + ret.push_back(Pair("window_payments", (int) nPaymentsDiff)); + ret.push_back(Pair("window_notarizations", (int) nNotarizationsDiff)); + ret.push_back(Pair("window_fully_shielded_txcount", nFullyShieldedTxDiff)); + ret.push_back(Pair("window_deshielding_txcount", nDeshieldingTxDiff)); + ret.push_back(Pair("window_shielding_txcount", nShieldingTxDiff)); + ret.push_back(Pair("window_shielded_txcount", nShieldedTxDiff)); + ret.push_back(Pair("window_fully_shielded_payments", nFullyShieldedPaymentsDiff)); + ret.push_back(Pair("window_shielded_payments", nShieldedPaymentsDiff)); + ret.push_back(Pair("window_shielding_payments", nShieldingPaymentsDiff)); + ret.push_back(Pair("window_deshielding_payments", nDeshieldingPaymentsDiff)); + if (nTxDiff > 0) { + ret.push_back(Pair("shielded_tx_percent", ((double)nShieldedTxDiff) / nTxDiff)); + ret.push_back(Pair("fully_shielded_tx_percent", ((double)nFullyShieldedTxDiff) / nTxDiff)); + ret.push_back(Pair("shielding_tx_percent", ((double)nShieldingTxDiff) / nTxDiff)); + ret.push_back(Pair("deshielding_tx_percent", ((double)nDeshieldingTxDiff) / nTxDiff)); + } + if (nPaymentsDiff > 0) { + ret.push_back(Pair("shielded_payments_percent", ((double)nShieldedPaymentsDiff) / nPaymentsDiff)); + ret.push_back(Pair("fully_shielded_payments_percent", ((double)nFullyShieldedPaymentsDiff) / nPaymentsDiff)); + ret.push_back(Pair("shielding_payments_percent", ((double)nShieldingPaymentsDiff) / nPaymentsDiff)); + ret.push_back(Pair("deshielding_payments_percent", ((double)nDeshieldingPaymentsDiff) / nPaymentsDiff)); + } + + // Statistics considering only zxtns + UniValue shielded(UniValue::VOBJ); + if (nShieldedTxDiff > 0) { + shielded.push_back(Pair("fully_shielded_tx_percent", ((double)nFullyShieldedTxDiff) / nShieldedTxDiff )); + shielded.push_back(Pair("shielding_tx_percent", ((double)nShieldingTxDiff) / nShieldedTxDiff )); + shielded.push_back(Pair("deshielding_tx_percent", ((double)nDeshieldingTxDiff) / nShieldedTxDiff )); + } + if (nShieldedPaymentsDiff > 0) { + shielded.push_back(Pair("fully_shielded_payments_percent", ((double)nFullyShieldedPaymentsDiff) / nShieldedPaymentsDiff )); + shielded.push_back(Pair("shielding_payments_percent", ((double)nShieldingPaymentsDiff) / nShieldedPaymentsDiff )); + shielded.push_back(Pair("deshielding_payments_percent", ((double)nDeshieldingPaymentsDiff) / nShieldedPaymentsDiff )); + } + + if(nShieldedTxDiff+nShieldedPaymentsDiff > 0) + ret.push_back(Pair("shielded", shielded)); + + // Organic tx stats = Raw - Coinbase - DPoW + if (nTxDiff > 0) { + UniValue organic(UniValue::VOBJ); + + if(ORG(nTxDiff) > 0) { + organic.push_back(Pair("shielded_tx_percent", ((double)nShieldedTxDiff) / ORG(nTxDiff))); + organic.push_back(Pair("fully_shielded_tx_percent", ((double)nFullyShieldedTxDiff) / ORG(nTxDiff))); + organic.push_back(Pair("shielding_tx_percent", ((double)nShieldingTxDiff) / ORG(nTxDiff))); + organic.push_back(Pair("deshielding_tx_percent", ((double)nDeshieldingTxDiff) / ORG(nTxDiff))); + } + if(ORG(nPaymentsDiff) > 0) { + organic.push_back(Pair("shielded_payments_percent", ((double)nShieldedPaymentsDiff) / ORG(nPaymentsDiff))); + organic.push_back(Pair("fully_shielded_payments_percent", ((double)nFullyShieldedPaymentsDiff) / ORG(nPaymentsDiff))); + organic.push_back(Pair("shielding_payments_percent", ((double)nShieldingPaymentsDiff) / ORG(nPaymentsDiff))); + organic.push_back(Pair("deshielding_payments_percent", ((double)nDeshieldingPaymentsDiff) / ORG(nPaymentsDiff))); + } + if (nTimeDiff > 0) { + organic.push_back(Pair("paymentrate", ((double)ORG(nPaymentsDiff)) / nTimeDiff)); + organic.push_back(Pair("txrate", ((double)ORG(nTxDiff)) / nTimeDiff)); + } + organic.push_back(Pair("txcount", (int) ORG(nTxDiff))); + organic.push_back(Pair("payments", (int) ORG(nPaymentsDiff))); + ret.push_back(Pair("organic", organic)); + } + + } + } + + return ret; +} + UniValue invalidateblock(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) @@ -1303,6 +1536,7 @@ static const CRPCCommand commands[] = { "blockchain", "getblockhashes", &getblockhashes, true }, { "blockchain", "getblockheader", &getblockheader, true }, { "blockchain", "getchaintips", &getchaintips, true }, + { "blockchain", "getchaintxstats", &getchaintxstats, true }, { "blockchain", "getdifficulty", &getdifficulty, true }, { "blockchain", "getmempoolinfo", &getmempoolinfo, true }, { "blockchain", "getrawmempool", &getrawmempool, true }, diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 7b80293dc8c..4b801e9e783 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -178,7 +178,8 @@ static const CRPCConvertParam vRPCConvertParams[] = { "getsaplingblocks", 0}, { "getsaplingblocks", 1}, { "getsaplingblocks", 2}, - + { "getchaintxstats", 0}, + }; class CRPCConvertTable diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 9b60ef911cb..457fdb59ad3 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -777,6 +777,10 @@ bool CTxMemPool::IsFullyNotified() { return nRecentlyAddedSequence == nNotifiedSequence; } +std::map CTxMemPool::getNullifiers() { + return mapSaplingNullifiers; +} + CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView *baseIn, CTxMemPool &mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { } bool CCoinsViewMemPool::GetNullifier(const uint256 &nf, ShieldedType type) const diff --git a/src/txmempool.h b/src/txmempool.h index 9a9c9fd1eb3..dca24b8228f 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -178,6 +178,8 @@ class CTxMemPool CTxMemPool(const CFeeRate& _minRelayFee); ~CTxMemPool(); + std::map getNullifiers(); + /** * If sanity-checking is turned on, check makes sure the pool is * consistent (does not contain two transactions that spend the same inputs, diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index ea8a9e9480b..1ff47efad64 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1164,6 +1164,37 @@ bool CWallet::GetVinAndKeysFromOutput(COutput out, CTxIn& txinRet, CPubKey& pubK return true; } +std::set CWallet::GetNullifiers() +{ + std::set nullifierSet; + for (const auto & txPair : mapWallet) { + // Sapling + for (const auto & noteDataPair : txPair.second.mapSaplingNoteData) { + auto & noteData = noteDataPair.second; + auto & nullifier = noteData.nullifier; + if (nullifier) { + nullifierSet.insert(nullifier.get()); + } + } + } + return nullifierSet; +} + +int64_t CWallet::NullifierCount() +{ + LOCK(cs_wallet); + if(fDebug) { + // this is our *local* nullifier count + LogPrint("zindex","%s:mapTxSaplingNullifers.size=%d\n",__FUNCTION__,(int)mapTxSaplingNullifiers.size() ); + // here be dragons + LogPrint("zindex","%s:mempool.getNullifiers.size=%d\n",__FUNCTION__,(int)mempool.getNullifiers().size() ); + // this is the global nullifier count + LogPrint("zindex","%s:cacheSaplingNullifiers.size=%d\n",__FUNCTION__,(int)pcoinsTip->getNullifiers().size() ); + } + // TODO: expose local nullifier stats, for now global only + return pcoinsTip->getNullifiers().size(); +} + void CWallet::ClearNoteWitnessCache() { LOCK(cs_wallet); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 7eae4187354..7a425c107bf 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -885,6 +885,9 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface void ClearNoteWitnessCache(); + int64_t NullifierCount(); + std::set GetNullifiers(); + protected: int SproutWitnessMinimumHeight(const uint256& nullifier, int nWitnessHeight, int nMinimumHeight); From c387a59195a2d44ce6adb2e949b08171f1f2ebfb Mon Sep 17 00:00:00 2001 From: cryptoforge Date: Mon, 30 Mar 2020 12:06:31 -0700 Subject: [PATCH 394/395] additonal zindex logging --- src/main.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 4ce968511de..d8b569d2818 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4071,7 +4071,7 @@ bool ReceivedBlockTransactions( pindexNew->nUndoPos = 0; pindexNew->nStatus |= BLOCK_HAVE_DATA; pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS); - setDirtyBlockIndex.insert(pindexNew); + //setDirtyBlockIndex.insert(pindexNew); if (fZindex) { pindexNew->nPayments = nPayments; @@ -4100,8 +4100,8 @@ bool ReceivedBlockTransactions( pindex->nChainTx = (pindex->pprev ? pindex->pprev->nChainTx : 0) + pindex->nTx; if (fZindex) { - if (fDebug) - LogPrint("zindex","%s: setting blockchain zstats with zouts=%d\n", __FUNCTION__, nShieldedOutputsInBlock ); + //if (fDebug) + LogPrint("zindex","%s: setting blockchain zstats with zouts=%d\n", __FUNCTION__, nShieldedOutputsInBlock ); pindex->nChainNotarizations = (pindex->pprev ? pindex->pprev->nChainNotarizations : 0) + pindex->nNotarizations; pindex->nChainShieldedTx = (pindex->pprev ? pindex->pprev->nChainShieldedTx : 0) + pindex->nShieldedTx; pindex->nChainShieldedOutputs = (pindex->pprev ? pindex->pprev->nChainShieldedOutputs : 0) + pindex->nShieldedOutputs; @@ -4113,6 +4113,17 @@ bool ReceivedBlockTransactions( pindex->nChainFullyShieldedPayments = (pindex->pprev ? pindex->pprev->nChainFullyShieldedPayments : 0) + pindex->nFullyShieldedPayments; pindex->nChainShieldingPayments = (pindex->pprev ? pindex->pprev->nChainShieldingPayments : 0) + pindex->nShieldingPayments; pindex->nChainDeshieldingPayments = (pindex->pprev ? pindex->pprev->nChainDeshieldingPayments : 0) + pindex->nDeshieldingPayments; + + LogPrint("zindex", "ht.%d, ChainNotarizations=%d, ChainShieldedTx=%d, ChainShieldedOutputs=%d, ChainFullyShieldedTx=%d\n", + pindex->nHeight, pindex->nChainNotarizations, pindex->nChainShieldedTx, pindex->nChainShieldedOutputs, pindex->nChainFullyShieldedTx); + + LogPrint("zindex", "ht.%d, ChainShieldingTx=%d, ChainDeshieldingTx=%d, ChainPayments=%d, ChainShieldedPayments=%d\n", + pindex->nHeight, pindex->nChainShieldingTx, pindex->nChainDeshieldingTx, pindex->nChainPayments, pindex->nChainShieldedPayments); + + LogPrint("zindex", "ht.%d, ChainFullyShieldedPayments=%d, ChainShieldingPayments=%d, ChainDeshieldingPayments=%d\n", + pindex->nHeight, pindex->nChainFullyShieldedPayments, pindex->nChainShieldingPayments, pindex->nChainDeshieldingPayments); + + } if (pindex->pprev) { From dc02c55dca7ee9ef2ce951654cd0c5db5dae0ffe Mon Sep 17 00:00:00 2001 From: Cryptoforge Date: Thu, 4 Jun 2020 21:15:42 -0700 Subject: [PATCH 395/395] bump version to 3.1.1 --- README.md | 16 ++++++++-------- configure.ac | 2 +- doc/man/zero-cli.1 | 6 +++--- doc/man/zero-tx.1 | 6 +++--- doc/man/zerod.1 | 6 +++--- src/clientversion.cpp | 2 +- src/deprecation.h | 2 +- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 8a503d00aa7..ffbc529f592 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,30 @@ ![alt text](https://github.com/zerocurrencycoin/Zero/blob/master/art/zero%203d%20mountain.png?raw=true) -[ZERO](https://zerocurrency.io) - [Pegasus:3.1.0](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.1.0) +[ZERO](https://zerocurrency.io) - [Cygnus:3.1.1](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.1.1) ||FAST|| ||DECENTRALISED|| ||ANONYMOUS|| ||SECURE|| ||ASIC RESISTANT|| - LAUNCE DATE: 2017-02-19 GENESIS BLOCK - 19th Feb 2017 11:26:40 - 068cbb5db6bc11be5b93479ea4df41fa7e012e92ca8603c315f9b1a2202205c6 -Download the latest version here - [ZERO - Latest Version - Pegasus:3.1.0](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.1.0) +Download the latest version here - [ZERO - Latest Version - Cygnus:3.1.1](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.1.1) ------------------------------------------ ❓ What is ZERO? -------------- -[ZERO](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.1.0) is a revolutionary cryptocurrency and transaction platform based on Zcash. +[ZERO](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.1.1) is a revolutionary cryptocurrency and transaction platform based on Zcash. -[ZERO](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.1.0) offers total payment confidentiality, while still maintaining a decentralised network using a public blockchain. +[ZERO](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.1.1) offers total payment confidentiality, while still maintaining a decentralised network using a public blockchain. -[ZERO](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.1.0) combines Bitcoin’s security with Zcash’s anonymity and privacy. +[ZERO](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.1.1) combines Bitcoin’s security with Zcash’s anonymity and privacy. -[ZERO](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.1.0) stands out from the competition as a fully working product that has already +[ZERO](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.1.1) stands out from the competition as a fully working product that has already implemented a set of special features not found in any other cryptocurrency. Our main focus as a team and community is to remain as transparent as we can possibly be and to maintain an interactive relationship with everyone involved. We are fully open about the project, listening to all suggestions from investors, miners and supporters. -This software is the [ZERO](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.1.0) node. It downloads and stores the entire history of ZERO's transactions, about 1.2GB at this point. +This software is the [ZERO](https://github.com/zerocurrencycoin/Zero/releases/tag/v3.1.1) node. It downloads and stores the entire history of ZERO's transactions, about 1.2GB at this point. Depending on the speed of your computer and network connection, the synchronization process could take several hours. ------------------------------------------ @@ -128,7 +128,7 @@ See important security warnings on the 📒 Deprecation Policy ------------------ -Disabledeprecation flag has been removed. Old nodes will automatically be shut down and must be upgraded upon reaching the deprecation block height, which will occur approximately 26 weeks (6/27/2020) from the release of v3.1.0. +Disabledeprecation flag has been removed. Old nodes will automatically be shut down and must be upgraded upon reaching the deprecation block height, which will occur approximately 26 weeks (1/2/2021) from the release of v3.1.1. 🔧 Building diff --git a/configure.ac b/configure.ac index 8efaaa98ed5..7fb3f5691b2 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 3) define(_CLIENT_VERSION_MINOR, 1) -define(_CLIENT_VERSION_REVISION, 0) +define(_CLIENT_VERSION_REVISION, 1) define(_CLIENT_VERSION_BUILD, 50) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) diff --git a/doc/man/zero-cli.1 b/doc/man/zero-cli.1 index fa12b9300af..f10bcdac80c 100644 --- a/doc/man/zero-cli.1 +++ b/doc/man/zero-cli.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZERO-CLI "1" "December 2019" "zero-cli v3.1.0-79779934a" "User Commands" +.TH ZERO-CLI "1" "December 2019" "zero-cli v3.1.1-79779934a" "User Commands" .SH NAME -zero-cli \- manual page for zero-cli v3.1.0-79779934a +zero-cli \- manual page for zero-cli v3.1.1-79779934a .SH DESCRIPTION -Zero RPC client version v3.1.0\-79779934a +Zero RPC client version v3.1.1\-79779934a .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . diff --git a/doc/man/zero-tx.1 b/doc/man/zero-tx.1 index 6f31dceaf25..00f53ab3131 100644 --- a/doc/man/zero-tx.1 +++ b/doc/man/zero-tx.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZERO-TX "1" "December 2019" "zero-tx v3.1.0-79779934a" "User Commands" +.TH ZERO-TX "1" "December 2019" "zero-tx v3.1.1-79779934a" "User Commands" .SH NAME -zero-tx \- manual page for zero-tx v3.1.0-79779934a +zero-tx \- manual page for zero-tx v3.1.1-79779934a .SH DESCRIPTION -Zero zero\-tx utility version v3.1.0\-79779934a +Zero zero\-tx utility version v3.1.1\-79779934a .SS "Usage:" .TP zero\-tx [options] [commands] diff --git a/doc/man/zerod.1 b/doc/man/zerod.1 index ad38bf5e49e..cd551dc0022 100644 --- a/doc/man/zerod.1 +++ b/doc/man/zerod.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZEROD "1" "December 2019" "zerod v3.1.0-79779934a" "User Commands" +.TH ZEROD "1" "December 2019" "zerod v3.1.1-79779934a" "User Commands" .SH NAME -zerod \- manual page for zerod v3.1.0-79779934a +zerod \- manual page for zerod v3.1.1-79779934a .SH DESCRIPTION -Zero Daemon version v3.1.0\-79779934a +Zero Daemon version v3.1.1\-79779934a .PP In order to ensure you are adequately protecting your privacy when using Zcash, please see . diff --git a/src/clientversion.cpp b/src/clientversion.cpp index 71ce160cc32..7f8b024e320 100644 --- a/src/clientversion.cpp +++ b/src/clientversion.cpp @@ -19,7 +19,7 @@ * for both bitcoind and bitcoin-core, to make it harder for attackers to * target servers or GUI users specifically. */ -const std::string CLIENT_NAME("Pegasus"); +const std::string CLIENT_NAME("Cygnus"); /** * Client version number diff --git a/src/deprecation.h b/src/deprecation.h index 75e2f35ab95..951a4f00594 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -8,7 +8,7 @@ // Deprecation policy: // * Shut down 26 weeks' worth of blocks after the estimated release block height. // * A warning is shown during the 4 weeks' worth of blocks prior to shut down. -static const int APPROX_RELEASE_HEIGHT = 755075; +static const int APPROX_RELEASE_HEIGHT = 886075; static const int WEEKS_UNTIL_DEPRECATION = 26; //Fixing zero day size static const int DEPRECATION_HEIGHT = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 30);